ptsserv.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  1. #include <linux/module.h>
  2. #include <linux/list.h>
  3. #include <linux/spinlock.h>
  4. #include <linux/slab.h>
  5. #include <linux/amports/ptsserv.h>
  6. #include <linux/amports/timestamp.h>
  7. #include <mach/am_regs.h>
  8. #include "vdec_reg.h"
  9. //#define DEBUG_VIDEO
  10. //#define DEBUG_AUDIO
  11. //#define DEBUG_CHECKIN
  12. //#define DEBUG_CHECKOUT
  13. #define VIDEO_REC_SIZE 4096
  14. #define AUDIO_REC_SIZE 4096
  15. #define VIDEO_LOOKUP_RESOLUTION 2500
  16. #define AUDIO_LOOKUP_RESOLUTION 1024
  17. #define OFFSET_DIFF(x, y) ((int)(x - y))
  18. #define OFFSET_LATER(x, y) (OFFSET_DIFF(x, y) > 0)
  19. #define OFFSET_EQLATER(x, y) (OFFSET_DIFF(x, y) >= 0)
  20. enum {
  21. PTS_IDLE = 0,
  22. PTS_INIT = 1,
  23. PTS_LOADING = 2,
  24. PTS_RUNNING = 3,
  25. PTS_DEINIT = 4
  26. };
  27. typedef struct pts_rec_s {
  28. struct list_head list;
  29. u32 offset;
  30. u32 val;
  31. } pts_rec_t;
  32. typedef struct pts_table_s {
  33. u32 status;
  34. int rec_num;
  35. int lookup_threshold;
  36. u32 lookup_cache_offset;
  37. bool lookup_cache_valid;
  38. u32 lookup_cache_pts;
  39. u32 buf_start;
  40. u32 buf_size;
  41. int first_checkin_pts;
  42. int first_lookup_ok;
  43. int first_lookup_is_fail; /* 1: first lookup fail; 0: first lookup success */
  44. pts_rec_t *pts_recs;
  45. unsigned long *pages_list;
  46. struct list_head *pts_search;
  47. struct list_head valid_list;
  48. struct list_head free_list;
  49. #ifdef CALC_CACHED_TIME
  50. u32 last_checkin_offset;
  51. u32 last_checkin_pts;
  52. u32 last_checkout_pts;
  53. #endif
  54. } pts_table_t;
  55. static DEFINE_SPINLOCK(lock);
  56. static pts_table_t pts_table[PTS_TYPE_MAX] = {
  57. {
  58. .status = PTS_IDLE,
  59. .rec_num = VIDEO_REC_SIZE,
  60. .lookup_threshold = VIDEO_LOOKUP_RESOLUTION,
  61. },
  62. {
  63. .status = PTS_IDLE,
  64. .rec_num = AUDIO_REC_SIZE,
  65. .lookup_threshold = AUDIO_LOOKUP_RESOLUTION,
  66. },
  67. };
  68. static inline void get_wrpage_offset(u8 type, u32 *page, u32 *page_offset)
  69. {
  70. ulong flags;
  71. u32 page1, page2, offset;
  72. if (type == PTS_TYPE_VIDEO) {
  73. do {
  74. local_irq_save(flags);
  75. page1 = READ_MPEG_REG(PARSER_AV_WRAP_COUNT) & 0xffff;
  76. offset = READ_MPEG_REG(PARSER_VIDEO_WP);
  77. page2 = READ_MPEG_REG(PARSER_AV_WRAP_COUNT) & 0xffff;
  78. local_irq_restore(flags);
  79. } while (page1 != page2);
  80. *page = page1;
  81. *page_offset = offset - pts_table[PTS_TYPE_VIDEO].buf_start;
  82. } else if (type == PTS_TYPE_AUDIO) {
  83. do {
  84. local_irq_save(flags);
  85. page1 = READ_MPEG_REG(PARSER_AV_WRAP_COUNT) >> 16;
  86. offset = READ_MPEG_REG(PARSER_AUDIO_WP);
  87. page2 = READ_MPEG_REG(PARSER_AV_WRAP_COUNT) >> 16;
  88. local_irq_restore(flags);
  89. } while (page1 != page2);
  90. *page = page1;
  91. *page_offset = offset - pts_table[PTS_TYPE_AUDIO].buf_start;
  92. }
  93. }
  94. static inline void get_rdpage_offset(u8 type, u32 *page, u32 *page_offset)
  95. {
  96. ulong flags;
  97. u32 page1, page2, offset;
  98. if (type == PTS_TYPE_VIDEO) {
  99. do {
  100. local_irq_save(flags);
  101. page1 = READ_VREG(VLD_MEM_VIFIFO_WRAP_COUNT) & 0xffff;
  102. offset = READ_VREG(VLD_MEM_VIFIFO_RP);
  103. page2 = READ_VREG(VLD_MEM_VIFIFO_WRAP_COUNT) & 0xffff;
  104. local_irq_restore(flags);
  105. } while (page1 != page2);
  106. *page = page1;
  107. *page_offset = offset - pts_table[PTS_TYPE_VIDEO].buf_start;
  108. } else if (type == PTS_TYPE_AUDIO) {
  109. do {
  110. local_irq_save(flags);
  111. page1 = READ_MPEG_REG(AIU_MEM_AIFIFO_BUF_WRAP_COUNT) & 0xffff;
  112. offset = READ_MPEG_REG(AIU_MEM_AIFIFO_MAN_RP);
  113. page2 = READ_MPEG_REG(AIU_MEM_AIFIFO_BUF_WRAP_COUNT) & 0xffff;
  114. local_irq_restore(flags);
  115. } while (page1 != page2);
  116. *page = page1;
  117. *page_offset = offset - pts_table[PTS_TYPE_AUDIO].buf_start;
  118. }
  119. }
  120. #ifdef CALC_CACHED_TIME
  121. int pts_cached_time(u8 type)
  122. {
  123. pts_table_t *pTable;
  124. if (type >= PTS_TYPE_MAX) {
  125. return 0;
  126. }
  127. pTable = &pts_table[type];
  128. if((pTable->last_checkin_pts==-1) || (pTable->last_checkout_pts==-1))
  129. return 0;
  130. return pTable->last_checkin_pts-pTable->last_checkout_pts;
  131. }
  132. EXPORT_SYMBOL(pts_cached_time);
  133. #endif
  134. int pts_checkin_offset(u8 type, u32 offset, u32 val)
  135. {
  136. ulong flags;
  137. pts_table_t *pTable;
  138. if (type >= PTS_TYPE_MAX) {
  139. return -EINVAL;
  140. }
  141. pTable = &pts_table[type];
  142. spin_lock_irqsave(&lock, flags);
  143. if (likely((pTable->status == PTS_RUNNING) ||
  144. (pTable->status == PTS_LOADING))) {
  145. pts_rec_t *rec;
  146. if (type == PTS_TYPE_VIDEO && pTable->first_checkin_pts == -1) {
  147. pTable->first_checkin_pts = val;
  148. #ifdef DEBUG_CHECKIN
  149. #ifdef DEBUG_VIDEO
  150. printk("first check in vpts <0x%x:0x%x> ok!\n", offset, val);
  151. #endif
  152. #endif
  153. }
  154. if (type == PTS_TYPE_AUDIO && pTable->first_checkin_pts == -1) {
  155. pTable->first_checkin_pts = val;
  156. #ifdef DEBUG_CHECKIN
  157. #ifdef DEBUG_AUDIO
  158. printk("first check in apts <0x%x:0x%x> ok!\n", offset, val);
  159. #endif
  160. #endif
  161. }
  162. #ifdef DEBUG_CHECKIN
  163. #ifdef DEBUG_VIDEO
  164. if (type == PTS_TYPE_VIDEO) {
  165. printk("check in vpts <0x%x:0x%x>\n", offset, val);
  166. }
  167. #endif
  168. #ifdef DEBUG_AUDIO
  169. if (type == PTS_TYPE_AUDIO) {
  170. printk("check in apts <0x%x:0x%x>\n", offset, val);
  171. }
  172. #endif
  173. #endif
  174. if (list_empty(&pTable->free_list)) {
  175. rec = list_entry(pTable->valid_list.next, pts_rec_t, list);
  176. } else {
  177. rec = list_entry(pTable->free_list.next, pts_rec_t, list);
  178. }
  179. rec->offset = offset;
  180. rec->val = val;
  181. #ifdef CALC_CACHED_TIME
  182. {
  183. s32 diff = offset-pTable->last_checkin_offset;
  184. if(diff>0){
  185. pTable->last_checkin_offset = offset;
  186. pTable->last_checkin_pts = val;
  187. }
  188. }
  189. #endif
  190. list_move_tail(&rec->list, &pTable->valid_list);
  191. spin_unlock_irqrestore(&lock, flags);
  192. if (pTable->status == PTS_LOADING) {
  193. #ifdef DEBUG_VIDEO
  194. if (type == PTS_TYPE_VIDEO) {
  195. printk("init vpts[%d] at 0x%x\n", type, val);
  196. }
  197. #endif
  198. #ifdef DEBUG_VIDEO
  199. if (type == PTS_TYPE_AUDIO) {
  200. printk("init apts[%d] at 0x%x\n", type, val);
  201. }
  202. #endif
  203. if (type == PTS_TYPE_VIDEO) {
  204. WRITE_MPEG_REG(VIDEO_PTS, val);
  205. } else if (type == PTS_TYPE_AUDIO) {
  206. WRITE_MPEG_REG(AUDIO_PTS, val);
  207. }
  208. pTable->status = PTS_RUNNING;
  209. }
  210. return 0;
  211. } else {
  212. spin_unlock_irqrestore(&lock, flags);
  213. return -EINVAL;
  214. }
  215. }
  216. EXPORT_SYMBOL(pts_checkin_offset);
  217. /* This type of PTS could happen in the past,
  218. * e.g. from TS demux when the real time (wr_page, wr_ptr)
  219. * could be bigger than pts parameter here.
  220. */
  221. int pts_checkin_wrptr(u8 type, u32 ptr, u32 val)
  222. {
  223. u32 offset, cur_offset, page, page_no;
  224. if (type >= PTS_TYPE_MAX) {
  225. return -EINVAL;
  226. }
  227. offset = ptr - pts_table[type].buf_start;
  228. get_wrpage_offset(type, &page, &cur_offset);
  229. page_no = (offset > cur_offset) ? (page - 1) : page;
  230. return pts_checkin_offset(type,
  231. pts_table[type].buf_size * page_no + offset, val);
  232. }
  233. EXPORT_SYMBOL(pts_checkin_wrptr);
  234. int pts_checkin(u8 type, u32 val)
  235. {
  236. u32 page, offset;
  237. get_wrpage_offset(type, &page, &offset);
  238. if (type == PTS_TYPE_VIDEO) {
  239. offset = page * pts_table[PTS_TYPE_VIDEO].buf_size + offset;
  240. pts_checkin_offset(PTS_TYPE_VIDEO, offset, val);
  241. return 0;
  242. } else if (type == PTS_TYPE_AUDIO) {
  243. offset = page * pts_table[PTS_TYPE_AUDIO].buf_size + offset;
  244. pts_checkin_offset(PTS_TYPE_AUDIO, offset, val);
  245. return 0;
  246. } else {
  247. return -EINVAL;
  248. }
  249. }
  250. EXPORT_SYMBOL(pts_checkin);
  251. int pts_lookup(u8 type, u32 *val, u32 pts_margin)
  252. {
  253. u32 page, offset;
  254. get_rdpage_offset(type, &page, &offset);
  255. if (type == PTS_TYPE_VIDEO) {
  256. offset = page * pts_table[PTS_TYPE_VIDEO].buf_size + offset;
  257. pts_lookup_offset(PTS_TYPE_VIDEO, offset, val, pts_margin);
  258. return 0;
  259. } else if (type == PTS_TYPE_AUDIO) {
  260. offset = page * pts_table[PTS_TYPE_AUDIO].buf_size + offset;
  261. pts_lookup_offset(PTS_TYPE_AUDIO, offset, val, pts_margin);
  262. return 0;
  263. } else {
  264. return -EINVAL;
  265. }
  266. }
  267. EXPORT_SYMBOL(pts_lookup);
  268. int pts_lookup_offset(u8 type, u32 offset, u32 *val, u32 pts_margin)
  269. {
  270. ulong flags;
  271. pts_table_t *pTable;
  272. int lookup_threshold;
  273. #if defined(DEBUG_VIDEO) || defined(DEBUG_AUDIO)
  274. int look_cnt = 0;
  275. #endif
  276. if (type >= PTS_TYPE_MAX) {
  277. return -EINVAL;
  278. }
  279. pTable = &pts_table[type];
  280. if (pts_margin == 0) {
  281. lookup_threshold = pTable->lookup_threshold;
  282. } else {
  283. lookup_threshold = pts_margin;
  284. }
  285. if (!pTable->first_lookup_ok) {
  286. lookup_threshold <<= 1;
  287. }
  288. spin_lock_irqsave(&lock, flags);
  289. if (likely(pTable->status == PTS_RUNNING)) {
  290. pts_rec_t *p, *p2 = NULL;
  291. if ((pTable->lookup_cache_valid) &&
  292. (offset == pTable->lookup_cache_offset)) {
  293. spin_unlock_irqrestore(&lock, flags);
  294. *val = pTable->lookup_cache_pts;
  295. return 0;
  296. }
  297. if (list_empty(&pTable->valid_list)) {
  298. spin_unlock_irqrestore(&lock, flags);
  299. return -1;
  300. }
  301. if (pTable->pts_search == &pTable->valid_list) {
  302. p = list_entry(pTable->valid_list.next, pts_rec_t, list);
  303. } else {
  304. p = list_entry(pTable->pts_search, pts_rec_t, list);
  305. }
  306. if (OFFSET_LATER(offset, p->offset)) {
  307. p2 = p; /* lookup candidate */
  308. list_for_each_entry_continue(p, &pTable->valid_list, list) {
  309. #if 0
  310. if (type == PTS_TYPE_VIDEO) {
  311. printk(" >> rec: 0x%x\n", p->offset);
  312. }
  313. #endif
  314. #if defined(DEBUG_VIDEO) || defined(DEBUG_AUDIO)
  315. look_cnt++;
  316. #endif
  317. if (OFFSET_LATER(p->offset, offset)) {
  318. break;
  319. }
  320. if (type == PTS_TYPE_AUDIO) {
  321. list_move_tail(&p2->list, &pTable->free_list);
  322. }
  323. p2 = p;
  324. }
  325. } else if (OFFSET_LATER(p->offset, offset)) {
  326. list_for_each_entry_continue_reverse(p, &pTable->valid_list, list) {
  327. #if 0
  328. if (type == PTS_TYPE_VIDEO) {
  329. printk(" >> rec: 0x%x\n", p->offset);
  330. }
  331. #endif
  332. #ifdef DEBUG
  333. look_cnt++;
  334. #endif
  335. if (OFFSET_EQLATER(offset, p->offset)) {
  336. p2 = p;
  337. break;
  338. }
  339. }
  340. } else {
  341. p2 = p;
  342. }
  343. if ((p2) &&
  344. (OFFSET_DIFF(offset, p2->offset) < lookup_threshold)) {
  345. #ifdef DEBUG_CHECKOUT
  346. #ifdef DEBUG_VIDEO
  347. if (type == PTS_TYPE_VIDEO)
  348. printk("vpts look up offset<0x%x> --> <0x%x:0x%x>, look_cnt = %d\n",
  349. offset, p2->offset, p2->val, look_cnt);
  350. #endif
  351. #ifdef DEBUG_AUDIO
  352. if (type == PTS_TYPE_AUDIO)
  353. printk("apts look up offset<0x%x> --> <0x%x:0x%x>, look_cnt = %d\n",
  354. offset, p2->offset, p2->val, look_cnt);
  355. #endif
  356. #endif
  357. *val = p2->val;
  358. #ifdef CALC_CACHED_TIME
  359. pTable->last_checkout_pts = p2->val;
  360. #endif
  361. pTable->lookup_cache_pts = *val;
  362. pTable->lookup_cache_offset = offset;
  363. pTable->lookup_cache_valid = true;
  364. /* update next look up search start point */
  365. pTable->pts_search = p2->list.prev;
  366. list_move_tail(&p2->list, &pTable->free_list);
  367. spin_unlock_irqrestore(&lock, flags);
  368. if (!pTable->first_lookup_ok) {
  369. pTable->first_lookup_ok = 1;
  370. #ifdef DEBUG_CHECKOUT
  371. #ifdef DEBUG_VIDEO
  372. if (type == PTS_TYPE_VIDEO) {
  373. printk("=====first vpts look up offset<0x%x> --> <0x%x:0x%x> ok!\n", offset, p2->offset, p2->val);
  374. }
  375. #endif
  376. #ifdef DEBUG_AUDIO
  377. if (type == PTS_TYPE_AUDIO) {
  378. printk("====first apts look up offset<0x%x> --> <0x%x:0x%x> ok!\n", offset, p2->offset, p2->val);
  379. }
  380. #endif
  381. #endif
  382. }
  383. return 0;
  384. } else {
  385. /* when first pts lookup failed, use first checkin pts instead */
  386. if (!pTable->first_lookup_ok) {
  387. *val = pTable->first_checkin_pts;
  388. pTable->first_lookup_ok = 1;
  389. pTable->first_lookup_is_fail = 1;
  390. #ifdef DEBUG_CHECKOUT
  391. #ifdef DEBUG_VIDEO
  392. if (type == PTS_TYPE_VIDEO)
  393. printk("first vpts look up offset<0x%x> failed, return first_checkin_pts<0x%x>\n",
  394. offset, *val);
  395. #endif
  396. #ifdef DEBUG_AUDIO
  397. if (type == PTS_TYPE_AUDIO)
  398. printk("first apts look up offset<0x%x> failed, return first_checkin_pts<0x%x>\n",
  399. offset, *val);
  400. #endif
  401. #endif
  402. spin_unlock_irqrestore(&lock, flags);
  403. return 0;
  404. }
  405. #ifdef DEBUG_CHECKOUT
  406. #ifdef DEBUG_VIDEO
  407. if (type == PTS_TYPE_VIDEO) {
  408. printk("vpts look up offset<0x%x> failed, look_cnt = %d\n", offset, look_cnt);
  409. }
  410. #endif
  411. #ifdef DEBUG_AUDIO
  412. if (type == PTS_TYPE_AUDIO) {
  413. printk("apts look up offset<0x%x> failed, look_cnt = %d\n", offset, look_cnt);
  414. }
  415. #endif
  416. #endif
  417. spin_unlock_irqrestore(&lock, flags);
  418. return -1;
  419. }
  420. }
  421. spin_unlock_irqrestore(&lock, flags);
  422. return -1;
  423. }
  424. EXPORT_SYMBOL(pts_lookup_offset);
  425. int pts_set_resolution(u8 type, u32 level)
  426. {
  427. if (type >= PTS_TYPE_MAX) {
  428. return -EINVAL;
  429. }
  430. pts_table[type].lookup_threshold = level;
  431. return 0;
  432. }
  433. EXPORT_SYMBOL(pts_set_resolution);
  434. int pts_set_rec_size(u8 type, u32 val)
  435. {
  436. ulong flags;
  437. if (type >= PTS_TYPE_MAX) {
  438. return -EINVAL;
  439. }
  440. spin_lock_irqsave(&lock, flags);
  441. if (pts_table[type].status == PTS_IDLE) {
  442. pts_table[type].rec_num = val;
  443. spin_unlock_irqrestore(&lock, flags);
  444. return 0;
  445. } else {
  446. spin_unlock_irqrestore(&lock, flags);
  447. return -EBUSY;
  448. }
  449. }
  450. EXPORT_SYMBOL(pts_set_rec_size);
  451. //#define SIMPLE_ALLOC_LIST
  452. static void free_pts_list(pts_table_t *pTable)
  453. {
  454. #ifdef SIMPLE_ALLOC_LIST
  455. if(0){/*don't free,used a static memory*/
  456. kfree(pTable->pts_recs);
  457. pTable->pts_recs = NULL;
  458. }
  459. #else
  460. unsigned long *p=pTable->pages_list;
  461. void *onepage=(void *)p[0];
  462. while(onepage!=NULL){
  463. free_page((unsigned long)onepage);
  464. p++;
  465. onepage=(void *)p[0];
  466. }
  467. if(pTable->pages_list)
  468. kfree(pTable->pages_list);
  469. pTable->pages_list=NULL;
  470. #endif
  471. INIT_LIST_HEAD(&pTable->valid_list);
  472. INIT_LIST_HEAD(&pTable->free_list);
  473. }
  474. static int alloc_pts_list(pts_table_t *pTable)
  475. {
  476. int i;
  477. int page_nums;
  478. INIT_LIST_HEAD(&pTable->valid_list);
  479. INIT_LIST_HEAD(&pTable->free_list);
  480. #ifdef SIMPLE_ALLOC_LIST
  481. if (!pTable->pts_recs){
  482. pTable->pts_recs = kcalloc(pTable->rec_num,
  483. sizeof(pts_rec_t), GFP_KERNEL);
  484. }
  485. if (!pTable->pts_recs) {
  486. pTable->status = 0;
  487. return -ENOMEM;
  488. }
  489. for (i = 0; i < pTable->rec_num; i++)
  490. list_add_tail(&pTable->pts_recs[i].list, &pTable->free_list);
  491. return 0;
  492. #else
  493. page_nums=pTable->rec_num*sizeof(pts_rec_t)/PAGE_SIZE;
  494. if(PAGE_SIZE/sizeof(pts_rec_t)!=0){
  495. page_nums=(pTable->rec_num+page_nums+1)*sizeof(pts_rec_t)/PAGE_SIZE;
  496. }
  497. pTable->pages_list=kzalloc(page_nums*4+4,GFP_KERNEL);
  498. if(pTable->pages_list==NULL)
  499. return -ENOMEM;
  500. for(i=0;i<page_nums;i++)
  501. {
  502. int j;
  503. void *one_page=(void *)__get_free_page(GFP_KERNEL);
  504. pts_rec_t *recs=one_page;
  505. if(one_page==NULL)
  506. goto error_alloc_pages;
  507. for(j=0;j<PAGE_SIZE/sizeof(pts_rec_t);j++)
  508. list_add_tail(&recs[j].list, &pTable->free_list);
  509. pTable->pages_list[i]=(unsigned long)one_page;
  510. }
  511. return 0;
  512. error_alloc_pages:
  513. free_pts_list(pTable);
  514. #endif
  515. return -ENOMEM;
  516. }
  517. int pts_start(u8 type)
  518. {
  519. ulong flags;
  520. pts_table_t *pTable;
  521. if (type >= PTS_TYPE_MAX) {
  522. return -EINVAL;
  523. }
  524. pTable = &pts_table[type];
  525. spin_lock_irqsave(&lock, flags);
  526. if (likely(pTable->status == PTS_IDLE)) {
  527. pTable->status = PTS_INIT;
  528. spin_unlock_irqrestore(&lock, flags);
  529. if(alloc_pts_list(pTable)!=0){
  530. return -ENOMEM;
  531. }
  532. if (type == PTS_TYPE_VIDEO) {
  533. pTable->buf_start = READ_VREG(VLD_MEM_VIFIFO_START_PTR);
  534. pTable->buf_size = READ_VREG(VLD_MEM_VIFIFO_END_PTR)
  535. - pTable->buf_start + 8;
  536. /* since the HW buffer wrap counter only have 16 bits,
  537. * a too small buf_size will make pts lookup fail with streaming
  538. * offset wrapped before 32 bits boundary.
  539. * This is unlikely to set such a small streaming buffer though.
  540. */
  541. //BUG_ON(pTable->buf_size <= 0x10000);
  542. WRITE_MPEG_REG(VIDEO_PTS, 0);
  543. timestamp_pcrscr_set(0);//video always need the pcrscr,Clear it to use later
  544. pTable->first_checkin_pts = -1;
  545. pTable->first_lookup_ok = 0;
  546. pTable->first_lookup_is_fail = 0;
  547. } else if (type == PTS_TYPE_AUDIO) {
  548. pTable->buf_start = READ_MPEG_REG(AIU_MEM_AIFIFO_START_PTR);
  549. pTable->buf_size = READ_MPEG_REG(AIU_MEM_AIFIFO_END_PTR)
  550. - pTable->buf_start + 8;
  551. //BUG_ON(pTable->buf_size <= 0x10000);
  552. WRITE_MPEG_REG(AUDIO_PTS, 0);
  553. pTable->first_checkin_pts = -1;
  554. pTable->first_lookup_ok = 0;
  555. pTable->first_lookup_is_fail = 0;
  556. }
  557. #ifdef CALC_CACHED_TIME
  558. pTable->last_checkin_offset = 0;
  559. pTable->last_checkin_pts = -1;
  560. pTable->last_checkout_pts = -1;
  561. #endif
  562. pTable->pts_search = &pTable->valid_list;
  563. pTable->status = PTS_LOADING;
  564. pTable->lookup_cache_valid = false;
  565. return 0;
  566. } else {
  567. spin_unlock_irqrestore(&lock, flags);
  568. return -EBUSY;
  569. }
  570. }
  571. EXPORT_SYMBOL(pts_start);
  572. int pts_stop(u8 type)
  573. {
  574. ulong flags;
  575. pts_table_t *pTable;
  576. if (type >= PTS_TYPE_MAX) {
  577. return -EINVAL;
  578. }
  579. pTable = &pts_table[type];
  580. spin_lock_irqsave(&lock, flags);
  581. if (likely((pTable->status == PTS_RUNNING) ||
  582. (pTable->status == PTS_LOADING))) {
  583. pTable->status = PTS_DEINIT;
  584. spin_unlock_irqrestore(&lock, flags);
  585. free_pts_list(pTable);
  586. pTable->status = PTS_IDLE;
  587. if (type == PTS_TYPE_AUDIO) {
  588. timestamp_apts_set(-1);
  589. }
  590. return 0;
  591. } else {
  592. spin_unlock_irqrestore(&lock, flags);
  593. return -EBUSY;
  594. }
  595. }
  596. EXPORT_SYMBOL(pts_stop);
  597. int first_lookup_pts_failed(u8 type)
  598. {
  599. pts_table_t *pTable;
  600. if (type >= PTS_TYPE_MAX) {
  601. return -EINVAL;
  602. }
  603. pTable = &pts_table[type];
  604. return pTable->first_lookup_is_fail;
  605. }
  606. EXPORT_SYMBOL(first_lookup_pts_failed);
  607. int first_pts_checkin_complete(u8 type)
  608. {
  609. pts_table_t *pTable;
  610. if (type >= PTS_TYPE_MAX) {
  611. return -EINVAL;
  612. }
  613. pTable = &pts_table[type];
  614. if (pTable->first_checkin_pts == -1)
  615. return 0;
  616. else
  617. return 1;
  618. }
  619. EXPORT_SYMBOL(first_pts_checkin_complete);