Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys Add UDA1341TS audio CODEC support. Code is written by
details: https://anonhg.NetBSD.org/src/rev/87f08ddcf21f
branches: trunk
changeset: 773118:87f08ddcf21f
user: nisimura <nisimura%NetBSD.org@localhost>
date: Sat Jan 28 08:37:22 2012 +0000
description:
Add UDA1341TS audio CODEC support. Code is written by
Paul Fleischer.
diffstat:
sys/conf/files | 6 +-
sys/dev/ic/uda1341.c | 762 ++++++++++++++++++++++++++++++++++++++++++++++++
sys/dev/ic/uda1341reg.h | 121 +++++++
sys/dev/ic/uda1341var.h | 95 +++++
4 files changed, 983 insertions(+), 1 deletions(-)
diffs (truncated from 1010 to 300 lines):
diff -r a111e0a148aa -r 87f08ddcf21f sys/conf/files
--- a/sys/conf/files Sat Jan 28 08:29:55 2012 +0000
+++ b/sys/conf/files Sat Jan 28 08:37:22 2012 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: files,v 1.1039 2012/01/22 06:44:30 christos Exp $
+# $NetBSD: files,v 1.1040 2012/01/28 08:37:22 nisimura Exp $
# @(#)files.newconf 7.5 (Berkeley) 5/10/93
version 20100430
@@ -913,6 +913,10 @@
define ac97
file dev/ic/ac97.c ac97
+# UDA1341 CODEC support
+define uda1341
+file dev/ic/uda1341.c uda1341
+
# Oki MSM6258 support code
#
define msm6258
diff -r a111e0a148aa -r 87f08ddcf21f sys/dev/ic/uda1341.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/ic/uda1341.c Sat Jan 28 08:37:22 2012 +0000
@@ -0,0 +1,762 @@
+/*-
+ * Copyright (c) 2012 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Paul Fleischer <paul%xpg.dk@localhost>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/audioio.h>
+#include <sys/fcntl.h>
+
+#include <dev/audio_if.h>
+
+#include <dev/ic/uda1341var.h>
+#include <dev/ic/uda1341reg.h>
+
+/*#define UDA1341_DEBUG*/
+
+#ifdef UDA1341_DEBUG
+#define DPRINTF(x) do {printf x; } while (/*CONSTCOND*/0)
+#else
+#define DPRINTF(s) do {} while (/*CONSTCOND*/0)
+#endif
+
+const struct audio_format uda1341_formats[UDA1341_NFORMATS] =
+{
+ {NULL, AUMODE_PLAY|AUMODE_RECORD, AUDIO_ENCODING_SLINEAR_LE, 8, 8, 2,
+ AUFMT_STEREO, 0, {8000, 48000}
+ },
+ {NULL, AUMODE_PLAY|AUMODE_RECORD, AUDIO_ENCODING_SLINEAR_LE, 16, 16, 2,
+ AUFMT_STEREO, 0, {8000, 48000}
+ },
+ {NULL, AUMODE_PLAY|AUMODE_RECORD, AUDIO_ENCODING_ULINEAR_LE, 8, 8, 2,
+ AUFMT_STEREO, 0, {8000, 48000}
+ },
+ {NULL, AUMODE_PLAY|AUMODE_RECORD, AUDIO_ENCODING_ULINEAR_LE, 16, 16, 2,
+ AUFMT_STEREO, 0, {8000, 48000}
+ },
+};
+
+static void uda1341_update_sound_settings(struct uda1341_softc *sc);
+
+
+int
+uda1341_attach(struct uda1341_softc *sc)
+{
+ sc->sc_system_clock = UDA1341_CLOCK_NA;
+ sc->sc_l3_write = NULL;
+ sc->sc_volume = 127;
+ sc->sc_bass = 0;
+ sc->sc_treble = 0;
+ sc->sc_mode = 0;
+ sc->sc_mute = 0;
+ sc->sc_ogain = 0;
+ sc->sc_deemphasis = UDA1341_DEEMPHASIS_AUTO;
+ sc->sc_dac_power = 0;
+ sc->sc_adc_power = 0;
+ sc->sc_inmix1 = 0;
+ sc->sc_inmix2 = 0;
+ sc->sc_micvol = 0;
+ sc->sc_inmode = 0;
+ sc->sc_agc = 0;
+ sc->sc_agc_lvl = 0;
+ sc->sc_ch2_gain = 0;
+
+ return 0;
+}
+
+int
+uda1341_query_encodings(void *handle, audio_encoding_t *ae)
+{
+ switch(ae->index) {
+ case 0:
+ strlcpy(ae->name, AudioEmulaw, sizeof(ae->name));
+ ae->encoding = AUDIO_ENCODING_ULAW;
+ ae->precision = 8;
+ ae->flags = AUDIO_ENCODINGFLAG_EMULATED;
+ break;
+ case 1:
+ strlcpy(ae->name, AudioEslinear_le, sizeof(ae->name));
+ ae->encoding = AUDIO_ENCODING_SLINEAR_LE;
+ ae->precision = 8;
+ ae->flags = 0;
+ break;
+ case 2:
+ strlcpy(ae->name, AudioEslinear_le, sizeof(ae->name));
+ ae->encoding = AUDIO_ENCODING_SLINEAR_LE;
+ ae->precision = 16;
+ ae->flags = 0;
+ break;
+ case 3:
+ strlcpy(ae->name, AudioEulinear_le, sizeof(ae->name));
+ ae->encoding = AUDIO_ENCODING_ULINEAR_LE;
+ ae->precision = 8;
+ ae->flags = 0;
+ break;
+ case 4:
+ strlcpy(ae->name, AudioEulinear_le, sizeof(ae->name));
+ ae->encoding = AUDIO_ENCODING_ULINEAR_LE;
+ ae->precision = 16;
+ ae->flags = 0;
+ break;
+
+ default:
+ return EINVAL;
+ }
+
+ return 0;
+}
+
+int
+uda1341_open(void *handle, int flags)
+{
+ struct uda1341_softc *sc = handle;
+
+ /* Reset the UDA1341 */
+ sc->sc_l3_write(sc, 0, UDA1341_L3_ADDR_DEVICE |
+ UDA1341_L3_ADDR_STATUS);
+ sc->sc_l3_write(sc, 1,
+ UDA1341_L3_STATUS0 |
+ UDA1341_L3_STATUS0_RST);
+
+ if (flags & FREAD) {
+ sc->sc_adc_power = 1;
+ }
+ if (flags & FWRITE) {
+ sc->sc_dac_power = 1;
+ }
+
+#if 0
+ /* Power on DAC */
+ sc->sc_l3_write(sc, 1,
+ UDA1341_L3_STATUS1 | UDA1341_L3_STATUS1_PC_DAC);
+#endif
+ uda1341_update_sound_settings(sc);
+
+#if 0
+ /* TODO: Add mixer support */
+ sc->sc_l3_write(sc, 0, 0x14 | 0x0);
+ sc->sc_l3_write(sc, 1, 0x15); /* Volume */
+#endif
+
+ return 0;
+}
+
+void
+uda1341_close(void *handle)
+{
+ struct uda1341_softc *sc = handle;
+ /* Reset the UDA1341 */
+ sc->sc_l3_write(sc, 0, UDA1341_L3_ADDR_DEVICE |
+ UDA1341_L3_ADDR_STATUS);
+
+ /* Power off DAC and ADC*/
+ sc->sc_l3_write(sc, 1,
+ UDA1341_L3_STATUS1);
+
+ sc->sc_dac_power = 0;
+ sc->sc_adc_power = 0;
+}
+
+int
+uda1341_set_params(void *handle, int setmode, int usemode,
+ audio_params_t *play, audio_params_t *rec,
+ stream_filter_list_t *pfil, stream_filter_list_t *rfil)
+{
+ struct uda1341_softc *sc = handle;
+ if (sc->sc_system_clock == UDA1341_CLOCK_NA)
+ panic("uda1341_set_params was called without sc_system_clock set!\n");
+
+ /* Select status register */
+ sc->sc_l3_write(sc, 0, UDA1341_L3_ADDR_DEVICE |
+ UDA1341_L3_ADDR_STATUS);
+
+ sc->sc_l3_write(sc, 1, UDA1341_L3_STATUS0 |
+ sc->sc_system_clock << UDA1341_L3_STATUS0_SC_SHIFT |
+ sc->sc_bus_format << UDA1341_L3_STATUS0_IF_SHIFT
+ );
+
+ if (sc->sc_sample_rate_approx != play->sample_rate) {
+ sc->sc_sample_rate_approx = play->sample_rate;
+ uda1341_update_sound_settings(sc);
+ }
+
+ return 0;
+}
+
+#define AUDIO_LEVELS (AUDIO_MAX_GAIN-AUDIO_MIN_GAIN+1)
+static void
+uda1341_update_sound_settings(struct uda1341_softc *sc)
+{
+ /* TODO: Refactor this function into smaller parts, such that
+ * a volume change does not trigger updates of all the
+ * other -- unrelated -- registers.
+ */
+
+ uint8_t val, volume, bass, treble, deemphasis;
+
+ sc->sc_l3_write(sc, 0, UDA1341_L3_ADDR_DEVICE | UDA1341_L3_ADDR_STATUS);
+ val = UDA1341_L3_STATUS1;
+ if (sc->sc_dac_power)
+ val |= UDA1341_L3_STATUS1_PC_DAC;
+ if (sc->sc_adc_power)
+ val |= UDA1341_L3_STATUS1_PC_ADC;
+ if (sc->sc_ogain)
+ val |= UDA1341_L3_STATUS1_OGS_6DB;
+
+ sc->sc_l3_write(sc, 1, val);
+
+ sc->sc_l3_write(sc, 0, UDA1341_L3_ADDR_DEVICE | UDA1341_L3_ADDR_DATA0);
+
+ /* Update volume */
+ /* On the UDA1341 maximal volume is 0x0,
+ while minimal volume is 0x3f */
+ volume = (0x3f) - ((sc->sc_volume*(0x3f+1)) / (AUDIO_LEVELS));
+
+ val = UDA1341_L3_DATA0_VOLUME;
+ val |= volume & UDA1341_L3_DATA0_VOLUME_MASK;
+ sc->sc_l3_write(sc, 1, val);
+
+ /* Update bass and treble */
+ bass = (sc->sc_bass*(0xf+1)) / AUDIO_LEVELS;
+ treble = (sc->sc_treble*(0x3+1)) / AUDIO_LEVELS;
+ val = UDA1341_L3_DATA0_BASS_TREBLE;
+ val |= (bass << UDA1341_L3_DATA0_BASS_SHIFT) &
+ UDA1341_L3_DATA0_BASS_MASK;
+ val |= (treble << UDA1341_L3_DATA0_TREBLE_SHIFT) &
+ UDA1341_L3_DATA0_TREBLE_MASK;
+ sc->sc_l3_write(sc, 1, val);
+
+ /* Update the remaining output sound controls:
+ * - Peak-detect position
+ * - De-emphasis
+ * - Mute
+ * - Mode Switch
+ * XXX: Only Mode-switch, de-emphasis, and mute is currently supported.
+ */
+ val = UDA1341_L3_DATA0_SOUNDC;
+
+ deemphasis = sc->sc_deemphasis;
+ if( deemphasis == UDA1341_DEEMPHASIS_AUTO) {
+ /* Set deemphasis according to current sample rate */
+ switch (sc->sc_sample_rate_approx) {
+ case 32000:
+ deemphasis = 0x1;
+ break;
+ case 44100:
+ deemphasis = 0x2;
+ break;
+ case 48000:
+ deemphasis = 0x3;
Home |
Main Index |
Thread Index |
Old Index