videobuf2-dvb.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. /*
  2. *
  3. * some helper function for simple DVB cards which simply DMA the
  4. * complete transport stream and let the computer sort everything else
  5. * (i.e. we are using the software demux, ...). Also uses the
  6. * video-buf to manage DMA buffers.
  7. *
  8. * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SUSE Labs]
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version.
  14. */
  15. #include <linux/module.h>
  16. #include <linux/init.h>
  17. #include <linux/device.h>
  18. #include <linux/slab.h>
  19. #include <media/videobuf2-dvb.h>
  20. /* ------------------------------------------------------------------ */
  21. MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
  22. MODULE_LICENSE("GPL");
  23. /* ------------------------------------------------------------------ */
  24. static int dvb_fnc(struct vb2_buffer *vb, void *priv)
  25. {
  26. struct vb2_dvb *dvb = priv;
  27. dvb_dmx_swfilter(&dvb->demux, vb2_plane_vaddr(vb, 0),
  28. vb2_get_plane_payload(vb, 0));
  29. return 0;
  30. }
  31. static int vb2_dvb_start_feed(struct dvb_demux_feed *feed)
  32. {
  33. struct dvb_demux *demux = feed->demux;
  34. struct vb2_dvb *dvb = demux->priv;
  35. int rc = 0;
  36. if (!demux->dmx.frontend)
  37. return -EINVAL;
  38. mutex_lock(&dvb->lock);
  39. dvb->nfeeds++;
  40. if (!dvb->dvbq.threadio) {
  41. rc = vb2_thread_start(&dvb->dvbq, dvb_fnc, dvb, dvb->name);
  42. if (rc)
  43. dvb->nfeeds--;
  44. }
  45. if (!rc)
  46. rc = dvb->nfeeds;
  47. mutex_unlock(&dvb->lock);
  48. return rc;
  49. }
  50. static int vb2_dvb_stop_feed(struct dvb_demux_feed *feed)
  51. {
  52. struct dvb_demux *demux = feed->demux;
  53. struct vb2_dvb *dvb = demux->priv;
  54. int err = 0;
  55. mutex_lock(&dvb->lock);
  56. dvb->nfeeds--;
  57. if (0 == dvb->nfeeds)
  58. err = vb2_thread_stop(&dvb->dvbq);
  59. mutex_unlock(&dvb->lock);
  60. return err;
  61. }
  62. static int vb2_dvb_register_adapter(struct vb2_dvb_frontends *fe,
  63. struct module *module,
  64. void *adapter_priv,
  65. struct device *device,
  66. char *adapter_name,
  67. short *adapter_nr,
  68. int mfe_shared)
  69. {
  70. int result;
  71. mutex_init(&fe->lock);
  72. /* register adapter */
  73. result = dvb_register_adapter(&fe->adapter, adapter_name, module,
  74. device, adapter_nr);
  75. if (result < 0) {
  76. pr_warn("%s: dvb_register_adapter failed (errno = %d)\n",
  77. adapter_name, result);
  78. }
  79. fe->adapter.priv = adapter_priv;
  80. fe->adapter.mfe_shared = mfe_shared;
  81. return result;
  82. }
  83. static int vb2_dvb_register_frontend(struct dvb_adapter *adapter,
  84. struct vb2_dvb *dvb)
  85. {
  86. int result;
  87. /* register frontend */
  88. result = dvb_register_frontend(adapter, dvb->frontend);
  89. if (result < 0) {
  90. pr_warn("%s: dvb_register_frontend failed (errno = %d)\n",
  91. dvb->name, result);
  92. goto fail_frontend;
  93. }
  94. /* register demux stuff */
  95. dvb->demux.dmx.capabilities =
  96. DMX_TS_FILTERING | DMX_SECTION_FILTERING |
  97. DMX_MEMORY_BASED_FILTERING;
  98. dvb->demux.priv = dvb;
  99. dvb->demux.filternum = 256;
  100. dvb->demux.feednum = 256;
  101. dvb->demux.start_feed = vb2_dvb_start_feed;
  102. dvb->demux.stop_feed = vb2_dvb_stop_feed;
  103. result = dvb_dmx_init(&dvb->demux);
  104. if (result < 0) {
  105. pr_warn("%s: dvb_dmx_init failed (errno = %d)\n",
  106. dvb->name, result);
  107. goto fail_dmx;
  108. }
  109. dvb->dmxdev.filternum = 256;
  110. dvb->dmxdev.demux = &dvb->demux.dmx;
  111. dvb->dmxdev.capabilities = 0;
  112. result = dvb_dmxdev_init(&dvb->dmxdev, adapter);
  113. if (result < 0) {
  114. pr_warn("%s: dvb_dmxdev_init failed (errno = %d)\n",
  115. dvb->name, result);
  116. goto fail_dmxdev;
  117. }
  118. dvb->fe_hw.source = DMX_FRONTEND_0;
  119. result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw);
  120. if (result < 0) {
  121. pr_warn("%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n",
  122. dvb->name, result);
  123. goto fail_fe_hw;
  124. }
  125. dvb->fe_mem.source = DMX_MEMORY_FE;
  126. result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem);
  127. if (result < 0) {
  128. pr_warn("%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n",
  129. dvb->name, result);
  130. goto fail_fe_mem;
  131. }
  132. result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw);
  133. if (result < 0) {
  134. pr_warn("%s: connect_frontend failed (errno = %d)\n",
  135. dvb->name, result);
  136. goto fail_fe_conn;
  137. }
  138. /* register network adapter */
  139. result = dvb_net_init(adapter, &dvb->net, &dvb->demux.dmx);
  140. if (result < 0) {
  141. pr_warn("%s: dvb_net_init failed (errno = %d)\n",
  142. dvb->name, result);
  143. goto fail_fe_conn;
  144. }
  145. return 0;
  146. fail_fe_conn:
  147. dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
  148. fail_fe_mem:
  149. dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
  150. fail_fe_hw:
  151. dvb_dmxdev_release(&dvb->dmxdev);
  152. fail_dmxdev:
  153. dvb_dmx_release(&dvb->demux);
  154. fail_dmx:
  155. dvb_unregister_frontend(dvb->frontend);
  156. fail_frontend:
  157. dvb_frontend_detach(dvb->frontend);
  158. dvb->frontend = NULL;
  159. return result;
  160. }
  161. /* ------------------------------------------------------------------ */
  162. /* Register a single adapter and one or more frontends */
  163. int vb2_dvb_register_bus(struct vb2_dvb_frontends *f,
  164. struct module *module,
  165. void *adapter_priv,
  166. struct device *device,
  167. short *adapter_nr,
  168. int mfe_shared)
  169. {
  170. struct list_head *list, *q;
  171. struct vb2_dvb_frontend *fe;
  172. int res;
  173. fe = vb2_dvb_get_frontend(f, 1);
  174. if (!fe) {
  175. pr_warn("Unable to register the adapter which has no frontends\n");
  176. return -EINVAL;
  177. }
  178. /* Bring up the adapter */
  179. res = vb2_dvb_register_adapter(f, module, adapter_priv, device,
  180. fe->dvb.name, adapter_nr, mfe_shared);
  181. if (res < 0) {
  182. pr_warn("vb2_dvb_register_adapter failed (errno = %d)\n", res);
  183. return res;
  184. }
  185. /* Attach all of the frontends to the adapter */
  186. mutex_lock(&f->lock);
  187. list_for_each_safe(list, q, &f->felist) {
  188. fe = list_entry(list, struct vb2_dvb_frontend, felist);
  189. res = vb2_dvb_register_frontend(&f->adapter, &fe->dvb);
  190. if (res < 0) {
  191. pr_warn("%s: vb2_dvb_register_frontend failed (errno = %d)\n",
  192. fe->dvb.name, res);
  193. goto err;
  194. }
  195. }
  196. mutex_unlock(&f->lock);
  197. return 0;
  198. err:
  199. mutex_unlock(&f->lock);
  200. vb2_dvb_unregister_bus(f);
  201. return res;
  202. }
  203. EXPORT_SYMBOL(vb2_dvb_register_bus);
  204. void vb2_dvb_unregister_bus(struct vb2_dvb_frontends *f)
  205. {
  206. vb2_dvb_dealloc_frontends(f);
  207. dvb_unregister_adapter(&f->adapter);
  208. }
  209. EXPORT_SYMBOL(vb2_dvb_unregister_bus);
  210. struct vb2_dvb_frontend *vb2_dvb_get_frontend(
  211. struct vb2_dvb_frontends *f, int id)
  212. {
  213. struct list_head *list, *q;
  214. struct vb2_dvb_frontend *fe, *ret = NULL;
  215. mutex_lock(&f->lock);
  216. list_for_each_safe(list, q, &f->felist) {
  217. fe = list_entry(list, struct vb2_dvb_frontend, felist);
  218. if (fe->id == id) {
  219. ret = fe;
  220. break;
  221. }
  222. }
  223. mutex_unlock(&f->lock);
  224. return ret;
  225. }
  226. EXPORT_SYMBOL(vb2_dvb_get_frontend);
  227. int vb2_dvb_find_frontend(struct vb2_dvb_frontends *f,
  228. struct dvb_frontend *p)
  229. {
  230. struct list_head *list, *q;
  231. struct vb2_dvb_frontend *fe = NULL;
  232. int ret = 0;
  233. mutex_lock(&f->lock);
  234. list_for_each_safe(list, q, &f->felist) {
  235. fe = list_entry(list, struct vb2_dvb_frontend, felist);
  236. if (fe->dvb.frontend == p) {
  237. ret = fe->id;
  238. break;
  239. }
  240. }
  241. mutex_unlock(&f->lock);
  242. return ret;
  243. }
  244. EXPORT_SYMBOL(vb2_dvb_find_frontend);
  245. struct vb2_dvb_frontend *vb2_dvb_alloc_frontend(
  246. struct vb2_dvb_frontends *f, int id)
  247. {
  248. struct vb2_dvb_frontend *fe;
  249. fe = kzalloc(sizeof(struct vb2_dvb_frontend), GFP_KERNEL);
  250. if (fe == NULL)
  251. return NULL;
  252. fe->id = id;
  253. mutex_init(&fe->dvb.lock);
  254. mutex_lock(&f->lock);
  255. list_add_tail(&fe->felist, &f->felist);
  256. mutex_unlock(&f->lock);
  257. return fe;
  258. }
  259. EXPORT_SYMBOL(vb2_dvb_alloc_frontend);
  260. void vb2_dvb_dealloc_frontends(struct vb2_dvb_frontends *f)
  261. {
  262. struct list_head *list, *q;
  263. struct vb2_dvb_frontend *fe;
  264. mutex_lock(&f->lock);
  265. list_for_each_safe(list, q, &f->felist) {
  266. fe = list_entry(list, struct vb2_dvb_frontend, felist);
  267. if (fe->dvb.net.dvbdev) {
  268. dvb_net_release(&fe->dvb.net);
  269. fe->dvb.demux.dmx.remove_frontend(&fe->dvb.demux.dmx,
  270. &fe->dvb.fe_mem);
  271. fe->dvb.demux.dmx.remove_frontend(&fe->dvb.demux.dmx,
  272. &fe->dvb.fe_hw);
  273. dvb_dmxdev_release(&fe->dvb.dmxdev);
  274. dvb_dmx_release(&fe->dvb.demux);
  275. dvb_unregister_frontend(fe->dvb.frontend);
  276. }
  277. if (fe->dvb.frontend)
  278. /* always allocated, may have been reset */
  279. dvb_frontend_detach(fe->dvb.frontend);
  280. list_del(list); /* remove list entry */
  281. kfree(fe); /* free frontend allocation */
  282. }
  283. mutex_unlock(&f->lock);
  284. }
  285. EXPORT_SYMBOL(vb2_dvb_dealloc_frontends);