ym_acpi.c revision 1.5
11.5Scegger/* $NetBSD: ym_acpi.c,v 1.5 2008/04/05 21:44:50 cegger 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.5Scegger__KERNEL_RCSID(0, "$NetBSD: ym_acpi.c,v 1.5 2008/04/05 21:44:50 cegger 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.1Sitohystatic int	ym_acpi_match(struct device *, struct cfdata *, void *);
521.1Sitohystatic void	ym_acpi_attach(struct device *, struct device *, 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.3Schristosym_acpi_match(struct device *parent, struct cfdata *match,
621.2Schristos    void *aux)
631.1Sitohy{
641.1Sitohy	struct acpi_attach_args *aa = aux;
651.1Sitohy
661.1Sitohy	if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE)
671.1Sitohy		return 0;
681.1Sitohy	/* Yamaha OPL3-SA2 or OPL3-SA3 */
691.1Sitohy	if (strcmp("YMH0021", aa->aa_node->ad_devinfo->HardwareId.Value))
701.1Sitohy		return 0;
711.1Sitohy
721.1Sitohy	return 1;
731.1Sitohy}
741.1Sitohy
751.1Sitohy/*
761.1Sitohy * ym_acpi_attach: autoconf(9) attach routine
771.1Sitohy */
781.1Sitohystatic void
791.3Schristosym_acpi_attach(struct device *parent, struct device *self, void *aux)
801.1Sitohy{
811.1Sitohy	struct ym_softc *sc = (struct ym_softc *)self;
821.1Sitohy	struct acpi_attach_args *aa = aux;
831.1Sitohy	struct acpi_resources res;
841.1Sitohy	struct acpi_io *sb_io, *codec_io, *opl_io, *control_io;
851.1Sitohy#if NMPU_YM > 0
861.1Sitohy	struct acpi_io *mpu_io;
871.1Sitohy#endif
881.1Sitohy	struct acpi_irq *irq;
891.1Sitohy	struct acpi_drq *playdrq, *recdrq;
901.1Sitohy	struct ad1848_softc *ac = &sc->sc_ad1848.sc_ad1848;
911.1Sitohy	ACPI_STATUS rv;
921.1Sitohy
931.1Sitohy	aprint_naive("\n");
941.1Sitohy	aprint_normal("\n");
951.1Sitohy
961.1Sitohy	/* Parse our resources */
971.1Sitohy	rv = acpi_resource_parse(&sc->sc_ad1848.sc_ad1848.sc_dev,
981.1Sitohy	    aa->aa_node->ad_handle, "_CRS", &res,
991.1Sitohy	    &acpi_resource_parse_ops_default);
1001.1Sitohy	if (ACPI_FAILURE(rv))
1011.1Sitohy		return;
1021.1Sitohy
1031.1Sitohy	/*
1041.1Sitohy	 * sc_sb_ioh	 @ 0
1051.1Sitohy	 * sc_ioh	 @ 1
1061.1Sitohy	 * sc_opl_ioh	 @ 2
1071.1Sitohy	 * sc_mpu_ioh	 @ 3
1081.1Sitohy	 * sc_controlioh @ 4
1091.1Sitohy	 */
1101.1Sitohy
1111.1Sitohy	/* Find and map our i/o registers */
1121.1Sitohy	sc->sc_iot = aa->aa_iot;
1131.1Sitohy	sb_io	 = acpi_res_io(&res, 0);
1141.1Sitohy	codec_io = acpi_res_io(&res, 1);
1151.1Sitohy	opl_io	 = acpi_res_io(&res, 2);
1161.1Sitohy#if NMPU_YM > 0
1171.1Sitohy	mpu_io	 = acpi_res_io(&res, 3);
1181.1Sitohy#endif
1191.1Sitohy	control_io = acpi_res_io(&res, 4);
1201.1Sitohy
1211.1Sitohy	if (sb_io == NULL || codec_io == NULL || opl_io == NULL ||
1221.1Sitohy#if NMPU_YM > 0
1231.1Sitohy	    mpu_io == NULL ||
1241.1Sitohy#endif
1251.1Sitohy	    control_io == NULL) {
1261.5Scegger		aprint_error_dev(self, "unable to find i/o registers resource\n");
1271.1Sitohy		goto out;
1281.1Sitohy	}
1291.1Sitohy	if (bus_space_map(sc->sc_iot, sb_io->ar_base, sb_io->ar_length,
1301.1Sitohy	    0, &sc->sc_sb_ioh) != 0) {
1311.5Scegger		aprint_error_dev(self, "unable to map i/o registers (sb)\n");
1321.1Sitohy		goto out;
1331.1Sitohy	}
1341.1Sitohy	if (bus_space_map(sc->sc_iot, codec_io->ar_base, codec_io->ar_length,
1351.1Sitohy	    0, &sc->sc_ioh) != 0) {
1361.5Scegger		aprint_error_dev(self, "unable to map i/o registers (codec)\n");
1371.1Sitohy		goto out;
1381.1Sitohy	}
1391.1Sitohy	if (bus_space_map(sc->sc_iot, opl_io->ar_base, opl_io->ar_length,
1401.1Sitohy	    0, &sc->sc_opl_ioh) != 0) {
1411.5Scegger		aprint_error_dev(self, "unable to map i/o registers (opl)\n");
1421.1Sitohy		goto out;
1431.1Sitohy	}
1441.1Sitohy#if NMPU_YM > 0
1451.1Sitohy	if (bus_space_map(sc->sc_iot, mpu_io->ar_base, mpu_io->ar_length,
1461.1Sitohy	    0, &sc->sc_mpu_ioh) != 0) {
1471.5Scegger		aprint_error_dev(self, "unable to map i/o registers (mpu)\n");
1481.1Sitohy		goto out;
1491.1Sitohy	}
1501.1Sitohy#endif
1511.1Sitohy	if (bus_space_map(sc->sc_iot, control_io->ar_base,
1521.1Sitohy	    control_io->ar_length, 0, &sc->sc_controlioh) != 0) {
1531.5Scegger		aprint_error_dev(self, "unable to map i/o registers (control)\n");
1541.1Sitohy		goto out;
1551.1Sitohy	}
1561.1Sitohy
1571.1Sitohy	sc->sc_ic = aa->aa_ic;
1581.1Sitohy
1591.1Sitohy	/* Find our IRQ */
1601.1Sitohy	irq = acpi_res_irq(&res, 0);
1611.1Sitohy	if (irq == NULL) {
1621.5Scegger		aprint_error_dev(self, "unable to find irq resource\n");
1631.1Sitohy		/* XXX bus_space_unmap */
1641.1Sitohy		goto out;
1651.1Sitohy	}
1661.1Sitohy	sc->ym_irq = irq->ar_irq;
1671.1Sitohy
1681.1Sitohy	/* Find our playback and record DRQs */
1691.1Sitohy	playdrq = acpi_res_drq(&res, 0);
1701.1Sitohy	recdrq = acpi_res_drq(&res, 1);
1711.1Sitohy	if (playdrq == NULL) {
1721.5Scegger		aprint_error_dev(self, "unable to find drq resources\n");
1731.1Sitohy		/* XXX bus_space_unmap */
1741.1Sitohy		goto out;
1751.1Sitohy	}
1761.1Sitohy	if (recdrq == NULL) {
1771.1Sitohy		/* half-duplex mode */
1781.1Sitohy		sc->ym_recdrq = sc->ym_playdrq = playdrq->ar_drq;
1791.1Sitohy	} else {
1801.1Sitohy		sc->ym_playdrq = playdrq->ar_drq;
1811.1Sitohy		sc->ym_recdrq = recdrq->ar_drq;
1821.1Sitohy	}
1831.1Sitohy
1841.1Sitohy	ac->sc_iot = sc->sc_iot;
1851.1Sitohy	if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, WSS_CODEC,
1861.1Sitohy	    AD1848_NPORT, &ac->sc_ioh)) {
1871.5Scegger		aprint_error_dev(self, "bus_space_subregion failed\n");
1881.1Sitohy		/* XXX cleanup */
1891.1Sitohy		goto out;
1901.1Sitohy	}
1911.1Sitohy
1921.5Scegger	aprint_normal_dev(self, "");
1931.1Sitohy
1941.1Sitohy	ac->mode = 2;
1951.1Sitohy	ac->MCE_bit = MODE_CHANGE_ENABLE;
1961.1Sitohy
1971.1Sitohy	sc->sc_ad1848.sc_ic = sc->sc_ic;
1981.1Sitohy
1991.1Sitohy	/* Attach our ym device */
2001.1Sitohy	ym_attach(sc);
2011.1Sitohy
2021.1Sitohy out:
2031.1Sitohy	acpi_resource_cleanup(&res);
2041.1Sitohy}
205