videobuf2-dvb.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  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. struct media_device *mdev,
  67. char *adapter_name,
  68. short *adapter_nr,
  69. int mfe_shared)
  70. {
  71. int result;
  72. mutex_init(&fe->lock);
  73. /* register adapter */
  74. result = dvb_register_adapter(&fe->adapter, adapter_name, module,
  75. device, adapter_nr);
  76. if (result < 0) {
  77. pr_warn("%s: dvb_register_adapter failed (errno = %d)\n",
  78. adapter_name, result);
  79. }
  80. fe->adapter.priv = adapter_priv;
  81. fe->adapter.mfe_shared = mfe_shared;
  82. #ifdef CONFIG_MEDIA_CONTROLLER_DVB
  83. if (mdev)
  84. fe->adapter.mdev = mdev;
  85. #endif
  86. return result;
  87. }
  88. static int vb2_dvb_register_frontend(struct dvb_adapter *adapter,
  89. struct vb2_dvb *dvb)
  90. {
  91. int result;
  92. /* register frontend */
  93. result = dvb_register_frontend(adapter, dvb->frontend);
  94. if (result < 0) {
  95. pr_warn("%s: dvb_register_frontend failed (errno = %d)\n",
  96. dvb->name, result);
  97. goto fail_frontend;
  98. }
  99. /* register demux stuff */
  100. dvb->demux.dmx.capabilities =
  101. DMX_TS_FILTERING | DMX_SECTION_FILTERING |
  102. DMX_MEMORY_BASED_FILTERING;
  103. dvb->demux.priv = dvb;
  104. dvb->demux.filternum = 256;
  105. dvb->demux.feednum = 256;
  106. dvb->demux.start_feed = vb2_dvb_start_feed;
  107. dvb->demux.stop_feed = vb2_dvb_stop_feed;
  108. result = dvb_dmx_init(&dvb->demux);
  109. if (result < 0) {
  110. pr_warn("%s: dvb_dmx_init failed (errno = %d)\n",
  111. dvb->name, result);
  112. goto fail_dmx;
  113. }
  114. dvb->dmxdev.filternum = 256;
  115. dvb->dmxdev.demux = &dvb->demux.dmx;
  116. dvb->dmxdev.capabilities = 0;
  117. result = dvb_dmxdev_init(&dvb->dmxdev, adapter);
  118. if (result < 0) {
  119. pr_warn("%s: dvb_dmxdev_init failed (errno = %d)\n",
  120. dvb->name, result);
  121. goto fail_dmxdev;
  122. }
  123. dvb->fe_hw.source = DMX_FRONTEND_0;
  124. result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw);
  125. if (result < 0) {
  126. pr_warn("%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n",
  127. dvb->name, result);
  128. goto fail_fe_hw;
  129. }
  130. dvb->fe_mem.source = DMX_MEMORY_FE;
  131. result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem);
  132. if (result < 0) {
  133. pr_warn("%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n",
  134. dvb->name, result);
  135. goto fail_fe_mem;
  136. }
  137. result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw);
  138. if (result < 0) {
  139. pr_warn("%s: connect_frontend failed (errno = %d)\n",
  140. dvb->name, result);
  141. goto fail_fe_conn;
  142. }
  143. /* register network adapter */
  144. result = dvb_net_init(adapter, &dvb->net, &dvb->demux.dmx);
  145. if (result < 0) {
  146. pr_warn("%s: dvb_net_init failed (errno = %d)\n",
  147. dvb->name, result);
  148. goto fail_fe_conn;
  149. }
  150. return 0;
  151. fail_fe_conn:
  152. dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
  153. fail_fe_mem:
  154. dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
  155. fail_fe_hw:
  156. dvb_dmxdev_release(&dvb->dmxdev);
  157. fail_dmxdev:
  158. dvb_dmx_release(&dvb->demux);
  159. fail_dmx:
  160. dvb_unregister_frontend(dvb->frontend);
  161. fail_frontend:
  162. dvb_frontend_detach(dvb->frontend);
  163. dvb->frontend = NULL;
  164. return result;
  165. }
  166. /* ------------------------------------------------------------------ */
  167. /* Register a single adapter and one or more frontends */
  168. int vb2_dvb_register_bus(struct vb2_dvb_frontends *f,
  169. struct module *module,
  170. void *adapter_priv,
  171. struct device *device,
  172. struct media_device *mdev,
  173. short *adapter_nr,
  174. int mfe_shared)
  175. {
  176. struct list_head *list, *q;
  177. struct vb2_dvb_frontend *fe;
  178. int res;
  179. fe = vb2_dvb_get_frontend(f, 1);
  180. if (!fe) {
  181. pr_warn("Unable to register the adapter which has no frontends\n");
  182. return -EINVAL;
  183. }
  184. /* Bring up the adapter */
  185. res = vb2_dvb_register_adapter(f, module, adapter_priv, device, mdev,
  186. fe->dvb.name, adapter_nr, mfe_shared);
  187. if (res < 0) {
  188. pr_warn("vb2_dvb_register_adapter failed (errno = %d)\n", res);
  189. return res;
  190. }
  191. /* Attach all of the frontends to the adapter */
  192. mutex_lock(&f->lock);
  193. list_for_each_safe(list, q, &f->felist) {
  194. fe = list_entry(list, struct vb2_dvb_frontend, felist);
  195. res = vb2_dvb_register_frontend(&f->adapter, &fe->dvb);
  196. if (res < 0) {
  197. pr_warn("%s: vb2_dvb_register_frontend failed (errno = %d)\n",
  198. fe->dvb.name, res);
  199. goto err;
  200. }
  201. res = dvb_create_media_graph(&f->adapter, false);
  202. if (res < 0)
  203. goto err;
  204. }
  205. mutex_unlock(&f->lock);
  206. return 0;
  207. err:
  208. mutex_unlock(&f->lock);
  209. vb2_dvb_unregister_bus(f);
  210. return res;
  211. }
  212. EXPORT_SYMBOL(vb2_dvb_register_bus);
  213. void vb2_dvb_unregister_bus(struct vb2_dvb_frontends *f)
  214. {
  215. vb2_dvb_dealloc_frontends(f);
  216. dvb_unregister_adapter(&f->adapter);
  217. }
  218. EXPORT_SYMBOL(vb2_dvb_unregister_bus);
  219. struct vb2_dvb_frontend *vb2_dvb_get_frontend(
  220. struct vb2_dvb_frontends *f, int id)
  221. {
  222. struct list_head *list, *q;
  223. struct vb2_dvb_frontend *fe, *ret = NULL;
  224. mutex_lock(&f->lock);
  225. list_for_each_safe(list, q, &f->felist) {
  226. fe = list_entry(list, struct vb2_dvb_frontend, felist);
  227. if (fe->id == id) {
  228. ret = fe;
  229. break;
  230. }
  231. }
  232. mutex_unlock(&f->lock);
  233. return ret;
  234. }
  235. EXPORT_SYMBOL(vb2_dvb_get_frontend);
  236. int vb2_dvb_find_frontend(struct vb2_dvb_frontends *f,
  237. struct dvb_frontend *p)
  238. {
  239. struct list_head *list, *q;
  240. struct vb2_dvb_frontend *fe = NULL;
  241. int ret = 0;
  242. mutex_lock(&f->lock);
  243. list_for_each_safe(list, q, &f->felist) {
  244. fe = list_entry(list, struct vb2_dvb_frontend, felist);
  245. if (fe->dvb.frontend == p) {
  246. ret = fe->id;
  247. break;
  248. }
  249. }
  250. mutex_unlock(&f->lock);
  251. return ret;
  252. }
  253. EXPORT_SYMBOL(vb2_dvb_find_frontend);
  254. struct vb2_dvb_frontend *vb2_dvb_alloc_frontend(
  255. struct vb2_dvb_frontends *f, int id)
  256. {
  257. struct vb2_dvb_frontend *fe;
  258. fe = kzalloc(sizeof(struct vb2_dvb_frontend), GFP_KERNEL);
  259. if (fe == NULL)
  260. return NULL;
  261. fe->id = id;
  262. mutex_init(&fe->dvb.lock);
  263. mutex_lock(&f->lock);
  264. list_add_tail(&fe->felist, &f->felist);
  265. mutex_unlock(&f->lock);
  266. return fe;
  267. }
  268. EXPORT_SYMBOL(vb2_dvb_alloc_frontend);
  269. void vb2_dvb_dealloc_frontends(struct vb2_dvb_frontends *f)
  270. {
  271. struct list_head *list, *q;
  272. struct vb2_dvb_frontend *fe;
  273. mutex_lock(&f->lock);
  274. list_for_each_safe(list, q, &f->felist) {
  275. fe = list_entry(list, struct vb2_dvb_frontend, felist);
  276. if (fe->dvb.net.dvbdev) {
  277. dvb_net_release(&fe->dvb.net);
  278. fe->dvb.demux.dmx.remove_frontend(&fe->dvb.demux.dmx,
  279. &fe->dvb.fe_mem);
  280. fe->dvb.demux.dmx.remove_frontend(&fe->dvb.demux.dmx,
  281. &fe->dvb.fe_hw);
  282. dvb_dmxdev_release(&fe->dvb.dmxdev);
  283. dvb_dmx_release(&fe->dvb.demux);
  284. dvb_unregister_frontend(fe->dvb.frontend);
  285. }
  286. if (fe->dvb.frontend)
  287. /* always allocated, may have been reset */
  288. dvb_frontend_detach(fe->dvb.frontend);
  289. list_del(list); /* remove list entry */
  290. kfree(fe); /* free frontend allocation */
  291. }
  292. mutex_unlock(&f->lock);
  293. }
  294. EXPORT_SYMBOL(vb2_dvb_dealloc_frontends);