2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License version 2 as
4 * published by the Free Software Foundation.
5 * pcm.c - pcm internal function
15 unsigned int sys_dma_inited
= 0; /* if other driver inited dma ,set this flag to ture */
20 //#define XRUN_AND_INTRLOST_DEBUG
22 static const struct pcm_format_data pcm_formats
[(INT
)SNDRV_PCM_FORMAT_LAST
+1] = {
23 [SNDRV_PCM_FORMAT_S8
] = {
24 .width
= 8, .phys
= 8, .le
= -1, .signd
= 1,
27 [SNDRV_PCM_FORMAT_U8
] = {
28 .width
= 8, .phys
= 8, .le
= -1, .signd
= 0,
31 [SNDRV_PCM_FORMAT_S16_LE
] = {
32 .width
= 16, .phys
= 16, .le
= 1, .signd
= 1,
33 .silence
= {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
35 [SNDRV_PCM_FORMAT_S16_BE
] = {
36 .width
= 16, .phys
= 16, .le
= 0, .signd
= 1,
39 [SNDRV_PCM_FORMAT_U16_LE
] = {
40 .width
= 16, .phys
= 16, .le
= 1, .signd
= 0,
41 .silence
= { 0x00, 0x80 },
43 [SNDRV_PCM_FORMAT_U16_BE
] = {
44 .width
= 16, .phys
= 16, .le
= 0, .signd
= 0,
45 .silence
= { 0x80, 0x00 },
47 [SNDRV_PCM_FORMAT_S24_LE
] = {
48 .width
= 24, .phys
= 32, .le
= 1, .signd
= 1,
51 [SNDRV_PCM_FORMAT_S24_BE
] = {
52 .width
= 24, .phys
= 32, .le
= 0, .signd
= 1,
55 [SNDRV_PCM_FORMAT_U24_LE
] = {
56 .width
= 24, .phys
= 32, .le
= 1, .signd
= 0,
57 .silence
= { 0x00, 0x00, 0x80 },
59 [SNDRV_PCM_FORMAT_U24_BE
] = {
60 .width
= 24, .phys
= 32, .le
= 0, .signd
= 0,
61 .silence
= { 0x00, 0x80, 0x00, 0x00 },
63 [SNDRV_PCM_FORMAT_S32_LE
] = {
64 .width
= 32, .phys
= 32, .le
= 1, .signd
= 1,
67 [SNDRV_PCM_FORMAT_S32_BE
] = {
68 .width
= 32, .phys
= 32, .le
= 0, .signd
= 1,
71 [SNDRV_PCM_FORMAT_U32_LE
] = {
72 .width
= 32, .phys
= 32, .le
= 1, .signd
= 0,
73 .silence
= { 0x00, 0x00, 0x00, 0x80 },
75 [SNDRV_PCM_FORMAT_U32_BE
] = {
76 .width
= 32, .phys
= 32, .le
= 0, .signd
= 0,
77 .silence
= { 0x80, 0x00, 0x00, 0x00 },
80 [SNDRV_PCM_FORMAT_FLOAT_LE
] = {
81 .width
= 32, .phys
= 32, .le
= 1, .signd
= -1,
84 [SNDRV_PCM_FORMAT_FLOAT_BE
] = {
85 .width
= 32, .phys
= 32, .le
= 0, .signd
= -1,
88 [SNDRV_PCM_FORMAT_FLOAT64_LE
] = {
89 .width
= 64, .phys
= 64, .le
= 1, .signd
= -1,
92 [SNDRV_PCM_FORMAT_FLOAT64_BE
] = {
93 .width
= 64, .phys
= 64, .le
= 0, .signd
= -1,
97 [SNDRV_PCM_FORMAT_S24_3LE
] = {
98 .width
= 24, .phys
= 24, .le
= 1, .signd
= 1,
101 [SNDRV_PCM_FORMAT_S24_3BE
] = {
102 .width
= 24, .phys
= 24, .le
= 0, .signd
= 1,
105 [SNDRV_PCM_FORMAT_U24_3LE
] = {
106 .width
= 24, .phys
= 24, .le
= 1, .signd
= 0,
107 .silence
= { 0x00, 0x00, 0x80 },
109 [SNDRV_PCM_FORMAT_U24_3BE
] = {
110 .width
= 24, .phys
= 24, .le
= 0, .signd
= 0,
111 .silence
= { 0x80, 0x00, 0x00 },
114 #ifndef LIMITED_FORMATS
115 [SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE
] = {
116 .width
= 32, .phys
= 32, .le
= 1, .signd
= -1,
119 [SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE
] = {
120 .width
= 32, .phys
= 32, .le
= 0, .signd
= -1,
123 [SNDRV_PCM_FORMAT_MU_LAW
] = {
124 .width
= 8, .phys
= 8, .le
= -1, .signd
= -1,
127 [SNDRV_PCM_FORMAT_A_LAW
] = {
128 .width
= 8, .phys
= 8, .le
= -1, .signd
= -1,
131 [SNDRV_PCM_FORMAT_IMA_ADPCM
] = {
132 .width
= 4, .phys
= 4, .le
= -1, .signd
= -1,
135 [SNDRV_PCM_FORMAT_G723_24
] = {
136 .width
= 3, .phys
= 3, .le
= -1, .signd
= -1,
139 [SNDRV_PCM_FORMAT_G723_40
] = {
140 .width
= 5, .phys
= 5, .le
= -1, .signd
= -1,
143 /* FIXME: the following three formats are not defined properly yet */
144 [SNDRV_PCM_FORMAT_MPEG
] = {
145 .le
= -1, .signd
= -1,
147 [SNDRV_PCM_FORMAT_GSM
] = {
148 .le
= -1, .signd
= -1,
150 [SNDRV_PCM_FORMAT_SPECIAL
] = {
151 .le
= -1, .signd
= -1,
154 [SNDRV_PCM_FORMAT_S24_3LE
] = {
155 .width
= 24, .phys
= 24, .le
= 1, .signd
= 1,
158 [SNDRV_PCM_FORMAT_S24_3BE
] = {
159 .width
= 24, .phys
= 24, .le
= 0, .signd
= 1,
162 [SNDRV_PCM_FORMAT_U24_3LE
] = {
163 .width
= 24, .phys
= 24, .le
= 1, .signd
= 0,
164 .silence
= { 0x00, 0x00, 0x80 },
166 [SNDRV_PCM_FORMAT_U24_3BE
] = {
167 .width
= 24, .phys
= 24, .le
= 0, .signd
= 0,
168 .silence
= { 0x80, 0x00, 0x00 },
171 [SNDRV_PCM_FORMAT_FLOAT_LE
] = {
172 .width
= 32, .phys
= 32, .le
= 1, .signd
= -1,
175 [SNDRV_PCM_FORMAT_FLOAT_BE
] = {
176 .width
= 32, .phys
= 32, .le
= 0, .signd
= -1,
179 [SNDRV_PCM_FORMAT_FLOAT64_LE
] = {
180 .width
= 64, .phys
= 64, .le
= 1, .signd
= -1,
183 [SNDRV_PCM_FORMAT_FLOAT64_BE
] = {
184 .width
= 64, .phys
= 64, .le
= 0, .signd
= -1,
188 [SNDRV_PCM_FORMAT_S20_3LE
] = {
189 .width
= 20, .phys
= 24, .le
= 1, .signd
= 1,
192 [SNDRV_PCM_FORMAT_S20_3BE
] = {
193 .width
= 20, .phys
= 24, .le
= 0, .signd
= 1,
196 [SNDRV_PCM_FORMAT_U20_3LE
] = {
197 .width
= 20, .phys
= 24, .le
= 1, .signd
= 0,
198 .silence
= { 0x00, 0x00, 0x08 },
200 [SNDRV_PCM_FORMAT_U20_3BE
] = {
201 .width
= 20, .phys
= 24, .le
= 0, .signd
= 0,
202 .silence
= { 0x08, 0x00, 0x00 },
204 [SNDRV_PCM_FORMAT_S18_3LE
] = {
205 .width
= 18, .phys
= 24, .le
= 1, .signd
= 1,
208 [SNDRV_PCM_FORMAT_S18_3BE
] = {
209 .width
= 18, .phys
= 24, .le
= 0, .signd
= 1,
212 [SNDRV_PCM_FORMAT_U18_3LE
] = {
213 .width
= 18, .phys
= 24, .le
= 1, .signd
= 0,
214 .silence
= { 0x00, 0x00, 0x02 },
216 [SNDRV_PCM_FORMAT_U18_3BE
] = {
217 .width
= 18, .phys
= 24, .le
= 0, .signd
= 0,
218 .silence
= { 0x02, 0x00, 0x00 },
220 [SNDRV_PCM_FORMAT_G723_24_1B
] = {
221 .width
= 3, .phys
= 8, .le
= -1, .signd
= -1,
224 [SNDRV_PCM_FORMAT_G723_40_1B
] = {
225 .width
= 5, .phys
= 8, .le
= -1, .signd
= -1,
232 static void snd_pcm_period_elapsed(struct snd_pcm_runtime
*runtime
);
233 static int snd_pcm_attach_runtime(struct snd_pcm_runtime
**runtime
);
234 static void snd_pcm_detach_runtime(struct snd_pcm_runtime
*runtime
);
235 int snd_pcm_update_hw_ptr(struct snd_pcm_runtime
*runtime
);
238 /******************************************************************************/
239 /* dma operation functions */
240 static snd_pcm_uframes_t
snd_pcm_pointer(struct snd_pcm_runtime
*runtime
,int in_interrupt
)
242 struct sco_pcm_runtime_data
*iprtd
= runtime
->private_data
;
244 /* printf("%s: %ld %ld,%d\n", __func__, iprtd->offset,
245 bytes_to_frames(runtime, iprtd->offset),in_interrupt);
247 return bytes_to_frames(runtime
, iprtd
->offset
);
251 * dma interrupt callback
253 void audio_dma_irq(void *data
,uint_8 chan
)
255 struct snd_pcm_runtime
*runtime
= (struct snd_pcm_runtime
*)data
;
256 struct sco_pcm_runtime_data
*iprtd
= (struct sco_pcm_runtime_data
*)runtime
->private_data
;
258 iprtd
->offset
+= iprtd
->period_bytes
;
259 iprtd
->offset
%= iprtd
->period_bytes
* iprtd
->periods
; /* offeset = 0,1period, 2periods ... n periods .(circle) */
261 snd_pcm_period_elapsed(runtime
); /* update ring buffer by call snd_pcm_update_hw_ptr0 */
263 // os_get_ticks_interval (runtime); // hw_ptr_ticks_inteval ,get accurate intrrupts interval
267 * set the silence data on the buffer
269 static int snd_pcm_format_set_silence(struct snd_pcm_runtime
*runtime
, void *data
, unsigned int samples
)
273 const unsigned char * pat
;
274 snd_pcm_format_t format
;
276 format
= runtime
->format
;
278 if ((INT
)format
< 0 || (INT
)format
> (INT
)SNDRV_PCM_FORMAT_LAST
)
283 width
= pcm_formats
[(INT
)format
].phys
;
284 pat
= pcm_formats
[(INT
)format
].silence
;
287 /* signed or 1 byte data */
288 if (pcm_formats
[(INT
)format
].signd
== 1 || width
<= 8) {
289 unsigned int bytes
= samples
* width
/ 8;
291 bytes
= (bytes
* runtime
->sample_aligned_bits
/ width
/*runtime->sample_bits*/);
292 os_memset(data
, *pat
, bytes
);
295 /* non-zero samples, fill using a loop */
300 memcpy(dst
, pat
, width
);
304 /* a bit optimization for constant width */
308 os_memcpy(dst
, pat
, 2);
314 os_memcpy(dst
, pat
, 3);
320 os_memcpy(dst
, pat
, 4);
326 os_memcpy(dst
, pat
, 8);
337 * fill ring buffer with silence
338 * runtime->silence_start: starting pointer to silence area
339 * runtime->silence_filled: size filled with silence
340 * runtime->silence_threshold: threshold from application
341 * runtime->silence_size: maximal size from application
343 * when runtime->silence_size >= runtime->boundary - fill processed area with silence immediately
345 void snd_pcm_playback_silence(struct snd_pcm_runtime
*runtime
, snd_pcm_uframes_t new_hw_ptr
)
347 snd_pcm_uframes_t frames
, ofs
, transfer
;
349 if (runtime
->silence_size
< runtime
->boundary
) {
350 snd_pcm_sframes_t noise_dist
, n
;
351 if (runtime
->silence_start
!= runtime
->control
->appl_ptr
) {
352 n
= runtime
->control
->appl_ptr
- runtime
->silence_start
;
354 n
+= runtime
->boundary
;
355 if ((snd_pcm_uframes_t
)n
< runtime
->silence_filled
)
356 runtime
->silence_filled
-= n
;
358 runtime
->silence_filled
= 0;
359 runtime
->silence_start
= runtime
->control
->appl_ptr
;
361 if (runtime
->silence_filled
>= runtime
->buffer_size
)
363 noise_dist
= snd_pcm_playback_hw_avail(runtime
) + runtime
->silence_filled
;
364 if (noise_dist
>= (snd_pcm_sframes_t
) runtime
->silence_threshold
)
366 frames
= runtime
->silence_threshold
- noise_dist
;
367 if (frames
> runtime
->silence_size
)
368 frames
= runtime
->silence_size
;
370 if (new_hw_ptr
== ULONG_MAX
) { /* initialization */
371 snd_pcm_sframes_t avail
= snd_pcm_playback_hw_avail(runtime
);
372 if (avail
> runtime
->buffer_size
)
373 avail
= runtime
->buffer_size
;
374 runtime
->silence_filled
= avail
> 0 ? avail
: 0;
375 runtime
->silence_start
= (runtime
->status
->hw_ptr
+
376 runtime
->silence_filled
) %
377 runtime
->boundary
; /* initialization silence_start pointer always at the end of valid pcm data */
379 ofs
= runtime
->status
->hw_ptr
;
380 frames
= new_hw_ptr
- ofs
;
381 if ((snd_pcm_sframes_t
)frames
< 0)
382 frames
+= runtime
->boundary
;
383 runtime
->silence_filled
-= frames
;
384 if ((snd_pcm_sframes_t
)runtime
->silence_filled
< 0) {
385 runtime
->silence_filled
= 0;
386 runtime
->silence_start
= new_hw_ptr
;
388 runtime
->silence_start
= ofs
;
391 /* at init, fill silence from the end of valid pcm data to the end of buffer */
392 frames
= runtime
->buffer_size
- runtime
->silence_filled
;
394 if (snd_BUG_ON(frames
> runtime
->buffer_size
))
398 ofs
= runtime
->silence_start
% runtime
->buffer_size
;
400 transfer
= ofs
+ frames
> runtime
->buffer_size
? runtime
->buffer_size
- ofs
: frames
;
401 if (runtime
->access
== SNDRV_PCM_ACCESS_INTERLEAVED
) { /* left sample, right sample */
402 /* if (ops->silence) { sco_pcm_silence
404 err = ops->silence(runtime, -1, ofs, transfer);
407 //unsigned char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, ofs) * (runtime->sample_aligned_bits / runtime->sample_bits); /* fixme */
408 unsigned char *hwbuf
= runtime
->dma_area
+ frames_to_bytes(runtime
, ofs
) * runtime
->sample_aligned_bits
/ runtime
->sample_phy_bits
/* runtime->sample_bits*/; /* fixme */
409 /* remove silence fill temprary ,fixme */
410 snd_pcm_format_set_silence(runtime
/*->format*/, hwbuf
, transfer
* runtime
->channels
);
413 /* support lefts and rights */
415 unsigned int channels
= runtime
->channels
;
416 /* sco_pcm_silence dont implement
418 for (c = 0; c < channels; ++c) {
420 err = ops->silence(runtime, c, ofs, transfer);
424 size_t dma_csize
= runtime
->dma_bytes
/ channels
; /* left samples | right samples */
425 for (c
= 0; c
< channels
; ++c
) { /* fixme for sample aliged size in dma buff */
426 char *hwbuf
= (char *)runtime
->dma_area
+ (c
* dma_csize
) + samples_to_bytes(runtime
, ofs
);
427 snd_pcm_format_set_silence(runtime
/*->format*/, hwbuf
, transfer
);
430 runtime
->silence_filled
+= transfer
;
437 /*******************************************************************/
438 /* start ,stop,reset ,prepare */
443 int (*pre_action
)(struct snd_pcm_runtime
*runtime
, int state
);
444 int (*do_action
)(struct snd_pcm_runtime
*runtime
, int state
);
445 void (*undo_action
)(struct snd_pcm_runtime
*runtime
, int state
);
446 void (*post_action
)(struct snd_pcm_runtime
*runtime
, int state
);
449 static int snd_pcm_action(struct action_ops
*ops
,
450 struct snd_pcm_runtime
*runtime
, int state
)
454 /* snd_pcm_start set state = SNDRV_PCM_STATE_RUNNING */
455 res
= ops
->pre_action(runtime
, state
);
458 res
= ops
->do_action(runtime
, state
);
460 ops
->post_action(runtime
, state
);
461 else if (ops
->undo_action
)
462 ops
->undo_action(runtime
, state
);
466 static int snd_pcm_pre_start(struct snd_pcm_runtime
*runtime
, int state
)
468 if (runtime
->status
->state
!= SNDRV_PCM_STATE_PREPARED
)
473 static int snd_pcm_do_start(struct snd_pcm_runtime
*runtime
, int state
)
475 // the order of triger start
477 //cpu interface triger start
478 return sco_pcm_trigger(runtime
,SNDRV_PCM_TRIGGER_START
);
481 static void snd_pcm_undo_start(struct snd_pcm_runtime
*runtime
, int state
)
484 //cpu interface triger stop
485 sco_pcm_trigger(runtime
,/*SNDRV_PCM_TRIGGER_START*/ SNDRV_PCM_TRIGGER_STOP
);
488 static void snd_pcm_post_start(struct snd_pcm_runtime
*runtime
, int state
)
490 runtime
->hw_ptr_ticks
= get_curr_ticks();
491 runtime
->hw_ptr_buffer_ticks
= (runtime
->buffer_size
* HZ
) / runtime
->rate
;
492 runtime
->status
->state
= state
;
494 if (runtime
->stream
== SNDRV_PCM_STREAM_PLAYBACK
&& runtime
->silence_size
> 0)
495 snd_pcm_playback_silence(runtime
, ULONG_MAX
);
498 static struct action_ops snd_pcm_action_start
= {
499 .pre_action
= snd_pcm_pre_start
,
500 .do_action
= snd_pcm_do_start
,
501 .undo_action
= snd_pcm_undo_start
,
502 .post_action
= snd_pcm_post_start
505 static int snd_pcm_start(struct snd_pcm_runtime
*runtime
)
507 /* previous state is prepare */
509 ret
= snd_pcm_action(&snd_pcm_action_start
, runtime
,
510 SNDRV_PCM_STATE_RUNNING
);
517 static int snd_pcm_pre_stop(struct snd_pcm_runtime
*runtime
, int state
)
519 if (runtime
->status
->state
== SNDRV_PCM_STATE_OPEN
)
524 static int snd_pcm_do_stop(struct snd_pcm_runtime
*runtime
, int state
)
526 if (snd_pcm_running(runtime
)){
527 //ops->trigger(runtime, SNDRV_PCM_TRIGGER_STOP);
529 //cpu interface triger stop
530 return sco_pcm_trigger(runtime
,SNDRV_PCM_TRIGGER_STOP
);
532 return 0; /* unconditonally stop all substreams */
535 static void snd_pcm_post_stop(struct snd_pcm_runtime
*runtime
, int state
)
537 if (runtime
->status
->state
!= state
) {
538 runtime
->status
->state
= state
;
540 // To wake_up something at this
543 static struct action_ops snd_pcm_action_stop
= {
544 .pre_action
= snd_pcm_pre_stop
,
545 .do_action
= snd_pcm_do_stop
,
546 .post_action
= snd_pcm_post_stop
550 * try to stop all running streams in the substream group
551 * The state of each stream is then changed to the given state unconditionally.
553 int snd_pcm_stop(struct snd_pcm_runtime
*runtime
, snd_pcm_state_t state
)
555 return snd_pcm_action(&snd_pcm_action_stop
, runtime
, state
);
561 static int snd_pcm_lib_reset(struct snd_pcm_runtime
*runtime
,
565 snd_pcm_stream_lock_irqsave(runtime
, flags
);
566 if (snd_pcm_running(runtime
) &&
567 snd_pcm_update_hw_ptr(runtime
) >= 0){
568 printf("reset at run time,hw_ptr >0\n");
569 runtime
->status
->hw_ptr
%= runtime
->buffer_size
;
572 //---printf("reset at not runtime \n");
573 runtime
->status
->hw_ptr
= 0;
575 snd_pcm_stream_unlock_irqrestore(runtime
, flags
);
579 static int snd_pcm_pre_reset(struct snd_pcm_runtime
*runtime
, int state
)
581 switch (runtime
->status
->state
) {
582 case SNDRV_PCM_STATE_RUNNING
:
583 case SNDRV_PCM_STATE_PREPARED
:
584 case SNDRV_PCM_STATE_PAUSED
:
585 case SNDRV_PCM_STATE_SUSPENDED
:
592 static int snd_pcm_do_reset(struct snd_pcm_runtime
*runtime
, int state
)
594 /* snd_pcm_lib_reset => runtime->status->hw_ptr = 0; */
595 int err
= snd_pcm_lib_reset(runtime
, NULL
);
598 runtime
->hw_ptr_base
= 0;
599 runtime
->hw_ptr_interrupt
= runtime
->status
->hw_ptr
-
600 runtime
->status
->hw_ptr
% runtime
->period_size
;
601 runtime
->silence_start
= runtime
->status
->hw_ptr
;
602 runtime
->silence_filled
= 0;
606 static void snd_pcm_post_reset(struct snd_pcm_runtime
*runtime
, int state
)
608 runtime
->control
->appl_ptr
= runtime
->status
->hw_ptr
;
610 if (runtime
->stream
== SNDRV_PCM_STREAM_PLAYBACK
&& runtime
->silence_size
> 0)
611 snd_pcm_playback_silence(runtime
, ULONG_MAX
);
614 static struct action_ops snd_pcm_action_reset
= {
615 .pre_action
= snd_pcm_pre_reset
,
616 .do_action
= snd_pcm_do_reset
,
617 .post_action
= snd_pcm_post_reset
620 int snd_pcm_reset(struct snd_pcm_runtime
*runtime
)
622 /* snd_pcm_start set state = SNDRV_PCM_STATE_RUNNING */
623 return snd_pcm_action(&snd_pcm_action_reset
, runtime
,
624 SNDRV_PCM_STATE_RUNNING
);
627 /* we use the second argument for updating f_flags,
628 must prepare before runing */
629 static int snd_pcm_pre_prepare(struct snd_pcm_runtime
*runtime
, int f_flags
)
631 if (runtime
->status
->state
== SNDRV_PCM_STATE_OPEN
||
632 runtime
->status
->state
== SNDRV_PCM_STATE_DISCONNECTED
)
634 if (snd_pcm_running(runtime
)) /* if pcm in the running state */
636 /*runtime->f_flags = f_flags;*/
640 static int snd_pcm_do_prepare(struct snd_pcm_runtime
*runtime
, int state
)
643 sco_pcm_prepare(runtime
);
645 /* mark '*' is essential ( sco_pcm_prepare )
648 codec interface prepare
649 cpu interface prepare
652 /* reset silence start = hw_ptr */
653 return snd_pcm_do_reset(runtime
, 0);
656 static void snd_pcm_post_prepare(struct snd_pcm_runtime
*runtime
, int state
)
658 /* set appl_prt of write equal the hw_ptr of read*/
659 runtime
->control
->appl_ptr
= runtime
->status
->hw_ptr
;
661 /* set prepared directly ? */
662 runtime
->status
->state
= SNDRV_PCM_STATE_PREPARED
;
665 static struct action_ops snd_pcm_action_prepare
= {
666 .pre_action
= snd_pcm_pre_prepare
,
667 .do_action
= snd_pcm_do_prepare
,
668 .post_action
= snd_pcm_post_prepare
672 * snd_pcm_prepare - prepare the PCM substream to be triggerable
674 int snd_pcm_prepare(void * handle
)
677 struct snd_pcm_runtime
*runtime
= (struct snd_pcm_runtime
*)handle
;
678 // wait poweron ,clock on
680 res
= snd_pcm_action(&snd_pcm_action_prepare
, runtime
, 0);
687 static int snd_pcm_drop(struct snd_pcm_runtime
*runtime
)
691 if (runtime
->status
->state
== SNDRV_PCM_STATE_OPEN
||
692 runtime
->status
->state
== SNDRV_PCM_STATE_DISCONNECTED
||
693 runtime
->status
->state
== SNDRV_PCM_STATE_SUSPENDED
){
694 pr_err(" Before snd_pcm_drop ,the state is error\n");
698 snd_pcm_stream_lock_irq(runtime
);
700 //if (runtime->status->state == SNDRV_PCM_STATE_PAUSED)
701 //snd_pcm_pause(substream, 0); // runtime->hw_ptr_ticks = get_curr_ticks() - HZ * 1000;
703 snd_pcm_stop(runtime
, SNDRV_PCM_STATE_SETUP
);
704 /* runtime->control->appl_ptr = runtime->status->hw_ptr; */
705 snd_pcm_stream_unlock_irq(runtime
);
711 /* start ,stop,reset ,prepare */
712 /*******************************************************************/
714 static void xrun(struct snd_pcm_runtime
*runtime
)
716 //os_printf("XRUN\n");
717 #ifdef XRUN_AND_INTRLOST_DEBUG
720 snd_pcm_stop(runtime
, SNDRV_PCM_STATE_XRUN
);
723 int snd_pcm_update_state(struct snd_pcm_runtime
*runtime
)
725 snd_pcm_uframes_t avail
;
727 if (runtime
->stream
== SNDRV_PCM_STREAM_PLAYBACK
)
728 avail
= snd_pcm_playback_avail(runtime
);
730 avail
= snd_pcm_capture_avail(runtime
);
732 if (avail
> runtime
->avail_max
)
733 runtime
->avail_max
= avail
;
734 #if 0 /* don't support draining */
735 if (runtime
->status
->state
== SNDRV_PCM_STATE_DRAINING
) {
736 if (avail
>= runtime
->buffer_size
) {
737 snd_pcm_drain_done(runtime
);
742 if (avail
>= runtime
->stop_threshold
) {
743 os_printf("x%d\n",avail
/*,runtime->stop_threshold*/);
750 static int snd_pcm_update_hw_ptr0(struct snd_pcm_runtime
*runtime
,
751 unsigned int in_interrupt
) /* flag indicate that called by dma complete intr */
753 snd_pcm_uframes_t pos
;
754 snd_pcm_uframes_t old_hw_ptr
, new_hw_ptr
, hw_base
;
755 snd_pcm_sframes_t hdelta
, delta
;
756 unsigned long jdelta
;
758 old_hw_ptr
= runtime
->status
->hw_ptr
;
760 pos
= snd_pcm_pointer(runtime
,in_interrupt
); /* get hardware frame ptr => snd_imx_pcm_pointer */
762 if (pos
== /*-1*/SNDRV_PCM_POS_XRUN
) { /* indicate over or under run */
765 if (pos
>= runtime
->buffer_size
) { /* current hardware pointer more than buffer size */
766 os_printf("BUG: pos >= runtime->buffer_size, pos = %ld, "
767 "buffer size = %ld, period size = %ld\n",
768 pos
, runtime
->buffer_size
,
769 runtime
->period_size
);
772 pos
-= pos
% runtime
->min_align
;
774 hw_base
= runtime
->hw_ptr_base
;
775 new_hw_ptr
= hw_base
+ pos
;
777 /* we know that one period was processed */
778 /* delta = "expected next hw_ptr" for in_interrupt != 0 */
779 delta
= runtime
->hw_ptr_interrupt
+ runtime
->period_size
;
780 if (delta
> new_hw_ptr
) {
781 #ifdef CHECK_DOUBLE_ACKED_INTRS
782 /* check for double acknowledged interrupts */
783 hdelta
= get_curr_ticks() - runtime
->hw_ptr_ticks
;
784 if (hdelta
> runtime
->hw_ptr_buffer_ticks
/2) {
785 printf(" check for double acknowledged interrupts\n");
786 hw_base
+= runtime
->buffer_size
; /* reasign hw_base */
787 if (hw_base
>= runtime
->boundary
)
789 new_hw_ptr
= hw_base
+ pos
;
793 hw_base
+= runtime
->buffer_size
;
794 if (hw_base
>= runtime
->boundary
)
796 new_hw_ptr
= hw_base
+ pos
;
798 os_printf("\nd%d>%d\n",delta
,new_hw_ptr
);
803 /* new_hw_ptr might be lower than old_hw_ptr in case when */
804 /* pointer crosses the end of the ring buffer */
805 if (new_hw_ptr
< old_hw_ptr
) {
806 hw_base
+= runtime
->buffer_size
;
807 if (hw_base
>= runtime
->boundary
)
809 new_hw_ptr
= hw_base
+ pos
;
812 delta
= new_hw_ptr
- old_hw_ptr
;
814 delta
+= runtime
->boundary
;
815 /* xrun debug message
816 snd_printd("_update: %s: pos=%u/%u/%u, "
817 "hwptr=%ld/%ld/%ld/%ld\n",
818 in_interrupt ? "period" : "hwptr",
820 (unsigned int)runtime->period_size,
821 (unsigned int)runtime->buffer_size,
822 (unsigned long)delta,
823 (unsigned long)old_hw_ptr,
824 (unsigned long)new_hw_ptr,
825 (unsigned long)runtime->hw_ptr_base);
828 //if (runtime->no_period_wakeup) {
829 //this is in not period interrupt condition,
830 //(but period interrupt defined a interrupt occured when period data process completely )
833 /* something must be really wrong */
834 if (delta
>= runtime
->buffer_size
+ runtime
->period_size
) {
835 printf("Unexpected hw_pointer value %s"
836 "( pos=%ld, new_hw_ptr=%ld, "
838 in_interrupt
? "[Q] " : "[P]",
840 (long)new_hw_ptr
, (long)old_hw_ptr
);
843 #if 0 /* don't support ticks check */
844 /* Skip the ticks check for hardwares with BATCH flag.
845 * Such hardware usually just increases the position at each IRQ,
846 * thus it can't give any strange position.
848 if (runtime
->hw
.info
& SNDRV_PCM_INFO_BATCH
)
851 /* if (hdelta < runtime->delay) // remove for no runtime delay (hdelta 's unit is frames)
853 hdelta -= runtime->delay; */
854 jdelta
= get_curr_ticks() - runtime
->hw_ptr_ticks
;
855 if (((hdelta
* HZ
) / runtime
->rate
) > jdelta
+ HZ
/100) {
856 delta
= jdelta
/(((runtime
->period_size
* HZ
) / runtime
->rate
) + HZ
/100);
857 /* move new_hw_ptr according ticks not pos variable */
858 new_hw_ptr
= old_hw_ptr
;
860 /* use loop to avoid checks for delta overflows */
861 /* the delta value is small or zero in most cases */
863 new_hw_ptr
+= runtime
->period_size
;
864 if (new_hw_ptr
>= runtime
->boundary
)
865 new_hw_ptr
-= runtime
->boundary
;
868 /* align hw_base to buffer_size */
871 "hw_ptr skipping! %s"
872 "(pos=%ld, delta=%ld, period=%ld, "
873 "jdelta=%lu/%lu/%lu, hw_ptr=%ld/%ld)\n",
874 in_interrupt ? "[Q] " : "",
875 (long)pos, (long)hdelta,
876 (long)runtime->period_size, jdelta,
877 ((hdelta * HZ) / runtime->rate), hw_base,
878 (unsigned long)old_hw_ptr,
879 (unsigned long)new_hw_ptr); */
880 /* reset values to proper state */
882 hw_base
= new_hw_ptr
- (new_hw_ptr
% runtime
->buffer_size
);
887 if (delta
> runtime
->period_size
+ runtime
->period_size
/ 2) {
888 /* printf("Lost interrupts? %s"
889 "(stream=%d, delta=%ld, new_hw_ptr=%ld, "
891 in_interrupt ? "[Q] " : "",
892 runtime->stream, (long)delta,
895 //printf("Lost interrupts?\n");
896 #ifdef XRUN_AND_INTRLOST_DEBUG
902 if (runtime
->status
->hw_ptr
== new_hw_ptr
)
905 if (runtime
->stream
== SNDRV_PCM_STREAM_PLAYBACK
906 && runtime
->silence_size
> 0)
907 snd_pcm_playback_silence(runtime
, new_hw_ptr
);
910 delta
= new_hw_ptr
- runtime
->hw_ptr_interrupt
;
912 delta
+= runtime
->boundary
;
913 delta
-= (snd_pcm_uframes_t
)delta
% runtime
->period_size
;
914 runtime
->hw_ptr_interrupt
+= delta
;
915 if (runtime
->hw_ptr_interrupt
>= runtime
->boundary
)
916 runtime
->hw_ptr_interrupt
-= runtime
->boundary
;
918 runtime
->hw_ptr_base
= hw_base
;
919 runtime
->status
->hw_ptr
= new_hw_ptr
;
920 #ifdef CHECK_DOUBLE_ACKED_INTRS
921 runtime
->hw_ptr_ticks
= get_curr_ticks();
924 return snd_pcm_update_state( runtime
);
929 int pcm_format_width(snd_pcm_format_t format
)
932 if ((INT
)format
< 0 || (INT
)format
> (INT
)SNDRV_PCM_FORMAT_LAST
)
934 if ((val
= pcm_formats
[(INT
)format
].width
) == 0)
939 int pcm_format_physical_width(snd_pcm_format_t format
)
942 if ((INT
)format
< 0 || (INT
)format
> (INT
)SNDRV_PCM_FORMAT_LAST
)
944 if ((val
= pcm_formats
[(INT
)format
].phys
) == 0)
949 int pcm_format_little_endian(snd_pcm_format_t format
)
952 if ((INT
)format
< 0 || (INT
)format
> (INT
)SNDRV_PCM_FORMAT_LAST
)
954 if ((val
= pcm_formats
[(INT
)format
].le
) < 0)
959 /* CAUTION: call it with irq disabled */
960 int snd_pcm_update_hw_ptr(struct snd_pcm_runtime
*runtime
)
962 return snd_pcm_update_hw_ptr0(runtime
, 0);
965 /* called by period interrupt */
966 static void snd_pcm_period_elapsed(struct snd_pcm_runtime
*runtime
)
970 snd_pcm_stream_lock_irqsave(runtime
, flags
);
971 if (!snd_pcm_running(runtime
) ||
972 snd_pcm_update_hw_ptr0(runtime
, 1) < 0) /* update hw ptr at dma buffer ! */
976 snd_pcm_stream_unlock_irqrestore(runtime
, flags
);
977 /* after transfer callback ack end
978 if (transfer_ack_end)
979 transfer_ack_end(substream); */
983 /* write call back */
984 static int snd_pcm_write_transfer(struct snd_pcm_runtime
*runtime
,
986 unsigned long data
, unsigned int off
,
987 snd_pcm_uframes_t frames
)
990 /* the offset of playback write data */
991 char *buf
= (char *) data
+ frames_to_bytes(runtime
, off
);
993 if (pcm_stream_copy
) {
994 if ((err
= pcm_stream_copy(runtime
, -1, hwoff
, buf
, frames
)) < 0)
997 /* copy to the place of dma_area hwbuf offset */
998 char *hwbuf
= runtime
->dma_area
+ frames_to_bytes(runtime
, hwoff
);
999 os_memcpy(hwbuf
, buf
, frames_to_bytes(runtime
, frames
));
1002 sco_pcm_stream_copy(runtime
, -1, hwoff
, buf
, frames
);
1008 * Wait until avail_min data becomes available
1009 * Returns a negative error code if any error occurs during operation.
1010 * The available space is stored on availp. When err = 0 and avail = 0
1011 * on the capture stream, it indicates the stream is in DRAINING state.
1013 static int wait_for_avail(struct snd_pcm_runtime
*runtime
,
1014 snd_pcm_uframes_t
*availp
)
1016 int is_playback
= (runtime
->stream
== SNDRV_PCM_STREAM_PLAYBACK
);
1017 /* wait_queue_t wait; */
1019 snd_pcm_uframes_t avail
= 0;
1020 long wait_time
/*, tout*/;
1023 if (runtime
->no_period_wakeup
)
1024 wait_time
= MAX_SCHEDULE_TIMEOUT
;
1027 if (runtime
->rate
) {
1028 long t
= runtime
->period_size
* 2 / runtime
->rate
;
1029 wait_time
= max(t
, wait_time
);
1033 struct sco_pcm_runtime_data
*iprtd
= (struct sco_pcm_runtime_data
*)runtime
->private_data
;
1036 if (runtime
->rate
) {
1037 long t
= /* runtime->period_size * 2 / runtime->rate */iprtd
->period_time
;
1038 wait_time
= max(t
, wait_time
); /* use ms delay */
1044 * We need to check if space became available already
1045 * (and thus the wakeup happened already) first to close
1046 * the race of space already having become available.
1047 * This check must happen after been added to the waitqueue
1048 * and having current state be INTERRUPTIBLE.
1051 avail
= snd_pcm_playback_avail(runtime
);
1053 avail
= snd_pcm_capture_avail(runtime
);
1055 if (avail
>= Wait_avail_min
)
1057 snd_pcm_stream_unlock_irq(runtime
);
1059 /* or use wait availd event (transfer_ack_end)*/
1060 os_msleep(wait_time
);
1062 snd_pcm_stream_lock_irq(runtime
);
1065 err
= -(avail
== 0);
1069 snd_pcm_sframes_t
snd_pcm_lib_write(void * handle
,
1070 unsigned long data
, snd_pcm_uframes_t size
,int nonblock
)
1072 snd_pcm_uframes_t xfer
= 0;
1073 snd_pcm_uframes_t offset
= 0;
1076 struct snd_pcm_runtime
*runtime
= (struct snd_pcm_runtime
*)handle
;
1078 snd_pcm_stream_lock_irq(runtime
);
1080 #if 1 /* open -> prepared -> running */
1081 switch (runtime
->status
->state
) {
1082 case SNDRV_PCM_STATE_PREPARED
:
1083 case SNDRV_PCM_STATE_RUNNING
:
1084 case SNDRV_PCM_STATE_PAUSED
:
1086 case SNDRV_PCM_STATE_XRUN
:
1089 case SNDRV_PCM_STATE_SUSPENDED
:
1098 while (size
> 0) { /* while until size == 0 */
1099 snd_pcm_uframes_t frames
, appl_ptr
, appl_ofs
;
1100 snd_pcm_uframes_t avail
;
1101 snd_pcm_uframes_t cont
;
1102 if (runtime
->status
->state
== SNDRV_PCM_STATE_RUNNING
)
1103 snd_pcm_update_hw_ptr(runtime
);
1104 avail
= snd_pcm_playback_avail(runtime
);
1111 runtime->twake = min_t(snd_pcm_uframes_t, size,
1112 runtime->control->avail_min ? : 1); */
1113 err
= wait_for_avail(runtime
, &avail
); /* wait for peroid consuming time to check has avild space ? */
1118 frames
= size
> avail
? avail
: size
; /* min of the size and availd*/
1119 cont
= runtime
->buffer_size
- runtime
->control
->appl_ptr
% runtime
->buffer_size
;
1120 if (frames
> cont
) /* where space at the both of end and first of the dma buffer , process the end space filling firstly */
1123 if (snd_BUG_ON(!frames
)) {
1124 //runtime->twake = 0;
1125 snd_pcm_stream_unlock_irq(runtime
);
1129 appl_ptr
= runtime
->control
->appl_ptr
;
1130 appl_ofs
= appl_ptr
% runtime
->buffer_size
; /* attention the mod! it caulate the indeed writing pointer */
1131 snd_pcm_stream_unlock_irq(runtime
);
1132 err
= snd_pcm_write_transfer(runtime
, appl_ofs
, data
, offset
, frames
); /* snd_pcm_lib_write_transfer(...) */
1134 snd_pcm_stream_lock_irq(runtime
);
1139 if (appl_ptr
>= runtime
->boundary
)
1140 appl_ptr
-= runtime
->boundary
; /* update appl_ptr (+frames)*/
1141 runtime
->control
->appl_ptr
= appl_ptr
;
1147 if (runtime
->status
->state
== SNDRV_PCM_STATE_PREPARED
&&
1148 snd_pcm_playback_hw_avail(runtime
) >= (snd_pcm_sframes_t
)runtime
->start_threshold
) {
1149 err
= snd_pcm_start(runtime
); /* start dma */
1156 if (xfer
> 0 && err
>= 0){
1157 snd_pcm_update_state(runtime
);
1159 snd_pcm_stream_unlock_irq(runtime
);
1160 return xfer
> 0 ? (snd_pcm_sframes_t
)xfer
: err
;
1164 size_t u_audio_playback(void * handle
, void *buf
, size_t count
)
1167 snd_pcm_sframes_t frames
;
1169 struct snd_pcm_runtime
*runtime
= (struct snd_pcm_runtime
*)handle
;
1174 if (runtime
->status
->state
== SNDRV_PCM_STATE_XRUN
||
1175 runtime
->status
->state
== SNDRV_PCM_STATE_SUSPENDED
) {
1176 result
= snd_pcm_prepare(runtime
);
1178 printf("Preparing sound card failed: %d\n", (int)result
);
1183 frames
= bytes_to_frames(runtime
, count
);
1184 result
= snd_pcm_lib_write(runtime
,(unsigned long)buf
, frames
, NON_BLOCK
/*RW_BLOCK*/);
1185 if (result
!= frames
) {
1186 if ( runtime
->status
->state
!= SNDRV_PCM_STATE_XRUN
) {
1187 //count -= frames_to_bytes(runtime,result);
1188 os_msleep((HZ
* runtime
->period_size
+ (runtime
->rate
-1)) /runtime
->rate
); /* or sleep 10ms */
1189 //printf("Playback %d error: %d\n", frames, (int)result);
1190 #ifdef XRUN_AND_INTRLOST_DEBUG
1191 printf("%d:%d\n", frames
, (int)result
);
1201 size_t file_playback(void * handle
, void *buf
, size_t count
)
1204 snd_pcm_sframes_t frames
;
1206 struct snd_pcm_runtime
*runtime
= (struct snd_pcm_runtime
*)handle
;
1211 if (runtime
->status
->state
== SNDRV_PCM_STATE_XRUN
||
1212 runtime
->status
->state
== SNDRV_PCM_STATE_SUSPENDED
) {
1213 result
= snd_pcm_prepare(runtime
);
1215 printf("Preparing sound card failed: %d\n", (int)result
);
1220 frames
= bytes_to_frames(runtime
, count
);
1221 result
= snd_pcm_lib_write(runtime
,(unsigned long)buf
, frames
,/*NON_BLOCK*/RW_BLOCK
);
1222 if (result
!= frames
) {
1225 os_msleep(/* 10 */(HZ
* runtime
->period_size
+ (runtime
->rate
-1)) /runtime
->rate
);
1226 printf("Playback error: %d\n", (int)result
);
1233 size_t sync_capture(void * handle
, void *buf
, size_t count
)
1236 snd_pcm_sframes_t frames
;
1238 struct snd_pcm_runtime
*runtime
= (struct snd_pcm_runtime
*)handle
;
1243 if (runtime
->status
->state
== SNDRV_PCM_STATE_XRUN
||
1244 runtime
->status
->state
== SNDRV_PCM_STATE_SUSPENDED
) {
1245 result
= snd_pcm_prepare(runtime
);
1247 printf("Preparing sound card failed: %d\n", (int)result
);
1252 frames
= bytes_to_frames(runtime
, count
);
1253 result
= snd_pcm_lib_read(runtime
,(unsigned long)buf
, frames
,/*NON_BLOCK*/RW_BLOCK
);
1254 if (result
!= frames
) {
1257 os_msleep(/* 10 */(HZ
* runtime
->period_size
+ (runtime
->rate
-1)) /runtime
->rate
);
1258 printf("scapture error: %d\n", (int)result
);
1262 return 0 /*result*/;
1265 static int snd_pcm_read_transfer(struct snd_pcm_runtime
*runtime
,
1267 unsigned long data
, unsigned int off
,
1268 snd_pcm_uframes_t frames
)
1271 char *buf
= (char *) data
+ frames_to_bytes(runtime
, off
);
1274 if ((err
= pcm_copy(runtime
, -1, hwoff
, buf
, frames
)) < 0)
1277 char *hwbuf
= runtime
->dma_area
+ frames_to_bytes(runtime
, hwoff
);
1278 os_memcpy(buf
, hwbuf
, frames_to_bytes(runtime
, frames
));
1281 sco_pcm_stream_copy(runtime
, -1, hwoff
, buf
, frames
);
1287 snd_pcm_sframes_t
snd_pcm_lib_read(void * handle
,
1288 unsigned long data
, snd_pcm_uframes_t size
, int nonblock
)
1290 snd_pcm_uframes_t xfer
= 0;
1291 snd_pcm_uframes_t offset
= 0;
1294 struct snd_pcm_runtime
*runtime
= (struct snd_pcm_runtime
*)handle
;
1299 snd_pcm_stream_lock_irq(runtime
);
1301 switch (runtime
->status
->state
) {
1302 case SNDRV_PCM_STATE_PREPARED
:
1303 if (size
>= runtime
->start_threshold
) {
1304 err
= snd_pcm_start(runtime
);
1309 case SNDRV_PCM_STATE_DRAINING
:
1310 case SNDRV_PCM_STATE_RUNNING
:
1311 case SNDRV_PCM_STATE_PAUSED
:
1313 case SNDRV_PCM_STATE_XRUN
:
1316 case SNDRV_PCM_STATE_SUSPENDED
:
1325 snd_pcm_uframes_t frames
, appl_ptr
, appl_ofs
;
1326 snd_pcm_uframes_t avail
;
1327 snd_pcm_uframes_t cont
;
1328 if (runtime
->status
->state
== SNDRV_PCM_STATE_RUNNING
)
1329 snd_pcm_update_hw_ptr(runtime
);
1330 avail
= snd_pcm_capture_avail(runtime
);
1333 if (runtime
->status
->state
==
1334 SNDRV_PCM_STATE_DRAINING
) {
1335 snd_pcm_stop(runtime
, SNDRV_PCM_STATE_SETUP
);
1345 runtime->twake = min_t(snd_pcm_uframes_t, size,
1346 runtime->control->avail_min ? : 1); */
1347 err
= wait_for_avail(runtime
, &avail
);
1351 continue; /* draining */
1354 frames
= size
> avail
? avail
: size
;
1355 cont
= runtime
->buffer_size
- runtime
->control
->appl_ptr
% runtime
->buffer_size
;
1358 if (snd_BUG_ON(!frames
)) {
1359 //runtime->twake = 0;
1360 snd_pcm_stream_unlock_irq(runtime
);
1363 appl_ptr
= runtime
->control
->appl_ptr
;
1364 appl_ofs
= appl_ptr
% runtime
->buffer_size
;
1365 snd_pcm_stream_unlock_irq(runtime
);
1366 err
= /* transfer*/ snd_pcm_read_transfer(runtime
, appl_ofs
, data
, offset
, frames
);
1367 snd_pcm_stream_lock_irq(runtime
);
1371 switch (runtime
->status
->state
) {
1372 case SNDRV_PCM_STATE_XRUN
:
1375 case SNDRV_PCM_STATE_SUSPENDED
:
1383 if (appl_ptr
>= runtime
->boundary
)
1384 appl_ptr
-= runtime
->boundary
;
1385 runtime
->control
->appl_ptr
= appl_ptr
;
1394 if (xfer
> 0 && err
>= 0)
1395 snd_pcm_update_state(runtime
);
1396 snd_pcm_stream_unlock_irq(runtime
);
1397 return xfer
> 0 ? (snd_pcm_sframes_t
)xfer
: err
;
1400 int snd_pcm_params(void * handle
,
1401 struct snd_pcm_params
*params
)
1405 snd_pcm_uframes_t frames
;
1406 struct snd_pcm_runtime
*runtime
= (struct snd_pcm_runtime
*)handle
;
1408 /*if (PCM_RUNTIME_CHECK(runtime))
1410 snd_pcm_stream_lock_irq(runtime
);
1411 switch (runtime
->status
->state
) {
1412 case SNDRV_PCM_STATE_OPEN
:
1413 case SNDRV_PCM_STATE_SETUP
:
1414 case SNDRV_PCM_STATE_PREPARED
:
1415 break; /* set params only at the state of open,setup and prepared ! */
1417 snd_pcm_stream_unlock_irq(runtime
);
1420 snd_pcm_stream_unlock_irq(runtime
);
1422 /* Default params */
1423 /* SNDRV_PCM_ACCESS_INTERLEAVED;
1424 SNDRV_PCM_ACCESS_NONINTERLEAVED
1425 for two channels ,one channel SNDRV_PCM_ACCESS_INTERLEAVED */
1426 runtime
->access
= params
->access
;
1428 runtime
->format
= params
->format
;
1429 runtime
->channels
= params
->channels
;
1431 /* lookup sample bits from runtime format */
1432 bits
= pcm_format_physical_width (runtime
->format
);
1433 runtime
->sample_bits
= bits
;
1434 bits
*= runtime
->channels
;
1435 runtime
->frame_bits
= bits
;
1437 runtime
->sample_aligned_bits
= runtime
->sample_bits
; /* hw buf ,sample aligned bits */
1438 runtime
->sample_phy_bits
= pcm_format_physical_width(runtime
->format
);
1441 while (bits
% 8 != 0) {
1445 /* runtime->byte_align = bits / 8; */
1446 runtime
->min_align
= frames
;
1448 runtime
->rate
= params
->rate
;
1450 /* must set before soc codec paramaters setting ! */
1451 runtime
->period_size
= params
->period_size
;
1453 err
= sco_pcm_params(runtime
,params
);
1455 runtime
->dma_bytes
= frames_to_bytes(runtime
,runtime
->buffer_size
)
1456 * runtime
->sample_aligned_bits
/ runtime
->sample_phy_bits
;
1461 int pcm_stream_init(void ** handle
, unsigned int direction
,struct snd_pcm_params
*params
)
1463 /* static int sco_pcm_open(struct snd_pcm_substream *substream) platform ,sco,cpu dai init startup */
1466 snd_pcm_uframes_t frames
;
1467 //struct sco_pcm_runtime_data *iprtd = NULL;
1468 struct snd_pcm_runtime
**runtime
= (struct snd_pcm_runtime
**)handle
;
1469 static int sys_inited
= 0;
1474 os_printf("system HZ is %d\n",HZ
);
1477 ret
= snd_pcm_attach_runtime(runtime
);
1481 (*runtime
)->stream
= direction
;
1483 //iprtd = (struct sco_pcm_runtime_data *)(*runtime)->private_data;
1485 ret
= sco_pcm_open(*runtime
);
1490 ret
= snd_pcm_params((void *)(*runtime
),params
);
1492 snd_pcm_prepare((void *)(*runtime
));
1498 void pcm_stream_deinit(void * handle
)
1500 struct snd_pcm_runtime
*runtime
= (struct snd_pcm_runtime
*)handle
;
1501 //printf("pcm_stream_deinit+\n");
1502 if (PCM_RUNTIME_CHECK(runtime
))
1505 snd_pcm_drop(runtime
);
1507 sco_pcm_close(runtime
);
1509 //edma_free_chan(SSI_TX_DMA_CHN);
1511 snd_pcm_detach_runtime(runtime
);
1513 //printf("pcm_stream_deinit-\n");
1516 /* This is first executed function when use this pcm lib , then playback_pcm_runtime_init */
1517 static int snd_pcm_attach_runtime(struct snd_pcm_runtime
**runtime
)
1520 int extra_size
= sizeof(struct sco_pcm_runtime_data
);
1522 struct snd_pcm_runtime
* pt
;
1524 *runtime
= os_zalloc(sizeof(struct snd_pcm_runtime
) + extra_size
);
1525 if (*runtime
== NULL
)
1527 //printf("%d\n",sizeof(struct snd_pcm_runtime));
1528 os_memset((void *)(*runtime
),0, sizeof(struct snd_pcm_runtime
) + extra_size
);
1532 size
= sizeof(struct snd_pcm_rt_status
);
1533 /* alloc and zero the snd_pcm_mmap_status struct */
1534 pt
->status
= os_zalloc(size
);
1535 if (pt
->status
== NULL
) {
1540 os_memset((void*)(pt
->status
), 0, sizeof(struct snd_pcm_rt_status
));
1542 size
= sizeof(struct snd_pcm_rt_control
);
1543 pt
->control
= os_zalloc(size
);
1544 if (pt
->control
== NULL
) {
1545 PCM_mem_free((void*)pt
->status
);
1549 os_memset((void*)(pt
->control
), 0, sizeof(struct snd_pcm_rt_control
));
1551 pt
->private_data
= (char *)pt
+ sizeof(struct snd_pcm_runtime
);
1554 pt
->status
->state
= SNDRV_PCM_STATE_OPEN
;
1559 void snd_pcm_detach_runtime(struct snd_pcm_runtime
*runtime
)
1561 PCM_mem_free((void*)runtime
->status
);
1562 PCM_mem_free((void*)runtime
->control
);
1564 PCM_mem_free(runtime
);
1567 int pcm_stream_rate(void * handle
)
1569 struct snd_pcm_runtime
*runtime
= (struct snd_pcm_runtime
*)handle
;
1570 unsigned int curr_ticks
;
1571 // check handle not null
1572 if (PCM_RUNTIME_CHECK(runtime
))
1575 if(snd_pcm_running(runtime
)){
1576 //printf("%d\n",runtime->hw_ptr_ticks_inteval);
1577 return runtime
->period_size
* 1000 *100 / runtime
->hw_ptr_ticks_inteval
;
1583 int snd_pcm_get_avail_rate(void * handle
)
1585 struct snd_pcm_runtime
*runtime
= (struct snd_pcm_runtime
*)handle
;
1588 if(!snd_pcm_running(runtime
))
1590 snd_pcm_stream_lock_irq(runtime
);
1591 if (runtime
->stream
== SNDRV_PCM_STREAM_PLAYBACK
)
1592 rate
= snd_pcm_playback_avail(runtime
) * 100 / runtime
->buffer_size
;
1594 rate
= snd_pcm_capture_avail(runtime
) * 100 / runtime
->buffer_size
;
1595 snd_pcm_stream_unlock_irq(runtime
);
1599 int snd_pcm_vol_ctrl(void * handle
,int updown
) /* 1 up , 0 down */
1602 return sco_pcm_vol_up();
1604 return sco_pcm_vol_down();