dsp_control.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. #include <linux/module.h>
  2. #include <linux/sched.h>
  3. #include <linux/kernel.h>
  4. #include <linux/cache.h>
  5. #include <linux/slab.h>
  6. #include <asm/cacheflush.h>
  7. //include <asm/arch/am_regs.h>
  8. #include <mach/am_regs.h>
  9. //#include <asm/bsp.h>
  10. #include <linux/dma-mapping.h>
  11. #include "dsp_microcode.h"
  12. #include "audiodsp_module.h"
  13. #include "dsp_control.h"
  14. //#include <asm/dsp/dsp_register.h>
  15. #include "dsp_register.h"
  16. #include "dsp_mailbox.h"
  17. #include <linux/delay.h>
  18. #include <linux/clk.h>
  19. #define MIN_CACHE_ALIGN(x) (((x-4)&(~0x1f)))
  20. #define MAX_CACHE_ALIGN(x) ((x+0x1f)&(~0x1f))
  21. #ifndef AUD_ARC_CTL
  22. #define AUD_ARC_CTL MEDIA_CPU_CTL
  23. #endif
  24. extern unsigned IEC958_mode_raw;
  25. static int decopt = 0x0000ffff;
  26. #define RESET_AUD_ARC (1<<13)
  27. static void enable_dsp(int flag)
  28. {
  29. struct clk *clk;
  30. int xtal = 0;
  31. /* RESET DSP */
  32. if(!flag)
  33. CLEAR_MPEG_REG_MASK(AUD_ARC_CTL, 1);
  34. /*write more for make the dsp is realy reset!*/
  35. SET_MPEG_REG_MASK(RESET2_REGISTER, RESET_AUD_ARC);
  36. // M1 has this bug also????
  37. // SET_MPEG_REG_MASK(RESET2_REGISTER, RESET_AUD_ARC);
  38. //SET_MPEG_REG_MASK(RESET2_REGISTER, RESET_AUD_ARC);
  39. /* Enable BVCI low 16MB address mapping to DDR */
  40. // SET_MPEG_REG_MASK(AUD_ARC_CTRL, (1<<DDR_CTL_MAPDDR));
  41. /* polling highest bit of IREG_DDR_CTRL until the mapping is done */
  42. if (flag) {
  43. SET_MPEG_REG_MASK(AUD_ARC_CTL, 1);
  44. CLEAR_MPEG_REG_MASK(AUD_ARC_CTL, 1);
  45. clk=clk_get_sys("a9_clk", NULL);
  46. if(!clk)
  47. {
  48. printk(KERN_ERR "can't find clk %s for a9_clk SETTING!\n\n","clk_xtal");
  49. }
  50. else
  51. {
  52. xtal=clk_get_rate(clk);
  53. }
  54. DSP_WD(DSP_ARM_REF_CLK_VAL, xtal);
  55. }
  56. }
  57. void halt_dsp( struct audiodsp_priv *priv)
  58. {
  59. #ifndef AUDIODSP_RESET
  60. int i;
  61. #endif
  62. if(DSP_RD(DSP_STATUS)==DSP_STATUS_RUNING)
  63. {
  64. #ifndef AUDIODSP_RESET
  65. dsp_mailbox_send(priv,1,M2B_IRQ0_DSP_SLEEP,0,0,0);
  66. for(i = 0; i< 100;i++)
  67. {
  68. if(DSP_RD(DSP_STATUS)== DSP_STATUS_SLEEP)
  69. break;
  70. msleep(1);/*waiting arc2 sleep*/
  71. }
  72. if(i == 100)
  73. DSP_PRNT("warning: dsp is not sleeping when call dsp_stop\n");
  74. #else
  75. dsp_mailbox_send(priv,1,M2B_IRQ0_DSP_HALT,0,0,0);
  76. msleep(1);/*waiting arc2 sleep*/
  77. #endif
  78. }
  79. #ifdef AUDIODSP_RESET
  80. if(DSP_RD(DSP_STATUS)!=DSP_STATUS_RUNING)
  81. {
  82. DSP_WD(DSP_STATUS, DSP_STATUS_HALT);
  83. return ;
  84. }
  85. #endif
  86. if(!priv->dsp_is_started){
  87. enable_dsp(0);/*hardware halt the cpu*/
  88. DSP_WD(DSP_STATUS, DSP_STATUS_HALT);
  89. priv->last_stream_fmt=-1;/*mask the stream format is not valid*/
  90. }
  91. else
  92. DSP_WD(DSP_STATUS, DSP_STATUS_SLEEP);
  93. }
  94. void reset_dsp( struct audiodsp_priv *priv)
  95. {
  96. halt_dsp(priv);
  97. //flush_and_inv_dcache_all();
  98. /* map DSP 0 address so that reset vector points to same vector table as ARC1 */
  99. CLEAR_MPEG_REG_MASK(AUD_ARC_CTL, (0xfff << 4));
  100. // SET_MPEG_REG_MASK(SDRAM_CTL0,1);//arc mapping to ddr memory
  101. SET_MPEG_REG_MASK(AUD_ARC_CTL, ((AUDIO_DSP_START_PHY_ADDR)>> 20) << 4);
  102. // decode option
  103. DSP_WD(DSP_DECODE_OPTION, decopt|(IEC958_mode_raw<<31));
  104. printk("reset dsp : dec opt=%lx\n", DSP_RD(DSP_DECODE_OPTION));
  105. if(!priv->dsp_is_started){
  106. DSP_PRNT("dsp reset now\n");
  107. enable_dsp(1);
  108. }
  109. else{
  110. dsp_mailbox_send(priv,1,M2B_IRQ0_DSP_WAKEUP,0,0,0);
  111. DSP_WD(DSP_STATUS, DSP_STATUS_WAKEUP);
  112. msleep(1);/*waiting arc625 run again */
  113. }
  114. return;
  115. }
  116. static inline int dsp_set_stack( struct audiodsp_priv *priv)
  117. {
  118. dma_addr_t buf_map;
  119. if(priv->dsp_stack_start==0)
  120. priv->dsp_stack_start=(unsigned long)kmalloc(priv->dsp_stack_size,GFP_KERNEL);
  121. if(priv->dsp_stack_start==0)
  122. {
  123. DSP_PRNT("kmalloc error,no memory for audio dsp stack\n");
  124. return -ENOMEM;
  125. }
  126. memset((void*)priv->dsp_stack_start,0,priv->dsp_stack_size);
  127. buf_map = dma_map_single(NULL, (void *)priv->dsp_stack_start, priv->dsp_stack_size, DMA_FROM_DEVICE);
  128. dma_unmap_single(NULL, buf_map, priv->dsp_stack_size, DMA_FROM_DEVICE);
  129. DSP_WD(DSP_STACK_START,MAX_CACHE_ALIGN(ARM_2_ARC_ADDR_SWAP(priv->dsp_stack_start)));
  130. DSP_WD(DSP_STACK_END,MIN_CACHE_ALIGN(ARM_2_ARC_ADDR_SWAP(priv->dsp_stack_start)+priv->dsp_stack_size));
  131. DSP_PRNT("DSP statck start =%#lx,size=%#lx\n",(ulong)ARM_2_ARC_ADDR_SWAP(priv->dsp_stack_start),priv->dsp_stack_size);
  132. if(priv->dsp_gstack_start==0)
  133. priv->dsp_gstack_start=(unsigned long)kmalloc(priv->dsp_gstack_size,GFP_KERNEL);
  134. if(priv->dsp_gstack_start==0)
  135. {
  136. DSP_PRNT("kmalloc error,no memory for audio dsp gp stack\n");
  137. kfree((void *)priv->dsp_stack_start);
  138. return -ENOMEM;
  139. }
  140. memset((void*)priv->dsp_gstack_start,0,priv->dsp_gstack_size);
  141. buf_map = dma_map_single(NULL, (void *)priv->dsp_gstack_start, priv->dsp_gstack_size, DMA_FROM_DEVICE);
  142. dma_unmap_single(NULL, buf_map, priv->dsp_gstack_size, DMA_FROM_DEVICE);
  143. DSP_WD(DSP_GP_STACK_START,MAX_CACHE_ALIGN(ARM_2_ARC_ADDR_SWAP(priv->dsp_gstack_start)));
  144. DSP_WD(DSP_GP_STACK_END,MIN_CACHE_ALIGN(ARM_2_ARC_ADDR_SWAP(priv->dsp_gstack_start)+priv->dsp_gstack_size));
  145. DSP_PRNT("DSP gp statck start =%#lx,size=%#lx\n",(ulong)ARM_2_ARC_ADDR_SWAP(priv->dsp_gstack_start),priv->dsp_gstack_size);
  146. return 0;
  147. }
  148. static inline int dsp_set_heap( struct audiodsp_priv *priv)
  149. {
  150. dma_addr_t buf_map;
  151. if(priv->dsp_heap_size==0)
  152. return 0;
  153. if(priv->dsp_heap_start==0)
  154. priv->dsp_heap_start=(unsigned long)kmalloc(priv->dsp_heap_size,GFP_KERNEL);
  155. if(priv->dsp_heap_start==0)
  156. {
  157. DSP_PRNT("kmalloc error,no memory for audio dsp dsp_set_heap\n");
  158. return -ENOMEM;
  159. }
  160. memset((void *)priv->dsp_heap_start,0,priv->dsp_heap_size);
  161. buf_map = dma_map_single(NULL, (void *)priv->dsp_heap_start, priv->dsp_heap_size, DMA_FROM_DEVICE);
  162. dma_unmap_single(NULL, buf_map, priv->dsp_heap_size, DMA_FROM_DEVICE);
  163. DSP_WD(DSP_MEM_START,MAX_CACHE_ALIGN(ARM_2_ARC_ADDR_SWAP(priv->dsp_heap_start)));
  164. DSP_WD(DSP_MEM_END,MIN_CACHE_ALIGN(ARM_2_ARC_ADDR_SWAP(priv->dsp_heap_start)+priv->dsp_heap_size));
  165. DSP_PRNT("DSP heap start =%#lx,size=%#lx\n",(ulong)ARM_2_ARC_ADDR_SWAP(priv->dsp_heap_start),priv->dsp_heap_size);
  166. return 0;
  167. }
  168. static inline int dsp_set_stream_buffer( struct audiodsp_priv *priv)
  169. {
  170. dma_addr_t buf_map;
  171. if(priv->stream_buffer_mem_size==0)
  172. {
  173. DSP_WD(DSP_DECODE_OUT_START_ADDR,0);
  174. DSP_WD(DSP_DECODE_OUT_END_ADDR,0);
  175. DSP_WD(DSP_DECODE_OUT_RD_ADDR,0);
  176. DSP_WD(DSP_DECODE_OUT_WD_ADDR,0);
  177. return 0;
  178. }
  179. if(priv->stream_buffer_mem==NULL)
  180. priv->stream_buffer_mem=(void*)kmalloc(priv->stream_buffer_mem_size,GFP_KERNEL);
  181. if(priv->stream_buffer_mem==NULL)
  182. {
  183. DSP_PRNT("kmalloc error,no memory for audio dsp stream buffer\n");
  184. return -ENOMEM;
  185. }
  186. memset((void *)priv->stream_buffer_mem,0,priv->stream_buffer_mem_size);
  187. buf_map = dma_map_single(NULL, (void *)priv->stream_buffer_mem, priv->stream_buffer_mem_size, DMA_FROM_DEVICE);
  188. dma_unmap_single(NULL, buf_map, priv->stream_buffer_mem_size, DMA_FROM_DEVICE);
  189. priv->stream_buffer_start=MAX_CACHE_ALIGN((unsigned long)priv->stream_buffer_mem);
  190. priv->stream_buffer_end=MIN_CACHE_ALIGN((unsigned long)priv->stream_buffer_mem+priv->stream_buffer_mem_size);
  191. priv->stream_buffer_size=priv->stream_buffer_end-priv->stream_buffer_start;
  192. if(priv->stream_buffer_size<0)
  193. {
  194. DSP_PRNT("Stream buffer set error,must more larger,mensize=%d,buffer size=%ld\n",
  195. priv->stream_buffer_mem_size,priv->stream_buffer_size
  196. );
  197. kfree(priv->stream_buffer_mem);
  198. priv->stream_buffer_mem=NULL;
  199. return -2;
  200. }
  201. DSP_WD(DSP_DECODE_OUT_START_ADDR,ARM_2_ARC_ADDR_SWAP(priv->stream_buffer_start));
  202. DSP_WD(DSP_DECODE_OUT_END_ADDR,ARM_2_ARC_ADDR_SWAP(priv->stream_buffer_end));
  203. DSP_WD(DSP_DECODE_OUT_RD_ADDR,ARM_2_ARC_ADDR_SWAP(priv->stream_buffer_start));
  204. DSP_WD(DSP_DECODE_OUT_WD_ADDR,ARM_2_ARC_ADDR_SWAP(priv->stream_buffer_start));
  205. DSP_PRNT("DSP stream buffer to [%#lx-%#lx]\n",(ulong)ARM_2_ARC_ADDR_SWAP(priv->stream_buffer_start),(ulong)ARM_2_ARC_ADDR_SWAP(priv->stream_buffer_end));
  206. return 0;
  207. }
  208. int dsp_start( struct audiodsp_priv *priv, struct audiodsp_microcode *mcode)
  209. {
  210. int i;
  211. int res;
  212. mutex_lock(&priv->dsp_mutex);
  213. halt_dsp(priv);
  214. if(priv->stream_fmt!=priv->last_stream_fmt) // remove the trick, bug fixed on dsp side
  215. {
  216. if(audiodsp_microcode_load(audiodsp_privdata(),mcode)!=0)
  217. {
  218. printk("load microcode error\n");
  219. res=-1;
  220. goto exit;
  221. }
  222. priv->last_stream_fmt=priv->stream_fmt;
  223. }
  224. if((res=dsp_set_stack(priv)))
  225. goto exit;
  226. if((res=dsp_set_heap(priv)))
  227. goto exit;
  228. if((res=dsp_set_stream_buffer(priv)))
  229. goto exit;
  230. if(!priv->dsp_is_started)
  231. reset_dsp(priv);
  232. else{
  233. dsp_mailbox_send(priv,1,M2B_IRQ0_DSP_WAKEUP,0,0,0);
  234. msleep(1);/*waiting arc625 run again */
  235. }
  236. priv->dsp_start_time=jiffies;
  237. for(i=0;i<1000;i++)
  238. {
  239. if(DSP_RD(DSP_STATUS)==DSP_STATUS_RUNING)
  240. break;
  241. msleep(1);
  242. }
  243. if(i>=1000)
  244. {
  245. DSP_PRNT("dsp not running \n");
  246. res=-1;
  247. }
  248. else
  249. {
  250. DSP_PRNT("dsp status=%lx\n",DSP_RD(DSP_STATUS));
  251. priv->dsp_is_started=1;
  252. res=0;
  253. }
  254. exit:
  255. mutex_unlock(&priv->dsp_mutex);
  256. return res;
  257. }
  258. int dsp_stop( struct audiodsp_priv *priv)
  259. {
  260. mutex_lock(&priv->dsp_mutex);
  261. #ifdef AUDIODSP_RESET
  262. priv->dsp_is_started=0;
  263. #endif
  264. halt_dsp(priv);
  265. priv->dsp_end_time=jiffies;
  266. #if 0
  267. if(priv->dsp_stack_start!=0)
  268. kfree((void*)priv->dsp_stack_start);
  269. priv->dsp_stack_start=0;
  270. if(priv->dsp_gstack_start!=0)
  271. kfree((void*)priv->dsp_gstack_start);
  272. priv->dsp_gstack_start=0;
  273. if(priv->dsp_heap_start!=0)
  274. kfree((void*)priv->dsp_heap_start);
  275. priv->dsp_heap_start=0;
  276. if(priv->stream_buffer_mem!=NULL)
  277. {
  278. kfree(priv->stream_buffer_mem);
  279. priv->stream_buffer_mem=NULL;
  280. }
  281. #endif
  282. mutex_unlock(&priv->dsp_mutex);
  283. return 0;
  284. }
  285. static int __init decode_option_setup(char *s)
  286. {
  287. unsigned long value = 0xffffffffUL;
  288. if(strict_strtoul(s, 16, &value)){
  289. decopt = 0x0000ffff;
  290. return -1;
  291. }
  292. decopt = (int)value;
  293. return 0;
  294. }
  295. __setup("decopt=",decode_option_setup) ;