streambuf.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. /*
  2. * AMLOGIC Audio/Video streaming port driver.
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the named License,
  7. * or any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
  17. *
  18. * Author: Tim Yao <timyao@amlogic.com>
  19. *
  20. */
  21. #include <linux/kernel.h>
  22. #include <linux/spinlock.h>
  23. #include <linux/timer.h>
  24. #include <linux/sched.h>
  25. #include <linux/fs.h>
  26. #include <linux/amports/ptsserv.h>
  27. #include <asm/cacheflush.h>
  28. #include <asm/uaccess.h>
  29. #include <mach/am_regs.h>
  30. #include "vdec_reg.h"
  31. #include "streambuf_reg.h"
  32. #include "streambuf.h"
  33. #define STBUF_SIZE (64*1024)
  34. #define STBUF_WAIT_INTERVAL HZ/100
  35. ulong fetchbuf = 0;
  36. ulong *fetchbuf_remap = NULL;
  37. static s32 _stbuf_alloc(stream_buf_t *buf)
  38. {
  39. if (buf->buf_size == 0) {
  40. return -ENOBUFS;
  41. }
  42. if (buf->buf_start == 0) {
  43. buf->buf_start = __get_free_pages(GFP_KERNEL, get_order(buf->buf_size));
  44. if (!buf->buf_start) {
  45. return -ENOMEM;
  46. }
  47. printk("%s stbuf alloced at 0x%x, size = %d\n",
  48. (buf->type == BUF_TYPE_VIDEO) ? "Video" : (buf->type == BUF_TYPE_AUDIO) ? "Audio" : "Subtitle",
  49. buf->buf_start, buf->buf_size);
  50. }
  51. buf->flag |= BUF_FLAG_ALLOC;
  52. return 0;
  53. }
  54. int stbuf_change_size(struct stream_buf_s *buf, int size)
  55. {
  56. u32 old_buf, old_size;
  57. int ret;
  58. printk("buffersize=%d,%d,start=%x\n", size, buf->buf_size, buf->buf_start);
  59. if (buf->buf_size == size && buf->buf_start != 0) {
  60. return 0;
  61. }
  62. old_buf = buf->buf_start;
  63. old_size = buf->buf_size;
  64. buf->buf_start = 0;
  65. buf->buf_size = size;
  66. ret = size;
  67. if (size == 0 || ((ret = _stbuf_alloc(buf)) == 0)) {
  68. /*
  69. * size=0:We only free the old memory;
  70. * alloc ok,changed to new buffer
  71. */
  72. if (old_buf != 0) {
  73. free_pages(old_buf, get_order(old_size));
  74. }
  75. printk("changed the (%d) buffer size from %d to %d\n", buf->type, old_size, size);
  76. } else {
  77. /* alloc failed */
  78. buf->buf_start = old_buf;
  79. buf->buf_size = old_size;
  80. printk("changed the (%d) buffer size from %d to %d,failed\n", buf->type, old_size, size);
  81. }
  82. return ret;
  83. }
  84. int stbuf_fetch_init(void)
  85. {
  86. if (0 != fetchbuf) {
  87. return 0;
  88. }
  89. fetchbuf = __get_free_pages(GFP_KERNEL, get_order(FETCHBUF_SIZE));
  90. if (!fetchbuf) {
  91. printk("%s: Can not allocate fetch working buffer\n", __FUNCTION__);
  92. return -ENOMEM;
  93. }
  94. fetchbuf_remap = ioremap_nocache(virt_to_phys((u8 *)fetchbuf), FETCHBUF_SIZE);
  95. if (!fetchbuf_remap) {
  96. printk("%s: Can not remap fetch working buffer\n", __FUNCTION__);
  97. free_pages(fetchbuf, get_order(FETCHBUF_SIZE));
  98. fetchbuf = 0;
  99. return -ENOMEM;
  100. }
  101. return 0;
  102. }
  103. void stbuf_fetch_release(void)
  104. {
  105. if (fetchbuf_remap) {
  106. iounmap(fetchbuf_remap);
  107. fetchbuf_remap = 0;
  108. }
  109. if (fetchbuf) {
  110. free_pages(fetchbuf, get_order(FETCHBUF_SIZE));
  111. fetchbuf = 0;
  112. }
  113. return;
  114. }
  115. static inline u32 _stbuf_wp(stream_buf_t *buf)
  116. {
  117. return _READ_ST_REG(WP);
  118. }
  119. static void _stbuf_timer_func(unsigned long arg)
  120. {
  121. struct stream_buf_s *p = (struct stream_buf_s *)arg;
  122. if (stbuf_space(p) < p->wcnt) {
  123. p->timer.expires = jiffies + STBUF_WAIT_INTERVAL;
  124. add_timer(&p->timer);
  125. } else {
  126. wake_up_interruptible(&p->wq);
  127. }
  128. }
  129. u32 stbuf_level(struct stream_buf_s *buf)
  130. {
  131. return _READ_ST_REG(LEVEL);
  132. }
  133. u32 stbuf_rp(struct stream_buf_s *buf)
  134. {
  135. return _READ_ST_REG(RP);
  136. }
  137. u32 stbuf_space(struct stream_buf_s *buf)
  138. {
  139. /* reserved space for safe write, the parser fifo size is 1024byts, so reserve it */
  140. int size = (buf->buf_size - _READ_ST_REG(LEVEL)) - 1024;
  141. return size > 0 ? size : 0;
  142. }
  143. u32 stbuf_size(struct stream_buf_s *buf)
  144. {
  145. return buf->buf_size;
  146. }
  147. s32 stbuf_init(struct stream_buf_s *buf)
  148. {
  149. s32 r;
  150. u32 dummy;
  151. u32 phy_addr;
  152. if (buf->flag & BUF_FLAG_IOMEM) {
  153. phy_addr = buf->buf_start;
  154. } else {
  155. r = _stbuf_alloc(buf);
  156. if (r < 0) {
  157. return r;
  158. }
  159. phy_addr = virt_to_phys((void *)buf->buf_start);
  160. }
  161. init_waitqueue_head(&buf->wq);
  162. if (buf->type == BUF_TYPE_VIDEO) {
  163. _WRITE_ST_REG(CONTROL, 0);
  164. /* reset VLD before setting all pointers */
  165. WRITE_VREG(VLD_MEM_VIFIFO_WRAP_COUNT,0);
  166. #ifdef CONFIG_ARCH_MESON6
  167. WRITE_VREG(DOS_SW_RESET0, (1<<4));
  168. WRITE_VREG(DOS_SW_RESET0, 0);
  169. #else
  170. WRITE_MPEG_REG(RESET0_REGISTER, RESET_VLD);
  171. #endif
  172. dummy = READ_MPEG_REG(RESET0_REGISTER);
  173. WRITE_VREG(POWER_CTL_VLD, 1 << 4);
  174. } else if (buf->type == BUF_TYPE_AUDIO) {
  175. _WRITE_ST_REG(CONTROL, 0);
  176. WRITE_MPEG_REG(AIU_AIFIFO_GBIT, 0x80);
  177. }
  178. if (buf->type == BUF_TYPE_SUBTITLE) {
  179. WRITE_MPEG_REG(PARSER_SUB_RP, phy_addr);
  180. WRITE_MPEG_REG(PARSER_SUB_START_PTR, phy_addr);
  181. WRITE_MPEG_REG(PARSER_SUB_END_PTR, phy_addr + buf->buf_size - 8);
  182. return 0;
  183. }
  184. _WRITE_ST_REG(START_PTR, phy_addr);
  185. _WRITE_ST_REG(CURR_PTR, phy_addr);
  186. _WRITE_ST_REG(END_PTR, phy_addr + buf->buf_size - 8);
  187. _SET_ST_REG_MASK(CONTROL, MEM_BUFCTRL_INIT);
  188. _CLR_ST_REG_MASK(CONTROL, MEM_BUFCTRL_INIT);
  189. _WRITE_ST_REG(BUF_CTRL, MEM_BUFCTRL_MANUAL);
  190. _WRITE_ST_REG(WP, phy_addr);
  191. _SET_ST_REG_MASK(BUF_CTRL, MEM_BUFCTRL_INIT);
  192. _CLR_ST_REG_MASK(BUF_CTRL, MEM_BUFCTRL_INIT);
  193. _SET_ST_REG_MASK(CONTROL, MEM_FILL_ON_LEVEL | MEM_CTRL_FILL_EN | MEM_CTRL_EMPTY_EN);
  194. return 0;
  195. }
  196. s32 stbuf_wait_space(struct stream_buf_s *stream_buf, size_t count)
  197. {
  198. stream_buf_t *p = stream_buf;
  199. long time_out = 20;
  200. p->wcnt = count;
  201. setup_timer(&p->timer, _stbuf_timer_func, (ulong)p);
  202. mod_timer(&p->timer, jiffies + STBUF_WAIT_INTERVAL);
  203. if (wait_event_interruptible_timeout(p->wq, stbuf_space(p) >= count, time_out) == 0) {
  204. del_timer_sync(&p->timer);
  205. return -EAGAIN;
  206. }
  207. del_timer_sync(&p->timer);
  208. return 0;
  209. }
  210. void stbuf_release(struct stream_buf_s *buf)
  211. {
  212. buf->first_tstamp = INVALID_PTS;
  213. stbuf_init(buf); //reinit buffer
  214. if (buf->flag & BUF_FLAG_IOMEM) {
  215. buf->flag = BUF_FLAG_IOMEM;
  216. } else {
  217. buf->flag = 0;
  218. }
  219. }
  220. u32 stbuf_sub_rp_get(void)
  221. {
  222. return READ_MPEG_REG(PARSER_SUB_RP);
  223. }
  224. void stbuf_sub_rp_set(unsigned int sub_rp)
  225. {
  226. WRITE_MPEG_REG(PARSER_SUB_RP, sub_rp);
  227. return;
  228. }
  229. u32 stbuf_sub_wp_get(void)
  230. {
  231. return READ_MPEG_REG(PARSER_SUB_WP);
  232. }
  233. u32 stbuf_sub_start_get(void)
  234. {
  235. return READ_MPEG_REG(PARSER_SUB_START_PTR);
  236. }