auddrv_underflow_mach.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. /*
  2. * Copyright (C) 2007 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /*******************************************************************************
  17. *
  18. * Filename:
  19. * ---------
  20. * AudDrv_devtree_parser.c
  21. *
  22. * Project:
  23. * --------
  24. *
  25. *
  26. * Description:
  27. * ------------
  28. * AudDrv_devtree_parser
  29. *
  30. * Author:
  31. * -------
  32. * Chipeng Chang (mtk02308)
  33. *
  34. *------------------------------------------------------------------------------
  35. *
  36. *
  37. *******************************************************************************/
  38. #include <mt-plat/aee.h>
  39. #include "auddrv_underflow_mach.h"
  40. #define UnderflowrecordNumber (20)
  41. static bool bEnableDump;
  42. /* default setting for samplerate and interrupt count */
  43. static unsigned int mDlSamplerate = 44100;
  44. static const unsigned int DlSampleRateUpperBound = 192000;
  45. static unsigned int InterruptSample = 1024;
  46. static const unsigned int InterruptSampleUpperBound = 192000;
  47. /* static bool bDumpInit = false; */
  48. static unsigned int mDL1InterruptInterval;
  49. static unsigned int mDL1_Interrupt_Interval_Limit;
  50. static unsigned int mDl1Numerator = 8; /* 1.6 */
  51. static unsigned int mDl1denominator = 5;
  52. static unsigned long long Irq_time_t1 = 0, Irq_time_t2;
  53. static bool bAudioInterruptChange;
  54. static unsigned long long UnderflowTime[UnderflowrecordNumber] = { 0 };
  55. static unsigned int UnderflowCounter;
  56. static unsigned int UnderflowThreshold = 3;
  57. static void ClearInterruptTiming(void);
  58. static void DumpUnderFlowTime(void);
  59. static void ClearUnderFlowTime(void);
  60. void SetUnderFlowThreshold(unsigned int Threshold)
  61. {
  62. UnderflowThreshold = Threshold;
  63. }
  64. /* base on devtree name to pares dev tree. */
  65. void Auddrv_Aee_Dump(void)
  66. {
  67. pr_debug("+%s\n", __func__);
  68. if (bEnableDump == true) {
  69. #ifdef _GIT318_READY
  70. aee_kernel_exception_api(__FILE__, __LINE__, DB_OPT_FTRACE, "Audio is blocked",
  71. "audio blocked dump ftrace");
  72. #endif
  73. }
  74. Auddrv_Reset_Dump_State();
  75. pr_debug("-%s\n", __func__);
  76. }
  77. /*
  78. / dump underflow time in kernel
  79. */
  80. static void DumpUnderFlowTime(void)
  81. {
  82. int i = 0;
  83. pr_debug("%s\n", __func__);
  84. for (i = 0; i < UnderflowrecordNumber; i++)
  85. pr_debug("UnderflowTime[%d] = %llu\n", i, UnderflowTime[i]);
  86. }
  87. /*
  88. / when pcm playback is close , need to call this function to clear record.
  89. */
  90. void Auddrv_Set_UnderFlow(void)
  91. {
  92. unsigned long long underflow_time = sched_clock(); /* in ns (10^9) */
  93. pr_debug("%s UnderflowCounter = %d\n", __func__, UnderflowCounter);
  94. UnderflowTime[UnderflowCounter] = underflow_time;
  95. UnderflowCounter++;
  96. UnderflowCounter %= UnderflowrecordNumber;
  97. if (UnderflowCounter > UnderflowThreshold) {
  98. DumpUnderFlowTime();
  99. Auddrv_Aee_Dump();
  100. }
  101. }
  102. /*
  103. / dump underflow time in kernel
  104. */
  105. static void ClearUnderFlowTime(void)
  106. {
  107. int i = 0;
  108. for (i = 0; i < UnderflowrecordNumber; i++)
  109. UnderflowTime[i] = 0;
  110. UnderflowCounter = 0;
  111. }
  112. /*
  113. / when InterruptSample or mDlSamplerate is change , nned to refine mDL1InterruptInterval
  114. */
  115. void Auddrv_Set_Interrupt_Changed(bool bChange)
  116. {
  117. bAudioInterruptChange = bChange;
  118. }
  119. /*
  120. / when pcm playback is close , need to call this function to clear record.
  121. */
  122. void Auddrv_Reset_Dump_State(void)
  123. {
  124. ClearUnderFlowTime();
  125. Auddrv_Set_Interrupt_Changed(false);
  126. ClearInterruptTiming();
  127. }
  128. /*
  129. / when in interrupt , call this function to check irq timing
  130. */
  131. void Auddrv_CheckInterruptTiming(void)
  132. {
  133. if (Irq_time_t1 == 0) {
  134. Irq_time_t1 = sched_clock(); /* in ns (10^9) */
  135. } else {
  136. Irq_time_t2 = Irq_time_t1;
  137. Irq_time_t1 = sched_clock(); /* in ns (10^9) */
  138. if (bAudioInterruptChange == true) {
  139. /* for Audio Interrupt is change , so this interrupt interval may not clear.clearqueue */
  140. ClearInterruptTiming();
  141. return;
  142. }
  143. if ((Irq_time_t1 > Irq_time_t2) && mDL1_Interrupt_Interval_Limit) {
  144. pr_debug
  145. ("%s Irq_time_t2 = %llu Irq_time_t1 = %llu t1 - t2 = %llu Interval_Limit = %d\n",
  146. __func__, Irq_time_t2, Irq_time_t1, Irq_time_t1 - Irq_time_t2,
  147. mDL1_Interrupt_Interval_Limit);
  148. Irq_time_t2 = Irq_time_t1 - Irq_time_t2;
  149. if (Irq_time_t2 > mDL1_Interrupt_Interval_Limit * 1000000) {
  150. pr_debug
  151. ("%s interrupt may be blocked Irq_time_t2 = %llu Interval_Limit = %d\n",
  152. __func__, Irq_time_t2, mDL1_Interrupt_Interval_Limit);
  153. }
  154. }
  155. }
  156. }
  157. static void ClearInterruptTiming(void)
  158. {
  159. pr_debug("%s\n", __func__);
  160. Irq_time_t1 = 0;
  161. Irq_time_t2 = 0;
  162. }
  163. /*
  164. / when InterruptSample or mDlSamplerate is change , nned to refine mDL1InterruptInterval
  165. */
  166. void RefineInterrruptInterval(void)
  167. {
  168. mDL1InterruptInterval = ((InterruptSample * 1000) / mDlSamplerate) + 1;
  169. mDL1_Interrupt_Interval_Limit = mDL1InterruptInterval * mDl1Numerator / mDl1denominator;
  170. pr_debug("%s mDL1InterruptInterval = %d mDL1_Interrupt_Interval_Limit = %d\n",
  171. __func__, mDL1InterruptInterval, mDL1_Interrupt_Interval_Limit);
  172. }
  173. /*
  174. / function to set DL sampleRate
  175. */
  176. bool Auddrv_Set_DlSamplerate(unsigned int Samplerate)
  177. {
  178. pr_debug("%s Samplerate = %d\n", __func__, Samplerate);
  179. if (Samplerate < DlSampleRateUpperBound) {
  180. mDlSamplerate = Samplerate;
  181. RefineInterrruptInterval();
  182. }
  183. return true;
  184. }
  185. bool Auddrv_Set_InterruptSample(unsigned int count)
  186. {
  187. pr_debug("%s count = %d\n", __func__, count);
  188. if (count < InterruptSampleUpperBound) {
  189. InterruptSample = count;
  190. RefineInterrruptInterval();
  191. Auddrv_Set_Interrupt_Changed(true);
  192. }
  193. return true;
  194. }
  195. /*
  196. / function to enable / disable dump , only enable will arised aee
  197. */
  198. bool Auddrv_Enable_dump(bool bEnable)
  199. {
  200. pr_debug("%s bEnable = %d\n", __func__, bEnable);
  201. bEnableDump = bEnable;
  202. return true;
  203. }