Home | History | Annotate | Line # | Download | only in ic
am7930.c revision 1.40
      1  1.40        pk /*	$NetBSD: am7930.c,v 1.40 1998/08/28 08:59:14 pk Exp $	*/
      2   1.3       cgd 
      3   1.1        pk /*
      4   1.1        pk  * Copyright (c) 1995 Rolf Grossmann
      5   1.1        pk  * All rights reserved.
      6   1.1        pk  *
      7   1.1        pk  * Redistribution and use in source and binary forms, with or without
      8   1.1        pk  * modification, are permitted provided that the following conditions
      9   1.1        pk  * are met:
     10   1.1        pk  * 1. Redistributions of source code must retain the above copyright
     11   1.1        pk  *    notice, this list of conditions and the following disclaimer.
     12   1.1        pk  * 2. Redistributions in binary form must reproduce the above copyright
     13   1.1        pk  *    notice, this list of conditions and the following disclaimer in the
     14   1.1        pk  *    documentation and/or other materials provided with the distribution.
     15   1.1        pk  * 3. All advertising materials mentioning features or use of this software
     16   1.1        pk  *    must display the following acknowledgement:
     17   1.1        pk  *      This product includes software developed by Rolf Grossmann.
     18   1.1        pk  * 4. The name of the author may not be used to endorse or promote products
     19   1.1        pk  *    derived from this software without specific prior written permission
     20   1.1        pk  *
     21   1.1        pk  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     22   1.1        pk  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     23   1.1        pk  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     24   1.1        pk  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     25   1.1        pk  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     26   1.1        pk  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     27   1.1        pk  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     28   1.1        pk  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29   1.1        pk  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     30   1.1        pk  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31   1.1        pk  */
     32   1.1        pk 
     33  1.39  jonathan /*
     34  1.39  jonathan  * Front-end attachment independent layer for AMD 79c30
     35  1.39  jonathan  * audio driver. XXX isdn support??
     36  1.39  jonathan  */
     37  1.39  jonathan 
     38   1.1        pk #include "audio.h"
     39   1.1        pk #if NAUDIO > 0
     40   1.1        pk 
     41   1.1        pk #include <sys/param.h>
     42   1.1        pk #include <sys/systm.h>
     43   1.1        pk #include <sys/errno.h>
     44   1.1        pk #include <sys/ioctl.h>
     45   1.1        pk #include <sys/device.h>
     46   1.1        pk #include <sys/proc.h>
     47   1.1        pk 
     48  1.36        pk #include <machine/bus.h>
     49   1.1        pk #include <machine/autoconf.h>
     50   1.1        pk #include <machine/cpu.h>
     51   1.1        pk 
     52   1.1        pk #include <sys/audioio.h>
     53   1.1        pk #include <dev/audio_if.h>
     54   1.1        pk 
     55   1.3       cgd #include <dev/ic/am7930reg.h>
     56  1.39  jonathan #include <dev/ic/am7930var.h>
     57   1.1        pk 
     58  1.30  augustss #define AUDIO_ROM_NAME "audio"
     59  1.30  augustss 
     60   1.4    brezak #ifdef AUDIO_DEBUG
     61  1.39  jonathan int     am7930debug = 0;
     62  1.40        pk #define DPRINTF(x)      if (am7930debug) printf x
     63   1.1        pk #else
     64   1.1        pk #define DPRINTF(x)
     65   1.1        pk #endif
     66   1.1        pk 
     67  1.39  jonathan /* forward declarations */
     68  1.39  jonathan static void init_amd __P((volatile struct am7930 *));
     69  1.39  jonathan 
     70   1.1        pk /*
     71  1.39  jonathan  * Audio device descriptor (attachment independent)
     72   1.1        pk  */
     73   1.1        pk 
     74  1.39  jonathan struct audio_device am7930_device = {
     75   1.1        pk 	"amd7930",
     76   1.1        pk 	"x",
     77  1.27  augustss 	"audioamd"
     78   1.1        pk };
     79   1.1        pk 
     80   1.1        pk /* The following tables stolen from former (4.4Lite's) sys/sparc/bsd_audio.c */
     81   1.1        pk 
     82   1.1        pk /*
     83   1.1        pk  * gx, gr & stg gains.  this table must contain 256 elements with
     84   1.1        pk  * the 0th being "infinity" (the magic value 9008).  The remaining
     85   1.1        pk  * elements match sun's gain curve (but with higher resolution):
     86   1.1        pk  * -18 to 0dB in .16dB steps then 0 to 12dB in .08dB steps.
     87   1.1        pk  */
     88   1.1        pk static const u_short gx_coeff[256] = {
     89  1.21        pk 	0x9008, 0x8e7c, 0x8e51, 0x8e45, 0x8d42, 0x8d3b, 0x8c36, 0x8c33,
     90   1.1        pk 	0x8b32, 0x8b2a, 0x8b2b, 0x8b2c, 0x8b25, 0x8b23, 0x8b22, 0x8b22,
     91   1.1        pk 	0x9122, 0x8b1a, 0x8aa3, 0x8aa3, 0x8b1c, 0x8aa6, 0x912d, 0x912b,
     92   1.1        pk 	0x8aab, 0x8b12, 0x8aaa, 0x8ab2, 0x9132, 0x8ab4, 0x913c, 0x8abb,
     93   1.1        pk 	0x9142, 0x9144, 0x9151, 0x8ad5, 0x8aeb, 0x8a79, 0x8a5a, 0x8a4a,
     94   1.1        pk 	0x8b03, 0x91c2, 0x91bb, 0x8a3f, 0x8a33, 0x91b2, 0x9212, 0x9213,
     95   1.1        pk 	0x8a2c, 0x921d, 0x8a23, 0x921a, 0x9222, 0x9223, 0x922d, 0x9231,
     96   1.1        pk 	0x9234, 0x9242, 0x925b, 0x92dd, 0x92c1, 0x92b3, 0x92ab, 0x92a4,
     97   1.1        pk 	0x92a2, 0x932b, 0x9341, 0x93d3, 0x93b2, 0x93a2, 0x943c, 0x94b2,
     98   1.1        pk 	0x953a, 0x9653, 0x9782, 0x9e21, 0x9d23, 0x9cd2, 0x9c23, 0x9baa,
     99   1.1        pk 	0x9bde, 0x9b33, 0x9b22, 0x9b1d, 0x9ab2, 0xa142, 0xa1e5, 0x9a3b,
    100   1.1        pk 	0xa213, 0xa1a2, 0xa231, 0xa2eb, 0xa313, 0xa334, 0xa421, 0xa54b,
    101   1.1        pk 	0xada4, 0xac23, 0xab3b, 0xaaab, 0xaa5c, 0xb1a3, 0xb2ca, 0xb3bd,
    102   1.1        pk 	0xbe24, 0xbb2b, 0xba33, 0xc32b, 0xcb5a, 0xd2a2, 0xe31d, 0x0808,
    103   1.1        pk 	0x72ba, 0x62c2, 0x5c32, 0x52db, 0x513e, 0x4cce, 0x43b2, 0x4243,
    104   1.1        pk 	0x41b4, 0x3b12, 0x3bc3, 0x3df2, 0x34bd, 0x3334, 0x32c2, 0x3224,
    105   1.1        pk 	0x31aa, 0x2a7b, 0x2aaa, 0x2b23, 0x2bba, 0x2c42, 0x2e23, 0x25bb,
    106   1.1        pk 	0x242b, 0x240f, 0x231a, 0x22bb, 0x2241, 0x2223, 0x221f, 0x1a33,
    107   1.1        pk 	0x1a4a, 0x1acd, 0x2132, 0x1b1b, 0x1b2c, 0x1b62, 0x1c12, 0x1c32,
    108   1.1        pk 	0x1d1b, 0x1e71, 0x16b1, 0x1522, 0x1434, 0x1412, 0x1352, 0x1323,
    109   1.1        pk 	0x1315, 0x12bc, 0x127a, 0x1235, 0x1226, 0x11a2, 0x1216, 0x0a2a,
    110   1.1        pk 	0x11bc, 0x11d1, 0x1163, 0x0ac2, 0x0ab2, 0x0aab, 0x0b1b, 0x0b23,
    111   1.1        pk 	0x0b33, 0x0c0f, 0x0bb3, 0x0c1b, 0x0c3e, 0x0cb1, 0x0d4c, 0x0ec1,
    112   1.1        pk 	0x079a, 0x0614, 0x0521, 0x047c, 0x0422, 0x03b1, 0x03e3, 0x0333,
    113   1.1        pk 	0x0322, 0x031c, 0x02aa, 0x02ba, 0x02f2, 0x0242, 0x0232, 0x0227,
    114   1.1        pk 	0x0222, 0x021b, 0x01ad, 0x0212, 0x01b2, 0x01bb, 0x01cb, 0x01f6,
    115   1.1        pk 	0x0152, 0x013a, 0x0133, 0x0131, 0x012c, 0x0123, 0x0122, 0x00a2,
    116   1.1        pk 	0x011b, 0x011e, 0x0114, 0x00b1, 0x00aa, 0x00b3, 0x00bd, 0x00ba,
    117   1.1        pk 	0x00c5, 0x00d3, 0x00f3, 0x0062, 0x0051, 0x0042, 0x003b, 0x0033,
    118   1.1        pk 	0x0032, 0x002a, 0x002c, 0x0025, 0x0023, 0x0022, 0x001a, 0x0021,
    119   1.1        pk 	0x001b, 0x001b, 0x001d, 0x0015, 0x0013, 0x0013, 0x0012, 0x0012,
    120   1.1        pk 	0x000a, 0x000a, 0x0011, 0x0011, 0x000b, 0x000b, 0x000c, 0x000e,
    121   1.1        pk };
    122   1.1        pk 
    123   1.1        pk /*
    124   1.1        pk  * second stage play gain.
    125   1.1        pk  */
    126   1.1        pk static const u_short ger_coeff[] = {
    127   1.1        pk 	0x431f, /* 5. dB */
    128   1.1        pk 	0x331f, /* 5.5 dB */
    129   1.1        pk 	0x40dd, /* 6. dB */
    130   1.1        pk 	0x11dd, /* 6.5 dB */
    131   1.1        pk 	0x440f, /* 7. dB */
    132   1.1        pk 	0x411f, /* 7.5 dB */
    133   1.1        pk 	0x311f, /* 8. dB */
    134   1.1        pk 	0x5520, /* 8.5 dB */
    135   1.1        pk 	0x10dd, /* 9. dB */
    136   1.1        pk 	0x4211, /* 9.5 dB */
    137   1.1        pk 	0x410f, /* 10. dB */
    138   1.1        pk 	0x111f, /* 10.5 dB */
    139   1.1        pk 	0x600b, /* 11. dB */
    140   1.1        pk 	0x00dd, /* 11.5 dB */
    141   1.1        pk 	0x4210, /* 12. dB */
    142   1.1        pk 	0x110f, /* 13. dB */
    143   1.1        pk 	0x7200, /* 14. dB */
    144   1.1        pk 	0x2110, /* 15. dB */
    145   1.1        pk 	0x2200, /* 15.9 dB */
    146   1.1        pk 	0x000b, /* 16.9 dB */
    147   1.1        pk 	0x000f  /* 18. dB */
    148   1.1        pk #define NGER (sizeof(ger_coeff) / sizeof(ger_coeff[0]))
    149   1.1        pk };
    150   1.1        pk 
    151   1.1        pk 
    152   1.1        pk /*
    153  1.39  jonathan  * Reset chip and set boot-time softc defaults.
    154   1.1        pk  */
    155   1.1        pk void
    156  1.39  jonathan am7930_init(sc)
    157  1.39  jonathan 	struct am7930_softc *sc;
    158  1.36        pk {
    159   1.1        pk 	sc->sc_map.mr_mmr1 = AMD_MMR1_GX | AMD_MMR1_GER |
    160   1.1        pk 			     AMD_MMR1_GR | AMD_MMR1_STG;
    161  1.39  jonathan 
    162   1.1        pk 	/* set boot defaults */
    163   1.1        pk 	sc->sc_rlevel = 128;
    164   1.1        pk 	sc->sc_plevel = 128;
    165   1.1        pk 	sc->sc_mlevel = 0;
    166   1.1        pk 	sc->sc_out_port = SUNAUDIO_SPEAKER;
    167  1.39  jonathan 	init_amd(sc->sc_amd);
    168   1.1        pk }
    169   1.1        pk 
    170   1.1        pk static void
    171   1.1        pk init_amd(amd)
    172  1.39  jonathan 	register volatile struct am7930 *amd;
    173   1.1        pk {
    174   1.1        pk 	/* disable interrupts */
    175   1.1        pk 	amd->cr = AMDR_INIT;
    176   1.1        pk 	amd->dr = AMD_INIT_PMS_ACTIVE | AMD_INIT_INT_DISABLE;
    177   1.1        pk 
    178   1.1        pk 	/*
    179   1.1        pk 	 * Initialize the mux unit.  We use MCR3 to route audio (MAP)
    180   1.1        pk 	 * through channel Bb.  MCR1 and MCR2 are unused.
    181   1.1        pk 	 * Setting the INT enable bit in MCR4 will generate an interrupt
    182   1.1        pk 	 * on each converted audio sample.
    183   1.1        pk 	 */
    184   1.1        pk 	amd->cr = AMDR_MUX_1_4;
    185   1.1        pk  	amd->dr = 0;
    186   1.1        pk 	amd->dr = 0;
    187   1.1        pk 	amd->dr = (AMD_MCRCHAN_BB << 4) | AMD_MCRCHAN_BA;
    188   1.1        pk 	amd->dr = AMD_MCR4_INT_ENABLE;
    189   1.1        pk }
    190   1.1        pk 
    191   1.1        pk int
    192  1.39  jonathan am7930_open(addr, flags)
    193  1.26  augustss 	void *addr;
    194   1.1        pk 	int flags;
    195   1.1        pk {
    196  1.39  jonathan 	struct am7930_softc *sc = addr;
    197   1.1        pk 
    198  1.26  augustss 	DPRINTF(("sa_open: unit %p\n", sc));
    199   1.1        pk 
    200   1.1        pk 	if (sc->sc_open)
    201   1.1        pk 		return (EBUSY);
    202   1.1        pk 	sc->sc_open = 1;
    203   1.1        pk 	sc->sc_locked = 0;
    204   1.1        pk 
    205  1.39  jonathan 	/* tell attach layer about open */
    206  1.39  jonathan 	sc->sc_onopen(sc);
    207   1.1        pk 
    208  1.40        pk 	DPRINTF(("saopen: ok -> sc=%p\n", sc));
    209   1.1        pk 
    210   1.1        pk 	return (0);
    211   1.1        pk }
    212   1.1        pk 
    213   1.1        pk void
    214  1.39  jonathan am7930_close(addr)
    215   1.1        pk 	void *addr;
    216   1.1        pk {
    217  1.39  jonathan 	register struct am7930_softc *sc = addr;
    218   1.1        pk 
    219  1.40        pk 	DPRINTF(("sa_close: sc=%p\n", sc));
    220   1.1        pk 	/*
    221   1.1        pk 	 * halt i/o, clear open flag, and done.
    222   1.1        pk 	 */
    223  1.39  jonathan 	sc->sc_onclose(sc);
    224   1.1        pk 	sc->sc_open = 0;
    225   1.1        pk 
    226   1.1        pk 	DPRINTF(("sa_close: closed.\n"));
    227   1.1        pk }
    228   1.1        pk 
    229   1.1        pk int
    230  1.39  jonathan am7930_set_params(addr, setmode, usemode, p, r)
    231   1.1        pk 	void *addr;
    232  1.28  augustss 	int setmode, usemode;
    233  1.28  augustss 	struct audio_params *p, *r;
    234   1.1        pk {
    235  1.18  augustss 	if (p->sample_rate < 7500 || p->sample_rate > 8500 ||
    236  1.18  augustss 	    p->encoding != AUDIO_ENCODING_ULAW ||
    237  1.18  augustss 	    p->precision != 8 ||
    238  1.18  augustss 	    p->channels != 1)
    239   1.1        pk 		return EINVAL;
    240  1.20  augustss 	p->sample_rate = 8000;	/* no other sampling rates supported by amd chip */
    241  1.20  augustss 
    242  1.20  augustss 	return 0;
    243   1.1        pk }
    244   1.1        pk 
    245   1.1        pk int
    246  1.39  jonathan am7930_query_encoding(addr, fp)
    247   1.1        pk 	void *addr;
    248   1.1        pk 	struct audio_encoding *fp;
    249   1.1        pk {
    250   1.1        pk 	switch (fp->index) {	/* ??? */
    251   1.1        pk 	    case 0:
    252  1.19  augustss 		    strcpy(fp->name, AudioEmulaw);
    253  1.19  augustss 		    fp->encoding = AUDIO_ENCODING_ULAW;
    254  1.19  augustss 		    fp->precision = 8;
    255  1.19  augustss 		    fp->flags = 0;
    256   1.1        pk 		    break;
    257   1.1        pk 	    default:
    258   1.1        pk 		    return(EINVAL);
    259   1.1        pk 		    /*NOTREACHED*/
    260   1.1        pk 	}
    261   1.1        pk 	return(0);
    262   1.1        pk }
    263   1.1        pk 
    264  1.39  jonathan 
    265   1.1        pk int
    266  1.39  jonathan am7930_round_blocksize(addr, blk)
    267   1.1        pk 	void *addr;
    268   1.1        pk 	int blk;
    269   1.1        pk {
    270   1.1        pk 	return(blk);
    271   1.1        pk }
    272   1.1        pk 
    273   1.1        pk int
    274  1.39  jonathan am7930_commit_settings(addr)
    275   1.1        pk 	void *addr;
    276   1.1        pk {
    277  1.39  jonathan 	register struct am7930_softc *sc = addr;
    278   1.1        pk 	register struct mapreg *map;
    279  1.39  jonathan 	register volatile struct am7930 *amd;
    280   1.1        pk 	register int s, level;
    281  1.10        pk 
    282   1.1        pk 	DPRINTF(("sa_commit.\n"));
    283   1.1        pk 
    284   1.1        pk 	map = &sc->sc_map;
    285  1.39  jonathan 	amd = sc->sc_amd;
    286   1.1        pk 
    287   1.1        pk 	map->mr_gx = gx_coeff[sc->sc_rlevel];
    288   1.1        pk 	map->mr_stgr = gx_coeff[sc->sc_mlevel];
    289  1.10        pk 
    290   1.1        pk 	level = (sc->sc_plevel * (256 + NGER)) >> 8;
    291   1.1        pk 	if (level >= 256) {
    292   1.1        pk 		map->mr_ger = ger_coeff[level - 256];
    293   1.1        pk 		map->mr_gr = gx_coeff[255];
    294   1.1        pk 	} else {
    295   1.1        pk 		map->mr_ger = ger_coeff[0];
    296   1.1        pk 		map->mr_gr = gx_coeff[level];
    297   1.1        pk 	}
    298   1.1        pk 
    299   1.1        pk 	if (sc->sc_out_port == SUNAUDIO_SPEAKER)
    300   1.1        pk 		map->mr_mmr2 |= AMD_MMR2_LS;
    301   1.1        pk 	else
    302   1.1        pk 		map->mr_mmr2 &= ~AMD_MMR2_LS;
    303  1.10        pk 
    304   1.1        pk 	s = splaudio();
    305  1.10        pk 
    306   1.1        pk 	amd->cr = AMDR_MAP_MMR1;
    307   1.1        pk 	amd->dr = map->mr_mmr1;
    308   1.1        pk 	amd->cr = AMDR_MAP_GX;
    309  1.39  jonathan 	WAMD16(sc, amd, map->mr_gx);
    310   1.1        pk 	amd->cr = AMDR_MAP_STG;
    311  1.39  jonathan 	WAMD16(sc, amd, map->mr_stgr);
    312   1.1        pk 	amd->cr = AMDR_MAP_GR;
    313  1.39  jonathan 	WAMD16(sc, amd, map->mr_gr);
    314   1.1        pk 	amd->cr = AMDR_MAP_GER;
    315  1.39  jonathan 	WAMD16(sc, amd, map->mr_ger);
    316   1.1        pk 	amd->cr = AMDR_MAP_MMR2;
    317   1.1        pk 	amd->dr = map->mr_mmr2;
    318   1.1        pk 
    319   1.1        pk 	splx(s);
    320   1.1        pk 	return(0);
    321   1.1        pk }
    322   1.1        pk 
    323   1.1        pk int
    324  1.39  jonathan am7930_halt_output(addr)
    325   1.1        pk 	void *addr;
    326   1.1        pk {
    327  1.39  jonathan 	register struct am7930_softc *sc = addr;
    328  1.39  jonathan 	register volatile struct am7930 *amd = sc->sc_amd;
    329   1.1        pk 
    330   1.1        pk 	/* XXX only halt, if input is also halted ?? */
    331   1.1        pk 	amd->cr = AMDR_INIT;
    332   1.1        pk 	amd->dr = AMD_INIT_PMS_ACTIVE | AMD_INIT_INT_DISABLE;
    333   1.1        pk 	sc->sc_locked = 0;
    334   1.1        pk 
    335   1.1        pk 	return(0);
    336   1.1        pk }
    337   1.1        pk 
    338   1.1        pk int
    339  1.39  jonathan am7930_halt_input(addr)
    340   1.1        pk 	void *addr;
    341   1.1        pk {
    342  1.39  jonathan 	register struct am7930_softc *sc = addr;
    343  1.39  jonathan 	register volatile struct am7930 *amd = sc->sc_amd;
    344   1.1        pk 
    345   1.1        pk 	/* XXX only halt, if output is also halted ?? */
    346   1.1        pk 	amd->cr = AMDR_INIT;
    347   1.1        pk 	amd->dr = AMD_INIT_PMS_ACTIVE | AMD_INIT_INT_DISABLE;
    348   1.1        pk 	sc->sc_locked = 0;
    349   1.1        pk 
    350   1.1        pk 	return(0);
    351   1.1        pk }
    352   1.1        pk 
    353   1.1        pk int
    354  1.39  jonathan am7930_getdev(addr, retp)
    355   1.1        pk         void *addr;
    356   1.1        pk         struct audio_device *retp;
    357   1.1        pk {
    358  1.39  jonathan         *retp = am7930_device;
    359   1.1        pk         return 0;
    360   1.1        pk }
    361   1.1        pk 
    362  1.26  augustss 
    363  1.39  jonathan /*
    364  1.39  jonathan  * XXX chip is full-duplex, but really attach-dependent.
    365  1.39  jonathan  * For now we know of no half-duplex attachments.
    366  1.39  jonathan  */
    367  1.26  augustss int
    368  1.39  jonathan am7930_get_props(addr)
    369  1.26  augustss 	void *addr;
    370  1.26  augustss {
    371  1.26  augustss 	return AUDIO_PROP_FULLDUPLEX;
    372   1.1        pk }
    373  1.39  jonathan #endif	/* NAUDIO */
    374