mail archive of the barebox mailing list
 help / color / mirror / Atom feed
From: Ahmad Fatoum <ahmad@a3f.at>
To: barebox@lists.infradead.org
Subject: [PATCH 2/7] drivers: add sound card driver support
Date: Sun, 31 Jan 2021 21:18:41 +0100	[thread overview]
Message-ID: <20210131201846.3440477-3-ahmad@a3f.at> (raw)
In-Reply-To: <20210131201846.3440477-1-ahmad@a3f.at>

Add driver core boilerplate for sound support in barebox. Using the
provided API in <sound.h>, consumers can play beeps for a fixed duration
of time.

Playing beeps is not blocking and new beeps can be enqueued while one
is already playing. They will be played in succession by a poller, which
will also turn off the sound card when the beep tune is over.

API is also available for blocking until all beeps are played and for
cancelling an underway beep tune.

The API could be later extended for arbitrary PCM audio, should the
need arise.

Signed-off-by: Ahmad Fatoum <ahmad@a3f.at>
---
 drivers/Kconfig        |   1 +
 drivers/Makefile       |   1 +
 drivers/sound/Kconfig  |   8 +++
 drivers/sound/Makefile |   2 +
 drivers/sound/core.c   | 121 +++++++++++++++++++++++++++++++++++++++++
 include/poller.h       |   4 ++
 include/sound.h        |  45 +++++++++++++++
 7 files changed, 182 insertions(+)
 create mode 100644 drivers/sound/Kconfig
 create mode 100644 drivers/sound/Makefile
 create mode 100644 drivers/sound/core.c
 create mode 100644 include/sound.h

diff --git a/drivers/Kconfig b/drivers/Kconfig
index dda240578067..0b87c2af2a83 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -13,6 +13,7 @@ source "drivers/mtd/Kconfig"
 source "drivers/ata/Kconfig"
 source "drivers/usb/Kconfig"
 source "drivers/video/Kconfig"
+source "drivers/sound/Kconfig"
 source "drivers/mci/Kconfig"
 source "drivers/clk/Kconfig"
 source "drivers/clocksource/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 5a03bdceab81..fab3790288f7 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -43,3 +43,4 @@ obj-y	+= soc/imx/
 obj-y	+= nvme/
 obj-y	+= ddr/
 obj-y	+= power/
+obj-$(CONFIG_SOUND) += sound/
diff --git a/drivers/sound/Kconfig b/drivers/sound/Kconfig
new file mode 100644
index 000000000000..cce5c760afdc
--- /dev/null
+++ b/drivers/sound/Kconfig
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0-only
+menuconfig SOUND
+	bool "Sound drivers"
+	select POLLER
+	help
+	  Say Y here for sound support. At the moment that's just beep tones.
+	  Tones are played asynchronously in a poller. Check the beep command
+	  for how to exercise the API.
diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile
new file mode 100644
index 000000000000..e343e0fa72b0
--- /dev/null
+++ b/drivers/sound/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-y += core.o
diff --git a/drivers/sound/core.c b/drivers/sound/core.c
new file mode 100644
index 000000000000..801b1fade552
--- /dev/null
+++ b/drivers/sound/core.c
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: © 2021 Ahmad Fatoum
+
+#include <common.h>
+#include <linux/list.h>
+#include <sound.h>
+#include <poller.h>
+#include <linux/iopoll.h>
+
+static LIST_HEAD(card_list);
+
+struct beep {
+	int freq;
+	unsigned int us;
+	struct list_head list;
+};
+
+static int sound_card_do_beep(struct sound_card *card,
+			      int freq, unsigned int us)
+{
+	if (freq == -1)
+		freq = card->bell_frequency;
+
+	return card->beep(card, freq, us);
+}
+
+static void sound_card_poller_cb(void *_card)
+{
+	struct sound_card *card = _card;
+	struct beep *beep;
+
+	beep = list_first_entry_or_null(&card->tune, struct beep, list);
+	if (!beep) {
+		sound_card_do_beep(card, 0, 0);
+		return;
+	}
+
+	list_del(&beep->list);
+
+	poller_call_async(&card->poller, beep->us * 1000ULL,
+			  sound_card_poller_cb, card);
+	sound_card_do_beep(card, beep->freq, beep->us);
+
+	free(beep);
+}
+
+int sound_card_register(struct sound_card *card)
+{
+	if (!card->name)
+		return -EINVAL;
+
+	if (card->bell_frequency <= 0)
+		card->bell_frequency = 1000;
+
+	poller_async_register(&card->poller, card->name);
+	INIT_LIST_HEAD(&card->tune);
+
+	list_add_tail(&card->list, &card_list);
+	return 0;
+}
+
+struct sound_card *sound_card_get_default(void)
+{
+	return list_first_entry_or_null(&card_list, struct sound_card, list);
+}
+
+int sound_card_beep(struct sound_card *card, int freq, unsigned int us)
+{
+	struct beep *beep;
+	int ret;
+
+	if (!card)
+		return -ENODEV;
+
+	if (!poller_async_active(&card->poller)) {
+		ret = sound_card_do_beep(card, freq, us);
+		if (!ret)
+			poller_call_async(&card->poller, us * 1000ULL,
+					  sound_card_poller_cb, card);
+
+		return ret;
+	}
+
+	beep = malloc(sizeof(*beep));
+	if (!beep)
+		return -ENOMEM;
+
+	beep->freq = freq;
+	beep->us = us;
+
+	list_add_tail(&beep->list, &card->tune);
+
+	return 0;
+}
+
+int sound_card_beep_wait(struct sound_card *card, unsigned timeout)
+{
+	bool active;
+	return read_poll_timeout(poller_async_active, active,
+				 !active, timeout, &card->poller);
+}
+
+int sound_card_beep_cancel(struct sound_card *card)
+{
+	struct beep *beep, *tmp;
+	int ret;
+
+	if (!card)
+		return -ENODEV;
+
+	poller_async_cancel(&card->poller);
+
+	ret = card->beep(card, 0, 0);
+
+	list_for_each_entry_safe(beep, tmp, &card->tune, list) {
+		list_del(&beep->list);
+		free(beep);
+	}
+
+	return ret;
+}
diff --git a/include/poller.h b/include/poller.h
index 886557252b69..db773265b2f6 100644
--- a/include/poller.h
+++ b/include/poller.h
@@ -34,6 +34,10 @@ int poller_async_unregister(struct poller_async *pa);
 int poller_call_async(struct poller_async *pa, uint64_t delay_ns,
 		void (*fn)(void *), void *ctx);
 int poller_async_cancel(struct poller_async *pa);
+static inline bool poller_async_active(struct poller_async *pa)
+{
+	return pa->active;
+}
 
 #ifdef CONFIG_POLLER
 void poller_call(void);
diff --git a/include/sound.h b/include/sound.h
new file mode 100644
index 000000000000..f5124aebbda1
--- /dev/null
+++ b/include/sound.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* SPDX-FileCopyrightText: © 2021 Ahmad Fatoum */
+
+#ifndef __SOUND_H_
+#define __SOUND_H_
+
+#include <linux/list.h>
+#include <poller.h>
+
+#define BELL_DEFAULT_FREQUENCY	-1
+
+struct sound_card {
+	const char *name;
+	int bell_frequency;
+	int (*beep)(struct sound_card *, unsigned freq, unsigned us);
+
+	/* private */
+	struct list_head list;
+	struct list_head tune;
+	struct poller_async poller;
+};
+
+int sound_card_register(struct sound_card *card);
+int sound_card_beep_wait(struct sound_card *card, unsigned timeout_us);
+int sound_card_beep(struct sound_card *card, int freq, unsigned int us);
+int sound_card_beep_cancel(struct sound_card *card);
+
+struct sound_card *sound_card_get_default(void);
+
+static inline int beep(int freq, unsigned us)
+{
+	return sound_card_beep(sound_card_get_default(), freq, us);
+}
+
+static inline int beep_wait(unsigned timeout_us)
+{
+	return sound_card_beep_wait(sound_card_get_default(), timeout_us);
+}
+
+static inline int beep_cancel(void)
+{
+	return sound_card_beep_cancel(sound_card_get_default());
+}
+
+#endif
-- 
2.30.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

  parent reply	other threads:[~2021-01-31 20:18 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-01-31 20:18 [PATCH 0/7] Add sound and GRUB beep tune support Ahmad Fatoum
2021-01-31 20:18 ` [PATCH 1/7] sandbox: migrate to SDL 2.0 Ahmad Fatoum
2021-01-31 20:18 ` Ahmad Fatoum [this message]
2021-01-31 20:18 ` [PATCH 3/7] sound: add basic synthesizers for PCM beeper use Ahmad Fatoum
2021-01-31 20:18 ` [PATCH 4/7] sound: add SDL 2.0 sound driver Ahmad Fatoum
2021-01-31 20:18 ` [PATCH 5/7] commands: add beep command Ahmad Fatoum
2021-01-31 20:18 ` [PATCH 6/7] sound: add PWM beeper support Ahmad Fatoum
2021-01-31 20:18 ` [PATCH 7/7] sound: add gpio-beeper support Ahmad Fatoum
2021-02-08 10:42 ` [PATCH 0/7] Add sound and GRUB beep tune support Sascha Hauer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210131201846.3440477-3-ahmad@a3f.at \
    --to=ahmad@a3f.at \
    --cc=barebox@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox