ym_acpi.c revision 1.10
11.10Sjmcneill/* $NetBSD: ym_acpi.c,v 1.10 2009/08/19 00:31:16 jmcneill Exp $ */
21.1Sitohy
31.1Sitohy/*
41.1Sitohy * Copyright (c) 2006 Jasper Wallace <jasper@pointless.net>
51.1Sitohy * All rights reserved.
61.1Sitohy *
71.1Sitohy * Copyright (c) 2002 Jared D. McNeill <jmcneill@invisible.ca>
81.1Sitohy * All rights reserved.
91.1Sitohy *
101.1Sitohy * Redistribution and use in source and binary forms, with or without
111.1Sitohy * modification, are permitted provided that the following conditions
121.1Sitohy * are met:
131.1Sitohy * 1. Redistributions of source code must retain the above copyright
141.1Sitohy *    notice, this list of conditions and the following disclaimer.
151.1Sitohy * 2. The name of the author may not be used to endorse or promote products
161.1Sitohy *    derived from this software without specific prior written permission.
171.1Sitohy *
181.1Sitohy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
191.1Sitohy * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
201.1Sitohy * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
211.1Sitohy * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
221.1Sitohy * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
231.1Sitohy * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
241.1Sitohy * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
251.1Sitohy * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
261.1Sitohy * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
271.1Sitohy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
281.1Sitohy * SUCH DAMAGE.
291.1Sitohy */
301.1Sitohy
311.1Sitohy#include <sys/cdefs.h>
321.10Sjmcneill__KERNEL_RCSID(0, "$NetBSD: ym_acpi.c,v 1.10 2009/08/19 00:31:16 jmcneill Exp $");
331.1Sitohy
341.1Sitohy#include "mpu_ym.h"
351.1Sitohy
361.1Sitohy#include <sys/param.h>
371.4Sad#include <sys/bus.h>
381.1Sitohy
391.1Sitohy#include <dev/acpi/acpivar.h>
401.1Sitohy
411.1Sitohy#include <dev/audio_if.h>
421.1Sitohy
431.1Sitohy#include <dev/ic/ad1848reg.h>
441.1Sitohy#include <dev/isa/ad1848var.h>
451.1Sitohy
461.1Sitohy#include <dev/ic/opl3sa3reg.h>
471.1Sitohy#include <dev/isa/wssreg.h>
481.1Sitohy#include <dev/isa/ymvar.h>
491.1Sitohy
501.1Sitohy
511.8Sceggerstatic int	ym_acpi_match(device_t, cfdata_t, void *);
521.8Sceggerstatic void	ym_acpi_attach(device_t, device_t, void *);
531.1Sitohy
541.1SitohyCFATTACH_DECL(ym_acpi, sizeof(struct ym_softc), ym_acpi_match,
551.1Sitohy    ym_acpi_attach, NULL, NULL);
561.1Sitohy
571.1Sitohy/*
581.1Sitohy * ym_acpi_match: autoconf(9) match routine
591.1Sitohy */
601.1Sitohystatic int
611.8Sceggerym_acpi_match(device_t parent, cfdata_t match, void *aux)
621.1Sitohy{
631.1Sitohy	struct acpi_attach_args *aa = aux;
641.1Sitohy
651.1Sitohy	if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE)
661.1Sitohy		return 0;
671.10Sjmcneill	if (!aa->aa_node->ad_devinfo->HardwareId.String)
681.10Sjmcneill		return 0;
691.1Sitohy	/* Yamaha OPL3-SA2 or OPL3-SA3 */
701.9Sjmcneill	if (strcmp("YMH0021", aa->aa_node->ad_devinfo->HardwareId.String))
711.1Sitohy		return 0;
721.1Sitohy
731.1Sitohy	return 1;
741.1Sitohy}
751.1Sitohy
761.1Sitohy/*
771.1Sitohy * ym_acpi_attach: autoconf(9) attach routine
781.1Sitohy */
791.1Sitohystatic void
801.8Sceggerym_acpi_attach(device_t parent, device_t self, void *aux)
811.1Sitohy{
821.1Sitohy	struct ym_softc *sc = (struct ym_softc *)self;
831.1Sitohy	struct acpi_attach_args *aa = aux;
841.1Sitohy	struct acpi_resources res;
851.1Sitohy	struct acpi_io *sb_io, *codec_io, *opl_io, *control_io;
861.1Sitohy#if NMPU_YM > 0
871.1Sitohy	struct acpi_io *mpu_io;
881.1Sitohy#endif
891.1Sitohy	struct acpi_irq *irq;
901.1Sitohy	struct acpi_drq *playdrq, *recdrq;
911.1Sitohy	struct ad1848_softc *ac = &sc->sc_ad1848.sc_ad1848;
921.1Sitohy	ACPI_STATUS rv;
931.1Sitohy
941.1Sitohy	/* Parse our resources */
951.1Sitohy	rv = acpi_resource_parse(&sc->sc_ad1848.sc_ad1848.sc_dev,
961.1Sitohy	    aa->aa_node->ad_handle, "_CRS", &res,
971.1Sitohy	    &acpi_resource_parse_ops_default);
981.1Sitohy	if (ACPI_FAILURE(rv))
991.1Sitohy		return;
1001.1Sitohy
1011.1Sitohy	/*
1021.1Sitohy	 * sc_sb_ioh	 @ 0
1031.1Sitohy	 * sc_ioh	 @ 1
1041.1Sitohy	 * sc_opl_ioh	 @ 2
1051.1Sitohy	 * sc_mpu_ioh	 @ 3
1061.1Sitohy	 * sc_controlioh @ 4
1071.1Sitohy	 */
1081.1Sitohy
1091.1Sitohy	/* Find and map our i/o registers */
1101.1Sitohy	sc->sc_iot = aa->aa_iot;
1111.1Sitohy	sb_io	 = acpi_res_io(&res, 0);
1121.1Sitohy	codec_io = acpi_res_io(&res, 1);
1131.1Sitohy	opl_io	 = acpi_res_io(&res, 2);
1141.1Sitohy#if NMPU_YM > 0
1151.1Sitohy	mpu_io	 = acpi_res_io(&res, 3);
1161.1Sitohy#endif
1171.1Sitohy	control_io = acpi_res_io(&res, 4);
1181.1Sitohy
1191.1Sitohy	if (sb_io == NULL || codec_io == NULL || opl_io == NULL ||
1201.1Sitohy#if NMPU_YM > 0
1211.1Sitohy	    mpu_io == NULL ||
1221.1Sitohy#endif
1231.1Sitohy	    control_io == NULL) {
1241.5Scegger		aprint_error_dev(self, "unable to find i/o registers resource\n");
1251.1Sitohy		goto out;
1261.1Sitohy	}
1271.1Sitohy	if (bus_space_map(sc->sc_iot, sb_io->ar_base, sb_io->ar_length,
1281.1Sitohy	    0, &sc->sc_sb_ioh) != 0) {
1291.5Scegger		aprint_error_dev(self, "unable to map i/o registers (sb)\n");
1301.1Sitohy		goto out;
1311.1Sitohy	}
1321.1Sitohy	if (bus_space_map(sc->sc_iot, codec_io->ar_base, codec_io->ar_length,
1331.1Sitohy	    0, &sc->sc_ioh) != 0) {
1341.5Scegger		aprint_error_dev(self, "unable to map i/o registers (codec)\n");
1351.1Sitohy		goto out;
1361.1Sitohy	}
1371.1Sitohy	if (bus_space_map(sc->sc_iot, opl_io->ar_base, opl_io->ar_length,
1381.1Sitohy	    0, &sc->sc_opl_ioh) != 0) {
1391.5Scegger		aprint_error_dev(self, "unable to map i/o registers (opl)\n");
1401.1Sitohy		goto out;
1411.1Sitohy	}
1421.1Sitohy#if NMPU_YM > 0
1431.1Sitohy	if (bus_space_map(sc->sc_iot, mpu_io->ar_base, mpu_io->ar_length,
1441.1Sitohy	    0, &sc->sc_mpu_ioh) != 0) {
1451.5Scegger		aprint_error_dev(self, "unable to map i/o registers (mpu)\n");
1461.1Sitohy		goto out;
1471.1Sitohy	}
1481.1Sitohy#endif
1491.1Sitohy	if (bus_space_map(sc->sc_iot, control_io->ar_base,
1501.1Sitohy	    control_io->ar_length, 0, &sc->sc_controlioh) != 0) {
1511.5Scegger		aprint_error_dev(self, "unable to map i/o registers (control)\n");
1521.1Sitohy		goto out;
1531.1Sitohy	}
1541.1Sitohy
1551.1Sitohy	sc->sc_ic = aa->aa_ic;
1561.1Sitohy
1571.1Sitohy	/* Find our IRQ */
1581.1Sitohy	irq = acpi_res_irq(&res, 0);
1591.1Sitohy	if (irq == NULL) {
1601.5Scegger		aprint_error_dev(self, "unable to find irq resource\n");
1611.1Sitohy		/* XXX bus_space_unmap */
1621.1Sitohy		goto out;
1631.1Sitohy	}
1641.1Sitohy	sc->ym_irq = irq->ar_irq;
1651.1Sitohy
1661.1Sitohy	/* Find our playback and record DRQs */
1671.1Sitohy	playdrq = acpi_res_drq(&res, 0);
1681.1Sitohy	recdrq = acpi_res_drq(&res, 1);
1691.1Sitohy	if (playdrq == NULL) {
1701.5Scegger		aprint_error_dev(self, "unable to find drq resources\n");
1711.1Sitohy		/* XXX bus_space_unmap */
1721.1Sitohy		goto out;
1731.1Sitohy	}
1741.1Sitohy	if (recdrq == NULL) {
1751.1Sitohy		/* half-duplex mode */
1761.1Sitohy		sc->ym_recdrq = sc->ym_playdrq = playdrq->ar_drq;
1771.1Sitohy	} else {
1781.1Sitohy		sc->ym_playdrq = playdrq->ar_drq;
1791.1Sitohy		sc->ym_recdrq = recdrq->ar_drq;
1801.1Sitohy	}
1811.1Sitohy
1821.1Sitohy	ac->sc_iot = sc->sc_iot;
1831.1Sitohy	if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, WSS_CODEC,
1841.1Sitohy	    AD1848_NPORT, &ac->sc_ioh)) {
1851.5Scegger		aprint_error_dev(self, "bus_space_subregion failed\n");
1861.1Sitohy		/* XXX cleanup */
1871.1Sitohy		goto out;
1881.1Sitohy	}
1891.1Sitohy
1901.5Scegger	aprint_normal_dev(self, "");
1911.1Sitohy
1921.1Sitohy	ac->mode = 2;
1931.1Sitohy	ac->MCE_bit = MODE_CHANGE_ENABLE;
1941.1Sitohy
1951.1Sitohy	sc->sc_ad1848.sc_ic = sc->sc_ic;
1961.1Sitohy
1971.1Sitohy	/* Attach our ym device */
1981.1Sitohy	ym_attach(sc);
1991.1Sitohy
2001.1Sitohy out:
2011.1Sitohy	acpi_resource_cleanup(&res);
2021.1Sitohy}
203