| File: | dev/pci/yds.c |
| Warning: | line 402, column 2 Value stored to 'ecs' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* $OpenBSD: yds.c,v 1.63 2022/10/26 20:19:08 kn Exp $ */ |
| 2 | /* $NetBSD: yds.c,v 1.5 2001/05/21 23:55:04 minoura Exp $ */ |
| 3 | |
| 4 | /* |
| 5 | * Copyright (c) 2000, 2001 Kazuki Sakamoto and Minoura Makoto. |
| 6 | * All rights reserved. |
| 7 | * |
| 8 | * Redistribution and use in source and binary forms, with or without |
| 9 | * modification, are permitted provided that the following conditions |
| 10 | * are met: |
| 11 | * 1. Redistributions of source code must retain the above copyright |
| 12 | * notice, this list of conditions and the following disclaimer. |
| 13 | * 2. Redistributions in binary form must reproduce the above copyright |
| 14 | * notice, this list of conditions and the following disclaimer in the |
| 15 | * documentation and/or other materials provided with the distribution. |
| 16 | * |
| 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
| 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| 19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
| 20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
| 21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
| 22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| 26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | */ |
| 28 | |
| 29 | /* |
| 30 | * Yamaha YMF724[B-F]/740[B-C]/744/754 |
| 31 | * |
| 32 | * Documentation links: |
| 33 | * - ftp://ftp.alsa-project.org/pub/manuals/yamaha/ |
| 34 | * - ftp://ftp.alsa-project.org/pub/manuals/yamaha/pci/ |
| 35 | * |
| 36 | * TODO: |
| 37 | * - FM synth volume (difficult: mixed before ac97) |
| 38 | * - Digital in/out (SPDIF) support |
| 39 | * - Effect?? |
| 40 | */ |
| 41 | |
| 42 | #include <sys/param.h> |
| 43 | #include <sys/systm.h> |
| 44 | #include <sys/kernel.h> |
| 45 | #include <sys/fcntl.h> |
| 46 | #include <sys/malloc.h> |
| 47 | #include <sys/device.h> |
| 48 | #include <sys/queue.h> |
| 49 | |
| 50 | #include <dev/pci/pcidevs.h> |
| 51 | #include <dev/pci/pcireg.h> |
| 52 | #include <dev/pci/pcivar.h> |
| 53 | |
| 54 | #include <sys/audioio.h> |
| 55 | #include <dev/audio_if.h> |
| 56 | #include <dev/midi_if.h> |
| 57 | #include <dev/ic/ac97.h> |
| 58 | |
| 59 | #include <machine/bus.h> |
| 60 | #include <machine/intr.h> |
| 61 | |
| 62 | #include <dev/pci/ydsreg.h> |
| 63 | #include <dev/pci/ydsvar.h> |
| 64 | |
| 65 | /* Debug */ |
| 66 | #undef YDS_USE_REC_SLOT |
| 67 | #define YDS_USE_P44 |
| 68 | |
| 69 | #ifdef AUDIO_DEBUG |
| 70 | # define DPRINTF(x) if (ydsdebug) printf x |
| 71 | # define DPRINTFN(n,x) if (ydsdebug>(n)) printf x |
| 72 | int ydsdebug = 0; |
| 73 | #else |
| 74 | # define DPRINTF(x) |
| 75 | # define DPRINTFN(n,x) |
| 76 | #endif |
| 77 | #ifdef YDS_USE_REC_SLOT |
| 78 | # define YDS_INPUT_SLOT1 0 /* REC slot = ADC + loopbacks */ |
| 79 | #else |
| 80 | # define YDS_INPUT_SLOT1 1 /* ADC slot */ |
| 81 | #endif |
| 82 | |
| 83 | static int ac97_id2; |
| 84 | |
| 85 | int yds_match(struct device *, void *, void *); |
| 86 | void yds_attach(struct device *, struct device *, void *); |
| 87 | int yds_activate(struct device *, int); |
| 88 | int yds_intr(void *); |
| 89 | |
| 90 | static void nswaph(u_int32_t *p, int wcount); |
| 91 | |
| 92 | #define DMAADDR(p)((p)->map->dm_segs[0].ds_addr) ((p)->map->dm_segs[0].ds_addr) |
| 93 | #define KERNADDR(p)((void *)((p)->addr)) ((void *)((p)->addr)) |
| 94 | |
| 95 | int yds_allocmem(struct yds_softc *, size_t, size_t, |
| 96 | struct yds_dma *); |
| 97 | int yds_freemem(struct yds_softc *, struct yds_dma *); |
| 98 | |
| 99 | #ifndef AUDIO_DEBUG |
| 100 | #define YWRITE1(sc, r, x)(((sc)->memt)->write_1(((sc)->memh), ((r)), ((x)))) bus_space_write_1((sc)->memt, (sc)->memh, (r), (x))(((sc)->memt)->write_1(((sc)->memh), ((r)), ((x)))) |
| 101 | #define YWRITE2(sc, r, x)(((sc)->memt)->write_2(((sc)->memh), ((r)), ((x)))) bus_space_write_2((sc)->memt, (sc)->memh, (r), (x))(((sc)->memt)->write_2(((sc)->memh), ((r)), ((x)))) |
| 102 | #define YWRITE4(sc, r, x)(((sc)->memt)->write_4(((sc)->memh), ((r)), ((x)))) bus_space_write_4((sc)->memt, (sc)->memh, (r), (x))(((sc)->memt)->write_4(((sc)->memh), ((r)), ((x)))) |
| 103 | #define YREAD1(sc, r)(((sc)->memt)->read_1(((sc)->memh), ((r)))) bus_space_read_1((sc)->memt, (sc)->memh, (r))(((sc)->memt)->read_1(((sc)->memh), ((r)))) |
| 104 | #define YREAD2(sc, r)(((sc)->memt)->read_2(((sc)->memh), ((r)))) bus_space_read_2((sc)->memt, (sc)->memh, (r))(((sc)->memt)->read_2(((sc)->memh), ((r)))) |
| 105 | #define YREAD4(sc, r)(((sc)->memt)->read_4(((sc)->memh), ((r)))) bus_space_read_4((sc)->memt, (sc)->memh, (r))(((sc)->memt)->read_4(((sc)->memh), ((r)))) |
| 106 | #else |
| 107 | |
| 108 | u_int16_t YREAD2(struct yds_softc *sc,bus_size_t r)(((struct yds_softc *sc)->memt)->read_2(((struct yds_softc *sc)->memh), ((bus_size_t r)))); |
| 109 | u_int32_t YREAD4(struct yds_softc *sc,bus_size_t r)(((struct yds_softc *sc)->memt)->read_4(((struct yds_softc *sc)->memh), ((bus_size_t r)))); |
| 110 | void YWRITE1(struct yds_softc *sc,bus_size_t r,u_int8_t x)(((struct yds_softc *sc)->memt)->write_1(((struct yds_softc *sc)->memh), ((bus_size_t r)), ((u_int8_t x)))); |
| 111 | void YWRITE2(struct yds_softc *sc,bus_size_t r,u_int16_t x)(((struct yds_softc *sc)->memt)->write_2(((struct yds_softc *sc)->memh), ((bus_size_t r)), ((u_int16_t x)))); |
| 112 | void YWRITE4(struct yds_softc *sc,bus_size_t r,u_int32_t x)(((struct yds_softc *sc)->memt)->write_4(((struct yds_softc *sc)->memh), ((bus_size_t r)), ((u_int32_t x)))); |
| 113 | |
| 114 | u_int16_t YREAD2(struct yds_softc *sc,bus_size_t r)(((struct yds_softc *sc)->memt)->read_2(((struct yds_softc *sc)->memh), ((bus_size_t r)))) |
| 115 | { |
| 116 | DPRINTFN(5, (" YREAD2(0x%lX)\n",(unsigned long)r)); |
| 117 | return bus_space_read_2(sc->memt,sc->memh,r)((sc->memt)->read_2((sc->memh), (r))); |
| 118 | } |
| 119 | u_int32_t YREAD4(struct yds_softc *sc,bus_size_t r)(((struct yds_softc *sc)->memt)->read_4(((struct yds_softc *sc)->memh), ((bus_size_t r)))) |
| 120 | { |
| 121 | DPRINTFN(5, (" YREAD4(0x%lX)\n",(unsigned long)r)); |
| 122 | return bus_space_read_4(sc->memt,sc->memh,r)((sc->memt)->read_4((sc->memh), (r))); |
| 123 | } |
| 124 | void YWRITE1(struct yds_softc *sc,bus_size_t r,u_int8_t x)(((struct yds_softc *sc)->memt)->write_1(((struct yds_softc *sc)->memh), ((bus_size_t r)), ((u_int8_t x)))) |
| 125 | { |
| 126 | DPRINTFN(5, (" YWRITE1(0x%lX,0x%lX)\n",(unsigned long)r,(unsigned long)x)); |
| 127 | bus_space_write_1(sc->memt,sc->memh,r,x)((sc->memt)->write_1((sc->memh), (r), (x))); |
| 128 | } |
| 129 | void YWRITE2(struct yds_softc *sc,bus_size_t r,u_int16_t x)(((struct yds_softc *sc)->memt)->write_2(((struct yds_softc *sc)->memh), ((bus_size_t r)), ((u_int16_t x)))) |
| 130 | { |
| 131 | DPRINTFN(5, (" YWRITE2(0x%lX,0x%lX)\n",(unsigned long)r,(unsigned long)x)); |
| 132 | bus_space_write_2(sc->memt,sc->memh,r,x)((sc->memt)->write_2((sc->memh), (r), (x))); |
| 133 | } |
| 134 | void YWRITE4(struct yds_softc *sc,bus_size_t r,u_int32_t x)(((struct yds_softc *sc)->memt)->write_4(((struct yds_softc *sc)->memh), ((bus_size_t r)), ((u_int32_t x)))) |
| 135 | { |
| 136 | DPRINTFN(5, (" YWRITE4(0x%lX,0x%lX)\n",(unsigned long)r,(unsigned long)x)); |
| 137 | bus_space_write_4(sc->memt,sc->memh,r,x)((sc->memt)->write_4((sc->memh), (r), (x))); |
| 138 | } |
| 139 | #endif |
| 140 | |
| 141 | #define YWRITEREGION4(sc, r, x, c)(((sc)->memt)->write_region_4(((sc)->memh), ((r)), ( (x)), ((c) / 4))) \ |
| 142 | bus_space_write_region_4((sc)->memt, (sc)->memh, (r), (x), (c) / 4)(((sc)->memt)->write_region_4(((sc)->memh), ((r)), ( (x)), ((c) / 4))) |
| 143 | |
| 144 | const struct cfattach yds_ca = { |
| 145 | sizeof(struct yds_softc), yds_match, yds_attach, NULL((void *)0), |
| 146 | yds_activate |
| 147 | }; |
| 148 | |
| 149 | struct cfdriver yds_cd = { |
| 150 | NULL((void *)0), "yds", DV_DULL |
| 151 | }; |
| 152 | |
| 153 | int yds_open(void *, int); |
| 154 | void yds_close(void *); |
| 155 | int yds_set_params(void *, int, int, |
| 156 | struct audio_params *, struct audio_params *); |
| 157 | int yds_round_blocksize(void *, int); |
| 158 | int yds_trigger_output(void *, void *, void *, int, void (*)(void *), |
| 159 | void *, struct audio_params *); |
| 160 | int yds_trigger_input(void *, void *, void *, int, void (*)(void *), |
| 161 | void *, struct audio_params *); |
| 162 | int yds_halt_output(void *); |
| 163 | int yds_halt_input(void *); |
| 164 | int yds_mixer_set_port(void *, mixer_ctrl_t *); |
| 165 | int yds_mixer_get_port(void *, mixer_ctrl_t *); |
| 166 | void *yds_malloc(void *, int, size_t, int, int); |
| 167 | void yds_free(void *, void *, int); |
| 168 | size_t yds_round_buffersize(void *, int, size_t); |
| 169 | int yds_query_devinfo(void *addr, mixer_devinfo_t *dip); |
| 170 | |
| 171 | int yds_attach_codec(void *sc, struct ac97_codec_if *); |
| 172 | int yds_read_codec(void *sc, u_int8_t a, u_int16_t *d); |
| 173 | int yds_write_codec(void *sc, u_int8_t a, u_int16_t d); |
| 174 | void yds_reset_codec(void *sc); |
| 175 | int yds_get_portnum_by_name(struct yds_softc *, char *, char *, |
| 176 | char *); |
| 177 | |
| 178 | static u_int yds_get_dstype(int); |
| 179 | static int yds_download_mcode(struct yds_softc *); |
| 180 | static int yds_allocate_slots(struct yds_softc *, int); |
| 181 | static void yds_configure_legacy(struct yds_softc *arg); |
| 182 | static void yds_enable_dsp(struct yds_softc *); |
| 183 | static int yds_disable_dsp(struct yds_softc *); |
| 184 | static int yds_ready_codec(struct yds_codec_softc *); |
| 185 | static int yds_halt(struct yds_softc *); |
| 186 | static u_int32_t yds_get_lpfq(u_int); |
| 187 | static u_int32_t yds_get_lpfk(u_int); |
| 188 | static struct yds_dma *yds_find_dma(struct yds_softc *, void *); |
| 189 | |
| 190 | int yds_init(struct yds_softc *, int); |
| 191 | void yds_attachhook(struct device *); |
| 192 | |
| 193 | #ifdef AUDIO_DEBUG |
| 194 | static void yds_dump_play_slot(struct yds_softc *, int); |
| 195 | #define YDS_DUMP_PLAY_SLOT(n,sc,bank) \ |
| 196 | if (ydsdebug > (n)) yds_dump_play_slot(sc, bank) |
| 197 | #else |
| 198 | #define YDS_DUMP_PLAY_SLOT(n,sc,bank) |
| 199 | #endif /* AUDIO_DEBUG */ |
| 200 | |
| 201 | static const struct audio_hw_if yds_hw_if = { |
| 202 | .open = yds_open, |
| 203 | .close = yds_close, |
| 204 | .set_params = yds_set_params, |
| 205 | .round_blocksize = yds_round_blocksize, |
| 206 | .halt_output = yds_halt_output, |
| 207 | .halt_input = yds_halt_input, |
| 208 | .set_port = yds_mixer_set_port, |
| 209 | .get_port = yds_mixer_get_port, |
| 210 | .query_devinfo = yds_query_devinfo, |
| 211 | .allocm = yds_malloc, |
| 212 | .freem = yds_free, |
| 213 | .round_buffersize = yds_round_buffersize, |
| 214 | .trigger_output = yds_trigger_output, |
| 215 | .trigger_input = yds_trigger_input, |
| 216 | }; |
| 217 | |
| 218 | static const struct { |
| 219 | u_int id; |
| 220 | u_int flags; |
| 221 | #define YDS_CAP_MCODE_10x0001 0x0001 |
| 222 | #define YDS_CAP_MCODE_1E0x0002 0x0002 |
| 223 | #define YDS_CAP_LEGACY_SELECTABLE0x0004 0x0004 |
| 224 | #define YDS_CAP_LEGACY_FLEXIBLE0x0008 0x0008 |
| 225 | #define YDS_CAP_HAS_P440x0010 0x0010 |
| 226 | #define YDS_CAP_LEGACY_SMOD_DISABLE0x1000 0x1000 |
| 227 | } yds_chip_capability_list[] = { |
| 228 | { PCI_PRODUCT_YAMAHA_YMF7240x0004, |
| 229 | YDS_CAP_MCODE_10x0001|YDS_CAP_LEGACY_SELECTABLE0x0004 }, |
| 230 | /* 740[C] has only 32 slots. But anyway we use only 2 */ |
| 231 | { PCI_PRODUCT_YAMAHA_YMF7400x000a, |
| 232 | YDS_CAP_MCODE_10x0001|YDS_CAP_LEGACY_SELECTABLE0x0004 }, /* XXX NOT TESTED */ |
| 233 | { PCI_PRODUCT_YAMAHA_YMF740C0x000c, |
| 234 | YDS_CAP_MCODE_1E0x0002|YDS_CAP_LEGACY_SELECTABLE0x0004 }, |
| 235 | { PCI_PRODUCT_YAMAHA_YMF724F0x000d, |
| 236 | YDS_CAP_MCODE_1E0x0002|YDS_CAP_LEGACY_SELECTABLE0x0004 }, |
| 237 | { PCI_PRODUCT_YAMAHA_YMF7440x0010, |
| 238 | YDS_CAP_MCODE_1E0x0002|YDS_CAP_LEGACY_FLEXIBLE0x0008 }, |
| 239 | { PCI_PRODUCT_YAMAHA_YMF7540x0012, |
| 240 | YDS_CAP_MCODE_1E0x0002|YDS_CAP_LEGACY_FLEXIBLE0x0008|YDS_CAP_HAS_P440x0010 }, |
| 241 | /* How about 734/737/738?? */ |
| 242 | { 0, 0 } |
| 243 | }; |
| 244 | #ifdef AUDIO_DEBUG |
| 245 | #define YDS_CAP_BITS "\020\005P44\004LEGFLEX\003LEGSEL\002MCODE1E\001MCODE1" |
| 246 | #endif |
| 247 | |
| 248 | #ifdef AUDIO_DEBUG |
| 249 | static void |
| 250 | yds_dump_play_slot(struct yds_softc *sc, int bank) |
| 251 | { |
| 252 | int i, j; |
| 253 | u_int32_t *p; |
| 254 | u_int32_t num; |
| 255 | struct yds_dma *dma; |
| 256 | |
| 257 | for (i = 0; i < N_PLAY_SLOTS2; i++) { |
| 258 | printf("pbankp[%d] = %p,", i*2, sc->pbankp[i*2]); |
| 259 | printf("pbankp[%d] = %p\n", i*2+1, sc->pbankp[i*2+1]); |
| 260 | } |
| 261 | |
| 262 | p = (u_int32_t*)sc->ptbl; |
| 263 | for (i = 0; i < N_PLAY_SLOTS2+1; i++) { |
| 264 | printf("ptbl + %d:0x%x\n", i, *p); |
| 265 | p++; |
| 266 | } |
| 267 | |
| 268 | num = *(u_int32_t*)sc->ptbl; |
| 269 | printf("num = %d\n", num); |
| 270 | |
| 271 | for (i = 0; i < num; i++) { |
| 272 | |
| 273 | p = (u_int32_t *)sc->pbankp[i]; |
| 274 | |
| 275 | dma = yds_find_dma(sc,(void *)p); |
| 276 | |
| 277 | for (j = 0; j < sizeof(struct play_slot_ctrl_bank) / |
| 278 | sizeof(u_int32_t); j++) { |
| 279 | printf(" 0x%02x: 0x%08x\n", |
| 280 | (unsigned) (j * sizeof(u_int32_t)), |
| 281 | (unsigned) *p++); |
| 282 | } |
| 283 | /* |
| 284 | p = (u_int32_t *)sc->pbankp[i*2 + 1]; |
| 285 | printf(" pbankp[%d] : %p\n", i*2 + 1, p); |
| 286 | for (j = 0; j < sizeof(struct play_slot_ctrl_bank) / |
| 287 | sizeof(u_int32_t); j++) { |
| 288 | printf(" 0x%02x: 0x%08x\n", |
| 289 | j * sizeof(u_int32_t), *p++); |
| 290 | delay(1); |
| 291 | } |
| 292 | */ |
| 293 | } |
| 294 | } |
| 295 | #endif /* AUDIO_DEBUG */ |
| 296 | |
| 297 | static u_int |
| 298 | yds_get_dstype(int id) |
| 299 | { |
| 300 | int i; |
| 301 | |
| 302 | for (i = 0; yds_chip_capability_list[i].id; i++) { |
| 303 | if (PCI_PRODUCT(id)(((id) >> 16) & 0xffff) == yds_chip_capability_list[i].id) |
| 304 | return yds_chip_capability_list[i].flags; |
| 305 | } |
| 306 | |
| 307 | return -1; |
| 308 | } |
| 309 | |
| 310 | static void |
| 311 | nswaph(u_int32_t *p, int wcount) |
| 312 | { |
| 313 | for (; wcount; wcount -=4) { |
| 314 | *p = ntohl(*p)(__uint32_t)(__builtin_constant_p(*p) ? (__uint32_t)(((__uint32_t )(*p) & 0xff) << 24 | ((__uint32_t)(*p) & 0xff00 ) << 8 | ((__uint32_t)(*p) & 0xff0000) >> 8 | ((__uint32_t)(*p) & 0xff000000) >> 24) : __swap32md (*p)); |
| 315 | p++; |
| 316 | } |
| 317 | } |
| 318 | |
| 319 | static int |
| 320 | yds_download_mcode(struct yds_softc *sc) |
| 321 | { |
| 322 | u_int ctrl; |
| 323 | const u_int32_t *p; |
| 324 | size_t size; |
| 325 | u_char *buf; |
| 326 | size_t buflen; |
| 327 | int error; |
| 328 | struct yds_firmware *yf; |
| 329 | |
| 330 | error = loadfirmware("yds", &buf, &buflen); |
| 331 | if (error) |
| 332 | return 1; |
| 333 | yf = (struct yds_firmware *)buf; |
| 334 | |
| 335 | if (sc->sc_flags & YDS_CAP_MCODE_10x0001) { |
| 336 | p = (u_int32_t *)&yf->data[ntohl(yf->dsplen)(__uint32_t)(__builtin_constant_p(yf->dsplen) ? (__uint32_t )(((__uint32_t)(yf->dsplen) & 0xff) << 24 | ((__uint32_t )(yf->dsplen) & 0xff00) << 8 | ((__uint32_t)(yf-> dsplen) & 0xff0000) >> 8 | ((__uint32_t)(yf->dsplen ) & 0xff000000) >> 24) : __swap32md(yf->dsplen))]; |
| 337 | size = ntohl(yf->ds1len)(__uint32_t)(__builtin_constant_p(yf->ds1len) ? (__uint32_t )(((__uint32_t)(yf->ds1len) & 0xff) << 24 | ((__uint32_t )(yf->ds1len) & 0xff00) << 8 | ((__uint32_t)(yf-> ds1len) & 0xff0000) >> 8 | ((__uint32_t)(yf->ds1len ) & 0xff000000) >> 24) : __swap32md(yf->ds1len)); |
| 338 | } else if (sc->sc_flags & YDS_CAP_MCODE_1E0x0002) { |
| 339 | p = (u_int32_t *)&yf->data[ntohl(yf->dsplen)(__uint32_t)(__builtin_constant_p(yf->dsplen) ? (__uint32_t )(((__uint32_t)(yf->dsplen) & 0xff) << 24 | ((__uint32_t )(yf->dsplen) & 0xff00) << 8 | ((__uint32_t)(yf-> dsplen) & 0xff0000) >> 8 | ((__uint32_t)(yf->dsplen ) & 0xff000000) >> 24) : __swap32md(yf->dsplen)) + ntohl(yf->ds1len)(__uint32_t)(__builtin_constant_p(yf->ds1len) ? (__uint32_t )(((__uint32_t)(yf->ds1len) & 0xff) << 24 | ((__uint32_t )(yf->ds1len) & 0xff00) << 8 | ((__uint32_t)(yf-> ds1len) & 0xff0000) >> 8 | ((__uint32_t)(yf->ds1len ) & 0xff000000) >> 24) : __swap32md(yf->ds1len))]; |
| 340 | size = ntohl(yf->ds1elen)(__uint32_t)(__builtin_constant_p(yf->ds1elen) ? (__uint32_t )(((__uint32_t)(yf->ds1elen) & 0xff) << 24 | ((__uint32_t )(yf->ds1elen) & 0xff00) << 8 | ((__uint32_t)(yf ->ds1elen) & 0xff0000) >> 8 | ((__uint32_t)(yf-> ds1elen) & 0xff000000) >> 24) : __swap32md(yf->ds1elen )); |
| 341 | } else { |
| 342 | free(buf, M_DEVBUF2, buflen); |
| 343 | return 1; /* unknown */ |
| 344 | } |
| 345 | |
| 346 | if (size > buflen) { |
| 347 | printf("%s: old firmware file, update please\n", |
| 348 | sc->sc_dev.dv_xname); |
| 349 | free(buf, M_DEVBUF2, buflen); |
| 350 | return 1; |
| 351 | } |
| 352 | |
| 353 | if (yds_disable_dsp(sc)) { |
| 354 | free(buf, M_DEVBUF2, buflen); |
| 355 | return 1; |
| 356 | } |
| 357 | |
| 358 | /* Software reset */ |
| 359 | YWRITE4(sc, YDS_MODE, YDS_MODE_RESET)(((sc)->memt)->write_4(((sc)->memh), ((0x0108)), ((0x00010000 )))); |
| 360 | YWRITE4(sc, YDS_MODE, 0)(((sc)->memt)->write_4(((sc)->memh), ((0x0108)), ((0 )))); |
| 361 | |
| 362 | YWRITE4(sc, YDS_MAPOF_REC, 0)(((sc)->memt)->write_4(((sc)->memh), ((0x0150)), ((0 )))); |
| 363 | YWRITE4(sc, YDS_MAPOF_EFFECT, 0)(((sc)->memt)->write_4(((sc)->memh), ((0x0154)), ((0 )))); |
| 364 | YWRITE4(sc, YDS_PLAY_CTRLBASE, 0)(((sc)->memt)->write_4(((sc)->memh), ((0x0158)), ((0 )))); |
| 365 | YWRITE4(sc, YDS_REC_CTRLBASE, 0)(((sc)->memt)->write_4(((sc)->memh), ((0x015c)), ((0 )))); |
| 366 | YWRITE4(sc, YDS_EFFECT_CTRLBASE, 0)(((sc)->memt)->write_4(((sc)->memh), ((0x0160)), ((0 )))); |
| 367 | YWRITE4(sc, YDS_WORK_BASE, 0)(((sc)->memt)->write_4(((sc)->memh), ((0x0164)), ((0 )))); |
| 368 | |
| 369 | ctrl = YREAD2(sc, YDS_GLOBAL_CONTROL)(((sc)->memt)->read_2(((sc)->memh), ((0x0008)))); |
| 370 | YWRITE2(sc, YDS_GLOBAL_CONTROL, ctrl & ~0x0007)(((sc)->memt)->write_2(((sc)->memh), ((0x0008)), ((ctrl & ~0x0007)))); |
| 371 | |
| 372 | /* Download DSP microcode. */ |
| 373 | nswaph((u_int32_t *)&yf->data[0], ntohl(yf->dsplen)(__uint32_t)(__builtin_constant_p(yf->dsplen) ? (__uint32_t )(((__uint32_t)(yf->dsplen) & 0xff) << 24 | ((__uint32_t )(yf->dsplen) & 0xff00) << 8 | ((__uint32_t)(yf-> dsplen) & 0xff0000) >> 8 | ((__uint32_t)(yf->dsplen ) & 0xff000000) >> 24) : __swap32md(yf->dsplen))); |
| 374 | YWRITEREGION4(sc, YDS_DSP_INSTRAM, (u_int32_t *)&yf->data[0],(((sc)->memt)->write_region_4(((sc)->memh), ((0x1000 )), (((u_int32_t *)&yf->data[0])), (((__uint32_t)(__builtin_constant_p (yf->dsplen) ? (__uint32_t)(((__uint32_t)(yf->dsplen) & 0xff) << 24 | ((__uint32_t)(yf->dsplen) & 0xff00 ) << 8 | ((__uint32_t)(yf->dsplen) & 0xff0000) >> 8 | ((__uint32_t)(yf->dsplen) & 0xff000000) >> 24 ) : __swap32md(yf->dsplen))) / 4))) |
| 375 | ntohl(yf->dsplen))(((sc)->memt)->write_region_4(((sc)->memh), ((0x1000 )), (((u_int32_t *)&yf->data[0])), (((__uint32_t)(__builtin_constant_p (yf->dsplen) ? (__uint32_t)(((__uint32_t)(yf->dsplen) & 0xff) << 24 | ((__uint32_t)(yf->dsplen) & 0xff00 ) << 8 | ((__uint32_t)(yf->dsplen) & 0xff0000) >> 8 | ((__uint32_t)(yf->dsplen) & 0xff000000) >> 24 ) : __swap32md(yf->dsplen))) / 4))); |
| 376 | |
| 377 | /* Download CONTROL microcode. */ |
| 378 | nswaph((u_int32_t *)p, size); |
| 379 | YWRITEREGION4(sc, YDS_CTRL_INSTRAM, p, size)(((sc)->memt)->write_region_4(((sc)->memh), ((0x4000 )), ((p)), ((size) / 4))); |
| 380 | |
| 381 | yds_enable_dsp(sc); |
| 382 | delay(10*1000)(*delay_func)(10*1000); /* necessary on my 724F (??) */ |
| 383 | |
| 384 | free(buf, M_DEVBUF2, buflen); |
| 385 | return 0; |
| 386 | } |
| 387 | |
| 388 | static int |
| 389 | yds_allocate_slots(struct yds_softc *sc, int resuming) |
| 390 | { |
| 391 | size_t pcs, rcs, ecs, ws, memsize; |
| 392 | void *mp; |
| 393 | u_int32_t da; /* DMA address */ |
| 394 | char *va; /* KVA */ |
| 395 | off_t cb; |
| 396 | int i; |
| 397 | struct yds_dma *p; |
| 398 | |
| 399 | /* Alloc DSP Control Data */ |
| 400 | pcs = YREAD4(sc, YDS_PLAY_CTRLSIZE)(((sc)->memt)->read_4(((sc)->memh), ((0x0140)))) * sizeof(u_int32_t); |
| 401 | rcs = YREAD4(sc, YDS_REC_CTRLSIZE)(((sc)->memt)->read_4(((sc)->memh), ((0x0144)))) * sizeof(u_int32_t); |
| 402 | ecs = YREAD4(sc, YDS_EFFECT_CTRLSIZE)(((sc)->memt)->read_4(((sc)->memh), ((0x0148)))) * sizeof(u_int32_t); |
Value stored to 'ecs' is never read | |
| 403 | ws = WORK_SIZE0x0400; |
| 404 | YWRITE4(sc, YDS_WORK_SIZE, ws / sizeof(u_int32_t))(((sc)->memt)->write_4(((sc)->memh), ((0x014c)), ((ws / sizeof(u_int32_t))))); |
| 405 | |
| 406 | DPRINTF(("play control size : %d\n", (unsigned int)pcs)); |
| 407 | DPRINTF(("rec control size : %d\n", (unsigned int)rcs)); |
| 408 | DPRINTF(("eff control size : %d\n", (unsigned int)ecs)); |
| 409 | DPRINTF(("work size : %d\n", (unsigned int)ws)); |
| 410 | #ifdef DIAGNOSTIC1 |
| 411 | if (pcs != sizeof(struct play_slot_ctrl_bank)) { |
| 412 | printf("%s: invalid play slot ctrldata %d != %d\n", |
| 413 | sc->sc_dev.dv_xname, (unsigned int)pcs, |
| 414 | (unsigned int)sizeof(struct play_slot_ctrl_bank)); |
| 415 | } |
| 416 | if (rcs != sizeof(struct rec_slot_ctrl_bank)) { |
| 417 | printf("%s: invalid rec slot ctrldata %d != %d\n", |
| 418 | sc->sc_dev.dv_xname, (unsigned int)rcs, |
| 419 | (unsigned int)sizeof(struct rec_slot_ctrl_bank)); |
| 420 | } |
| 421 | #endif |
| 422 | |
| 423 | memsize = N_PLAY_SLOTS2*N_PLAY_SLOT_CTRL_BANK2*pcs + |
| 424 | N_REC_SLOT_CTRL2*N_REC_SLOT_CTRL_BANK2*rcs + ws; |
| 425 | memsize += (N_PLAY_SLOTS2+1)*sizeof(u_int32_t); |
| 426 | |
| 427 | p = &sc->sc_ctrldata; |
| 428 | if (!resuming) { |
| 429 | i = yds_allocmem(sc, memsize, 16, p); |
| 430 | if (i) { |
| 431 | printf("%s: couldn't alloc/map DSP DMA buffer, reason %d\n", |
| 432 | sc->sc_dev.dv_xname, i); |
| 433 | return 1; |
| 434 | } |
| 435 | } |
| 436 | mp = KERNADDR(p)((void *)((p)->addr)); |
| 437 | da = DMAADDR(p)((p)->map->dm_segs[0].ds_addr); |
| 438 | |
| 439 | DPRINTF(("mp:%p, DMA addr:%p\n", |
| 440 | mp, (void *) sc->sc_ctrldata.map->dm_segs[0].ds_addr)); |
| 441 | |
| 442 | bzero(mp, memsize)__builtin_bzero((mp), (memsize)); |
| 443 | |
| 444 | /* Work space */ |
| 445 | cb = 0; |
| 446 | va = (u_int8_t*)mp; |
| 447 | YWRITE4(sc, YDS_WORK_BASE, da + cb)(((sc)->memt)->write_4(((sc)->memh), ((0x0164)), ((da + cb)))); |
| 448 | cb += ws; |
| 449 | |
| 450 | /* Play control data table */ |
| 451 | sc->ptbl = (u_int32_t *)(va + cb); |
| 452 | sc->ptbloff = cb; |
| 453 | YWRITE4(sc, YDS_PLAY_CTRLBASE, da + cb)(((sc)->memt)->write_4(((sc)->memh), ((0x0158)), ((da + cb)))); |
| 454 | cb += (N_PLAY_SLOT_CTRL2 + 1) * sizeof(u_int32_t); |
| 455 | |
| 456 | /* Record slot control data */ |
| 457 | sc->rbank = (struct rec_slot_ctrl_bank *)(va + cb); |
| 458 | YWRITE4(sc, YDS_REC_CTRLBASE, da + cb)(((sc)->memt)->write_4(((sc)->memh), ((0x015c)), ((da + cb)))); |
| 459 | sc->rbankoff = cb; |
| 460 | cb += N_REC_SLOT_CTRL2 * N_REC_SLOT_CTRL_BANK2 * rcs; |
| 461 | |
| 462 | #if 0 |
| 463 | /* Effect slot control data -- unused */ |
| 464 | YWRITE4(sc, YDS_EFFECT_CTRLBASE, da + cb)(((sc)->memt)->write_4(((sc)->memh), ((0x0160)), ((da + cb)))); |
| 465 | cb += N_EFFECT_SLOT_CTRL * N_EFFECT_SLOT_CTRL_BANK * ecs; |
| 466 | #endif |
| 467 | |
| 468 | /* Play slot control data */ |
| 469 | sc->pbankoff = da + cb; |
| 470 | for (i=0; i<N_PLAY_SLOT_CTRL2; i++) { |
| 471 | sc->pbankp[i*2] = (struct play_slot_ctrl_bank *)(va + cb); |
| 472 | *(sc->ptbl + i+1) = da + cb; |
| 473 | cb += pcs; |
| 474 | |
| 475 | sc->pbankp[i*2+1] = (struct play_slot_ctrl_bank *)(va + cb); |
| 476 | cb += pcs; |
| 477 | } |
| 478 | /* Sync play control data table */ |
| 479 | bus_dmamap_sync(sc->sc_dmatag, p->map,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (p ->map), (sc->ptbloff), ((2 +1) * sizeof(u_int32_t)), (0x04 )) |
| 480 | sc->ptbloff, (N_PLAY_SLOT_CTRL+1) * sizeof(u_int32_t),(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (p ->map), (sc->ptbloff), ((2 +1) * sizeof(u_int32_t)), (0x04 )) |
| 481 | BUS_DMASYNC_PREWRITE)(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (p ->map), (sc->ptbloff), ((2 +1) * sizeof(u_int32_t)), (0x04 )); |
| 482 | |
| 483 | return 0; |
| 484 | } |
| 485 | |
| 486 | static void |
| 487 | yds_enable_dsp(struct yds_softc *sc) |
| 488 | { |
| 489 | YWRITE4(sc, YDS_CONFIG, YDS_DSP_SETUP)(((sc)->memt)->write_4(((sc)->memh), ((0x0114)), ((0x00000001 )))); |
| 490 | } |
| 491 | |
| 492 | static int |
| 493 | yds_disable_dsp(struct yds_softc *sc) |
| 494 | { |
| 495 | int to; |
| 496 | u_int32_t data; |
| 497 | |
| 498 | data = YREAD4(sc, YDS_CONFIG)(((sc)->memt)->read_4(((sc)->memh), ((0x0114)))); |
| 499 | if (data) |
| 500 | YWRITE4(sc, YDS_CONFIG, YDS_DSP_DISABLE)(((sc)->memt)->write_4(((sc)->memh), ((0x0114)), ((0 )))); |
| 501 | |
| 502 | for (to = 0; to < YDS_WORK_TIMEOUT250000; to++) { |
| 503 | if ((YREAD4(sc, YDS_STATUS)(((sc)->memt)->read_4(((sc)->memh), ((0x0100)))) & YDS_STAT_WORK0x00000002) == 0) |
| 504 | return 0; |
| 505 | delay(1)(*delay_func)(1); |
| 506 | } |
| 507 | |
| 508 | return 1; |
| 509 | } |
| 510 | |
| 511 | int |
| 512 | yds_match(struct device *parent, void *match, void *aux) |
| 513 | { |
| 514 | struct pci_attach_args *pa = (struct pci_attach_args *) aux; |
| 515 | |
| 516 | switch (PCI_VENDOR(pa->pa_id)(((pa->pa_id) >> 0) & 0xffff)) { |
| 517 | case PCI_VENDOR_YAMAHA0x1073: |
| 518 | switch (PCI_PRODUCT(pa->pa_id)(((pa->pa_id) >> 16) & 0xffff)) { |
| 519 | case PCI_PRODUCT_YAMAHA_YMF7240x0004: |
| 520 | case PCI_PRODUCT_YAMAHA_YMF7400x000a: |
| 521 | case PCI_PRODUCT_YAMAHA_YMF740C0x000c: |
| 522 | case PCI_PRODUCT_YAMAHA_YMF724F0x000d: |
| 523 | case PCI_PRODUCT_YAMAHA_YMF7440x0010: |
| 524 | case PCI_PRODUCT_YAMAHA_YMF7540x0012: |
| 525 | /* 734, 737, 738?? */ |
| 526 | return (1); |
| 527 | } |
| 528 | break; |
| 529 | } |
| 530 | |
| 531 | return (0); |
| 532 | } |
| 533 | |
| 534 | /* |
| 535 | * This routine is called after all the ISA devices are configured, |
| 536 | * to avoid conflict. |
| 537 | */ |
| 538 | static void |
| 539 | yds_configure_legacy(struct yds_softc *sc) |
| 540 | #define FLEXIBLE (sc->sc_flags & YDS_CAP_LEGACY_FLEXIBLE0x0008) |
| 541 | #define SELECTABLE (sc->sc_flags & YDS_CAP_LEGACY_SELECTABLE0x0004) |
| 542 | { |
| 543 | pcireg_t reg; |
| 544 | struct device *dev; |
| 545 | int i; |
| 546 | bus_addr_t opl_addrs[] = {0x388, 0x398, 0x3A0, 0x3A8}; |
| 547 | bus_addr_t mpu_addrs[] = {0x330, 0x300, 0x332, 0x334}; |
| 548 | |
| 549 | if (!FLEXIBLE && !SELECTABLE) |
| 550 | return; |
| 551 | |
| 552 | reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, YDS_PCI_LEGACY0x40); |
| 553 | reg &= ~0x8133c03f; /* these bits are out of interest */ |
| 554 | reg |= (YDS_PCI_EX_LEGACY_IMOD(0x8000 << 16) | YDS_PCI_LEGACY_FMEN0x0002 | |
| 555 | YDS_PCI_LEGACY_MEN0x0008 /*| YDS_PCI_LEGACY_MIEN*/); |
| 556 | if (sc->sc_flags & YDS_CAP_LEGACY_SMOD_DISABLE0x1000) |
| 557 | reg |= YDS_PCI_EX_LEGACY_SMOD_DISABLE(0x0800 << 16); |
| 558 | if (FLEXIBLE) { |
| 559 | pci_conf_write(sc->sc_pc, sc->sc_pcitag, YDS_PCI_LEGACY0x40, reg); |
| 560 | delay(100*1000)(*delay_func)(100*1000); |
| 561 | } |
| 562 | |
| 563 | /* Look for OPL */ |
| 564 | dev = 0; |
| 565 | for (i = 0; i < sizeof(opl_addrs) / sizeof (bus_addr_t); i++) { |
| 566 | if (SELECTABLE) { |
| 567 | pci_conf_write(sc->sc_pc, sc->sc_pcitag, |
| 568 | YDS_PCI_LEGACY0x40, reg | (i << (0+16))); |
| 569 | delay(100*1000)(*delay_func)(100*1000); /* wait 100ms */ |
| 570 | } else |
| 571 | pci_conf_write(sc->sc_pc, sc->sc_pcitag, |
| 572 | YDS_PCI_FM_BA0x60, opl_addrs[i]); |
| 573 | if (bus_space_map(sc->sc_opl_iotsc_legacy_iot, |
| 574 | opl_addrs[i], 4, 0, &sc->sc_opl_ioh) == 0) { |
| 575 | struct audio_attach_args aa; |
| 576 | |
| 577 | aa.type = AUDIODEV_TYPE_OPL2; |
| 578 | aa.hwif = aa.hdl = NULL((void *)0); |
| 579 | dev = config_found(&sc->sc_dev, &aa, audioprint)config_found_sm((&sc->sc_dev), (&aa), (audioprint) , ((void *)0)); |
| 580 | if (dev == 0) |
| 581 | bus_space_unmap(sc->sc_opl_iotsc_legacy_iot, |
| 582 | sc->sc_opl_ioh, 4); |
| 583 | else { |
| 584 | if (SELECTABLE) |
| 585 | reg |= (i << (0+16)); |
| 586 | break; |
| 587 | } |
| 588 | } |
| 589 | } |
| 590 | if (dev == 0) { |
| 591 | reg &= ~YDS_PCI_LEGACY_FMEN0x0002; |
| 592 | pci_conf_write(sc->sc_pc, sc->sc_pcitag, |
| 593 | YDS_PCI_LEGACY0x40, reg); |
| 594 | } else { |
| 595 | /* Max. volume */ |
| 596 | YWRITE4(sc, YDS_LEGACY_OUT_VOLUME, 0x3fff3fff)(((sc)->memt)->write_4(((sc)->memh), ((0x0080)), ((0x3fff3fff )))); |
| 597 | YWRITE4(sc, YDS_LEGACY_REC_VOLUME, 0x3fff3fff)(((sc)->memt)->write_4(((sc)->memh), ((0x0094)), ((0x3fff3fff )))); |
| 598 | } |
| 599 | |
| 600 | /* Look for MPU */ |
| 601 | dev = 0; |
| 602 | for (i = 0; i < sizeof(mpu_addrs) / sizeof (bus_addr_t); i++) { |
| 603 | if (SELECTABLE) |
| 604 | pci_conf_write(sc->sc_pc, sc->sc_pcitag, |
| 605 | YDS_PCI_LEGACY0x40, reg | (i << (4+16))); |
| 606 | else |
| 607 | pci_conf_write(sc->sc_pc, sc->sc_pcitag, |
| 608 | YDS_PCI_MPU_BA0x64, mpu_addrs[i]); |
| 609 | if (bus_space_map(sc->sc_mpu_iotsc_legacy_iot, |
| 610 | mpu_addrs[i], 2, 0, &sc->sc_mpu_ioh) == 0) { |
| 611 | struct audio_attach_args aa; |
| 612 | |
| 613 | aa.type = AUDIODEV_TYPE_MPU3; |
| 614 | aa.hwif = aa.hdl = NULL((void *)0); |
| 615 | dev = config_found(&sc->sc_dev, &aa, audioprint)config_found_sm((&sc->sc_dev), (&aa), (audioprint) , ((void *)0)); |
| 616 | if (dev == 0) |
| 617 | bus_space_unmap(sc->sc_mpu_iotsc_legacy_iot, |
| 618 | sc->sc_mpu_ioh, 2); |
| 619 | else { |
| 620 | if (SELECTABLE) |
| 621 | reg |= (i << (4+16)); |
| 622 | break; |
| 623 | } |
| 624 | } |
| 625 | } |
| 626 | if (dev == 0) { |
| 627 | reg &= ~(YDS_PCI_LEGACY_MEN0x0008 | YDS_PCI_LEGACY_MIEN0x0010); |
| 628 | pci_conf_write(sc->sc_pc, sc->sc_pcitag, |
| 629 | YDS_PCI_LEGACY0x40, reg); |
| 630 | } |
| 631 | sc->sc_mpu = dev; |
| 632 | } |
| 633 | #undef FLEXIBLE |
| 634 | #undef SELECTABLE |
| 635 | |
| 636 | void |
| 637 | yds_attach(struct device *parent, struct device *self, void *aux) |
| 638 | { |
| 639 | struct yds_softc *sc = (struct yds_softc *)self; |
| 640 | struct pci_attach_args *pa = (struct pci_attach_args *)aux; |
| 641 | pci_chipset_tag_t pc = pa->pa_pc; |
| 642 | char const *intrstr; |
| 643 | pci_intr_handle_t ih; |
| 644 | bus_size_t size; |
| 645 | pcireg_t reg; |
| 646 | int i; |
| 647 | |
| 648 | /* Map register to memory */ |
| 649 | if (pci_mapreg_map(pa, YDS_PCI_MBA0x10, PCI_MAPREG_TYPE_MEM0x00000000, 0, |
| 650 | &sc->memt, &sc->memh, NULL((void *)0), &size, 0)) { |
| 651 | printf(": can't map mem space\n"); |
| 652 | return; |
| 653 | } |
| 654 | |
| 655 | /* Map and establish the interrupt. */ |
| 656 | if (pci_intr_map(pa, &ih)) { |
| 657 | printf(": couldn't map interrupt\n"); |
| 658 | bus_space_unmap(sc->memt, sc->memh, size); |
| 659 | return; |
| 660 | } |
| 661 | intrstr = pci_intr_string(pc, ih); |
| 662 | sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO0xb | IPL_MPSAFE0x100, |
| 663 | yds_intr, sc, self->dv_xname); |
| 664 | if (sc->sc_ih == NULL((void *)0)) { |
| 665 | printf(": couldn't establish interrupt"); |
| 666 | if (intrstr != NULL((void *)0)) |
| 667 | printf(" at %s", intrstr); |
| 668 | printf("\n"); |
| 669 | bus_space_unmap(sc->memt, sc->memh, size); |
| 670 | return; |
| 671 | } |
| 672 | printf(": %s\n", intrstr); |
| 673 | |
| 674 | sc->sc_dmatag = pa->pa_dmat; |
| 675 | sc->sc_pc = pc; |
| 676 | sc->sc_pcitag = pa->pa_tag; |
| 677 | sc->sc_id = pa->pa_id; |
| 678 | sc->sc_revision = PCI_REVISION(pa->pa_class)(((pa->pa_class) >> 0) & 0xff); |
| 679 | sc->sc_flags = yds_get_dstype(sc->sc_id); |
| 680 | if (sc->sc_dev.dv_cfdata->cf_flags & YDS_CAP_LEGACY_SMOD_DISABLE0x1000) |
| 681 | sc->sc_flags |= YDS_CAP_LEGACY_SMOD_DISABLE0x1000; |
| 682 | #ifdef AUDIO_DEBUG |
| 683 | if (ydsdebug) |
| 684 | printf("%s: chip has %b\n", sc->sc_dev.dv_xname, |
| 685 | sc->sc_flags, YDS_CAP_BITS); |
| 686 | #endif |
| 687 | |
| 688 | /* Disable legacy mode */ |
| 689 | reg = pci_conf_read(pc, pa->pa_tag, YDS_PCI_LEGACY0x40); |
| 690 | pci_conf_write(pc, pa->pa_tag, YDS_PCI_LEGACY0x40, |
| 691 | reg & YDS_PCI_LEGACY_LAD0x8000); |
| 692 | |
| 693 | /* Mute all volumes */ |
| 694 | for (i = 0x80; i < 0xc0; i += 2) |
| 695 | YWRITE2(sc, i, 0)(((sc)->memt)->write_2(((sc)->memh), ((i)), ((0)))); |
| 696 | |
| 697 | sc->sc_legacy_iot = pa->pa_iot; |
| 698 | config_mountroot(self, yds_attachhook); |
| 699 | } |
| 700 | |
| 701 | void |
| 702 | yds_attachhook(struct device *self) |
| 703 | { |
| 704 | struct yds_softc *sc = (struct yds_softc *)self; |
| 705 | struct yds_codec_softc *codec; |
| 706 | mixer_ctrl_t ctl; |
| 707 | int r, i; |
| 708 | |
| 709 | /* Initialize the device */ |
| 710 | if (yds_init(sc, 0) == -1) |
| 711 | return; |
| 712 | |
| 713 | /* |
| 714 | * Attach ac97 codec |
| 715 | */ |
| 716 | for (i = 0; i < 2; i++) { |
| 717 | static struct { |
| 718 | int data; |
| 719 | int addr; |
| 720 | } statregs[] = { |
| 721 | {AC97_STAT_DATA10x0064, AC97_STAT_ADDR10x0066}, |
| 722 | {AC97_STAT_DATA20x0068, AC97_STAT_ADDR20x006a}, |
| 723 | }; |
| 724 | |
| 725 | if (i == 1 && ac97_id2 == -1) |
| 726 | break; /* secondary ac97 not available */ |
| 727 | |
| 728 | codec = &sc->sc_codec[i]; |
| 729 | memcpy(&codec->sc_dev, &sc->sc_dev, sizeof(codec->sc_dev))__builtin_memcpy((&codec->sc_dev), (&sc->sc_dev ), (sizeof(codec->sc_dev))); |
| 730 | codec->sc = sc; |
| 731 | codec->id = i == 1 ? ac97_id2 : 0; |
| 732 | codec->status_data = statregs[i].data; |
| 733 | codec->status_addr = statregs[i].addr; |
| 734 | codec->host_if.arg = codec; |
| 735 | codec->host_if.attach = yds_attach_codec; |
| 736 | codec->host_if.read = yds_read_codec; |
| 737 | codec->host_if.write = yds_write_codec; |
| 738 | codec->host_if.reset = yds_reset_codec; |
| 739 | |
| 740 | if ((r = ac97_attach(&codec->host_if)) != 0) { |
| 741 | printf("%s: can't attach codec (error 0x%X)\n", |
| 742 | sc->sc_dev.dv_xname, r); |
| 743 | return; |
| 744 | } |
| 745 | } |
| 746 | |
| 747 | /* Just enable the DAC and master volumes by default */ |
| 748 | ctl.type = AUDIO_MIXER_ENUM1; |
| 749 | ctl.un.ord = 0; /* off */ |
| 750 | ctl.dev = yds_get_portnum_by_name(sc, AudioCoutputs"outputs", |
| 751 | AudioNmaster"master", AudioNmute"mute"); |
| 752 | yds_mixer_set_port(sc, &ctl); |
| 753 | ctl.dev = yds_get_portnum_by_name(sc, AudioCinputs"inputs", |
| 754 | AudioNdac"dac", AudioNmute"mute"); |
| 755 | yds_mixer_set_port(sc, &ctl); |
| 756 | ctl.dev = yds_get_portnum_by_name(sc, AudioCinputs"inputs", |
| 757 | AudioNcd"cd", AudioNmute"mute"); |
| 758 | yds_mixer_set_port(sc, &ctl); |
| 759 | ctl.dev = yds_get_portnum_by_name(sc, AudioCrecord"record", |
| 760 | AudioNvolume"volume", AudioNmute"mute"); |
| 761 | yds_mixer_set_port(sc, &ctl); |
| 762 | |
| 763 | ctl.dev = yds_get_portnum_by_name(sc, AudioCrecord"record", |
| 764 | AudioNsource"source", NULL((void *)0)); |
| 765 | ctl.type = AUDIO_MIXER_ENUM1; |
| 766 | ctl.un.ord = 0; |
| 767 | yds_mixer_set_port(sc, &ctl); |
| 768 | |
| 769 | /* Set a reasonable default volume */ |
| 770 | ctl.type = AUDIO_MIXER_VALUE3; |
| 771 | ctl.un.value.num_channels = 2; |
| 772 | ctl.un.value.level[AUDIO_MIXER_LEVEL_LEFT0] = |
| 773 | ctl.un.value.level[AUDIO_MIXER_LEVEL_RIGHT1] = 127; |
| 774 | |
| 775 | ctl.dev = sc->sc_codec[0].codec_if->vtbl->get_portnum_by_name( |
| 776 | sc->sc_codec[0].codec_if, AudioCoutputs"outputs", AudioNmaster"master", NULL((void *)0)); |
| 777 | yds_mixer_set_port(sc, &ctl); |
| 778 | |
| 779 | audio_attach_mi(&yds_hw_if, sc, NULL((void *)0), &sc->sc_dev); |
| 780 | |
| 781 | /* Watch for power changes */ |
| 782 | sc->suspend = DVACT_RESUME4; |
| 783 | yds_configure_legacy(sc); |
| 784 | } |
| 785 | |
| 786 | int |
| 787 | yds_attach_codec(void *sc_, struct ac97_codec_if *codec_if) |
| 788 | { |
| 789 | struct yds_codec_softc *sc = sc_; |
| 790 | |
| 791 | sc->codec_if = codec_if; |
| 792 | return 0; |
| 793 | } |
| 794 | |
| 795 | static int |
| 796 | yds_ready_codec(struct yds_codec_softc *sc) |
| 797 | { |
| 798 | int to; |
| 799 | |
| 800 | for (to = 0; to < AC97_TIMEOUT1000; to++) { |
| 801 | if ((YREAD2(sc->sc, sc->status_addr)(((sc->sc)->memt)->read_2(((sc->sc)->memh), (( sc->status_addr)))) & AC97_BUSY0x8000) == 0) |
| 802 | return 0; |
| 803 | delay(1)(*delay_func)(1); |
| 804 | } |
| 805 | |
| 806 | return 1; |
| 807 | } |
| 808 | |
| 809 | int |
| 810 | yds_read_codec(void *sc_, u_int8_t reg, u_int16_t *data) |
| 811 | { |
| 812 | struct yds_codec_softc *sc = sc_; |
| 813 | |
| 814 | YWRITE2(sc->sc, AC97_CMD_ADDR, AC97_CMD_READ | AC97_ID(sc->id) | reg)(((sc->sc)->memt)->write_2(((sc->sc)->memh), ( (0x0062)), ((0x8000 | ((sc->id) << 8) | reg)))); |
| 815 | |
| 816 | if (yds_ready_codec(sc)) { |
| 817 | printf("%s: yds_read_codec timeout\n", |
| 818 | sc->sc->sc_dev.dv_xname); |
| 819 | return EIO5; |
| 820 | } |
| 821 | |
| 822 | if (PCI_PRODUCT(sc->sc->sc_id)(((sc->sc->sc_id) >> 16) & 0xffff) == PCI_PRODUCT_YAMAHA_YMF7440x0010 && |
| 823 | sc->sc->sc_revision < 2) { |
| 824 | int i; |
| 825 | |
| 826 | for (i = 0; i < 600; i++) |
| 827 | YREAD2(sc->sc, sc->status_data)(((sc->sc)->memt)->read_2(((sc->sc)->memh), (( sc->status_data)))); |
| 828 | } |
| 829 | *data = YREAD2(sc->sc, sc->status_data)(((sc->sc)->memt)->read_2(((sc->sc)->memh), (( sc->status_data)))); |
| 830 | |
| 831 | return 0; |
| 832 | } |
| 833 | |
| 834 | int |
| 835 | yds_write_codec(void *sc_, u_int8_t reg, u_int16_t data) |
| 836 | { |
| 837 | struct yds_codec_softc *sc = sc_; |
| 838 | |
| 839 | YWRITE2(sc->sc, AC97_CMD_ADDR, AC97_CMD_WRITE | AC97_ID(sc->id) | reg)(((sc->sc)->memt)->write_2(((sc->sc)->memh), ( (0x0062)), ((0x0000 | ((sc->id) << 8) | reg)))); |
| 840 | YWRITE2(sc->sc, AC97_CMD_DATA, data)(((sc->sc)->memt)->write_2(((sc->sc)->memh), ( (0x0060)), ((data)))); |
| 841 | |
| 842 | if (yds_ready_codec(sc)) { |
| 843 | printf("%s: yds_write_codec timeout\n", |
| 844 | sc->sc->sc_dev.dv_xname); |
| 845 | return EIO5; |
| 846 | } |
| 847 | |
| 848 | return 0; |
| 849 | } |
| 850 | |
| 851 | /* |
| 852 | * XXX: Must handle the secondary differently!! |
| 853 | */ |
| 854 | void |
| 855 | yds_reset_codec(void *sc_) |
| 856 | { |
| 857 | struct yds_codec_softc *codec = sc_; |
| 858 | struct yds_softc *sc = codec->sc; |
| 859 | pcireg_t reg; |
| 860 | |
| 861 | /* reset AC97 codec */ |
| 862 | reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, YDS_PCI_DSCTRL0x48); |
| 863 | if (reg & 0x03) { |
| 864 | pci_conf_write(sc->sc_pc, sc->sc_pcitag, |
| 865 | YDS_PCI_DSCTRL0x48, reg & ~0x03); |
| 866 | pci_conf_write(sc->sc_pc, sc->sc_pcitag, |
| 867 | YDS_PCI_DSCTRL0x48, reg | 0x03); |
| 868 | pci_conf_write(sc->sc_pc, sc->sc_pcitag, |
| 869 | YDS_PCI_DSCTRL0x48, reg & ~0x03); |
| 870 | delay(50000)(*delay_func)(50000); |
| 871 | } |
| 872 | |
| 873 | yds_ready_codec(sc_); |
| 874 | } |
| 875 | |
| 876 | int |
| 877 | yds_intr(void *p) |
| 878 | { |
| 879 | struct yds_softc *sc = p; |
| 880 | u_int status; |
| 881 | |
| 882 | mtx_enter(&audio_lock); |
| 883 | status = YREAD4(sc, YDS_STATUS)(((sc)->memt)->read_4(((sc)->memh), ((0x0100)))); |
| 884 | DPRINTFN(1, ("yds_intr: status=%08x\n", status)); |
| 885 | if ((status & (YDS_STAT_INT0x80000000|YDS_STAT_TINT0x00008000)) == 0) { |
| 886 | #if 0 |
| 887 | if (sc->sc_mpu) |
| 888 | return mpu_intr(sc->sc_mpu); |
| 889 | #endif |
| 890 | mtx_leave(&audio_lock); |
| 891 | return 0; |
| 892 | } |
| 893 | |
| 894 | if (status & YDS_STAT_TINT0x00008000) { |
| 895 | YWRITE4(sc, YDS_STATUS, YDS_STAT_TINT)(((sc)->memt)->write_4(((sc)->memh), ((0x0100)), ((0x00008000 )))); |
| 896 | printf ("yds_intr: timeout!\n"); |
| 897 | } |
| 898 | |
| 899 | if (status & YDS_STAT_INT0x80000000) { |
| 900 | int nbank = (YREAD4(sc, YDS_CONTROL_SELECT)(((sc)->memt)->read_4(((sc)->memh), ((0x0104)))) == 0); |
| 901 | |
| 902 | /* Clear interrupt flag */ |
| 903 | YWRITE4(sc, YDS_STATUS, YDS_STAT_INT)(((sc)->memt)->write_4(((sc)->memh), ((0x0100)), ((0x80000000 )))); |
| 904 | |
| 905 | /* Buffer for the next frame is always ready. */ |
| 906 | YWRITE4(sc, YDS_MODE, YREAD4(sc, YDS_MODE) | YDS_MODE_ACTV2)(((sc)->memt)->write_4(((sc)->memh), ((0x0108)), ((( ((sc)->memt)->read_4(((sc)->memh), ((0x0108)))) | 0x00000002 )))); |
| 907 | |
| 908 | if (sc->sc_play.intr) { |
| 909 | u_int dma, cpu, blk, len; |
| 910 | |
| 911 | /* Sync play slot control data */ |
| 912 | bus_dmamap_sync(sc->sc_dmatag, sc->sc_ctrldata.map,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->pbankoff), (sizeof(struct play_slot_ctrl_bank )* (*sc->ptbl)* 2), (0x08| 0x02)) |
| 913 | sc->pbankoff,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->pbankoff), (sizeof(struct play_slot_ctrl_bank )* (*sc->ptbl)* 2), (0x08| 0x02)) |
| 914 | sizeof(struct play_slot_ctrl_bank)*(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->pbankoff), (sizeof(struct play_slot_ctrl_bank )* (*sc->ptbl)* 2), (0x08| 0x02)) |
| 915 | (*sc->ptbl)*(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->pbankoff), (sizeof(struct play_slot_ctrl_bank )* (*sc->ptbl)* 2), (0x08| 0x02)) |
| 916 | N_PLAY_SLOT_CTRL_BANK,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->pbankoff), (sizeof(struct play_slot_ctrl_bank )* (*sc->ptbl)* 2), (0x08| 0x02)) |
| 917 | BUS_DMASYNC_POSTWRITE|(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->pbankoff), (sizeof(struct play_slot_ctrl_bank )* (*sc->ptbl)* 2), (0x08| 0x02)) |
| 918 | BUS_DMASYNC_POSTREAD)(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->pbankoff), (sizeof(struct play_slot_ctrl_bank )* (*sc->ptbl)* 2), (0x08| 0x02)); |
| 919 | dma = sc->pbankp[nbank]->pgstart; |
| 920 | cpu = sc->sc_play.offset; |
| 921 | blk = sc->sc_play.blksize; |
| 922 | len = sc->sc_play.length; |
| 923 | |
| 924 | if (((dma > cpu) && (dma - cpu > blk * 2)) || |
| 925 | ((cpu > dma) && (dma + len - cpu > blk * 2))) { |
| 926 | /* We can fill the next block */ |
| 927 | /* Sync ring buffer for previous write */ |
| 928 | bus_dmamap_sync(sc->sc_dmatag,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_play.dma->map), (cpu), (blk), (0x08)) |
| 929 | sc->sc_play.dma->map,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_play.dma->map), (cpu), (blk), (0x08)) |
| 930 | cpu, blk,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_play.dma->map), (cpu), (blk), (0x08)) |
| 931 | BUS_DMASYNC_POSTWRITE)(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_play.dma->map), (cpu), (blk), (0x08)); |
| 932 | sc->sc_play.intr(sc->sc_play.intr_arg); |
| 933 | sc->sc_play.offset += blk; |
| 934 | if (sc->sc_play.offset >= len) { |
| 935 | sc->sc_play.offset -= len; |
| 936 | #ifdef DIAGNOSTIC1 |
| 937 | if (sc->sc_play.offset != 0) |
| 938 | printf ("Audio ringbuffer botch\n"); |
| 939 | #endif |
| 940 | } |
| 941 | /* Sync ring buffer for next write */ |
| 942 | bus_dmamap_sync(sc->sc_dmatag,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_play.dma->map), (cpu), (blk), (0x04)) |
| 943 | sc->sc_play.dma->map,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_play.dma->map), (cpu), (blk), (0x04)) |
| 944 | cpu, blk,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_play.dma->map), (cpu), (blk), (0x04)) |
| 945 | BUS_DMASYNC_PREWRITE)(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_play.dma->map), (cpu), (blk), (0x04)); |
| 946 | } |
| 947 | } |
| 948 | if (sc->sc_rec.intr) { |
| 949 | u_int dma, cpu, blk, len; |
| 950 | |
| 951 | /* Sync rec slot control data */ |
| 952 | bus_dmamap_sync(sc->sc_dmatag, sc->sc_ctrldata.map,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->rbankoff), (sizeof(struct rec_slot_ctrl_bank )* 2* 2), (0x08| 0x02)) |
| 953 | sc->rbankoff,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->rbankoff), (sizeof(struct rec_slot_ctrl_bank )* 2* 2), (0x08| 0x02)) |
| 954 | sizeof(struct rec_slot_ctrl_bank)*(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->rbankoff), (sizeof(struct rec_slot_ctrl_bank )* 2* 2), (0x08| 0x02)) |
| 955 | N_REC_SLOT_CTRL*(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->rbankoff), (sizeof(struct rec_slot_ctrl_bank )* 2* 2), (0x08| 0x02)) |
| 956 | N_REC_SLOT_CTRL_BANK,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->rbankoff), (sizeof(struct rec_slot_ctrl_bank )* 2* 2), (0x08| 0x02)) |
| 957 | BUS_DMASYNC_POSTWRITE|(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->rbankoff), (sizeof(struct rec_slot_ctrl_bank )* 2* 2), (0x08| 0x02)) |
| 958 | BUS_DMASYNC_POSTREAD)(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->rbankoff), (sizeof(struct rec_slot_ctrl_bank )* 2* 2), (0x08| 0x02)); |
| 959 | dma = sc->rbank[YDS_INPUT_SLOT1*2 + nbank].pgstartadr; |
| 960 | cpu = sc->sc_rec.offset; |
| 961 | blk = sc->sc_rec.blksize; |
| 962 | len = sc->sc_rec.length; |
| 963 | |
| 964 | if (((dma > cpu) && (dma - cpu > blk * 2)) || |
| 965 | ((cpu > dma) && (dma + len - cpu > blk * 2))) { |
| 966 | /* We can drain the current block */ |
| 967 | /* Sync ring buffer first */ |
| 968 | bus_dmamap_sync(sc->sc_dmatag,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_rec.dma->map), (cpu), (blk), (0x02)) |
| 969 | sc->sc_rec.dma->map,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_rec.dma->map), (cpu), (blk), (0x02)) |
| 970 | cpu, blk,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_rec.dma->map), (cpu), (blk), (0x02)) |
| 971 | BUS_DMASYNC_POSTREAD)(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_rec.dma->map), (cpu), (blk), (0x02)); |
| 972 | sc->sc_rec.intr(sc->sc_rec.intr_arg); |
| 973 | sc->sc_rec.offset += blk; |
| 974 | if (sc->sc_rec.offset >= len) { |
| 975 | sc->sc_rec.offset -= len; |
| 976 | #ifdef DIAGNOSTIC1 |
| 977 | if (sc->sc_rec.offset != 0) |
| 978 | printf ("Audio ringbuffer botch\n"); |
| 979 | #endif |
| 980 | } |
| 981 | /* Sync ring buffer for next read */ |
| 982 | bus_dmamap_sync(sc->sc_dmatag,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_rec.dma->map), (cpu), (blk), (0x01)) |
| 983 | sc->sc_rec.dma->map,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_rec.dma->map), (cpu), (blk), (0x01)) |
| 984 | cpu, blk,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_rec.dma->map), (cpu), (blk), (0x01)) |
| 985 | BUS_DMASYNC_PREREAD)(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_rec.dma->map), (cpu), (blk), (0x01)); |
| 986 | } |
| 987 | } |
| 988 | } |
| 989 | mtx_leave(&audio_lock); |
| 990 | return 1; |
| 991 | } |
| 992 | |
| 993 | int |
| 994 | yds_allocmem(struct yds_softc *sc, size_t size, size_t align, struct yds_dma *p) |
| 995 | { |
| 996 | int error; |
| 997 | |
| 998 | p->size = size; |
| 999 | error = bus_dmamem_alloc(sc->sc_dmatag, p->size, align, 0,(*(sc->sc_dmatag)->_dmamem_alloc)((sc->sc_dmatag), ( p->size), (align), (0), (p->segs), ((sizeof((p->segs )) / sizeof((p->segs)[0]))), (&p->nsegs), (0x0001)) |
| 1000 | p->segs, nitems(p->segs),(*(sc->sc_dmatag)->_dmamem_alloc)((sc->sc_dmatag), ( p->size), (align), (0), (p->segs), ((sizeof((p->segs )) / sizeof((p->segs)[0]))), (&p->nsegs), (0x0001)) |
| 1001 | &p->nsegs, BUS_DMA_NOWAIT)(*(sc->sc_dmatag)->_dmamem_alloc)((sc->sc_dmatag), ( p->size), (align), (0), (p->segs), ((sizeof((p->segs )) / sizeof((p->segs)[0]))), (&p->nsegs), (0x0001)); |
| 1002 | if (error) |
| 1003 | return (error); |
| 1004 | |
| 1005 | error = bus_dmamem_map(sc->sc_dmatag, p->segs, p->nsegs, p->size,(*(sc->sc_dmatag)->_dmamem_map)((sc->sc_dmatag), (p-> segs), (p->nsegs), (p->size), (&p->addr), (0x0001 |0x0004)) |
| 1006 | &p->addr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)(*(sc->sc_dmatag)->_dmamem_map)((sc->sc_dmatag), (p-> segs), (p->nsegs), (p->size), (&p->addr), (0x0001 |0x0004)); |
| 1007 | if (error) |
| 1008 | goto free; |
| 1009 | |
| 1010 | error = bus_dmamap_create(sc->sc_dmatag, p->size, 1, p->size,(*(sc->sc_dmatag)->_dmamap_create)((sc->sc_dmatag), ( p->size), (1), (p->size), (0), (0x0001), (&p->map )) |
| 1011 | 0, BUS_DMA_NOWAIT, &p->map)(*(sc->sc_dmatag)->_dmamap_create)((sc->sc_dmatag), ( p->size), (1), (p->size), (0), (0x0001), (&p->map )); |
| 1012 | if (error) |
| 1013 | goto unmap; |
| 1014 | |
| 1015 | error = bus_dmamap_load(sc->sc_dmatag, p->map, p->addr, p->size, NULL,(*(sc->sc_dmatag)->_dmamap_load)((sc->sc_dmatag), (p ->map), (p->addr), (p->size), (((void *)0)), (0x0001 )) |
| 1016 | BUS_DMA_NOWAIT)(*(sc->sc_dmatag)->_dmamap_load)((sc->sc_dmatag), (p ->map), (p->addr), (p->size), (((void *)0)), (0x0001 )); |
| 1017 | if (error) |
| 1018 | goto destroy; |
| 1019 | return (0); |
| 1020 | |
| 1021 | destroy: |
| 1022 | bus_dmamap_destroy(sc->sc_dmatag, p->map)(*(sc->sc_dmatag)->_dmamap_destroy)((sc->sc_dmatag), (p->map)); |
| 1023 | unmap: |
| 1024 | bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size)(*(sc->sc_dmatag)->_dmamem_unmap)((sc->sc_dmatag), ( p->addr), (p->size)); |
| 1025 | free: |
| 1026 | bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs)(*(sc->sc_dmatag)->_dmamem_free)((sc->sc_dmatag), (p ->segs), (p->nsegs)); |
| 1027 | return (error); |
| 1028 | } |
| 1029 | |
| 1030 | int |
| 1031 | yds_freemem(struct yds_softc *sc, struct yds_dma *p) |
| 1032 | { |
| 1033 | bus_dmamap_unload(sc->sc_dmatag, p->map)(*(sc->sc_dmatag)->_dmamap_unload)((sc->sc_dmatag), ( p->map)); |
| 1034 | bus_dmamap_destroy(sc->sc_dmatag, p->map)(*(sc->sc_dmatag)->_dmamap_destroy)((sc->sc_dmatag), (p->map)); |
| 1035 | bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size)(*(sc->sc_dmatag)->_dmamem_unmap)((sc->sc_dmatag), ( p->addr), (p->size)); |
| 1036 | bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs)(*(sc->sc_dmatag)->_dmamem_free)((sc->sc_dmatag), (p ->segs), (p->nsegs)); |
| 1037 | return 0; |
| 1038 | } |
| 1039 | |
| 1040 | int |
| 1041 | yds_open(void *addr, int flags) |
| 1042 | { |
| 1043 | struct yds_softc *sc = addr; |
| 1044 | int mode; |
| 1045 | |
| 1046 | /* Select bank 0. */ |
| 1047 | YWRITE4(sc, YDS_CONTROL_SELECT, 0)(((sc)->memt)->write_4(((sc)->memh), ((0x0104)), ((0 )))); |
| 1048 | |
| 1049 | /* Start the DSP operation. */ |
| 1050 | mode = YREAD4(sc, YDS_MODE)(((sc)->memt)->read_4(((sc)->memh), ((0x0108)))); |
| 1051 | mode |= YDS_MODE_ACTV0x00000001; |
| 1052 | mode &= ~YDS_MODE_ACTV20x00000002; |
| 1053 | YWRITE4(sc, YDS_MODE, mode)(((sc)->memt)->write_4(((sc)->memh), ((0x0108)), ((mode )))); |
| 1054 | |
| 1055 | return 0; |
| 1056 | } |
| 1057 | |
| 1058 | /* |
| 1059 | * Close function is called at splaudio(). |
| 1060 | */ |
| 1061 | void |
| 1062 | yds_close(void *addr) |
| 1063 | { |
| 1064 | struct yds_softc *sc = addr; |
| 1065 | |
| 1066 | yds_halt_output(sc); |
| 1067 | yds_halt_input(sc); |
| 1068 | yds_halt(sc); |
| 1069 | } |
| 1070 | |
| 1071 | int |
| 1072 | yds_set_params(void *addr, int setmode, int usemode, |
| 1073 | struct audio_params *play, struct audio_params *rec) |
| 1074 | { |
| 1075 | struct audio_params *p; |
| 1076 | int mode; |
| 1077 | |
| 1078 | for (mode = AUMODE_RECORD0x02; mode != -1; |
| 1079 | mode = mode == AUMODE_RECORD0x02 ? AUMODE_PLAY0x01 : -1) { |
| 1080 | if ((setmode & mode) == 0) |
| 1081 | continue; |
| 1082 | |
| 1083 | p = mode == AUMODE_PLAY0x01 ? play : rec; |
| 1084 | |
| 1085 | if (p->sample_rate < 4000) |
| 1086 | p->sample_rate = 4000; |
| 1087 | if (p->sample_rate > 48000) |
| 1088 | p->sample_rate = 48000; |
| 1089 | if (p->precision > 16) |
| 1090 | p->precision = 16; |
| 1091 | if (p->channels > 2) |
| 1092 | p->channels = 2; |
| 1093 | |
| 1094 | switch (p->encoding) { |
| 1095 | case AUDIO_ENCODING_SLINEAR_LE6: |
| 1096 | if (p->precision != 16) |
| 1097 | return EINVAL22; |
| 1098 | break; |
| 1099 | case AUDIO_ENCODING_ULINEAR_LE8: |
| 1100 | case AUDIO_ENCODING_ULINEAR_BE9: |
| 1101 | if (p->precision != 8) |
| 1102 | return EINVAL22; |
| 1103 | break; |
| 1104 | default: |
| 1105 | return (EINVAL22); |
| 1106 | } |
| 1107 | p->bps = AUDIO_BPS(p->precision)(p->precision) <= 8 ? 1 : ((p->precision) <= 16 ? 2 : 4); |
| 1108 | p->msb = 1; |
| 1109 | } |
| 1110 | |
| 1111 | return 0; |
| 1112 | } |
| 1113 | |
| 1114 | int |
| 1115 | yds_round_blocksize(void *addr, int blk) |
| 1116 | { |
| 1117 | /* |
| 1118 | * Block size must be bigger than a frame. |
| 1119 | * That is 1024bytes at most, i.e. for 48000Hz, 16bit, 2ch. |
| 1120 | */ |
| 1121 | if (blk < 1024) |
| 1122 | blk = 1024; |
| 1123 | |
| 1124 | return blk & ~4; |
| 1125 | } |
| 1126 | |
| 1127 | static u_int32_t |
| 1128 | yds_get_lpfq(u_int sample_rate) |
| 1129 | { |
| 1130 | int i; |
| 1131 | static struct lpfqt { |
| 1132 | u_int rate; |
| 1133 | u_int32_t lpfq; |
| 1134 | } lpfqt[] = { |
| 1135 | {8000, 0x32020000}, |
| 1136 | {11025, 0x31770000}, |
| 1137 | {16000, 0x31390000}, |
| 1138 | {22050, 0x31c90000}, |
| 1139 | {32000, 0x33d00000}, |
| 1140 | {48000, 0x40000000}, |
| 1141 | {0, 0} |
| 1142 | }; |
| 1143 | |
| 1144 | if (sample_rate == 44100) /* for P44 slot? */ |
| 1145 | return 0x370A0000; |
| 1146 | |
| 1147 | for (i = 0; lpfqt[i].rate != 0; i++) |
| 1148 | if (sample_rate <= lpfqt[i].rate) |
| 1149 | break; |
| 1150 | |
| 1151 | return lpfqt[i].lpfq; |
| 1152 | } |
| 1153 | |
| 1154 | static u_int32_t |
| 1155 | yds_get_lpfk(u_int sample_rate) |
| 1156 | { |
| 1157 | int i; |
| 1158 | static struct lpfkt { |
| 1159 | u_int rate; |
| 1160 | u_int32_t lpfk; |
| 1161 | } lpfkt[] = { |
| 1162 | {8000, 0x18b20000}, |
| 1163 | {11025, 0x20930000}, |
| 1164 | {16000, 0x2b9a0000}, |
| 1165 | {22050, 0x35a10000}, |
| 1166 | {32000, 0x3eaa0000}, |
| 1167 | {48000, 0x40000000}, |
| 1168 | {0, 0} |
| 1169 | }; |
| 1170 | |
| 1171 | if (sample_rate == 44100) /* for P44 slot? */ |
| 1172 | return 0x46460000; |
| 1173 | |
| 1174 | for (i = 0; lpfkt[i].rate != 0; i++) |
| 1175 | if (sample_rate <= lpfkt[i].rate) |
| 1176 | break; |
| 1177 | |
| 1178 | return lpfkt[i].lpfk; |
| 1179 | } |
| 1180 | |
| 1181 | int |
| 1182 | yds_trigger_output(void *addr, void *start, void *end, int blksize, |
| 1183 | void (*intr)(void *), void *arg, struct audio_params *param) |
| 1184 | #define P44 (sc->sc_flags & YDS_CAP_HAS_P440x0010) |
| 1185 | { |
| 1186 | struct yds_softc *sc = addr; |
| 1187 | struct yds_dma *p; |
| 1188 | struct play_slot_ctrl_bank *psb; |
| 1189 | const u_int gain = 0x40000000; |
| 1190 | bus_addr_t s; |
| 1191 | size_t l; |
| 1192 | int i; |
| 1193 | int p44, channels; |
| 1194 | |
| 1195 | mtx_enter(&audio_lock); |
| 1196 | #ifdef DIAGNOSTIC1 |
| 1197 | if (sc->sc_play.intr) |
| 1198 | panic("yds_trigger_output: already running"); |
| 1199 | #endif |
| 1200 | sc->sc_play.intr = intr; |
| 1201 | sc->sc_play.intr_arg = arg; |
| 1202 | sc->sc_play.offset = 0; |
| 1203 | sc->sc_play.blksize = blksize; |
| 1204 | |
| 1205 | DPRINTFN(1, ("yds_trigger_output: sc=%p start=%p end=%p " |
| 1206 | "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg)); |
| 1207 | |
| 1208 | p = yds_find_dma(sc, start); |
| 1209 | if (!p) { |
| 1210 | printf("yds_trigger_output: bad addr %p\n", start); |
| 1211 | mtx_leave(&audio_lock); |
| 1212 | return (EINVAL22); |
| 1213 | } |
| 1214 | sc->sc_play.dma = p; |
| 1215 | |
| 1216 | #ifdef DIAGNOSTIC1 |
| 1217 | { |
| 1218 | u_int32_t ctrlsize; |
| 1219 | if ((ctrlsize = YREAD4(sc, YDS_PLAY_CTRLSIZE)(((sc)->memt)->read_4(((sc)->memh), ((0x0140))))) != |
| 1220 | sizeof(struct play_slot_ctrl_bank) / sizeof(u_int32_t)) |
| 1221 | panic("%s: invalid play slot ctrldata %d %zd", |
| 1222 | sc->sc_dev.dv_xname, ctrlsize, |
| 1223 | sizeof(struct play_slot_ctrl_bank)); |
| 1224 | } |
| 1225 | #endif |
| 1226 | |
| 1227 | #ifdef YDS_USE_P44 |
| 1228 | /* The document says the P44 SRC supports only stereo, 16bit PCM. */ |
| 1229 | if (P44) |
| 1230 | p44 = ((param->sample_rate == 44100) && |
| 1231 | (param->channels == 2) && |
| 1232 | (param->precision == 16)); |
| 1233 | else |
| 1234 | #endif |
| 1235 | p44 = 0; |
| 1236 | channels = p44 ? 1 : param->channels; |
| 1237 | |
| 1238 | s = DMAADDR(p)((p)->map->dm_segs[0].ds_addr); |
| 1239 | l = ((char *)end - (char *)start); |
| 1240 | sc->sc_play.length = l; |
| 1241 | |
| 1242 | *sc->ptbl = channels; /* Num of play */ |
| 1243 | |
| 1244 | psb = sc->pbankp[0]; |
| 1245 | memset(psb, 0, sizeof(*psb))__builtin_memset((psb), (0), (sizeof(*psb))); |
| 1246 | psb->format = ((channels == 2 ? PSLT_FORMAT_STEREO0x00010000 : 0) | |
| 1247 | (param->precision == 8 ? PSLT_FORMAT_8BIT0x80000000 : 0) | |
| 1248 | (p44 ? PSLT_FORMAT_SRC4410x10000000 : 0)); |
| 1249 | psb->pgbase = s; |
| 1250 | psb->pgloopend = l; |
| 1251 | if (!p44) { |
| 1252 | psb->pgdeltaend = (param->sample_rate * 65536 / 48000) << 12; |
| 1253 | psb->lpfkend = yds_get_lpfk(param->sample_rate); |
| 1254 | psb->eggainend = gain; |
| 1255 | psb->lpfq = yds_get_lpfq(param->sample_rate); |
| 1256 | psb->pgdelta = psb->pgdeltaend; |
| 1257 | psb->lpfk = yds_get_lpfk(param->sample_rate); |
| 1258 | psb->eggain = gain; |
| 1259 | } |
| 1260 | |
| 1261 | for (i = 0; i < channels; i++) { |
| 1262 | /* i == 0: left or mono, i == 1: right */ |
| 1263 | psb = sc->pbankp[i*2]; |
| 1264 | if (i) |
| 1265 | /* copy from left */ |
| 1266 | *psb = *(sc->pbankp[0]); |
| 1267 | if (channels == 2) { |
| 1268 | /* stereo */ |
| 1269 | if (i == 0) { |
| 1270 | psb->lchgain = psb->lchgainend = gain; |
| 1271 | } else { |
| 1272 | psb->lchgain = psb->lchgainend = 0; |
| 1273 | psb->rchgain = psb->rchgainend = gain; |
| 1274 | psb->format |= PSLT_FORMAT_RCH0x00000001; |
| 1275 | } |
| 1276 | } else if (!p44) { |
| 1277 | /* mono */ |
| 1278 | psb->lchgain = psb->rchgain = gain; |
| 1279 | psb->lchgainend = psb->rchgainend = gain; |
| 1280 | } |
| 1281 | /* copy to the other bank */ |
| 1282 | *(sc->pbankp[i*2+1]) = *psb; |
| 1283 | } |
| 1284 | |
| 1285 | YDS_DUMP_PLAY_SLOT(5, sc, 0); |
| 1286 | YDS_DUMP_PLAY_SLOT(5, sc, 1); |
| 1287 | |
| 1288 | if (p44) |
| 1289 | YWRITE4(sc, YDS_P44_OUT_VOLUME, 0x3fff3fff)(((sc)->memt)->write_4(((sc)->memh), ((0x00B0)), ((0x3fff3fff )))); |
| 1290 | else |
| 1291 | YWRITE4(sc, YDS_DAC_OUT_VOLUME, 0x3fff3fff)(((sc)->memt)->write_4(((sc)->memh), ((0x0084)), ((0x3fff3fff )))); |
| 1292 | |
| 1293 | /* Now the play slot for the next frame is set up!! */ |
| 1294 | /* Sync play slot control data for both directions */ |
| 1295 | bus_dmamap_sync(sc->sc_dmatag, sc->sc_ctrldata.map,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->ptbloff), (sizeof(struct play_slot_ctrl_bank ) * channels * 2), (0x04|0x01)) |
| 1296 | sc->ptbloff,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->ptbloff), (sizeof(struct play_slot_ctrl_bank ) * channels * 2), (0x04|0x01)) |
| 1297 | sizeof(struct play_slot_ctrl_bank) *(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->ptbloff), (sizeof(struct play_slot_ctrl_bank ) * channels * 2), (0x04|0x01)) |
| 1298 | channels * N_PLAY_SLOT_CTRL_BANK,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->ptbloff), (sizeof(struct play_slot_ctrl_bank ) * channels * 2), (0x04|0x01)) |
| 1299 | BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD)(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->ptbloff), (sizeof(struct play_slot_ctrl_bank ) * channels * 2), (0x04|0x01)); |
| 1300 | /* Sync ring buffer */ |
| 1301 | bus_dmamap_sync(sc->sc_dmatag, p->map, 0, blksize,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (p ->map), (0), (blksize), (0x04)) |
| 1302 | BUS_DMASYNC_PREWRITE)(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (p ->map), (0), (blksize), (0x04)); |
| 1303 | /* HERE WE GO!! */ |
| 1304 | YWRITE4(sc, YDS_MODE,(((sc)->memt)->write_4(((sc)->memh), ((0x0108)), ((( ((sc)->memt)->read_4(((sc)->memh), ((0x0108)))) | 0x00000001 | 0x00000002)))) |
| 1305 | YREAD4(sc, YDS_MODE) | YDS_MODE_ACTV | YDS_MODE_ACTV2)(((sc)->memt)->write_4(((sc)->memh), ((0x0108)), ((( ((sc)->memt)->read_4(((sc)->memh), ((0x0108)))) | 0x00000001 | 0x00000002)))); |
| 1306 | mtx_leave(&audio_lock); |
| 1307 | return 0; |
| 1308 | } |
| 1309 | #undef P44 |
| 1310 | |
| 1311 | int |
| 1312 | yds_trigger_input(void *addr, void *start, void *end, int blksize, |
| 1313 | void (*intr)(void *), void *arg, struct audio_params *param) |
| 1314 | { |
| 1315 | struct yds_softc *sc = addr; |
| 1316 | struct yds_dma *p; |
| 1317 | u_int srate, format; |
| 1318 | struct rec_slot_ctrl_bank *rsb; |
| 1319 | bus_addr_t s; |
| 1320 | size_t l; |
| 1321 | |
| 1322 | mtx_enter(&audio_lock); |
| 1323 | #ifdef DIAGNOSTIC1 |
| 1324 | if (sc->sc_rec.intr) |
| 1325 | panic("yds_trigger_input: already running"); |
| 1326 | #endif |
| 1327 | sc->sc_rec.intr = intr; |
| 1328 | sc->sc_rec.intr_arg = arg; |
| 1329 | sc->sc_rec.offset = 0; |
| 1330 | sc->sc_rec.blksize = blksize; |
| 1331 | |
| 1332 | DPRINTFN(1, ("yds_trigger_input: " |
| 1333 | "sc=%p start=%p end=%p blksize=%d intr=%p(%p)\n", |
| 1334 | addr, start, end, blksize, intr, arg)); |
| 1335 | DPRINTFN(1, (" parameters: rate=%lu, precision=%u, channels=%u\n", |
| 1336 | param->sample_rate, param->precision, param->channels)); |
| 1337 | |
| 1338 | p = yds_find_dma(sc, start); |
| 1339 | if (!p) { |
| 1340 | printf("yds_trigger_input: bad addr %p\n", start); |
| 1341 | mtx_leave(&audio_lock); |
| 1342 | return (EINVAL22); |
| 1343 | } |
| 1344 | sc->sc_rec.dma = p; |
| 1345 | |
| 1346 | s = DMAADDR(p)((p)->map->dm_segs[0].ds_addr); |
| 1347 | l = ((char *)end - (char *)start); |
| 1348 | sc->sc_rec.length = l; |
| 1349 | |
| 1350 | rsb = &sc->rbank[0]; |
| 1351 | memset(rsb, 0, sizeof(*rsb))__builtin_memset((rsb), (0), (sizeof(*rsb))); |
| 1352 | rsb->pgbase = s; |
| 1353 | rsb->pgloopendadr = l; |
| 1354 | /* Seems all 4 banks must be set up... */ |
| 1355 | sc->rbank[1] = *rsb; |
| 1356 | sc->rbank[2] = *rsb; |
| 1357 | sc->rbank[3] = *rsb; |
| 1358 | |
| 1359 | YWRITE4(sc, YDS_ADC_IN_VOLUME, 0x3fff3fff)(((sc)->memt)->write_4(((sc)->memh), ((0x00A8)), ((0x3fff3fff )))); |
| 1360 | YWRITE4(sc, YDS_REC_IN_VOLUME, 0x3fff3fff)(((sc)->memt)->write_4(((sc)->memh), ((0x00AC)), ((0x3fff3fff )))); |
| 1361 | srate = 48000 * 4096 / param->sample_rate - 1; |
| 1362 | format = ((param->precision == 8 ? YDS_FORMAT_8BIT0x01 : 0) | |
| 1363 | (param->channels == 2 ? YDS_FORMAT_STEREO0x02 : 0)); |
| 1364 | DPRINTF(("srate=%d, format=%08x\n", srate, format)); |
| 1365 | #ifdef YDS_USE_REC_SLOT |
| 1366 | YWRITE4(sc, YDS_DAC_REC_VOLUME, 0x3fff3fff)(((sc)->memt)->write_4(((sc)->memh), ((0x0098)), ((0x3fff3fff )))); |
| 1367 | YWRITE4(sc, YDS_P44_REC_VOLUME, 0x3fff3fff)(((sc)->memt)->write_4(((sc)->memh), ((0x00B4)), ((0x3fff3fff )))); |
| 1368 | YWRITE4(sc, YDS_MAPOF_REC, YDS_RECSLOT_VALID)(((sc)->memt)->write_4(((sc)->memh), ((0x0150)), ((0x00000001 )))); |
| 1369 | YWRITE4(sc, YDS_REC_SAMPLE_RATE, srate)(((sc)->memt)->write_4(((sc)->memh), ((0x00c4)), ((srate )))); |
| 1370 | YWRITE4(sc, YDS_REC_FORMAT, format)(((sc)->memt)->write_4(((sc)->memh), ((0x00cc)), ((format )))); |
| 1371 | #else |
| 1372 | YWRITE4(sc, YDS_MAPOF_REC, YDS_ADCSLOT_VALID)(((sc)->memt)->write_4(((sc)->memh), ((0x0150)), ((0x00000002 )))); |
| 1373 | YWRITE4(sc, YDS_ADC_SAMPLE_RATE, srate)(((sc)->memt)->write_4(((sc)->memh), ((0x00c0)), ((srate )))); |
| 1374 | YWRITE4(sc, YDS_ADC_FORMAT, format)(((sc)->memt)->write_4(((sc)->memh), ((0x00c8)), ((format )))); |
| 1375 | #endif |
| 1376 | /* Now the rec slot for the next frame is set up!! */ |
| 1377 | /* Sync record slot control data */ |
| 1378 | bus_dmamap_sync(sc->sc_dmatag, sc->sc_ctrldata.map,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->rbankoff), (sizeof(struct rec_slot_ctrl_bank )* 2* 2), (0x04|0x01)) |
| 1379 | sc->rbankoff,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->rbankoff), (sizeof(struct rec_slot_ctrl_bank )* 2* 2), (0x04|0x01)) |
| 1380 | sizeof(struct rec_slot_ctrl_bank)*(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->rbankoff), (sizeof(struct rec_slot_ctrl_bank )* 2* 2), (0x04|0x01)) |
| 1381 | N_REC_SLOT_CTRL*(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->rbankoff), (sizeof(struct rec_slot_ctrl_bank )* 2* 2), (0x04|0x01)) |
| 1382 | N_REC_SLOT_CTRL_BANK,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->rbankoff), (sizeof(struct rec_slot_ctrl_bank )* 2* 2), (0x04|0x01)) |
| 1383 | BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD)(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->rbankoff), (sizeof(struct rec_slot_ctrl_bank )* 2* 2), (0x04|0x01)); |
| 1384 | /* Sync ring buffer */ |
| 1385 | bus_dmamap_sync(sc->sc_dmatag, p->map, 0, blksize,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (p ->map), (0), (blksize), (0x01)) |
| 1386 | BUS_DMASYNC_PREREAD)(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (p ->map), (0), (blksize), (0x01)); |
| 1387 | /* HERE WE GO!! */ |
| 1388 | YWRITE4(sc, YDS_MODE,(((sc)->memt)->write_4(((sc)->memh), ((0x0108)), ((( ((sc)->memt)->read_4(((sc)->memh), ((0x0108)))) | 0x00000001 | 0x00000002)))) |
| 1389 | YREAD4(sc, YDS_MODE) | YDS_MODE_ACTV | YDS_MODE_ACTV2)(((sc)->memt)->write_4(((sc)->memh), ((0x0108)), ((( ((sc)->memt)->read_4(((sc)->memh), ((0x0108)))) | 0x00000001 | 0x00000002)))); |
| 1390 | mtx_leave(&audio_lock); |
| 1391 | return 0; |
| 1392 | } |
| 1393 | |
| 1394 | static int |
| 1395 | yds_halt(struct yds_softc *sc) |
| 1396 | { |
| 1397 | u_int32_t mode; |
| 1398 | |
| 1399 | /* Stop the DSP operation. */ |
| 1400 | mode = YREAD4(sc, YDS_MODE)(((sc)->memt)->read_4(((sc)->memh), ((0x0108)))); |
| 1401 | YWRITE4(sc, YDS_MODE, mode & ~(YDS_MODE_ACTV|YDS_MODE_ACTV2))(((sc)->memt)->write_4(((sc)->memh), ((0x0108)), ((mode & ~(0x00000001|0x00000002))))); |
| 1402 | |
| 1403 | /* Paranoia... mute all */ |
| 1404 | YWRITE4(sc, YDS_P44_OUT_VOLUME, 0)(((sc)->memt)->write_4(((sc)->memh), ((0x00B0)), ((0 )))); |
| 1405 | YWRITE4(sc, YDS_DAC_OUT_VOLUME, 0)(((sc)->memt)->write_4(((sc)->memh), ((0x0084)), ((0 )))); |
| 1406 | YWRITE4(sc, YDS_ADC_IN_VOLUME, 0)(((sc)->memt)->write_4(((sc)->memh), ((0x00A8)), ((0 )))); |
| 1407 | YWRITE4(sc, YDS_REC_IN_VOLUME, 0)(((sc)->memt)->write_4(((sc)->memh), ((0x00AC)), ((0 )))); |
| 1408 | YWRITE4(sc, YDS_DAC_REC_VOLUME, 0)(((sc)->memt)->write_4(((sc)->memh), ((0x0098)), ((0 )))); |
| 1409 | YWRITE4(sc, YDS_P44_REC_VOLUME, 0)(((sc)->memt)->write_4(((sc)->memh), ((0x00B4)), ((0 )))); |
| 1410 | |
| 1411 | return 0; |
| 1412 | } |
| 1413 | |
| 1414 | int |
| 1415 | yds_halt_output(void *addr) |
| 1416 | { |
| 1417 | struct yds_softc *sc = addr; |
| 1418 | |
| 1419 | DPRINTF(("yds: yds_halt_output\n")); |
| 1420 | mtx_enter(&audio_lock); |
| 1421 | if (sc->sc_play.intr) { |
| 1422 | sc->sc_play.intr = 0; |
| 1423 | /* Sync play slot control data */ |
| 1424 | bus_dmamap_sync(sc->sc_dmatag, sc->sc_ctrldata.map,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->pbankoff), (sizeof(struct play_slot_ctrl_bank )* (*sc->ptbl)*2), (0x08|0x02)) |
| 1425 | sc->pbankoff,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->pbankoff), (sizeof(struct play_slot_ctrl_bank )* (*sc->ptbl)*2), (0x08|0x02)) |
| 1426 | sizeof(struct play_slot_ctrl_bank)*(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->pbankoff), (sizeof(struct play_slot_ctrl_bank )* (*sc->ptbl)*2), (0x08|0x02)) |
| 1427 | (*sc->ptbl)*N_PLAY_SLOT_CTRL_BANK,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->pbankoff), (sizeof(struct play_slot_ctrl_bank )* (*sc->ptbl)*2), (0x08|0x02)) |
| 1428 | BUS_DMASYNC_POSTWRITE|BUS_DMASYNC_POSTREAD)(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->pbankoff), (sizeof(struct play_slot_ctrl_bank )* (*sc->ptbl)*2), (0x08|0x02)); |
| 1429 | /* Stop the play slot operation */ |
| 1430 | sc->pbankp[0]->status = |
| 1431 | sc->pbankp[1]->status = |
| 1432 | sc->pbankp[2]->status = |
| 1433 | sc->pbankp[3]->status = 1; |
| 1434 | /* Sync ring buffer */ |
| 1435 | bus_dmamap_sync(sc->sc_dmatag, sc->sc_play.dma->map,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_play.dma->map), (0), (sc->sc_play.length), (0x08 )) |
| 1436 | 0, sc->sc_play.length, BUS_DMASYNC_POSTWRITE)(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_play.dma->map), (0), (sc->sc_play.length), (0x08 )); |
| 1437 | } |
| 1438 | mtx_leave(&audio_lock); |
| 1439 | return 0; |
| 1440 | } |
| 1441 | |
| 1442 | int |
| 1443 | yds_halt_input(void *addr) |
| 1444 | { |
| 1445 | struct yds_softc *sc = addr; |
| 1446 | |
| 1447 | DPRINTF(("yds: yds_halt_input\n")); |
| 1448 | mtx_enter(&audio_lock); |
| 1449 | if (sc->sc_rec.intr) { |
| 1450 | /* Stop the rec slot operation */ |
| 1451 | YWRITE4(sc, YDS_MAPOF_REC, 0)(((sc)->memt)->write_4(((sc)->memh), ((0x0150)), ((0 )))); |
| 1452 | sc->sc_rec.intr = 0; |
| 1453 | /* Sync rec slot control data */ |
| 1454 | bus_dmamap_sync(sc->sc_dmatag, sc->sc_ctrldata.map,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->rbankoff), (sizeof(struct rec_slot_ctrl_bank )* 2*2), (0x08|0x02)) |
| 1455 | sc->rbankoff,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->rbankoff), (sizeof(struct rec_slot_ctrl_bank )* 2*2), (0x08|0x02)) |
| 1456 | sizeof(struct rec_slot_ctrl_bank)*(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->rbankoff), (sizeof(struct rec_slot_ctrl_bank )* 2*2), (0x08|0x02)) |
| 1457 | N_REC_SLOT_CTRL*N_REC_SLOT_CTRL_BANK,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->rbankoff), (sizeof(struct rec_slot_ctrl_bank )* 2*2), (0x08|0x02)) |
| 1458 | BUS_DMASYNC_POSTWRITE|BUS_DMASYNC_POSTREAD)(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_ctrldata.map), (sc->rbankoff), (sizeof(struct rec_slot_ctrl_bank )* 2*2), (0x08|0x02)); |
| 1459 | /* Sync ring buffer */ |
| 1460 | bus_dmamap_sync(sc->sc_dmatag, sc->sc_rec.dma->map,(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_rec.dma->map), (0), (sc->sc_rec.length), (0x02) ) |
| 1461 | 0, sc->sc_rec.length, BUS_DMASYNC_POSTREAD)(*(sc->sc_dmatag)->_dmamap_sync)((sc->sc_dmatag), (sc ->sc_rec.dma->map), (0), (sc->sc_rec.length), (0x02) ); |
| 1462 | } |
| 1463 | sc->sc_rec.intr = NULL((void *)0); |
| 1464 | mtx_leave(&audio_lock); |
| 1465 | return 0; |
| 1466 | } |
| 1467 | |
| 1468 | int |
| 1469 | yds_mixer_set_port(void *addr, mixer_ctrl_t *cp) |
| 1470 | { |
| 1471 | struct yds_softc *sc = addr; |
| 1472 | |
| 1473 | return (sc->sc_codec[0].codec_if->vtbl->mixer_set_port( |
| 1474 | sc->sc_codec[0].codec_if, cp)); |
| 1475 | } |
| 1476 | |
| 1477 | int |
| 1478 | yds_mixer_get_port(void *addr, mixer_ctrl_t *cp) |
| 1479 | { |
| 1480 | struct yds_softc *sc = addr; |
| 1481 | |
| 1482 | return (sc->sc_codec[0].codec_if->vtbl->mixer_get_port( |
| 1483 | sc->sc_codec[0].codec_if, cp)); |
| 1484 | } |
| 1485 | |
| 1486 | int |
| 1487 | yds_query_devinfo(void *addr, mixer_devinfo_t *dip) |
| 1488 | { |
| 1489 | struct yds_softc *sc = addr; |
| 1490 | |
| 1491 | return (sc->sc_codec[0].codec_if->vtbl->query_devinfo( |
| 1492 | sc->sc_codec[0].codec_if, dip)); |
| 1493 | } |
| 1494 | |
| 1495 | int |
| 1496 | yds_get_portnum_by_name(struct yds_softc *sc, char *class, char *device, |
| 1497 | char *qualifier) |
| 1498 | { |
| 1499 | return (sc->sc_codec[0].codec_if->vtbl->get_portnum_by_name( |
| 1500 | sc->sc_codec[0].codec_if, class, device, qualifier)); |
| 1501 | } |
| 1502 | |
| 1503 | void * |
| 1504 | yds_malloc(void *addr, int direction, size_t size, int pool, int flags) |
| 1505 | { |
| 1506 | struct yds_softc *sc = addr; |
| 1507 | struct yds_dma *p; |
| 1508 | int error; |
| 1509 | |
| 1510 | p = malloc(sizeof(*p), pool, flags); |
| 1511 | if (!p) |
| 1512 | return (0); |
| 1513 | error = yds_allocmem(sc, size, 16, p); |
| 1514 | if (error) { |
| 1515 | free(p, pool, sizeof *p); |
| 1516 | return (0); |
| 1517 | } |
| 1518 | p->next = sc->sc_dmas; |
| 1519 | sc->sc_dmas = p; |
| 1520 | return (KERNADDR(p)((void *)((p)->addr))); |
| 1521 | } |
| 1522 | |
| 1523 | void |
| 1524 | yds_free(void *addr, void *ptr, int pool) |
| 1525 | { |
| 1526 | struct yds_softc *sc = addr; |
| 1527 | struct yds_dma **pp, *p; |
| 1528 | |
| 1529 | for (pp = &sc->sc_dmas; (p = *pp) != NULL((void *)0); pp = &p->next) { |
| 1530 | if (KERNADDR(p)((void *)((p)->addr)) == ptr) { |
| 1531 | yds_freemem(sc, p); |
| 1532 | *pp = p->next; |
| 1533 | free(p, pool, sizeof *p); |
| 1534 | return; |
| 1535 | } |
| 1536 | } |
| 1537 | } |
| 1538 | |
| 1539 | static struct yds_dma * |
| 1540 | yds_find_dma(struct yds_softc *sc, void *addr) |
| 1541 | { |
| 1542 | struct yds_dma *p; |
| 1543 | |
| 1544 | for (p = sc->sc_dmas; p && KERNADDR(p)((void *)((p)->addr)) != addr; p = p->next) |
| 1545 | ; |
| 1546 | |
| 1547 | return p; |
| 1548 | } |
| 1549 | |
| 1550 | size_t |
| 1551 | yds_round_buffersize(void *addr, int direction, size_t size) |
| 1552 | { |
| 1553 | /* |
| 1554 | * Buffer size should be at least twice as bigger as a frame. |
| 1555 | */ |
| 1556 | if (size < 1024 * 3) |
| 1557 | size = 1024 * 3; |
| 1558 | return (size); |
| 1559 | } |
| 1560 | |
| 1561 | int |
| 1562 | yds_activate(struct device *self, int act) |
| 1563 | { |
| 1564 | struct yds_softc *sc = (struct yds_softc *)self; |
| 1565 | int rv = 0; |
| 1566 | |
| 1567 | switch (act) { |
| 1568 | case DVACT_QUIESCE2: |
| 1569 | if (sc->sc_play.intr || sc->sc_rec.intr) |
| 1570 | sc->sc_resume_active = 1; |
| 1571 | else |
| 1572 | sc->sc_resume_active = 0; |
| 1573 | rv = config_activate_children(self, act); |
| 1574 | if (sc->sc_resume_active) |
| 1575 | yds_close(sc); |
| 1576 | break; |
| 1577 | case DVACT_RESUME4: |
| 1578 | yds_halt(sc); |
| 1579 | yds_init(sc, 1); |
| 1580 | ac97_resume(&sc->sc_codec[0].host_if, sc->sc_codec[0].codec_if); |
| 1581 | if (sc->sc_resume_active) |
| 1582 | yds_open(sc, 0); |
| 1583 | rv = config_activate_children(self, act); |
| 1584 | break; |
| 1585 | default: |
| 1586 | rv = config_activate_children(self, act); |
| 1587 | break; |
| 1588 | } |
| 1589 | return (rv); |
| 1590 | } |
| 1591 | |
| 1592 | int |
| 1593 | yds_init(struct yds_softc *sc, int resuming) |
| 1594 | { |
| 1595 | u_int32_t reg; |
| 1596 | |
| 1597 | pci_chipset_tag_t pc = sc->sc_pc; |
| 1598 | |
| 1599 | int to; |
| 1600 | |
| 1601 | DPRINTF(("in yds_init()\n")); |
| 1602 | |
| 1603 | /* Download microcode */ |
| 1604 | if (!resuming) { |
| 1605 | if (yds_download_mcode(sc)) { |
| 1606 | printf("%s: download microcode failed\n", sc->sc_dev.dv_xname); |
| 1607 | return -1; |
| 1608 | } |
| 1609 | } |
| 1610 | /* Allocate DMA buffers */ |
| 1611 | if (yds_allocate_slots(sc, resuming)) { |
| 1612 | printf("%s: could not allocate slots\n", sc->sc_dev.dv_xname); |
| 1613 | return -1; |
| 1614 | } |
| 1615 | |
| 1616 | /* Warm reset */ |
| 1617 | reg = pci_conf_read(pc, sc->sc_pcitag, YDS_PCI_DSCTRL0x48); |
| 1618 | pci_conf_write(pc, sc->sc_pcitag, YDS_PCI_DSCTRL0x48, reg | YDS_DSCTRL_WRST0x00000004); |
| 1619 | delay(50000)(*delay_func)(50000); |
| 1620 | |
| 1621 | /* |
| 1622 | * Detect primary/secondary AC97 |
| 1623 | * YMF754 Hardware Specification Rev 1.01 page 24 |
| 1624 | */ |
| 1625 | reg = pci_conf_read(pc, sc->sc_pcitag, YDS_PCI_DSCTRL0x48); |
| 1626 | pci_conf_write(pc, sc->sc_pcitag, YDS_PCI_DSCTRL0x48, |
| 1627 | reg & ~YDS_DSCTRL_CRST0x00000001); |
| 1628 | delay(400000)(*delay_func)(400000); /* Needed for 740C. */ |
| 1629 | |
| 1630 | /* Primary */ |
| 1631 | for (to = 0; to < AC97_TIMEOUT1000; to++) { |
| 1632 | if ((YREAD2(sc, AC97_STAT_ADDR1)(((sc)->memt)->read_2(((sc)->memh), ((0x0066)))) & AC97_BUSY0x8000) == 0) |
| 1633 | break; |
| 1634 | delay(1)(*delay_func)(1); |
| 1635 | } |
| 1636 | if (to == AC97_TIMEOUT1000) { |
| 1637 | printf("%s: no AC97 available\n", sc->sc_dev.dv_xname); |
| 1638 | return -1; |
| 1639 | } |
| 1640 | |
| 1641 | /* Secondary */ |
| 1642 | /* Secondary AC97 is used for 4ch audio. Currently unused. */ |
| 1643 | ac97_id2 = -1; |
| 1644 | if ((YREAD2(sc, YDS_ACTIVITY)(((sc)->memt)->read_2(((sc)->memh), ((0x0006)))) & YDS_ACTIVITY_DOCKA0x0010) == 0) |
| 1645 | goto detected; |
| 1646 | #if 0 /* reset secondary... */ |
| 1647 | YWRITE2(sc, YDS_GPIO_OCTRL,(((sc)->memt)->write_2(((sc)->memh), ((0x0056)), ((( ((sc)->memt)->read_2(((sc)->memh), ((0x0056)))) & ~0x0004)))) |
| 1648 | YREAD2(sc, YDS_GPIO_OCTRL) & ~YDS_GPIO_GPO2)(((sc)->memt)->write_2(((sc)->memh), ((0x0056)), ((( ((sc)->memt)->read_2(((sc)->memh), ((0x0056)))) & ~0x0004)))); |
| 1649 | YWRITE2(sc, YDS_GPIO_FUNCE,(((sc)->memt)->write_2(((sc)->memh), ((0x0058)), ((( (((sc)->memt)->read_2(((sc)->memh), ((0x0058))))& (~0x0004))|0x0040)))) |
| 1650 | (YREAD2(sc, YDS_GPIO_FUNCE)&(~YDS_GPIO_GPC2))|YDS_GPIO_GPE2)(((sc)->memt)->write_2(((sc)->memh), ((0x0058)), ((( (((sc)->memt)->read_2(((sc)->memh), ((0x0058))))& (~0x0004))|0x0040)))); |
| 1651 | #endif |
| 1652 | for (to = 0; to < AC97_TIMEOUT1000; to++) { |
| 1653 | if ((YREAD2(sc, AC97_STAT_ADDR2)(((sc)->memt)->read_2(((sc)->memh), ((0x006a)))) & AC97_BUSY0x8000) == 0) |
| 1654 | break; |
| 1655 | delay(1)(*delay_func)(1); |
| 1656 | } |
| 1657 | if (to < AC97_TIMEOUT1000) { |
| 1658 | /* detect id */ |
| 1659 | for (ac97_id2 = 1; ac97_id2 < 4; ac97_id2++) { |
| 1660 | YWRITE2(sc, AC97_CMD_ADDR,(((sc)->memt)->write_2(((sc)->memh), ((0x0062)), ((0x8000 | ((ac97_id2) << 8) | 0x28)))) |
| 1661 | AC97_CMD_READ | AC97_ID(ac97_id2) | 0x28)(((sc)->memt)->write_2(((sc)->memh), ((0x0062)), ((0x8000 | ((ac97_id2) << 8) | 0x28)))); |
| 1662 | |
| 1663 | for (to = 0; to < AC97_TIMEOUT1000; to++) { |
| 1664 | if ((YREAD2(sc, AC97_STAT_ADDR2)(((sc)->memt)->read_2(((sc)->memh), ((0x006a)))) & AC97_BUSY0x8000) |
| 1665 | == 0) |
| 1666 | goto detected; |
| 1667 | delay(1)(*delay_func)(1); |
| 1668 | } |
| 1669 | } |
| 1670 | if (ac97_id2 == 4) |
| 1671 | ac97_id2 = -1; |
| 1672 | detected: |
| 1673 | ; |
| 1674 | } |
| 1675 | |
| 1676 | pci_conf_write(pc, sc->sc_pcitag, YDS_PCI_DSCTRL0x48, |
| 1677 | reg | YDS_DSCTRL_CRST0x00000001); |
| 1678 | delay (20)(*delay_func)(20); |
| 1679 | pci_conf_write(pc, sc->sc_pcitag, YDS_PCI_DSCTRL0x48, |
| 1680 | reg & ~YDS_DSCTRL_CRST0x00000001); |
| 1681 | delay (400000)(*delay_func)(400000); |
| 1682 | for (to = 0; to < AC97_TIMEOUT1000; to++) { |
| 1683 | if ((YREAD2(sc, AC97_STAT_ADDR1)(((sc)->memt)->read_2(((sc)->memh), ((0x0066)))) & AC97_BUSY0x8000) == 0) |
| 1684 | break; |
| 1685 | delay(1)(*delay_func)(1); |
| 1686 | } |
| 1687 | |
| 1688 | DPRINTF(("out of yds_init()\n")); |
| 1689 | |
| 1690 | return 0; |
| 1691 | } |