tdmb_data.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. /*
  2. *
  3. * drivers/media/tdmb/tdmb_data.c
  4. *
  5. * tdmb driver
  6. *
  7. * Copyright (C) (2011, Samsung Electronics)
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation version 2.
  12. *
  13. * This program is distributed "as is" WITHOUT ANY WARRANTY of any
  14. * kind, whether express or implied; without even the implied warranty
  15. * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. */
  19. #include <linux/kernel.h>
  20. #include <linux/fs.h>
  21. #include <linux/errno.h>
  22. #include <linux/device.h>
  23. #include <linux/platform_device.h>
  24. #include <linux/init.h>
  25. #include <linux/module.h>
  26. #include <linux/string.h>
  27. #include <linux/types.h>
  28. #include <linux/fcntl.h>
  29. /* for delay(sleep) */
  30. #include <linux/delay.h>
  31. /* for mutex */
  32. #include <linux/mutex.h>
  33. /*using copy to user */
  34. #include <linux/uaccess.h>
  35. #include <linux/clk.h>
  36. #include <linux/mm.h>
  37. #include <linux/slab.h>
  38. #include <linux/workqueue.h>
  39. #include <linux/irq.h>
  40. #include <asm/mach/irq.h>
  41. #include <linux/interrupt.h>
  42. #include <linux/vmalloc.h>
  43. #include <linux/io.h>
  44. #include <mach/gpio.h>
  45. #include "tdmb.h"
  46. #define TS_PACKET_SIZE 188
  47. #define MSC_BUF_SIZE 1024
  48. static unsigned char *msc_buff;
  49. static unsigned char *ts_buff;
  50. static int ts_buff_size;
  51. static int first_packet = 1;
  52. static int ts_buff_pos;
  53. static int msc_buff_pos;
  54. static int mp2_len;
  55. static const int bitrate_table[2][16] = {
  56. /* MPEG1 for id=1*/
  57. {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0},
  58. /* MPEG2 for id=0 */
  59. {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0}
  60. };
  61. static struct workqueue_struct *tdmb_workqueue;
  62. static DECLARE_WORK(tdmb_work, tdmb_pull_data);
  63. irqreturn_t tdmb_irq_handler(int irq, void *dev_id)
  64. {
  65. if (tdmb_workqueue) {
  66. int ret = 0;
  67. ret = queue_work(tdmb_workqueue, &tdmb_work);
  68. if (ret == 0)
  69. DPRINTK("failed in queue_work\n");
  70. }
  71. return IRQ_HANDLED;
  72. }
  73. bool tdmb_create_databuffer(unsigned long int_size)
  74. {
  75. ts_buff_size = int_size * 2;
  76. msc_buff = vmalloc(MSC_BUF_SIZE);
  77. ts_buff = vmalloc(ts_buff_size);
  78. if (msc_buff && ts_buff) {
  79. return true;
  80. } else {
  81. if (msc_buff)
  82. vfree(msc_buff);
  83. if (ts_buff)
  84. vfree(ts_buff);
  85. return false;
  86. }
  87. }
  88. void tdmb_destroy_databuffer(void)
  89. {
  90. if (msc_buff) {
  91. vfree(msc_buff);
  92. msc_buff = NULL;
  93. }
  94. if (ts_buff) {
  95. vfree(ts_buff);
  96. ts_buff = NULL;
  97. }
  98. }
  99. bool tdmb_create_workqueue(void)
  100. {
  101. tdmb_workqueue = create_singlethread_workqueue("ktdmbd");
  102. if (tdmb_workqueue)
  103. return true;
  104. else
  105. return false;
  106. }
  107. bool tdmb_destroy_workqueue(void)
  108. {
  109. if (tdmb_workqueue) {
  110. flush_workqueue(tdmb_workqueue);
  111. destroy_workqueue(tdmb_workqueue);
  112. tdmb_workqueue = NULL;
  113. }
  114. return true;
  115. }
  116. void tdmb_init_data(void)
  117. {
  118. first_packet = 1;
  119. ts_buff_pos = 0;
  120. msc_buff_pos = 0;
  121. mp2_len = 0;
  122. }
  123. static int __add_to_ringbuffer(unsigned char *data, unsigned long data_size)
  124. {
  125. int ret = 0;
  126. unsigned int size;
  127. unsigned int head;
  128. unsigned int tail;
  129. if (tdmb_ts_size == 0)
  130. return 0;
  131. size = data_size;
  132. head = *tdmb_ts_head;
  133. tail = *tdmb_ts_tail;
  134. if (size > tdmb_ts_size) {
  135. DPRINTK("Error - size too large\n");
  136. } else {
  137. unsigned int dist;
  138. if (head >= tail)
  139. dist = head-tail;
  140. else
  141. dist = tdmb_ts_size+head-tail;
  142. /* DPRINTK("dist: %x\n", dist); */
  143. if ((tdmb_ts_size-dist) < size) {
  144. DPRINTK("small space is left in ring(len:%d/free:%d)\n",
  145. size, (tdmb_ts_size-dist));
  146. DPRINTK("ts_head:0x%x, ts_tail:0x%x/head:%d,tail:%d\n",
  147. (unsigned int)tdmb_ts_head,
  148. (unsigned int)tdmb_ts_tail,
  149. (unsigned int)head, tail);
  150. } else {
  151. if (head+size <= tdmb_ts_size) {
  152. memcpy((tdmb_ts_buffer+head),
  153. (char *)data, size);
  154. head += size;
  155. if (head == tdmb_ts_size)
  156. head = 0;
  157. } else {
  158. unsigned int temp_size;
  159. temp_size = tdmb_ts_size-head;
  160. temp_size = (temp_size/DMB_TS_SIZE)*DMB_TS_SIZE;
  161. if (temp_size > 0)
  162. memcpy((tdmb_ts_buffer+head),
  163. (char *)data, temp_size);
  164. memcpy(tdmb_ts_buffer,
  165. (char *)(data+temp_size),
  166. size-temp_size);
  167. head = size-temp_size;
  168. }
  169. /*
  170. * DPRINTK("< data > %x, %x, %x, %x\n",
  171. * *(tdmb_ts_buffer+ *tdmb_ts_head),
  172. * *(tdmb_ts_buffer+ *tdmb_ts_head +1),
  173. * *(tdmb_ts_buffer+ *tdmb_ts_head +2),
  174. * *(tdmb_ts_buffer+ *tdmb_ts_head +3) );
  175. * DPRINTK("exiting - head : %d\n",head);
  176. */
  177. *tdmb_ts_head = head;
  178. }
  179. }
  180. return ret;
  181. }
  182. static int __add_ts_data(unsigned char *data, unsigned long data_size)
  183. {
  184. if (first_packet) {
  185. int j = 0;
  186. DPRINTK("! first sync Size = %ld !\n", data_size);
  187. for (j = 0; j < data_size; j++) {
  188. if (data[j] == 0x47) {
  189. int maxi;
  190. DPRINTK("!!!!! first sync j = %d !!!!!\n", j);
  191. maxi = (data_size - j) / TS_PACKET_SIZE;
  192. ts_buff_pos = (data_size - j) % TS_PACKET_SIZE;
  193. __add_to_ringbuffer(&data[j],
  194. maxi * TS_PACKET_SIZE);
  195. if (ts_buff_pos > 0)
  196. memcpy(ts_buff,
  197. &data[j+maxi*TS_PACKET_SIZE],
  198. ts_buff_pos);
  199. first_packet = 0;
  200. return 0;
  201. }
  202. }
  203. } else {
  204. if (ts_buff_pos > 0) {
  205. if (data[TS_PACKET_SIZE - ts_buff_pos] != 0x47) {
  206. DPRINTK("! error 0x%x,0x%x !\n",
  207. data[TS_PACKET_SIZE - ts_buff_pos],
  208. data[TS_PACKET_SIZE - ts_buff_pos + 1]);
  209. memset(ts_buff, 0, ts_buff_size);
  210. ts_buff_pos = 0;
  211. first_packet = 1;
  212. return -EPERM;
  213. }
  214. memcpy(&ts_buff[ts_buff_pos],
  215. data, TS_PACKET_SIZE-ts_buff_pos);
  216. __add_to_ringbuffer(ts_buff, TS_PACKET_SIZE);
  217. __add_to_ringbuffer(&data[TS_PACKET_SIZE - ts_buff_pos],
  218. data_size - TS_PACKET_SIZE);
  219. memcpy(ts_buff,
  220. &data[data_size-ts_buff_pos],
  221. ts_buff_pos);
  222. } else {
  223. if (data[0] != 0x47) {
  224. DPRINTK("!! error 0x%x,0x%x!!\n",
  225. data[0],
  226. data[1]);
  227. memset(ts_buff, 0, ts_buff_size);
  228. ts_buff_pos = 0;
  229. first_packet = 1;
  230. return -EPERM;
  231. }
  232. __add_to_ringbuffer(data, data_size);
  233. }
  234. }
  235. return 0;
  236. }
  237. static int __get_mp2_len(unsigned char *pkt)
  238. {
  239. int id;
  240. int layer_index;
  241. int bitrate_index;
  242. int fs_index;
  243. int samplerate;
  244. int bitrate;
  245. int length;
  246. id = (pkt[1]>>3)&0x01; /* 1: ISO/IEC 11172-3, 0:ISO/IEC 13818-3 */
  247. layer_index = (pkt[1]>>1)&0x03; /* 2 */
  248. bitrate_index = (pkt[2]>>4);
  249. fs_index = (pkt[2]>>2)&0x3; /* 1 */
  250. /* sync word check */
  251. if (pkt[0] == 0xff && (pkt[1]>>4) == 0xf) {
  252. if ((bitrate_index > 0 && bitrate_index < 15)
  253. && (layer_index == 2) && (fs_index == 1)) {
  254. if (id == 1 && layer_index == 2) {
  255. /* Fs==48 KHz*/
  256. bitrate = 1000*bitrate_table[0][bitrate_index];
  257. samplerate = 48000;
  258. } else if (id == 0 && layer_index == 2) {
  259. /* Fs=24 KHz */
  260. bitrate = 1000*bitrate_table[1][bitrate_index];
  261. samplerate = 24000;
  262. } else
  263. return -EPERM;
  264. } else
  265. return -EPERM;
  266. } else
  267. return -EPERM;
  268. if ((pkt[2]&0x02) != 0) { /* padding bit */
  269. return -EPERM;
  270. }
  271. length = (144*bitrate)/(samplerate);
  272. return length;
  273. }
  274. static int
  275. __add_msc_data(unsigned char *data, unsigned long data_size, int sub_ch_id)
  276. {
  277. unsigned char pOutAddr[TS_PACKET_SIZE];
  278. static int first = 1;
  279. if (first_packet) {
  280. int j;
  281. for (j = 0; j < data_size-4; j++) {
  282. if (data[j] == 0xFF && ((data[j+1]>>4) == 0xF)) {
  283. mp2_len = __get_mp2_len(&data[j]);
  284. DPRINTK("first sync mp2_len= %d\n", mp2_len);
  285. if (mp2_len <= 0 || mp2_len > MSC_BUF_SIZE)
  286. return -EPERM;
  287. memcpy(msc_buff, &data[j], data_size-j);
  288. msc_buff_pos = data_size-j;
  289. first_packet = 0;
  290. first = 1;
  291. return 0;
  292. }
  293. }
  294. } else {
  295. int remainbyte = 0;
  296. if (mp2_len <= 0 || mp2_len > MSC_BUF_SIZE) {
  297. msc_buff_pos = 0;
  298. first_packet = 1;
  299. return -EPERM;
  300. }
  301. remainbyte = data_size;
  302. if ((mp2_len-msc_buff_pos) >= data_size) {
  303. memcpy(msc_buff+msc_buff_pos, data, data_size);
  304. msc_buff_pos += data_size;
  305. remainbyte = 0;
  306. } else if (mp2_len-msc_buff_pos > 0) {
  307. memcpy(msc_buff+msc_buff_pos,
  308. data, (mp2_len - msc_buff_pos));
  309. remainbyte = data_size - (mp2_len - msc_buff_pos);
  310. msc_buff_pos = mp2_len;
  311. }
  312. if (msc_buff_pos == mp2_len) {
  313. int readpos = 0;
  314. while (msc_buff_pos > readpos) {
  315. if (first) {
  316. pOutAddr[0] = 0xDF;
  317. pOutAddr[1] = 0xDF;
  318. pOutAddr[2] = (sub_ch_id<<2);
  319. pOutAddr[2] |=
  320. (((msc_buff_pos>>3)>>8)&0x03);
  321. pOutAddr[3] = (msc_buff_pos>>3)&0xFF;
  322. if (!(msc_buff[0] == 0xFF
  323. && ((msc_buff[1]>>4) == 0xF))) {
  324. DPRINTK("!!error 0x%x,0x%x!!\n",
  325. msc_buff[0],
  326. msc_buff[1]);
  327. memset(msc_buff,
  328. 0,
  329. MSC_BUF_SIZE);
  330. msc_buff_pos = 0;
  331. first_packet = 1;
  332. return -EPERM;
  333. }
  334. memcpy(pOutAddr+4, msc_buff, 184);
  335. readpos = 184;
  336. first = 0;
  337. } else {
  338. pOutAddr[0] = 0xDF;
  339. pOutAddr[1] = 0xD0;
  340. if (msc_buff_pos-readpos >= 184) {
  341. memcpy(pOutAddr+4,
  342. msc_buff+readpos,
  343. 184);
  344. readpos += 184;
  345. } else {
  346. memcpy(pOutAddr+4,
  347. msc_buff+readpos,
  348. msc_buff_pos-readpos);
  349. readpos
  350. += (msc_buff_pos-readpos);
  351. }
  352. }
  353. __add_to_ringbuffer(pOutAddr, TS_PACKET_SIZE);
  354. }
  355. first = 1;
  356. msc_buff_pos = 0;
  357. if (remainbyte > 0) {
  358. memcpy(msc_buff
  359. , data+data_size-remainbyte
  360. , remainbyte);
  361. msc_buff_pos = remainbyte;
  362. }
  363. } else if (msc_buff_pos > mp2_len) {
  364. DPRINTK("! Error msc_buff_pos=%d, mp2_len =%d!\n",
  365. msc_buff_pos, mp2_len);
  366. memset(msc_buff, 0, MSC_BUF_SIZE);
  367. msc_buff_pos = 0;
  368. first_packet = 1;
  369. return -EPERM;
  370. }
  371. }
  372. return 0;
  373. }
  374. bool tdmb_store_data(unsigned char *data, unsigned long len)
  375. {
  376. unsigned long subch_id = tdmb_get_chinfo();
  377. if (subch_id == 0) {
  378. return false;
  379. } else {
  380. subch_id = subch_id % 1000;
  381. if (subch_id >= 64) {
  382. __add_ts_data(data, len);
  383. } else {
  384. unsigned long i;
  385. unsigned long maxi;
  386. maxi = len/TS_PACKET_SIZE;
  387. for (i = 0 ; i < maxi ; i++) {
  388. __add_msc_data(data, TS_PACKET_SIZE, subch_id);
  389. data += TS_PACKET_SIZE;
  390. }
  391. if (len - maxi * TS_PACKET_SIZE)
  392. __add_msc_data(data,\
  393. len - maxi * TS_PACKET_SIZE, subch_id);
  394. }
  395. return true;
  396. }
  397. }