Skip to content

Commit d679343

Browse files
author
Fox Snowpatch
committed
1 parent a2f7734 commit d679343

1 file changed

Lines changed: 44 additions & 11 deletions

File tree

  • sound/aoa/soundbus/i2sbus

sound/aoa/soundbus/i2sbus/pcm.c

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -165,17 +165,16 @@ static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in)
165165
* currently in use (if any). */
166166
hw->rate_min = 5512;
167167
hw->rate_max = 192000;
168-
/* if the other stream is active, then we can only
169-
* support what it is currently using.
170-
* FIXME: I lied. This comment is wrong. We can support
171-
* anything that works with the same serial format, ie.
172-
* when recording 24 bit sound we can well play 16 bit
173-
* sound at the same time iff using the same transfer mode.
168+
/* If the other stream is already prepared, keep this stream
169+
* on the same duplex format and rate.
170+
*
171+
* i2sbus_pcm_prepare() still programs one shared transport
172+
* configuration for both directions, so mixed duplex formats
173+
* are not supported here.
174174
*/
175175
if (other->active) {
176-
/* FIXME: is this guaranteed by the alsa api? */
177176
hw->formats &= pcm_format_to_bits(i2sdev->format);
178-
/* see above, restrict rates to the one we already have */
177+
/* Restrict rates to the one already in use. */
179178
hw->rate_min = i2sdev->rate;
180179
hw->rate_max = i2sdev->rate;
181180
}
@@ -283,6 +282,23 @@ void i2sbus_wait_for_stop_both(struct i2sbus_dev *i2sdev)
283282
}
284283
#endif
285284

285+
static void i2sbus_pcm_clear_active(struct i2sbus_dev *i2sdev, int in)
286+
{
287+
struct pcm_info *pi;
288+
289+
guard(mutex)(&i2sdev->lock);
290+
291+
get_pcm_info(i2sdev, in, &pi, NULL);
292+
pi->active = 0;
293+
}
294+
295+
static inline int i2sbus_hw_params(struct snd_pcm_substream *substream,
296+
struct snd_pcm_hw_params *params, int in)
297+
{
298+
i2sbus_pcm_clear_active(snd_pcm_substream_chip(substream), in);
299+
return 0;
300+
}
301+
286302
static inline int i2sbus_hw_free(struct snd_pcm_substream *substream, int in)
287303
{
288304
struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream);
@@ -291,14 +307,27 @@ static inline int i2sbus_hw_free(struct snd_pcm_substream *substream, int in)
291307
get_pcm_info(i2sdev, in, &pi, NULL);
292308
if (pi->dbdma_ring.stopping)
293309
i2sbus_wait_for_stop(i2sdev, pi);
310+
i2sbus_pcm_clear_active(i2sdev, in);
294311
return 0;
295312
}
296313

314+
static int i2sbus_playback_hw_params(struct snd_pcm_substream *substream,
315+
struct snd_pcm_hw_params *params)
316+
{
317+
return i2sbus_hw_params(substream, params, 0);
318+
}
319+
297320
static int i2sbus_playback_hw_free(struct snd_pcm_substream *substream)
298321
{
299322
return i2sbus_hw_free(substream, 0);
300323
}
301324

325+
static int i2sbus_record_hw_params(struct snd_pcm_substream *substream,
326+
struct snd_pcm_hw_params *params)
327+
{
328+
return i2sbus_hw_params(substream, params, 1);
329+
}
330+
302331
static int i2sbus_record_hw_free(struct snd_pcm_substream *substream)
303332
{
304333
return i2sbus_hw_free(substream, 1);
@@ -335,7 +364,6 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
335364
return -EINVAL;
336365

337366
runtime = pi->substream->runtime;
338-
pi->active = 1;
339367
if (other->active &&
340368
((i2sdev->format != runtime->format)
341369
|| (i2sdev->rate != runtime->rate)))
@@ -450,9 +478,11 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
450478

451479
/* early exit if already programmed correctly */
452480
/* not locking these is fine since we touch them only in this function */
453-
if (in_le32(&i2sdev->intfregs->serial_format) == sfr
454-
&& in_le32(&i2sdev->intfregs->data_word_sizes) == dws)
481+
if (in_le32(&i2sdev->intfregs->serial_format) == sfr &&
482+
in_le32(&i2sdev->intfregs->data_word_sizes) == dws) {
483+
pi->active = 1;
455484
return 0;
485+
}
456486

457487
/* let's notify the codecs about clocks going away.
458488
* For now we only do mastering on the i2s cell... */
@@ -490,6 +520,7 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
490520
if (cii->codec->switch_clock)
491521
cii->codec->switch_clock(cii, CLOCK_SWITCH_SLAVE);
492522

523+
pi->active = 1;
493524
return 0;
494525
}
495526

@@ -734,6 +765,7 @@ static snd_pcm_uframes_t i2sbus_playback_pointer(struct snd_pcm_substream
734765
static const struct snd_pcm_ops i2sbus_playback_ops = {
735766
.open = i2sbus_playback_open,
736767
.close = i2sbus_playback_close,
768+
.hw_params = i2sbus_playback_hw_params,
737769
.hw_free = i2sbus_playback_hw_free,
738770
.prepare = i2sbus_playback_prepare,
739771
.trigger = i2sbus_playback_trigger,
@@ -802,6 +834,7 @@ static snd_pcm_uframes_t i2sbus_record_pointer(struct snd_pcm_substream
802834
static const struct snd_pcm_ops i2sbus_record_ops = {
803835
.open = i2sbus_record_open,
804836
.close = i2sbus_record_close,
837+
.hw_params = i2sbus_record_hw_params,
805838
.hw_free = i2sbus_record_hw_free,
806839
.prepare = i2sbus_record_prepare,
807840
.trigger = i2sbus_record_trigger,

0 commit comments

Comments
 (0)