24
24
#define PLAYBACK_MIN_PERIOD_SIZE 128
25
25
#define CAPTURE_MIN_NUM_PERIODS 2
26
26
#define CAPTURE_MAX_NUM_PERIODS 8
27
- #define CAPTURE_MAX_PERIOD_SIZE 4096
28
- #define CAPTURE_MIN_PERIOD_SIZE 320
27
+ #define CAPTURE_MAX_PERIOD_SIZE 65536
28
+ #define CAPTURE_MIN_PERIOD_SIZE 6144
29
29
#define BUFFER_BYTES_MAX (PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE)
30
30
#define BUFFER_BYTES_MIN (PLAYBACK_MIN_NUM_PERIODS * PLAYBACK_MIN_PERIOD_SIZE)
31
31
#define COMPR_PLAYBACK_MAX_FRAGMENT_SIZE (128 * 1024)
@@ -64,12 +64,12 @@ struct q6apm_dai_rtd {
64
64
phys_addr_t phys ;
65
65
unsigned int pcm_size ;
66
66
unsigned int pcm_count ;
67
- unsigned int pos ; /* Buffer position */
68
67
unsigned int periods ;
69
68
unsigned int bytes_sent ;
70
69
unsigned int bytes_received ;
71
70
unsigned int copied_total ;
72
71
uint16_t bits_per_sample ;
72
+ snd_pcm_uframes_t queue_ptr ;
73
73
bool next_track ;
74
74
enum stream_state state ;
75
75
struct q6apm_graph * graph ;
@@ -123,25 +123,16 @@ static void event_handler(uint32_t opcode, uint32_t token, void *payload, void *
123
123
{
124
124
struct q6apm_dai_rtd * prtd = priv ;
125
125
struct snd_pcm_substream * substream = prtd -> substream ;
126
- unsigned long flags ;
127
126
128
127
switch (opcode ) {
129
128
case APM_CLIENT_EVENT_CMD_EOS_DONE :
130
129
prtd -> state = Q6APM_STREAM_STOPPED ;
131
130
break ;
132
131
case APM_CLIENT_EVENT_DATA_WRITE_DONE :
133
- spin_lock_irqsave (& prtd -> lock , flags );
134
- prtd -> pos += prtd -> pcm_count ;
135
- spin_unlock_irqrestore (& prtd -> lock , flags );
136
132
snd_pcm_period_elapsed (substream );
137
- if (prtd -> state == Q6APM_STREAM_RUNNING )
138
- q6apm_write_async (prtd -> graph , prtd -> pcm_count , 0 , 0 , 0 );
139
133
140
134
break ;
141
135
case APM_CLIENT_EVENT_DATA_READ_DONE :
142
- spin_lock_irqsave (& prtd -> lock , flags );
143
- prtd -> pos += prtd -> pcm_count ;
144
- spin_unlock_irqrestore (& prtd -> lock , flags );
145
136
snd_pcm_period_elapsed (substream );
146
137
if (prtd -> state == Q6APM_STREAM_RUNNING )
147
138
q6apm_read (prtd -> graph );
@@ -248,7 +239,6 @@ static int q6apm_dai_prepare(struct snd_soc_component *component,
248
239
}
249
240
250
241
prtd -> pcm_count = snd_pcm_lib_period_bytes (substream );
251
- prtd -> pos = 0 ;
252
242
/* rate and channels are sent to audio driver */
253
243
ret = q6apm_graph_media_format_shmem (prtd -> graph , & cfg );
254
244
if (ret < 0 ) {
@@ -294,6 +284,27 @@ static int q6apm_dai_prepare(struct snd_soc_component *component,
294
284
return 0 ;
295
285
}
296
286
287
+ static int q6apm_dai_ack (struct snd_soc_component * component , struct snd_pcm_substream * substream )
288
+ {
289
+ struct snd_pcm_runtime * runtime = substream -> runtime ;
290
+ struct q6apm_dai_rtd * prtd = runtime -> private_data ;
291
+ int i , ret = 0 , avail_periods ;
292
+
293
+ if (substream -> stream == SNDRV_PCM_STREAM_PLAYBACK ) {
294
+ avail_periods = (runtime -> control -> appl_ptr - prtd -> queue_ptr )/runtime -> period_size ;
295
+ for (i = 0 ; i < avail_periods ; i ++ ) {
296
+ ret = q6apm_write_async (prtd -> graph , prtd -> pcm_count , 0 , 0 , NO_TIMESTAMP );
297
+ if (ret < 0 ) {
298
+ dev_err (component -> dev , "Error queuing playback buffer %d\n" , ret );
299
+ return ret ;
300
+ }
301
+ prtd -> queue_ptr += runtime -> period_size ;
302
+ }
303
+ }
304
+
305
+ return ret ;
306
+ }
307
+
297
308
static int q6apm_dai_trigger (struct snd_soc_component * component ,
298
309
struct snd_pcm_substream * substream , int cmd )
299
310
{
@@ -305,9 +316,6 @@ static int q6apm_dai_trigger(struct snd_soc_component *component,
305
316
case SNDRV_PCM_TRIGGER_START :
306
317
case SNDRV_PCM_TRIGGER_RESUME :
307
318
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE :
308
- /* start writing buffers for playback only as we already queued capture buffers */
309
- if (substream -> stream == SNDRV_PCM_STREAM_PLAYBACK )
310
- ret = q6apm_write_async (prtd -> graph , prtd -> pcm_count , 0 , 0 , 0 );
311
319
break ;
312
320
case SNDRV_PCM_TRIGGER_STOP :
313
321
/* TODO support be handled via SoftPause Module */
@@ -377,13 +385,14 @@ static int q6apm_dai_open(struct snd_soc_component *component,
377
385
}
378
386
}
379
387
380
- ret = snd_pcm_hw_constraint_step (runtime , 0 , SNDRV_PCM_HW_PARAM_PERIOD_BYTES , 32 );
388
+ /* setup 10ms latency to accommodate DSP restrictions */
389
+ ret = snd_pcm_hw_constraint_step (runtime , 0 , SNDRV_PCM_HW_PARAM_PERIOD_SIZE , 480 );
381
390
if (ret < 0 ) {
382
391
dev_err (dev , "constraint for period bytes step ret = %d\n" , ret );
383
392
goto err ;
384
393
}
385
394
386
- ret = snd_pcm_hw_constraint_step (runtime , 0 , SNDRV_PCM_HW_PARAM_BUFFER_BYTES , 32 );
395
+ ret = snd_pcm_hw_constraint_step (runtime , 0 , SNDRV_PCM_HW_PARAM_BUFFER_SIZE , 480 );
387
396
if (ret < 0 ) {
388
397
dev_err (dev , "constraint for buffer bytes step ret = %d\n" , ret );
389
398
goto err ;
@@ -428,16 +437,12 @@ static snd_pcm_uframes_t q6apm_dai_pointer(struct snd_soc_component *component,
428
437
struct snd_pcm_runtime * runtime = substream -> runtime ;
429
438
struct q6apm_dai_rtd * prtd = runtime -> private_data ;
430
439
snd_pcm_uframes_t ptr ;
431
- unsigned long flags ;
432
440
433
- spin_lock_irqsave (& prtd -> lock , flags );
434
- if (prtd -> pos == prtd -> pcm_size )
435
- prtd -> pos = 0 ;
436
-
437
- ptr = bytes_to_frames (runtime , prtd -> pos );
438
- spin_unlock_irqrestore (& prtd -> lock , flags );
441
+ ptr = q6apm_get_hw_pointer (prtd -> graph , substream -> stream ) * runtime -> period_size ;
442
+ if (ptr )
443
+ return ptr - 1 ;
439
444
440
- return ptr ;
445
+ return 0 ;
441
446
}
442
447
443
448
static int q6apm_dai_hw_params (struct snd_soc_component * component ,
@@ -652,8 +657,6 @@ static int q6apm_dai_compr_set_params(struct snd_soc_component *component,
652
657
prtd -> pcm_size = runtime -> fragments * runtime -> fragment_size ;
653
658
prtd -> bits_per_sample = 16 ;
654
659
655
- prtd -> pos = 0 ;
656
-
657
660
if (prtd -> next_track != true) {
658
661
memcpy (& prtd -> codec , codec , sizeof (* codec ));
659
662
@@ -836,6 +839,7 @@ static const struct snd_soc_component_driver q6apm_fe_dai_component = {
836
839
.hw_params = q6apm_dai_hw_params ,
837
840
.pointer = q6apm_dai_pointer ,
838
841
.trigger = q6apm_dai_trigger ,
842
+ .ack = q6apm_dai_ack ,
839
843
.compress_ops = & q6apm_dai_compress_ops ,
840
844
.use_dai_pcm_id = true,
841
845
};
0 commit comments