From e98c8eadc2a658a4599ac3c5b74fcca6f94420d5 Mon Sep 17 00:00:00 2001 From: Christopher Pascoe Date: Fri, 15 Apr 2005 01:05:52 +0000 Subject: Add basic audio playback support for the Zaurus SL-C3000. ok dlg@ drahn@ uwe@ deraadt@ --- sys/arch/zaurus/conf/GENERIC | 5 +- sys/arch/zaurus/conf/files.zaurus | 9 +- sys/arch/zaurus/dev/zaurus_audio.c | 679 ++++++++++++++++++++++++++++++++++ sys/arch/zaurus/dev/zaurus_scoop.c | 25 +- sys/arch/zaurus/dev/zaurus_scoopvar.h | 3 +- sys/dev/i2c/wm8750reg.h | 317 ++++++++++++++++ 6 files changed, 1033 insertions(+), 5 deletions(-) create mode 100644 sys/arch/zaurus/dev/zaurus_audio.c create mode 100644 sys/dev/i2c/wm8750reg.h (limited to 'sys') diff --git a/sys/arch/zaurus/conf/GENERIC b/sys/arch/zaurus/conf/GENERIC index bc0248518c4..eacbdf27b6b 100644 --- a/sys/arch/zaurus/conf/GENERIC +++ b/sys/arch/zaurus/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.32 2005/04/14 23:40:34 pascoe Exp $ +# $OpenBSD: GENERIC,v 1.33 2005/04/15 01:05:50 pascoe Exp $ # # GENERIC machine description file # @@ -148,7 +148,8 @@ com1 at pxaip? addr 0x40200000 intr 21 # BlueTooth UART options FFUARTCONSOLE #options BTUARTCONSOLE -#aupxa0 at pxaip? # AC97 interface +zaudio0 at pxaip? # Zaurus I2S/I2C sound +audio* at zaudio? # CF (pcmcia) support pxapcic0 at pxaip? diff --git a/sys/arch/zaurus/conf/files.zaurus b/sys/arch/zaurus/conf/files.zaurus index 51726538074..6813b3395e9 100644 --- a/sys/arch/zaurus/conf/files.zaurus +++ b/sys/arch/zaurus/conf/files.zaurus @@ -1,4 +1,4 @@ -# $OpenBSD: files.zaurus,v 1.15 2005/01/28 17:14:31 drahn Exp $ +# $OpenBSD: files.zaurus,v 1.16 2005/04/15 01:05:50 pascoe Exp $ # # First try for arm-specific configuration info # @@ -52,6 +52,13 @@ device zts: wsmousedev attach zts at pxaip file arch/zaurus/dev/zts.c zts +# Zaurus sound +device zaudio: audio +attach zaudio at pxaip +file arch/zaurus/dev/zaurus_audio.c zaudio +file arch/arm/xscale/pxa2x0_i2s.c zaudio +file arch/arm/xscale/pxa2x0_i2c.c zaudio + # # Machine-independent ATA drivers # diff --git a/sys/arch/zaurus/dev/zaurus_audio.c b/sys/arch/zaurus/dev/zaurus_audio.c new file mode 100644 index 00000000000..478e6990976 --- /dev/null +++ b/sys/arch/zaurus/dev/zaurus_audio.c @@ -0,0 +1,679 @@ +/* $OpenBSD: zaurus_audio.c,v 1.1 2005/04/15 01:05:51 pascoe Exp $ */ + +/* + * Copyright (c) 2005 Christopher Pascoe + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#define WM8750_ADDRESS 0x1B +#define SPKR_VOLUME 112 + +#define wm8750_write(sc, reg, val) pxa2x0_i2c_write_2(&sc->sc_i2c, \ + WM8750_ADDRESS, (((reg) << 9) | ((val) & 0x1ff))) + +int zaudio_match(struct device *, void *, void *); +void zaudio_attach(struct device *, struct device *, void *); +int zaudio_detach(struct device *, int); +void zaudio_power(int, void *); + +struct zaudio_softc { + struct device sc_dev; + + /* i2s device softc */ + /* NB: pxa2x0_i2s requires this to be the second struct member */ + struct pxa2x0_i2s_softc sc_i2s; + + /* i2c device softc */ + struct pxa2x0_i2c_softc sc_i2c; + + void *sc_powerhook; + int sc_playing; +}; + +struct cfattach zaudio_ca = { + sizeof(struct zaudio_softc), zaudio_match, zaudio_attach, + zaudio_detach +}; + +struct cfdriver zaudio_cd = { + NULL, "zaudio", DV_DULL +}; + +struct audio_device wm8750_device = { + "WM8750", + "1.0", + "wm" +}; + +void zaudio_init(struct zaudio_softc *); +void zaudio_standby(struct zaudio_softc *); +void zaudio_play_setup(struct zaudio_softc *); +int zaudio_open(void *, int); +void zaudio_close(void *); +int zaudio_query_encoding(void *, struct audio_encoding *); +int zaudio_set_params(void *, int, int, struct audio_params *, + struct audio_params *); +int zaudio_halt_output(void *); +int zaudio_halt_input(void *); +int zaudio_getdev(void *, struct audio_device *); +int zaudio_set_port(void *, struct mixer_ctrl *); +int zaudio_get_port(void *, struct mixer_ctrl *); +int zaudio_query_devinfo(void *, struct mixer_devinfo *); +int zaudio_get_props(void *); +int zaudio_start_output(void *, void *, int, void (*)(void *), void *); +int zaudio_start_input(void *, void *, int, void (*)(void *), void *); + +struct audio_hw_if wm8750_hw_if = { + zaudio_open, + zaudio_close, + NULL /* zaudio_drain */, + zaudio_query_encoding, + zaudio_set_params, + pxa2x0_i2s_round_blocksize, + NULL /* zaudio_commit_settings */, + NULL /* zaudio_init_output */, + NULL /* zaudio_init_input */, + zaudio_start_output, + zaudio_start_input, + zaudio_halt_output, + zaudio_halt_input, + NULL /* zaudio_speaker_ctl */, + zaudio_getdev, + NULL /* zaudio_setfd */, + zaudio_set_port, + zaudio_get_port, + zaudio_query_devinfo, + pxa2x0_i2s_allocm, + pxa2x0_i2s_freem, + pxa2x0_i2s_round_buffersize, + pxa2x0_i2s_mappage, + zaudio_get_props, + NULL /* zaudio_trigger_output */, + NULL /* zaudio_trigger_input */ +}; + +static const unsigned short playback_registers[][2] = { + /* Unmute DAC */ + { ADCDACCTL_REG, 0x000 }, + + /* 16 bit audio words */ + { AUDINT_REG, AUDINT_SET_FORMAT(2) }, + + /* Enable thermal protection, power */ + { ADCTL1_REG, ADCTL1_TSDEN | ADCTL1_SET_VSEL(3) }, + + /* Enable speaker driver, DAC oversampling */ + { ADCTL2_REG, ADCTL2_ROUT2INV | ADCTL2_DACOSR }, + + /* Set DAC voltage references */ + { PWRMGMT1_REG, PWRMGMT1_SET_VMIDSEL(1) | PWRMGMT1_VREF }, + + /* Power DACs and outputs */ + { PWRMGMT2_REG, PWRMGMT2_DACL | PWRMGMT2_DACR | PWRMGMT2_LOUT1 | + PWRMGMT2_ROUT1 | PWRMGMT2_LOUT2 | PWRMGMT2_ROUT2 }, + + /* Set left/right channel mix mixer */ + { LOUTMIX1_REG, LOUTMIX1_LD2LO | LOUTMIX1_SET_LI2LOVOL(5) }, + { ROUTMIX2_REG, ROUTMIX2_RD2RO | ROUTMIX2_SET_RI2ROVOL(5) }, + + /* Set speaker volume */ + { LOUT2VOL_REG, LOUT2VOL_LO2VU | LOUT2VOL_SET_LOUT2VOL(SPKR_VOLUME) }, + { ROUT2VOL_REG, ROUT2VOL_RO2VU | ROUT2VOL_SET_ROUT2VOL(0) }, + + /* End of list */ + { 0xffff, 0xffff } +}; + +int +zaudio_match(struct device *parent, void *match, void *aux) +{ + return (1); +} + +void +zaudio_attach(struct device *parent, struct device *self, void *aux) +{ + struct zaudio_softc *sc = (struct zaudio_softc *)self; + struct pxaip_attach_args *pxa = aux; + + sc->sc_powerhook = powerhook_establish(zaudio_power, sc); + if (sc->sc_powerhook == NULL) { + printf(": unable to establish powerhook\n"); + return; + } + + sc->sc_i2s.sc_iot = pxa->pxa_iot; + sc->sc_i2s.sc_dmat = pxa->pxa_dmat; + sc->sc_i2s.sc_size = PXA2X0_I2S_SIZE; + if (pxa2x0_i2s_attach_sub(&sc->sc_i2s)) { + printf(": unable to attach I2S\n"); + goto fail_i2s; + } + + sc->sc_i2c.sc_iot = pxa->pxa_iot; + sc->sc_i2c.sc_size = PXA2X0_I2C_SIZE; + if (pxa2x0_i2c_attach_sub(&sc->sc_i2c)) { + printf(": unable to attach I2C\n"); + goto fail_i2c; + } + + /* Check for an I2C response from the wm8750 */ + pxa2x0_i2s_open(&sc->sc_i2s); /* supply the codec with a clock */ + pxa2x0_i2c_open(&sc->sc_i2c); + + if (wm8750_write(sc, RESET_REG, 0)) { + printf(": codec failed to respond\n"); + goto fail_probe; + } + delay(100); + + zaudio_init(sc); + + pxa2x0_i2c_close(&sc->sc_i2c); + pxa2x0_i2s_close(&sc->sc_i2s); + + printf(": I2C, I2S, WM8750 Audio\n"); + + audio_attach_mi(&wm8750_hw_if, sc, &sc->sc_dev); + + return; + +fail_probe: + pxa2x0_i2c_close(&sc->sc_i2c); + pxa2x0_i2s_close(&sc->sc_i2s); + pxa2x0_i2c_detach_sub(&sc->sc_i2c); +fail_i2c: + pxa2x0_i2s_detach_sub(&sc->sc_i2s); +fail_i2s: + powerhook_disestablish(sc->sc_powerhook); +} + +int +zaudio_detach(struct device *self, int flags) +{ + struct zaudio_softc *sc = (struct zaudio_softc *)self; + + if (sc->sc_powerhook != NULL) { + powerhook_disestablish(sc->sc_powerhook); + sc->sc_powerhook = NULL; + } + + pxa2x0_i2c_detach_sub(&sc->sc_i2c); + pxa2x0_i2s_detach_sub(&sc->sc_i2s); + + return (0); +} + +void +zaudio_power(int why, void *arg) +{ + /* XXX */ + return; +} + +void +zaudio_init(struct zaudio_softc *sc) +{ + /* Reset the codec */ + wm8750_write(sc, RESET_REG, 0); + delay(100); + + /* Switch to standby power only */ + wm8750_write(sc, PWRMGMT1_REG, PWRMGMT1_SET_VMIDSEL(2)); + wm8750_write(sc, PWRMGMT2_REG, 0); + + /* Configure digital interface for I2S */ + wm8750_write(sc, AUDINT_REG, AUDINT_SET_FORMAT(2)); +} + +void +zaudio_standby(struct zaudio_softc *sc) +{ + /* Switch codec to standby power only */ + wm8750_write(sc, PWRMGMT1_REG, PWRMGMT1_SET_VMIDSEL(2)); + wm8750_write(sc, PWRMGMT2_REG, 0); +} + +void +zaudio_play_setup(struct zaudio_softc *sc) +{ + int i = 0; + + pxa2x0_i2c_open(&sc->sc_i2c); + + /* Program the codec with playback settings */ + while (playback_registers[i][0] != 0xffff) { + wm8750_write(sc, playback_registers[i][0], + playback_registers[i][1]); + i++; + } + + pxa2x0_i2c_close(&sc->sc_i2c); +} + +int +zaudio_open(void *hdl, int flags) +{ + struct zaudio_softc *sc = hdl; + + /* Power on the I2S bus and codec */ + pxa2x0_i2s_open(&sc->sc_i2s); + scoop_audio_set(1); + + return 0; +} + +void +zaudio_close(void *hdl) +{ + struct zaudio_softc *sc = hdl; + + /* Power off the I2S bus and codec */ + pxa2x0_i2s_close(&sc->sc_i2s); + scoop_audio_set(0); +} + +int +zaudio_query_encoding(void *hdl, struct audio_encoding *aep) +{ + switch (aep->index) { + case 0: + strlcpy(aep->name, AudioEulinear, sizeof(aep->name)); + aep->encoding = AUDIO_ENCODING_ULINEAR; + aep->precision = 8; + aep->flags = 0; + return (0); + case 1: + strlcpy(aep->name, AudioEmulaw, sizeof(aep->name)); + aep->encoding = AUDIO_ENCODING_ULAW; + aep->precision = 8; + aep->flags = AUDIO_ENCODINGFLAG_EMULATED; + return (0); + case 2: + strlcpy(aep->name, AudioEalaw, sizeof(aep->name)); + aep->encoding = AUDIO_ENCODING_ALAW; + aep->precision = 8; + aep->flags = AUDIO_ENCODINGFLAG_EMULATED; + return (0); + case 3: + strlcpy(aep->name, AudioEslinear, sizeof(aep->name)); + aep->encoding = AUDIO_ENCODING_SLINEAR; + aep->precision = 8; + aep->flags = AUDIO_ENCODINGFLAG_EMULATED; + return (0); + case 4: + strlcpy(aep->name, AudioEslinear_le, sizeof(aep->name)); + aep->encoding = AUDIO_ENCODING_SLINEAR_LE; + aep->precision = 16; + aep->flags = 0; + return (0); + case 5: + strlcpy(aep->name, AudioEulinear_le, sizeof(aep->name)); + aep->encoding = AUDIO_ENCODING_ULINEAR_LE; + aep->precision = 16; + aep->flags = AUDIO_ENCODINGFLAG_EMULATED; + return (0); + case 6: + strlcpy(aep->name, AudioEslinear_be, sizeof(aep->name)); + aep->encoding = AUDIO_ENCODING_SLINEAR_BE; + aep->precision = 16; + aep->flags = AUDIO_ENCODINGFLAG_EMULATED; + return (0); + case 7: + strlcpy(aep->name, AudioEulinear_be, sizeof(aep->name)); + aep->encoding = AUDIO_ENCODING_ULINEAR_BE; + aep->precision = 16; + aep->flags = AUDIO_ENCODINGFLAG_EMULATED; + return (0); + default: + return (EINVAL); + } +} + +int +zaudio_set_params(void *hdl, int setmode, int usemode, + struct audio_params *play, struct audio_params *rec) +{ + struct zaudio_softc *sc = hdl; + + if (setmode & AUMODE_PLAY) { + play->factor = 1; + play->sw_code = NULL; + switch(play->encoding) { + case AUDIO_ENCODING_ULAW: + switch (play->channels) { + case 1: + play->factor = 4; + play->sw_code = mulaw_to_slinear16_mts; + break; + case 2: + play->factor = 2; + play->sw_code = mulaw_to_slinear16; + break; + default: + return (EINVAL); + } + break; + case AUDIO_ENCODING_SLINEAR_LE: + switch (play->precision) { + case 8: + switch (play->channels) { + case 1: + play->factor = 4; + play->sw_code = linear8_to_linear16_mts; + break; + case 2: + play->factor = 2; + play->sw_code = linear8_to_linear16; + break; + default: + return (EINVAL); + } + break; + case 16: + switch (play->channels) { + case 1: + play->factor = 2; + play->sw_code = noswap_bytes_mts; + break; + case 2: + break; + default: + return (EINVAL); + } + break; + default: + return (EINVAL); + } + break; + case AUDIO_ENCODING_ULINEAR_LE: + switch (play->precision) { + case 8: + switch (play->channels) { + case 1: + play->factor = 4; + play->sw_code = + ulinear8_to_linear16_mts; + break; + case 2: + play->factor = 2; + play->sw_code = ulinear8_to_linear16; + break; + default: + return (EINVAL); + } + break; + case 16: + switch (play->channels) { + case 1: + play->factor = 2; + play->sw_code = change_sign16_mts; + break; + case 2: + play->sw_code = change_sign16; + break; + default: + return (EINVAL); + } + break; + default: + return (EINVAL); + } + break; + case AUDIO_ENCODING_ALAW: + switch (play->channels) { + case 1: + play->factor = 4; + play->sw_code = alaw_to_slinear16_mts; + case 2: + play->factor = 2; + play->sw_code = alaw_to_slinear16; + default: + return (EINVAL); + } + break; + case AUDIO_ENCODING_SLINEAR_BE: + switch (play->precision) { + case 8: + switch (play->channels) { + case 1: + play->factor = 4; + play->sw_code = + linear8_to_linear16_mts; + break; + case 2: + play->factor = 2; + play->sw_code = linear8_to_linear16; + break; + default: + return (EINVAL); + } + break; + case 16: + switch (play->channels) { + case 1: + play->factor = 2; + play->sw_code = swap_bytes_mts; + break; + case 2: + play->sw_code = swap_bytes; + break; + default: + return (EINVAL); + } + break; + default: + return (EINVAL); + } + break; + case AUDIO_ENCODING_ULINEAR_BE: + switch (play->precision) { + case 8: + switch (play->channels) { + case 1: + play->factor = 4; + play->sw_code = + ulinear8_to_linear16_mts; + break; + case 2: + play->factor = 2; + play->sw_code = ulinear8_to_linear16; + break; + default: + return (EINVAL); + } + break; + case 16: + switch (play->channels) { + case 1: + play->factor = 2; + play->sw_code = + change_sign16_swap_bytes_mts; + break; + case 2: + play->sw_code = + change_sign16_swap_bytes; + break; + default: + return (EINVAL); + } + break; + default: + return (EINVAL); + } + break; + default: + return (EINVAL); + } + + pxa2x0_i2s_setspeed(&sc->sc_i2s, &play->sample_rate); + } + +#if RECORD_XXX_NOT_YET + if (setmode & AUMODE_RECORD) { + rec->factor = 1; + rec->sw_code = NULL; + switch(rec->encoding) { + case AUDIO_ENCODING_ULAW: + rec->sw_code = ulinear8_to_mulaw; + break; + case AUDIO_ENCODING_SLINEAR_LE: + if (rec->precision == 8) + rec->sw_code = change_sign8; + break; + case AUDIO_ENCODING_ULINEAR_LE: + if (rec->precision == 16) + rec->sw_code = change_sign16; + break; + case AUDIO_ENCODING_ALAW: + rec->sw_code = ulinear8_to_alaw; + break; + case AUDIO_ENCODING_SLINEAR_BE: + if (rec->precision == 16) + rec->sw_code = swap_bytes; + else + rec->sw_code = change_sign8; + break; + case AUDIO_ENCODING_ULINEAR_BE: + if (rec->precision == 16) + rec->sw_code = swap_bytes_change_sign16; + break; + default: + return (EINVAL); + } + + pxa2x0_i2s_setspeed(sc, &rec->sample_rate); + } +#endif + + return (0); +} + +int +zaudio_halt_output(void *hdl) +{ + struct zaudio_softc *sc = hdl; + + /* XXX forcibly stop output DMA? */ + + pxa2x0_i2c_open(&sc->sc_i2c); + + zaudio_standby(sc); + sc->sc_playing = 0; + + pxa2x0_i2c_close(&sc->sc_i2c); + + return 0; +} + +int +zaudio_halt_input(void *hdl) +{ + /* struct zaudio_softc *sc = hdl; */ + + return 0; +} + +int +zaudio_getdev(void *hdl, struct audio_device *ret) +{ + /* struct zaudio_softc *sc = hdl; */ + + *ret = wm8750_device; + return 0; +} + +int +zaudio_set_port(void *hdl, struct mixer_ctrl *mc) +{ + /* struct zaudio_softc *sc = hdl; */ + + return 0; +} + +int +zaudio_get_port(void *hdl, struct mixer_ctrl *mc) +{ + /* struct zaudio_softc *sc = hdl; */ + + return 0; +} + +int +zaudio_query_devinfo(void *hdl, struct mixer_devinfo *di) +{ + /* struct zaudio_softc *sc = hdl; */ + + di->prev = di->next = AUDIO_MIXER_LAST; + + return ENXIO; +} + +int +zaudio_get_props(void *hdl) +{ + return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX; +} + +int +zaudio_start_output(void *hdl, void *block, int bsize, void (*intr)(void *), + void *intrarg) +{ + struct zaudio_softc *sc = hdl; + int err; + + /* Power up codec if we are not already playing. */ + if (!sc->sc_playing) { + sc->sc_playing = 1; + zaudio_play_setup(sc); + } + + /* Start DMA via I2S */ + err = pxa2x0_i2s_start_output(&sc->sc_i2s, block, bsize, intr, intrarg); + if (err) { + zaudio_standby(sc); + sc->sc_playing = 0; + } + return err; +} + +int +zaudio_start_input(void *hdl, void *block, int bsize, void (*intr)(void *), + void *intrarg) +{ + return ENXIO; +} diff --git a/sys/arch/zaurus/dev/zaurus_scoop.c b/sys/arch/zaurus/dev/zaurus_scoop.c index b741464aa33..e46e28e93a1 100644 --- a/sys/arch/zaurus/dev/zaurus_scoop.c +++ b/sys/arch/zaurus/dev/zaurus_scoop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: zaurus_scoop.c,v 1.7 2005/03/08 23:29:06 uwe Exp $ */ +/* $OpenBSD: zaurus_scoop.c,v 1.8 2005/04/15 01:05:51 pascoe Exp $ */ /* * Copyright (c) 2005 Uwe Stuehler @@ -165,6 +165,29 @@ scoop_led_set(int led, int on) } } +void +scoop_audio_set(int on) +{ + if (scoop_cd.cd_ndevs < 1 || scoop_cd.cd_devs[0] == NULL) + return; + + if (on) { + scoop_gpio_pin_ctl(scoop_cd.cd_devs[0], SCOOP0_MUTE_L, + GPIO_PIN_OUTPUT); + scoop_gpio_pin_ctl(scoop_cd.cd_devs[0], SCOOP0_MUTE_R, + GPIO_PIN_OUTPUT); + scoop_gpio_pin_write(scoop_cd.cd_devs[0], SCOOP0_MUTE_L, + GPIO_PIN_LOW); + scoop_gpio_pin_write(scoop_cd.cd_devs[0], SCOOP0_MUTE_R, + GPIO_PIN_LOW); + } else { + scoop_gpio_pin_write(scoop_cd.cd_devs[0], SCOOP0_MUTE_L, + GPIO_PIN_HIGH); + scoop_gpio_pin_write(scoop_cd.cd_devs[0], SCOOP0_MUTE_R, + GPIO_PIN_HIGH); + } +} + void scoop_battery_temp_adc(int enable) { diff --git a/sys/arch/zaurus/dev/zaurus_scoopvar.h b/sys/arch/zaurus/dev/zaurus_scoopvar.h index 31307a16142..20c02284a49 100644 --- a/sys/arch/zaurus/dev/zaurus_scoopvar.h +++ b/sys/arch/zaurus/dev/zaurus_scoopvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: zaurus_scoopvar.h,v 1.6 2005/02/22 21:53:03 uwe Exp $ */ +/* $OpenBSD: zaurus_scoopvar.h,v 1.7 2005/04/15 01:05:51 pascoe Exp $ */ /* * Copyright (c) 2005 Uwe Stuehler @@ -25,5 +25,6 @@ void scoop_battery_temp_adc(int); void scoop_charge_battery(int, int); void scoop_discharge_battery(int); void scoop_check_mcr(void); +void scoop_audio_set(int); void scoop_suspend(void); void scoop_resume(void); diff --git a/sys/dev/i2c/wm8750reg.h b/sys/dev/i2c/wm8750reg.h new file mode 100644 index 00000000000..1d786964e98 --- /dev/null +++ b/sys/dev/i2c/wm8750reg.h @@ -0,0 +1,317 @@ +/* $OpenBSD: wm8750reg.h,v 1.1 2005/04/15 01:05:51 pascoe Exp $ */ + +/* + * Copyright (c) 2005 Christopher Pascoe + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Wolfson Microelectronics' WM8750 I2C/I2S audio codec: + * - I2C register definitions. Used in the Sharp Zaurus SL-C3000. + */ + +#define LINVOL_REG 0x00 /* Left Input volume */ +#define LINVOL_LIVU 0x100 +#define LINVOL_LINMUTE 0x80 +#define LINVOL_LIZC 0x40 +#define LINVOL_LINVOL_MASK 0x3F +#define LINVOL_GET_LINVOL(x) ((x) & 0x3F) +#define LINVOL_SET_LINVOL(x) (x) + +#define RINVOL_REG 0x01 /* Right Input volume */ +#define RINVOL_RIVU 0x100 +#define RINVOL_RINMUTE 0x80 +#define RINVOL_RIZC 0x40 +#define RINVOL_RINVOL_MASK 0x3F +#define RINVOL_GET_RINVOL(x) ((x) & 0x3F) +#define RINVOL_SET_RINVOL(x) (x) + +#define LOUT1VOL_REG 0x02 /* LOUT1 volume */ +#define LOUT1VOL_LO1VU 0x100 +#define LOUT1VOL_LO1ZC 0x80 +#define LOUT1VOL_LOUT1VOL_MASK 0x7F +#define LOUT1VOL_GET_LOUT1VOL(x) ((x) & 0x7F) +#define LOUT1VOL_SET_LOUT1VOL(x) (x) + +#define ROUT1VOL_REG 0x03 /* ROUT1 volume */ +#define ROUT1VOL_RO1VU 0x100 +#define ROUT1VOL_RO1ZC 0x80 +#define ROUT1VOL_ROUT1VOL_MASK 0x7F +#define ROUT1VOL_GET_ROUT1VOL(x) ((x) & 0x7F) +#define ROUT1VOL_SET_ROUT1VOL(x) (x) + +#define ADCDACCTL_REG 0x05 /* ADC & DAC Control */ +#define ADCDACCTL_ADCDIV2 0x100 +#define ADCDACCTL_DACDIV2 0x80 +#define ADCDACCTL_ADCPOL_MASK 0x60 +#define ADCDACCTL_GET_ADCPOL(x) (((x) >> 5) & 0x60) +#define ADCDACCTL_SET_ADCPOL(x) ((x) << 5) +#define ADCDACCTL_HPOR 0x10 +#define ADCDACCTL_DACMU 0x8 +#define ADCDACCTL_DEEMPH_MASK 0x6 +#define ADCDACCTL_GET_DEEMPH(x) (((x) >> 1) & 0x6) +#define ADCDACCTL_SET_DEEMPH(x) ((x) << 1) +#define ADCDACCTL_ADCHPD 0x1 + +#define AUDINT_REG 0x07 /* Audio Interface */ +#define AUDINT_BCLKINV 0x80 +#define AUDINT_MS 0x40 +#define AUDINT_LRSWAP 0x20 +#define AUDINT_LRP 0x10 +#define AUDINT_WL_MASK 0xC +#define AUDINT_GET_WL(x) (((x) >> 2) & 0xC) +#define AUDINT_SET_WL(x) ((x) << 2) +#define AUDINT_FORMAT_MASK 0x3 +#define AUDINT_GET_FORMAT(x) ((x) & 0x3) +#define AUDINT_SET_FORMAT(x) (x) + +#define SRATE_REG 0x08 /* Sample rate */ +#define SRATE_BCM_MASK 0x180 +#define SRATE_GET_BCM(x) (((x) >> 7) & 0x180) +#define SRATE_SET_BCM(x) ((x) << 7) +#define SRATE_CLKDIV2 0x40 +#define SRATE_SR_MASK 0x3E +#define SRATE_GET_SR(x) (((x) >> 1) & 0x3E) +#define SRATE_SET_SR(x) ((x) << 1) +#define SRATE_USB 0x1 + +#define LDACVOL_REG 0x0A /* Left DAC volume */ +#define LDACVOL_LDVU 0x100 +#define LDACVOL_LDACVOL_MASK 0xFF +#define LDACVOL_GET_LDACVOL(x) ((x) & 0xFF) +#define LDACVOL_SET_LDACVOL(x) (x) + +#define RDACVOL_REG 0x0B /* Right DAC volume */ +#define RDACVOL_RDVU 0x100 +#define RDACVOL_RDACVOL_MASK 0xFF +#define RDACVOL_GET_RDACVOL(x) ((x) & 0xFF) +#define RDACVOL_SET_RDACVOL(x) (x) + +#define BASSCTL_REG 0x0C /* Bass control */ +#define BASSCTL_BB 0x80 +#define BASSCTL_BC 0x40 +#define BASSCTL_BASS_MASK 0xF +#define BASSCTL_GET_BASS(x) ((x) & 0xF) +#define BASSCTL_SET_BASS(x) (x) + +#define TREBCTL_REG 0x0D /* Treble control */ +#define TREBCTL_TC 0x40 +#define TREBCTL_TRBL_MASK 0xF +#define TREBCTL_GET_TRBL(x) ((x) & 0xF) +#define TREBCTL_SET_TRBL(x) (x) + +#define RESET_REG 0x0F /* Reset */ + +#define C3DCTL_REG 0x10 /* 3D control */ +#define C3DCTL_MODE3D 0x80 +#define C3DCTL_3DUC 0x40 +#define C3DCTL_3DLC 0x20 +#define C3DCTL_3DDEPTH_MASK 0x1E +#define C3DCTL_GET_3DDEPTH(x) (((x) >> 1) & 0x1E) +#define C3DCTL_SET_3DDEPTH(x) ((x) << 1) +#define C3DCTL_3DEN 0x1 + +#define ALC1_REG 0x11 /* ALC1 */ +#define ALC1_ALCSEL_MASK 0x180 +#define ALC1_GET_ALCSEL(x) (((x) >> 7) & 0x180) +#define ALC1_SET_ALCSEL(x) ((x) << 7) +#define ALC1_MAXGAIN_MASK 0x70 +#define ALC1_GET_MAXGAIN(x) (((x) >> 4) & 0x70) +#define ALC1_SET_MAXGAIN(x) ((x) << 4) +#define ALC1_ALCL_MASK 0xF +#define ALC1_GET_ALCL(x) ((x) & 0xF) +#define ALC1_SET_ALCL(x) (x) + +#define ALC2_REG 0x12 /* ALC2 */ +#define ALC2_ALCZC 0x80 +#define ALC2_HLD_MASK 0xF +#define ALC2_GET_HLD(x) ((x) & 0xF) +#define ALC2_SET_HLD(x) (x) + +#define ALC3_REG 0x13 /* ALC3 */ +#define ALC3_DCY_MASK 0xF0 +#define ALC3_GET_DCY(x) (((x) >> 4) & 0xF0) +#define ALC3_SET_DCY(x) ((x) << 4) +#define ALC3_ATK_MASK 0xF +#define ALC3_GET_ATK(x) ((x) & 0xF) +#define ALC3_SET_ATK(x) (x) + +#define NOISEGATE_REG 0x14 /* Noise Gate */ +#define NOISEGATE_NGTH_MASK 0xF8 +#define NOISEGATE_GET_NGTH(x) (((x) >> 3) & 0xF8) +#define NOISEGATE_SET_NGTH(x) ((x) << 3) +#define NOISEGATE_NGG_MASK 0x6 +#define NOISEGATE_GET_NGG(x) (((x) >> 1) & 0x6) +#define NOISEGATE_SET_NGG(x) ((x) << 1) +#define NOISEGATE_NGAT 0x1 + +#define LADCVOL_REG 0x15 /* Left ADC volume */ +#define LADCVOL_LAVU 0x100 +#define LADCVOL_LADCVOL_MASK 0xFF +#define LADCVOL_GET_LADCVOL(x) ((x) & 0xFF) +#define LADCVOL_SET_LADCVOL(x) (x) + +#define RADCVOL_REG 0x16 /* Right ADC volume */ +#define RADCVOL_RAVU 0x100 +#define RADCVOL_RADCVOL_MASK 0xFF +#define RADCVOL_GET_RADCVOL(x) ((x) & 0xFF) +#define RADCVOL_SET_RADCVOL(x) (x) + +#define ADCTL1_REG 0x17 /* Additional control(1) */ +#define ADCTL1_TSDEN 0x100 +#define ADCTL1_VSEL_MASK 0xC0 +#define ADCTL1_GET_VSEL(x) (((x) >> 6) & 0xC0) +#define ADCTL1_SET_VSEL(x) ((x) << 6) +#define ADCTL1_DMONOMIX_MASK 0x30 +#define ADCTL1_GET_DMONOMIX(x) (((x) >> 4) & 0x30) +#define ADCTL1_SET_DMONOMIX(x) ((x) << 4) +#define ADCTL1_DATSEL_MASK 0xC +#define ADCTL1_GET_DATSEL(x) (((x) >> 2) & 0xC) +#define ADCTL1_SET_DATSEL(x) ((x) << 2) +#define ADCTL1_DACINV 0x2 +#define ADCTL1_TOEN 0x1 + +#define ADCTL2_REG 0x18 /* Additional control(2) */ +#define ADCTL2_OUTSW3_MASK 0x180 +#define ADCTL2_GET_OUTSW3(x) (((x) >> 7) & 0x180) +#define ADCTL2_SET_OUTSW3(x) ((x) << 7) +#define ADCTL2_HPSWEN 0x40 +#define ADCTL2_HPSWPOL 0x20 +#define ADCTL2_ROUT2INV 0x10 +#define ADCTL2_TRI 0x08 +#define ADCTL2_LRCM 0x04 +#define ADCTL2_ADCOSR 0x02 +#define ADCTL2_DACOSR 0x01 + +#define PWRMGMT1_REG 0x19 /* Pwr Mgmt (1) */ +#define PWRMGMT1_VMIDSEL_MASK 0x180 +#define PWRMGMT1_GET_VMIDSEL(x) (((x) >> 7) & 0x180) +#define PWRMGMT1_SET_VMIDSEL(x) ((x) << 7) +#define PWRMGMT1_VREF 0x40 +#define PWRMGMT1_AINL 0x20 +#define PWRMGMT1_AINR 0x10 +#define PWRMGMT1_ADCL 0x8 +#define PWRMGMT1_ADCR 0x4 +#define PWRMGMT1_MICB 0x2 +#define PWRMGMT1_DIGENB 0x1 + +#define PWRMGMT2_REG 0x1A /* Pwr Mgmt (2) */ +#define PWRMGMT2_DACL 0x100 +#define PWRMGMT2_DACR 0x80 +#define PWRMGMT2_LOUT1 0x40 +#define PWRMGMT2_ROUT1 0x20 +#define PWRMGMT2_LOUT2 0x10 +#define PWRMGMT2_ROUT2 0x8 +#define PWRMGMT2_MONO 0x4 +#define PWRMGMT2_OUT3 0x2 + +#define ADCTL3_REG 0x1B /* Additional Control (3) */ +#define ADCTL3_ADCLRM_MASK 0x180 +#define ADCTL3_GET_ADCLRM(x) (((x) >> 7) & 0x180) +#define ADCTL3_SET_ADCLRM(x) ((x) << 7) +#define ADCTL3_VROI 0x40 +#define ADCTL3_HPFLREN 0x20 + +#define ADCINPMODE_REG 0x1F /* ADC input mode */ +#define ADCINPMODE_DS 0x100 +#define ADCINPMODE_MONOMIX_MASK 0xC0 +#define ADCINPMODE_GET_MONOMIX(x) (((x) >> 6) & 0xC0) +#define ADCINPMODE_SET_MONOMIX(x) ((x) << 6) +#define ADCINPMODE_RDCM 0x20 +#define ADCINPMODE_LDCM 0x10 + +#define ADCLSPATH_REG 0x20 /* ADCL signal path */ +#define ADCLSPATH_LINSEL_MASK 0xC0 +#define ADCLSPATH_GET_LINSEL(x) (((x) >> 6) & 0xC0) +#define ADCLSPATH_SET_LINSEL(x) ((x) << 6) +#define ADCLSPATH_LMICBOOST_MASK 0x30 +#define ADCLSPATH_GET_LMICBOOST(x) (((x) >> 4) & 0x30) +#define ADCLSPATH_SET_LMICBOOST(x) ((x) << 4) + +#define ADCRSPATH_REG 0x21 /* ADCR signal path */ +#define ADCRSPATH_RINSEL_MASK 0xC0 +#define ADCRSPATH_GET_RINSEL(x) (((x) >> 6) & 0xC0) +#define ADCRSPATH_SET_RINSEL(x) ((x) << 6) +#define ADCRSPATH_RMICBOOST_MASK 0x30 +#define ADCRSPATH_GET_RMICBOOST(x) (((x) >> 4) & 0x30) +#define ADCRSPATH_SET_RMICBOOST(x) ((x) << 4) + +#define LOUTMIX1_REG 0x22 /* Left out Mix (1) */ +#define LOUTMIX1_LD2LO 0x100 +#define LOUTMIX1_LI2LO 0x80 +#define LOUTMIX1_LI2LOVOL_MASK 0x70 +#define LOUTMIX1_GET_LI2LOVOL(x) (((x) >> 4) & 0x70) +#define LOUTMIX1_SET_LI2LOVOL(x) ((x) << 4) +#define LOUTMIX1_LMIXSEL_MASK 0x7 +#define LOUTMIX1_GET_LMIXSEL(x) ((x) & 0x7) +#define LOUTMIX1_SET_LMIXSEL(x) (x) + +#define LOUTMIX2_REG 0x23 /* Left out Mix (2) */ +#define LOUTMIX2_RD2LO 0x100 +#define LOUTMIX2_RI2LO 0x80 +#define LOUTMIX2_RI2LOVOL_MASK 0x70 +#define LOUTMIX2_GET_RI2LOVOL(x) (((x) >> 4) & 0x70) +#define LOUTMIX2_SET_RI2LOVOL(x) ((x) << 4) + +#define ROUTMIX1_REG 0x24 /* Right out Mix (1) */ +#define ROUTMIX1_LD2RO 0x100 +#define ROUTMIX1_LI2RO 0x80 +#define ROUTMIX1_LI2ROVOL_MASK 0x70 +#define ROUTMIX1_GET_LI2ROVOL(x) (((x) >> 4) & 0x70) +#define ROUTMIX1_SET_LI2ROVOL(x) ((x) << 4) +#define ROUTMIX1_RMIXSEL_MASK 0x7 +#define ROUTMIX1_GET_RMIXSEL(x) ((x) & 0x7) +#define ROUTMIX1_SET_RMIXSEL(x) (x) + +#define ROUTMIX2_REG 0x25 /* Right out Mix (2) */ +#define ROUTMIX2_RD2RO 0x100 +#define ROUTMIX2_RI2RO 0x80 +#define ROUTMIX2_RI2ROVOL_MASK 0x70 +#define ROUTMIX2_GET_RI2ROVOL(x) (((x) >> 4) & 0x70) +#define ROUTMIX2_SET_RI2ROVOL(x) ((x) << 4) + +#define MOUTMIX1_REG 0x26 /* Mono out Mix (1) */ +#define MOUTMIX1_LD2MO 0x100 +#define MOUTMIX1_LI2MO 0x80 +#define MOUTMIX1_LI2MOVOL_MASK 0x70 +#define MOUTMIX1_GET_LI2MOVOL(x) (((x) >> 4) & 0x70) +#define MOUTMIX1_SET_LI2MOVOL(x) ((x) << 4) + +#define MOUTMIX2_REG 0x27 /* Mono out Mix (2) */ +#define MOUTMIX2_RD2MO 0x100 +#define MOUTMIX2_RI2MO 0x80 +#define MOUTMIX2_RI2MOVOL_MASK 0x70 +#define MOUTMIX2_GET_RI2MOVOL(x) (((x) >> 4) & 0x70) +#define MOUTMIX2_SET_RI2MOVOL(x) ((x) << 4) + +#define LOUT2VOL_REG 0x28 /* LOUT2 volume */ +#define LOUT2VOL_LO2VU 0x100 +#define LOUT2VOL_LO2ZC 0x80 +#define LOUT2VOL_LOUT2VOL_MASK 0x7F +#define LOUT2VOL_GET_LOUT2VOL(x) ((x) & 0x7F) +#define LOUT2VOL_SET_LOUT2VOL(x) (x) + +#define ROUT2VOL_REG 0x29 /* ROUT2 volume */ +#define ROUT2VOL_RO2VU 0x100 +#define ROUT2VOL_RO2ZC 0x80 +#define ROUT2VOL_ROUT2VOL_MASK 0x7F +#define ROUT2VOL_GET_ROUT2VOL(x) ((x) & 0x7F) +#define ROUT2VOL_SET_ROUT2VOL(x) (x) + +#define MOUTVOL_REG 0x2A /* MONOOUT volume */ +#define MOUTVOL_MOZC 0x80 +#define MOUTVOL_MOUTVOL_MASK 0x7F +#define MOUTVOL_GET_MOUTVOL(x) ((x) & 0x7F) +#define MOUTVOL_SET_MOUTVOL(x) (x) + -- cgit v1.2.3