Page MenuHomeFreeBSD

D59073.id187126.diff
No OneTemporary

D59073.id187126.diff

diff --git a/sys/dev/sound/macio/onyx.c b/sys/dev/sound/macio/onyx.c
--- a/sys/dev/sound/macio/onyx.c
+++ b/sys/dev/sound/macio/onyx.c
@@ -39,6 +39,7 @@
#include <sys/malloc.h>
#include <sys/lock.h>
#include <sys/mutex.h>
+#include <sys/taskqueue.h>
#include <machine/dbdma.h>
#include <machine/intr_machdep.h>
#include <machine/resource.h>
@@ -65,6 +66,10 @@
{
device_t sc_dev;
uint32_t sc_addr;
+ struct mtx sc_volume_mtx;
+ struct task sc_volume_task;
+ uint8_t sc_left;
+ uint8_t sc_right;
};
static int onyx_probe(device_t);
@@ -185,6 +190,26 @@
return (0);
}
+/*
+ * onyx_write() sleeps in iicbus_transfer(), so onyx_set() cannot program the
+ * volume registers inline. Hand the new values to a task instead, which runs
+ * with no lock held.
+ */
+static void
+onyx_volume_task(void *arg, int pending __unused)
+{
+ struct onyx_softc *sc = arg;
+ uint8_t l, r;
+
+ mtx_lock(&sc->sc_volume_mtx);
+ l = sc->sc_left;
+ r = sc->sc_right;
+ mtx_unlock(&sc->sc_volume_mtx);
+
+ onyx_write(sc, PCM3052_REG_LEFT_ATTN, l);
+ onyx_write(sc, PCM3052_REG_RIGHT_ATTN, r);
+}
+
static int
onyx_probe(device_t dev)
{
@@ -216,6 +241,9 @@
sc->sc_dev = dev;
sc->sc_addr = iicbus_get_addr(dev);
+ mtx_init(&sc->sc_volume_mtx, "onyx volume", NULL, MTX_DEF);
+ TASK_INIT(&sc->sc_volume_task, 0, onyx_volume_task, sc);
+
i2s_mixer_class = &onyx_mixer_class;
i2s_mixer = dev;
@@ -255,6 +283,12 @@
static int
onyx_uninit(struct snd_mixer *m)
{
+ struct onyx_softc *sc;
+
+ sc = device_get_softc(mix_getdevinfo(m));
+
+ taskqueue_drain(taskqueue_thread, &sc->sc_volume_task);
+
return (0);
}
@@ -280,8 +314,12 @@
l = left + 128;
r = right + 128;
- onyx_write(sc, PCM3052_REG_LEFT_ATTN, l);
- onyx_write(sc, PCM3052_REG_RIGHT_ATTN, r);
+ mtx_lock(&sc->sc_volume_mtx);
+ sc->sc_left = l;
+ sc->sc_right = r;
+ mtx_unlock(&sc->sc_volume_mtx);
+
+ taskqueue_enqueue(taskqueue_thread, &sc->sc_volume_task);
return (left | (right << 8));
}
diff --git a/sys/dev/sound/macio/snapper.c b/sys/dev/sound/macio/snapper.c
--- a/sys/dev/sound/macio/snapper.c
+++ b/sys/dev/sound/macio/snapper.c
@@ -65,6 +65,7 @@
#include <sys/malloc.h>
#include <sys/lock.h>
#include <sys/mutex.h>
+#include <sys/taskqueue.h>
#include <machine/dbdma.h>
#include <machine/intr_machdep.h>
#include <machine/resource.h>
@@ -91,6 +92,9 @@
{
device_t sc_dev;
uint32_t sc_addr;
+ struct mtx sc_volume_mtx;
+ struct task sc_volume_task;
+ u_char sc_volume_reg[6];
};
static int snapper_probe(device_t);
@@ -338,6 +342,24 @@
return (0);
}
+/*
+ * snapper_write() sleeps in iicbus_transfer(), so snapper_set() cannot
+ * program the volume registers inline. Hand the new values to a task
+ * instead, which runs with no lock held.
+ */
+static void
+snapper_volume_task(void *arg, int pending __unused)
+{
+ struct snapper_softc *sc = arg;
+ u_char reg[6];
+
+ mtx_lock(&sc->sc_volume_mtx);
+ memcpy(reg, sc->sc_volume_reg, sizeof(reg));
+ mtx_unlock(&sc->sc_volume_mtx);
+
+ snapper_write(sc, SNAPPER_VOLUME, reg);
+}
+
static int
snapper_probe(device_t dev)
{
@@ -371,6 +393,9 @@
sc->sc_dev = dev;
sc->sc_addr = iicbus_get_addr(dev);
+ mtx_init(&sc->sc_volume_mtx, "snapper volume", NULL, MTX_DEF);
+ TASK_INIT(&sc->sc_volume_task, 0, snapper_volume_task, sc);
+
i2s_mixer_class = &snapper_mixer_class;
i2s_mixer = dev;
@@ -423,6 +448,12 @@
static int
snapper_uninit(struct snd_mixer *m)
{
+ struct snapper_softc *sc;
+
+ sc = device_get_softc(mix_getdevinfo(m));
+
+ taskqueue_drain(taskqueue_thread, &sc->sc_volume_task);
+
return (0);
}
@@ -456,7 +487,11 @@
reg[4] = (r & 0x00ff00) >> 8;
reg[5] = r & 0x0000ff;
- snapper_write(sc, SNAPPER_VOLUME, reg);
+ mtx_lock(&sc->sc_volume_mtx);
+ memcpy(sc->sc_volume_reg, reg, sizeof(reg));
+ mtx_unlock(&sc->sc_volume_mtx);
+
+ taskqueue_enqueue(taskqueue_thread, &sc->sc_volume_task);
return (left | (right << 8));
}
diff --git a/sys/dev/sound/macio/tumbler.c b/sys/dev/sound/macio/tumbler.c
--- a/sys/dev/sound/macio/tumbler.c
+++ b/sys/dev/sound/macio/tumbler.c
@@ -65,6 +65,7 @@
#include <sys/malloc.h>
#include <sys/lock.h>
#include <sys/mutex.h>
+#include <sys/taskqueue.h>
#include <machine/dbdma.h>
#include <machine/intr_machdep.h>
#include <machine/resource.h>
@@ -91,6 +92,9 @@
{
device_t sc_dev;
uint32_t sc_addr;
+ struct mtx sc_volume_mtx;
+ struct task sc_volume_task;
+ u_char sc_volume_reg[6];
};
static int tumbler_probe(device_t);
@@ -299,6 +303,24 @@
return (0);
}
+/*
+ * tumbler_write() sleeps in iicbus_transfer(), so tumbler_set() cannot
+ * program the volume registers inline. Hand the new values to a task
+ * instead, which runs with no lock held.
+ */
+static void
+tumbler_volume_task(void *arg, int pending __unused)
+{
+ struct tumbler_softc *sc = arg;
+ u_char reg[6];
+
+ mtx_lock(&sc->sc_volume_mtx);
+ memcpy(reg, sc->sc_volume_reg, sizeof(reg));
+ mtx_unlock(&sc->sc_volume_mtx);
+
+ tumbler_write(sc, TUMBLER_VOLUME, reg);
+}
+
static int
tumbler_probe(device_t dev)
{
@@ -326,6 +348,9 @@
sc->sc_dev = dev;
sc->sc_addr = iicbus_get_addr(dev);
+ mtx_init(&sc->sc_volume_mtx, "tumbler volume", NULL, MTX_DEF);
+ TASK_INIT(&sc->sc_volume_task, 0, tumbler_volume_task, sc);
+
i2s_mixer_class = &tumbler_mixer_class;
i2s_mixer = dev;
@@ -370,6 +395,12 @@
static int
tumbler_uninit(struct snd_mixer *m)
{
+ struct tumbler_softc *sc;
+
+ sc = device_get_softc(mix_getdevinfo(m));
+
+ taskqueue_drain(taskqueue_thread, &sc->sc_volume_task);
+
return (0);
}
@@ -403,7 +434,11 @@
reg[4] = (r & 0x00ff00) >> 8;
reg[5] = r & 0x0000ff;
- tumbler_write(sc, TUMBLER_VOLUME, reg);
+ mtx_lock(&sc->sc_volume_mtx);
+ memcpy(sc->sc_volume_reg, reg, sizeof(reg));
+ mtx_unlock(&sc->sc_volume_mtx);
+
+ taskqueue_enqueue(taskqueue_thread, &sc->sc_volume_task);
return (left | (right << 8));
}

File Metadata

Mime Type
text/plain
Expires
Sun, Oct 4, 12:20 AM (12 h, 57 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
40160271
Default Alt Text
D59073.id187126.diff (5 KB)

Event Timeline