xref: /openbsd-src/sys/arch/macppc/dev/daca.c (revision cc5bdd413dc6810be27950ffc92a3e2dad4ebdcb)
1*cc5bdd41Skn /*	$OpenBSD: daca.c,v 1.15 2022/10/26 20:19:07 kn Exp $	*/
2833e7708Sjoris 
3833e7708Sjoris /*-
4833e7708Sjoris  * Copyright (c) 2002,2003 Tsubai Masanari.  All rights reserved.
5833e7708Sjoris  *
6833e7708Sjoris  * Redistribution and use in source and binary forms, with or without
7833e7708Sjoris  * modification, are permitted provided that the following conditions
8833e7708Sjoris  * are met:
9833e7708Sjoris  * 1. Redistributions of source code must retain the above copyright
10833e7708Sjoris  *    notice, this list of conditions and the following disclaimer.
11833e7708Sjoris  * 2. Redistributions in binary form must reproduce the above copyright
12833e7708Sjoris  *    notice, this list of conditions and the following disclaimer in the
13833e7708Sjoris  *    documentation and/or other materials provided with the distribution.
14833e7708Sjoris  * 3. The name of the author may not be used to endorse or promote products
15833e7708Sjoris  *    derived from this software without specific prior written permission.
16833e7708Sjoris  *
17833e7708Sjoris  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18833e7708Sjoris  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19833e7708Sjoris  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20833e7708Sjoris  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21833e7708Sjoris  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22833e7708Sjoris  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23833e7708Sjoris  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24833e7708Sjoris  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25833e7708Sjoris  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26833e7708Sjoris  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27833e7708Sjoris  */
28833e7708Sjoris 
29e307f517Sbrad /*
30e307f517Sbrad  * Datasheet is available from
31e307f517Sbrad  * http://www.indata.si/grega/pdfs/dac3550a.pdf
32e307f517Sbrad  */
33e307f517Sbrad 
34833e7708Sjoris #include <sys/param.h>
35833e7708Sjoris #include <sys/audioio.h>
36833e7708Sjoris #include <sys/device.h>
37833e7708Sjoris #include <sys/systm.h>
38833e7708Sjoris 
39833e7708Sjoris #include <dev/audio_if.h>
40833e7708Sjoris #include <dev/ofw/openfirm.h>
41833e7708Sjoris #include <macppc/dev/dbdma.h>
42833e7708Sjoris 
43833e7708Sjoris #include <machine/autoconf.h>
44833e7708Sjoris 
45833e7708Sjoris #include <macppc/dev/i2svar.h>
46833e7708Sjoris 
47833e7708Sjoris #ifdef DACA_DEBUG
48833e7708Sjoris # define DPRINTF printf
49833e7708Sjoris #else
50833e7708Sjoris # define DPRINTF while (0) printf
51833e7708Sjoris #endif
52833e7708Sjoris 
53ea884047Sbrad /* XXX */
54ea884047Sbrad #define daca_softc i2s_softc
55ea884047Sbrad 
56ea884047Sbrad /* XXX */
57715b6a7bSderaadt int kiic_write(struct device *, int, int, const void *, int);
58715b6a7bSderaadt int kiic_writereg(struct device *, int, u_int);
59833e7708Sjoris 
60833e7708Sjoris int daca_match(struct device *, void *, void *);
61833e7708Sjoris void daca_attach(struct device *, struct device *, void *);
62833e7708Sjoris void daca_defer(struct device *);
63833e7708Sjoris void daca_init(struct daca_softc *);
64833e7708Sjoris void daca_set_volume(struct daca_softc *, int, int);
65833e7708Sjoris 
6689ed722cSmpi const struct cfattach daca_ca = {
67833e7708Sjoris 	sizeof(struct daca_softc), daca_match, daca_attach
68833e7708Sjoris };
69833e7708Sjoris 
70833e7708Sjoris struct cfdriver daca_cd = {
71833e7708Sjoris 	NULL, "daca", DV_DULL
72833e7708Sjoris };
73833e7708Sjoris 
740d6a2fdeSmiod const struct audio_hw_if daca_hw_if = {
755a8d990aSkn 	.open = i2s_open,
765a8d990aSkn 	.close = i2s_close,
775a8d990aSkn 	.set_params = i2s_set_params,
785a8d990aSkn 	.round_blocksize = i2s_round_blocksize,
795a8d990aSkn 	.halt_output = i2s_halt_output,
805a8d990aSkn 	.halt_input = i2s_halt_input,
815a8d990aSkn 	.set_port = i2s_set_port,
825a8d990aSkn 	.get_port = i2s_get_port,
835a8d990aSkn 	.query_devinfo = i2s_query_devinfo,
845a8d990aSkn 	.allocm = i2s_allocm,
855a8d990aSkn 	.round_buffersize = i2s_round_buffersize,
865a8d990aSkn 	.trigger_output = i2s_trigger_output,
875a8d990aSkn 	.trigger_input = i2s_trigger_input,
88833e7708Sjoris };
89833e7708Sjoris 
90e307f517Sbrad /* DAC3550A registers */
91833e7708Sjoris #define DEQ_SR		0x01	/* Sample rate control (8) */
92833e7708Sjoris #define DEQ_AVOL	0x02	/* Analog volume (16) */
93833e7708Sjoris #define DEQ_GCFG	0x03	/* Global configuration (8) */
94833e7708Sjoris 
95833e7708Sjoris int
daca_match(struct device * parent,void * match,void * aux)96ea884047Sbrad daca_match(struct device *parent, void *match, void *aux)
97833e7708Sjoris {
98833e7708Sjoris 	struct confargs *ca = aux;
99833e7708Sjoris 	int soundbus, soundchip;
100833e7708Sjoris 	char compat[32];
101833e7708Sjoris 
102833e7708Sjoris 	if (strcmp(ca->ca_name, "i2s") != 0)
103ea884047Sbrad 		return (0);
104833e7708Sjoris 
105833e7708Sjoris 	if ((soundbus = OF_child(ca->ca_node)) == 0 ||
106833e7708Sjoris 	    (soundchip = OF_child(soundbus)) == 0)
107ea884047Sbrad 		return (0);
108833e7708Sjoris 
109833e7708Sjoris 	bzero(compat, sizeof compat);
110833e7708Sjoris 	OF_getprop(soundchip, "compatible", compat, sizeof compat);
111833e7708Sjoris 
112833e7708Sjoris 	if (strcmp(compat, "daca") != 0)
113ea884047Sbrad 		return (0);
114833e7708Sjoris 
115ea884047Sbrad 	return (1);
116833e7708Sjoris }
117833e7708Sjoris 
118833e7708Sjoris #define DEQaddr 0x9a
119833e7708Sjoris 
120833e7708Sjoris void
daca_attach(struct device * parent,struct device * self,void * aux)121ea884047Sbrad daca_attach(struct device *parent,struct device *self, void *aux)
122833e7708Sjoris {
123833e7708Sjoris 	struct daca_softc *sc = (struct daca_softc *)self;
124833e7708Sjoris 
125833e7708Sjoris 	sc->sc_setvolume = daca_set_volume;
126833e7708Sjoris 
127833e7708Sjoris 	i2s_attach(parent, sc, aux);
128833e7708Sjoris 	config_defer(self, daca_defer);
129833e7708Sjoris }
130833e7708Sjoris 
131833e7708Sjoris void
daca_defer(struct device * dev)132833e7708Sjoris daca_defer(struct device *dev)
133833e7708Sjoris {
134833e7708Sjoris 	struct daca_softc *sc = (struct daca_softc *)dev;
135833e7708Sjoris 	struct device *dv;
136833e7708Sjoris 
137ea884047Sbrad 	TAILQ_FOREACH(dv, &alldevs, dv_list)
1389f4ceda2Sderaadt 		if (strcmp(dv->dv_cfdata->cf_driver->cd_name, "kiic") == 0 &&
1399f4ceda2Sderaadt 		    strcmp(dv->dv_parent->dv_cfdata->cf_driver->cd_name, "macobio") == 0)
140833e7708Sjoris 			sc->sc_i2c = dv;
141833e7708Sjoris 	if (sc->sc_i2c == NULL) {
142833e7708Sjoris 		printf("%s: unable to find i2c\n", sc->sc_dev.dv_xname);
143833e7708Sjoris 		return;
144833e7708Sjoris 	}
145833e7708Sjoris 
146ea884047Sbrad 	/* XXX If i2c has failed to attach, what should we do? */
147ea884047Sbrad 
1482baa08e2Santon 	audio_attach_mi(&daca_hw_if, sc, NULL, &sc->sc_dev);
149ea884047Sbrad 
150833e7708Sjoris 	daca_init(sc);
151833e7708Sjoris }
152833e7708Sjoris 
153833e7708Sjoris void
daca_init(struct daca_softc * sc)154833e7708Sjoris daca_init(struct daca_softc *sc)
155833e7708Sjoris {
156833e7708Sjoris 	i2s_set_rate(sc, 44100);
157715b6a7bSderaadt 	kiic_writereg(sc->sc_i2c, 4, 0x01 | 0x02 | 0x04);
158833e7708Sjoris }
159833e7708Sjoris 
160833e7708Sjoris void
daca_set_volume(struct daca_softc * sc,int left,int right)161ea884047Sbrad daca_set_volume(struct daca_softc *sc, int left, int right)
162833e7708Sjoris {
163833e7708Sjoris 	u_int16_t data;
164833e7708Sjoris 
165833e7708Sjoris 	sc->sc_vol_l = left;
166833e7708Sjoris 	sc->sc_vol_r = right;
167833e7708Sjoris 
168833e7708Sjoris 	left >>= 2;
169833e7708Sjoris 	right >>= 2;
170833e7708Sjoris 	data = left << 8 | right;
171715b6a7bSderaadt 	kiic_write(sc->sc_i2c, DEQaddr, DEQ_AVOL, &data, 2);
172833e7708Sjoris }
173