sound: Add a new stop_play() method
authorSimon Glass <sjg@chromium.org>
Mon, 3 Feb 2020 14:36:06 +0000 (07:36 -0700)
committerSimon Glass <sjg@chromium.org>
Thu, 6 Feb 2020 02:33:46 +0000 (19:33 -0700)
At present there is no positive indication that U-Boot has finished
sending sound data. This means that it is not possible to power down an
audio codec, for example. Add a new method that is called once all sound
data has been sent.

Add a new method for this, called when the sound_play() call is done.

Signed-off-by: Simon Glass <sjg@chromium.org>
arch/sandbox/include/asm/test.h
drivers/sound/sandbox.c
drivers/sound/sound-uclass.c
include/sound.h
test/dm/sound.c

index 2421922c9ea6db490adbb9ec067168e0a5103fe8..92ff494453ca27f9cfc8668ffb37728aff8afb47 100644 (file)
@@ -165,6 +165,13 @@ int sandbox_get_i2s_sum(struct udevice *dev);
  */
 int sandbox_get_setup_called(struct udevice *dev);
 
+/**
+ * sandbox_get_sound_active() - Returns whether sound play is in progress
+ *
+ * @return true if active, false if not
+ */
+int sandbox_get_sound_active(struct udevice *dev);
+
 /**
  * sandbox_get_sound_sum() - Read back the sum of the sound data so far
  *
index 363c687bafd11d2ebcf16ba3dda3c69157352c35..9034a8385a8c78b1e868070585a5499728d662ca 100644 (file)
@@ -26,7 +26,8 @@ struct sandbox_i2s_priv {
 };
 
 struct sandbox_sound_priv {
-       int setup_called;
+       int setup_called;       /* Incremented when setup() method is called */
+       bool active;            /* TX data is being sent */
        int sum;                /* Use to sum the provided audio data */
        bool allow_beep;        /* true to allow the start_beep() interface */
        int frequency_hz;       /* Beep frequency if active, else 0 */
@@ -59,6 +60,13 @@ int sandbox_get_setup_called(struct udevice *dev)
        return priv->setup_called;
 }
 
+int sandbox_get_sound_active(struct udevice *dev)
+{
+       struct sandbox_sound_priv *priv = dev_get_priv(dev);
+
+       return priv->active;
+}
+
 int sandbox_get_sound_sum(struct udevice *dev)
 {
        struct sandbox_sound_priv *priv = dev_get_priv(dev);
@@ -163,6 +171,16 @@ static int sandbox_sound_play(struct udevice *dev, void *data, uint data_size)
        return i2s_tx_data(uc_priv->i2s, data, data_size);
 }
 
+static int sandbox_sound_stop_play(struct udevice *dev)
+{
+       struct sandbox_sound_priv *priv = dev_get_priv(dev);
+
+       sandbox_sdl_sound_stop();
+       priv->active = false;
+
+       return 0;
+}
+
 int sandbox_sound_start_beep(struct udevice *dev, int frequency_hz)
 {
        struct sandbox_sound_priv *priv = dev_get_priv(dev);
@@ -228,6 +246,7 @@ U_BOOT_DRIVER(sandbox_i2s) = {
 static const struct sound_ops sandbox_sound_ops = {
        .setup          = sandbox_sound_setup,
        .play           = sandbox_sound_play,
+       .stop_play      = sandbox_sound_stop_play,
        .start_beep     = sandbox_sound_start_beep,
        .stop_beep      = sandbox_sound_stop_beep,
 };
index d49f29bcd5b81cea57cf1c3673599050adea83b9..c213472d60666c27214101f120038f63f8ef6d70 100644 (file)
@@ -31,6 +31,16 @@ int sound_play(struct udevice *dev, void *data, uint data_size)
        return ops->play(dev, data, data_size);
 }
 
+int sound_stop_play(struct udevice *dev)
+{
+       struct sound_ops *ops = sound_get_ops(dev);
+
+       if (!ops->play)
+               return -ENOSYS;
+
+       return ops->stop_play(dev);
+}
+
 int sound_start_beep(struct udevice *dev, int frequency_hz)
 {
        struct sound_ops *ops = sound_get_ops(dev);
@@ -97,6 +107,7 @@ int sound_beep(struct udevice *dev, int msecs, int frequency_hz)
 
                ret = sound_play(dev, data, size);
        }
+       sound_stop_play(dev);
 
        free(data);
 
index 47de9fa3ed3ac70245cbedac9f811d2410009c31..71bd850652e4421a27244978b60258345cc027cf 100644 (file)
@@ -68,6 +68,18 @@ struct sound_ops {
         */
        int (*play)(struct udevice *dev, void *data, uint data_size);
 
+       /**
+        * stop_play() - Indicate that there is no more data coming
+        *
+        * This is called once play() has finished sending all the data to the
+        * output device. This may be used to tell the hardware to turn off the
+        * codec, for example.
+        *
+        * @dev: Sound device
+        * @return 0 if OK, -ve on error
+        */
+       int (*stop_play)(struct udevice *dev);
+
        /**
         * start_beep() - Start beeping (optional)
         *
index 3767abbd1c753064ebb3c1cf9e2cfd7b3df8da92..aa5368f05b9da0f699c2737bef9025faad5a4668 100644 (file)
@@ -28,6 +28,7 @@ static int dm_test_sound(struct unit_test_state *uts)
        ut_asserteq(4560, sandbox_get_sound_sum(dev));
        ut_assertok(sound_beep(dev, 1, 100));
        ut_asserteq(9120, sandbox_get_sound_sum(dev));
+       ut_asserteq(false, sandbox_get_sound_active(dev));
 
        return 0;
 }