Commit 2850266965ade165f913a66f679a0449faf21180

Authored by Simon Glass
Committed by Bin Meng
1 parent e65f9ef9f2

sound: Add uclass operations for beeping

Some audio codecs such as Intel HDA do not need to use digital data to
play sounds, but instead have a way to emit beeps. Add this interface as
an option. If the beep interface is not supported, then the sound uclass
falls back to the I2S interface.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

Showing 5 changed files with 157 additions and 4 deletions Side-by-side Diff

arch/sandbox/include/asm/test.h
... ... @@ -162,6 +162,22 @@
162 162 int sandbox_get_sound_sum(struct udevice *dev);
163 163  
164 164 /**
  165 + * sandbox_set_allow_beep() - Set whether the 'beep' interface is supported
  166 + *
  167 + * @dev: Device to update
  168 + * @allow: true to allow the start_beep() method, false to disallow it
  169 + */
  170 +void sandbox_set_allow_beep(struct udevice *dev, bool allow);
  171 +
  172 +/**
  173 + * sandbox_get_beep_frequency() - Get the frequency of the current beep
  174 + *
  175 + * @dev: Device to check
  176 + * @return frequency of beep, if there is an active beep, else 0
  177 + */
  178 +int sandbox_get_beep_frequency(struct udevice *dev);
  179 +
  180 +/**
165 181 * sandbox_get_pch_spi_protect() - Get the PCI SPI protection status
166 182 *
167 183 * @dev: Device to check
drivers/sound/sandbox.c
... ... @@ -24,7 +24,9 @@
24 24  
25 25 struct sandbox_sound_priv {
26 26 int setup_called;
27   - int sum; /* Use to sum the provided audio data */
  27 + int sum; /* Use to sum the provided audio data */
  28 + bool allow_beep; /* true to allow the start_beep() interface */
  29 + int frequency_hz; /* Beep frequency if active, else 0 */
28 30 };
29 31  
30 32 void sandbox_get_codec_params(struct udevice *dev, int *interfacep, int *ratep,
... ... @@ -61,6 +63,20 @@
61 63 return priv->sum;
62 64 }
63 65  
  66 +void sandbox_set_allow_beep(struct udevice *dev, bool allow)
  67 +{
  68 + struct sandbox_sound_priv *priv = dev_get_priv(dev);
  69 +
  70 + priv->allow_beep = allow;
  71 +}
  72 +
  73 +int sandbox_get_beep_frequency(struct udevice *dev)
  74 +{
  75 + struct sandbox_sound_priv *priv = dev_get_priv(dev);
  76 +
  77 + return priv->frequency_hz;
  78 +}
  79 +
64 80 static int sandbox_codec_set_params(struct udevice *dev, int interface,
65 81 int rate, int mclk_freq,
66 82 int bits_per_sample, uint channels)
... ... @@ -128,6 +144,28 @@
128 144 return i2s_tx_data(uc_priv->i2s, data, data_size);
129 145 }
130 146  
  147 +int sandbox_sound_start_beep(struct udevice *dev, int frequency_hz)
  148 +{
  149 + struct sandbox_sound_priv *priv = dev_get_priv(dev);
  150 +
  151 + if (!priv->allow_beep)
  152 + return -ENOSYS;
  153 + priv->frequency_hz = frequency_hz;
  154 +
  155 + return 0;
  156 +}
  157 +
  158 +int sandbox_sound_stop_beep(struct udevice *dev)
  159 +{
  160 + struct sandbox_sound_priv *priv = dev_get_priv(dev);
  161 +
  162 + if (!priv->allow_beep)
  163 + return -ENOSYS;
  164 + priv->frequency_hz = 0;
  165 +
  166 + return 0;
  167 +}
  168 +
131 169 static int sandbox_sound_probe(struct udevice *dev)
132 170 {
133 171 return sound_find_codec_i2s(dev);
... ... @@ -169,8 +207,10 @@
169 207 };
170 208  
171 209 static const struct sound_ops sandbox_sound_ops = {
172   - .setup = sandbox_sound_setup,
173   - .play = sandbox_sound_play,
  210 + .setup = sandbox_sound_setup,
  211 + .play = sandbox_sound_play,
  212 + .start_beep = sandbox_sound_start_beep,
  213 + .stop_beep = sandbox_sound_stop_beep,
174 214 };
175 215  
176 216 static const struct udevice_id sandbox_sound_ids[] = {
drivers/sound/sound-uclass.c
... ... @@ -31,10 +31,30 @@
31 31 return ops->play(dev, data, data_size);
32 32 }
33 33  
  34 +int sound_start_beep(struct udevice *dev, int frequency_hz)
  35 +{
  36 + struct sound_ops *ops = sound_get_ops(dev);
  37 +
  38 + if (!ops->start_beep)
  39 + return -ENOSYS;
  40 +
  41 + return ops->start_beep(dev, frequency_hz);
  42 +}
  43 +
  44 +int sound_stop_beep(struct udevice *dev)
  45 +{
  46 + struct sound_ops *ops = sound_get_ops(dev);
  47 +
  48 + if (!ops->stop_beep)
  49 + return -ENOSYS;
  50 +
  51 + return ops->stop_beep(dev);
  52 +}
  53 +
34 54 int sound_beep(struct udevice *dev, int msecs, int frequency_hz)
35 55 {
36 56 struct sound_uc_priv *uc_priv = dev_get_uclass_priv(dev);
37   - struct i2s_uc_priv *i2s_uc_priv = dev_get_uclass_priv(uc_priv->i2s);
  57 + struct i2s_uc_priv *i2s_uc_priv;
38 58 unsigned short *data;
39 59 uint data_size;
40 60 int ret;
41 61  
... ... @@ -43,7 +63,19 @@
43 63 if (ret && ret != -EALREADY)
44 64 return ret;
45 65  
  66 + /* Try using the beep interface if available */
  67 + ret = sound_start_beep(dev, frequency_hz);
  68 + if (ret != -ENOSYS) {
  69 + if (ret)
  70 + return ret;
  71 + mdelay(msecs);
  72 + ret = sound_stop_beep(dev);
  73 +
  74 + return ret;
  75 + }
  76 +
46 77 /* Buffer length computation */
  78 + i2s_uc_priv = dev_get_uclass_priv(uc_priv->i2s);
47 79 data_size = i2s_uc_priv->samplingrate * i2s_uc_priv->channels;
48 80 data_size *= (i2s_uc_priv->bitspersample / SOUND_BITS_IN_BYTE);
49 81 data = malloc(data_size);
... ... @@ -67,6 +67,28 @@
67 67 * @return 0 if OK, -ve on error
68 68 */
69 69 int (*play)(struct udevice *dev, void *data, uint data_size);
  70 +
  71 + /**
  72 + * start_beep() - Start beeping (optional)
  73 + *
  74 + * This tells the sound hardware to start a beep. It will continue until
  75 + * stopped by sound_stop_beep().
  76 + *
  77 + * @dev: Sound device
  78 + * @frequency_hz: Beep frequency in hertz
  79 + * @return if OK, -ENOSYS if not supported, -ve on error
  80 + */
  81 + int (*start_beep)(struct udevice *dev, int frequency_hz);
  82 +
  83 + /**
  84 + * stop_beep() - Stop beeping (optional)
  85 + *
  86 + * This tells the sound hardware to stop a previously started beep.
  87 + *
  88 + * @dev: Sound device
  89 + * @return if OK, -ve on error
  90 + */
  91 + int (*stop_beep)(struct udevice *dev);
70 92 };
71 93  
72 94 #define sound_get_ops(dev) ((struct sound_ops *)(dev)->driver->ops)
... ... @@ -85,6 +107,28 @@
85 107 * @return 0 if OK, -ve on error
86 108 */
87 109 int sound_beep(struct udevice *dev, int msecs, int frequency_hz);
  110 +
  111 +/**
  112 + * sound_start_beep() - Start beeping
  113 + *
  114 + * This tells the sound hardware to start a beep. It will continue until stopped
  115 + * by sound_stop_beep().
  116 + *
  117 + * @dev: Sound device
  118 + * @frequency_hz: Beep frequency in hertz
  119 + * @return if OK, -ve on error
  120 + */
  121 +int sound_start_beep(struct udevice *dev, int frequency_hz);
  122 +
  123 +/**
  124 + * sound_stop_beep() - Stop beeping
  125 + *
  126 + * This tells the sound hardware to stop a previously started beep.
  127 + *
  128 + * @dev: Sound device
  129 + * @return if OK, -ve on error
  130 + */
  131 +int sound_stop_beep(struct udevice *dev);
88 132  
89 133 /**
90 134 * sound_find_codec_i2s() - Called by sound drivers to locate codec and i2s
... ... @@ -32,4 +32,25 @@
32 32 return 0;
33 33 }
34 34 DM_TEST(dm_test_sound, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
  35 +
  36 +/* Test of the 'start beep' operations */
  37 +static int dm_test_sound_beep(struct unit_test_state *uts)
  38 +{
  39 + struct udevice *dev;
  40 +
  41 + /* check probe success */
  42 + ut_assertok(uclass_first_device_err(UCLASS_SOUND, &dev));
  43 + ut_asserteq(-ENOSYS, sound_start_beep(dev, 100));
  44 + ut_asserteq(0, sandbox_get_beep_frequency(dev));
  45 +
  46 + sandbox_set_allow_beep(dev, true);
  47 + ut_asserteq(0, sound_start_beep(dev, 100));
  48 + ut_asserteq(100, sandbox_get_beep_frequency(dev));
  49 +
  50 + ut_asserteq(0, sound_stop_beep(dev));
  51 + ut_asserteq(0, sandbox_get_beep_frequency(dev));
  52 +
  53 + return 0;
  54 +}
  55 +DM_TEST(dm_test_sound_beep, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);