summaryrefslogtreecommitdiff
path: root/sys/dev/fdt/tascodec.c
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2022-09-02 16:53:29 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2022-09-02 16:53:29 +0000
commitaf69610e1d88806598baba57e7a20b8cef7245d2 (patch)
tree1952bf03c73df139baf828d1910213103b389bc5 /sys/dev/fdt/tascodec.c
parentfdd6ad80d3254346fa43ca1378b8160a41be53a7 (diff)
Add a callback for setting the TDM slot used by an audio codec.
Implement this callback in tascodec(4) such that we can pick the audio channel that it outputs. This will override the default which is to downmix stereo input from TDM channels 0 and 1 to mono output. ok ratchov@
Diffstat (limited to 'sys/dev/fdt/tascodec.c')
-rw-r--r--sys/dev/fdt/tascodec.c32
1 files changed, 31 insertions, 1 deletions
diff --git a/sys/dev/fdt/tascodec.c b/sys/dev/fdt/tascodec.c
index 12e1466ffe5..a7d5b295715 100644
--- a/sys/dev/fdt/tascodec.c
+++ b/sys/dev/fdt/tascodec.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tascodec.c,v 1.4 2022/07/25 16:35:41 kettenis Exp $ */
+/* $OpenBSD: tascodec.c,v 1.5 2022/09/02 16:53:28 kettenis Exp $ */
/*
* Copyright (c) 2022 Mark Kettenis <kettenis@openbsd.org>
*
@@ -49,7 +49,14 @@
#define TDM_CFG1_RX_EDGE (1 << 0)
#define TDM_CFG2 0x0c
#define TDM_CFG2_SCFG_MASK (3 << 4)
+#define TDM_CFG2_SCFG_MONO_LEFT (1 << 4)
+#define TDM_CFG2_SCFG_MONO_RIGHT (2 << 4)
#define TDM_CFG2_SCFG_STEREO_DOWNMIX (3 << 4)
+#define TDM_CFG3 0x0d
+#define TDM_CFG3_RX_SLOT_R_MASK 0xf0
+#define TDM_CFG3_RX_SLOT_R_SHIFT 4
+#define TDM_CFG3_RX_SLOT_L_MASK 0x0f
+#define TDM_CFG3_RX_SLOT_L_SHIFT 0
struct tascodec_softc {
struct device sc_dev;
@@ -74,6 +81,7 @@ struct cfdriver tascodec_cd = {
};
int tascodec_set_format(void *, uint32_t, uint32_t, uint32_t);
+int tascodec_set_tdm_slot(void *, int);
int tascodec_set_port(void *, mixer_ctrl_t *);
int tascodec_get_port(void *, mixer_ctrl_t *);
@@ -141,6 +149,7 @@ tascodec_attach(struct device *parent, struct device *self, void *aux)
sc->sc_dai.dd_cookie = sc;
sc->sc_dai.dd_hw_if = &tascodec_hw_if;
sc->sc_dai.dd_set_format = tascodec_set_format;
+ sc->sc_dai.dd_set_tdm_slot = tascodec_set_tdm_slot;
dai_register(&sc->sc_dai);
}
@@ -205,6 +214,27 @@ tascodec_set_format(void *cookie, uint32_t fmt, uint32_t pol,
return 0;
}
+int
+tascodec_set_tdm_slot(void *cookie, int slot)
+{
+ struct tascodec_softc *sc = cookie;
+ uint8_t cfg2, cfg3;
+
+ if (slot < 0 || slot >= 16)
+ return EINVAL;
+
+ cfg2 = tascodec_read(sc, TDM_CFG2);
+ cfg3 = tascodec_read(sc, TDM_CFG3);
+ cfg2 &= ~TDM_CFG2_SCFG_MASK;
+ cfg2 |= TDM_CFG2_SCFG_MONO_LEFT;
+ cfg3 &= ~TDM_CFG3_RX_SLOT_L_MASK;
+ cfg3 |= slot << TDM_CFG3_RX_SLOT_L_SHIFT;
+ tascodec_write(sc, TDM_CFG2, cfg2);
+ tascodec_write(sc, TDM_CFG3, cfg3);
+
+ return 0;
+}
+
/*
* Mixer controls; the gain of the TAS2770 is determined by the
* amplifier gain and digital volume control setting, but we only