mantis_dvb.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. Mantis PCI bridge driver
  4. Copyright (C) Manu Abraham ([email protected])
  5. */
  6. #include <linux/kernel.h>
  7. #include <linux/bitops.h>
  8. #include <linux/signal.h>
  9. #include <linux/sched.h>
  10. #include <linux/interrupt.h>
  11. #include <linux/pci.h>
  12. #include <linux/i2c.h>
  13. #include <media/dmxdev.h>
  14. #include <media/dvbdev.h>
  15. #include <media/dvb_demux.h>
  16. #include <media/dvb_frontend.h>
  17. #include <media/dvb_net.h>
  18. #include "mantis_common.h"
  19. #include "mantis_dma.h"
  20. #include "mantis_ca.h"
  21. #include "mantis_ioc.h"
  22. #include "mantis_dvb.h"
  23. DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
  24. int mantis_frontend_power(struct mantis_pci *mantis, enum mantis_power power)
  25. {
  26. struct mantis_hwconfig *config = mantis->hwconfig;
  27. switch (power) {
  28. case POWER_ON:
  29. dprintk(MANTIS_DEBUG, 1, "Power ON");
  30. mantis_gpio_set_bits(mantis, config->power, POWER_ON);
  31. msleep(100);
  32. mantis_gpio_set_bits(mantis, config->power, POWER_ON);
  33. msleep(100);
  34. break;
  35. case POWER_OFF:
  36. dprintk(MANTIS_DEBUG, 1, "Power OFF");
  37. mantis_gpio_set_bits(mantis, config->power, POWER_OFF);
  38. msleep(100);
  39. break;
  40. default:
  41. dprintk(MANTIS_DEBUG, 1, "Unknown state <%02x>", power);
  42. return -1;
  43. }
  44. return 0;
  45. }
  46. EXPORT_SYMBOL_GPL(mantis_frontend_power);
  47. void mantis_frontend_soft_reset(struct mantis_pci *mantis)
  48. {
  49. struct mantis_hwconfig *config = mantis->hwconfig;
  50. dprintk(MANTIS_DEBUG, 1, "Frontend RESET");
  51. mantis_gpio_set_bits(mantis, config->reset, 0);
  52. msleep(100);
  53. mantis_gpio_set_bits(mantis, config->reset, 0);
  54. msleep(100);
  55. mantis_gpio_set_bits(mantis, config->reset, 1);
  56. msleep(100);
  57. mantis_gpio_set_bits(mantis, config->reset, 1);
  58. msleep(100);
  59. return;
  60. }
  61. EXPORT_SYMBOL_GPL(mantis_frontend_soft_reset);
  62. static int mantis_frontend_shutdown(struct mantis_pci *mantis)
  63. {
  64. int err;
  65. mantis_frontend_soft_reset(mantis);
  66. err = mantis_frontend_power(mantis, POWER_OFF);
  67. if (err != 0) {
  68. dprintk(MANTIS_ERROR, 1, "Frontend POWER OFF failed! <%d>", err);
  69. return 1;
  70. }
  71. return 0;
  72. }
  73. static int mantis_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
  74. {
  75. struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
  76. struct mantis_pci *mantis = dvbdmx->priv;
  77. dprintk(MANTIS_DEBUG, 1, "Mantis DVB Start feed");
  78. if (!dvbdmx->dmx.frontend) {
  79. dprintk(MANTIS_DEBUG, 1, "no frontend ?");
  80. return -EINVAL;
  81. }
  82. mantis->feeds++;
  83. dprintk(MANTIS_DEBUG, 1, "mantis start feed, feeds=%d", mantis->feeds);
  84. if (mantis->feeds == 1) {
  85. dprintk(MANTIS_DEBUG, 1, "mantis start feed & dma");
  86. mantis_dma_start(mantis);
  87. tasklet_enable(&mantis->tasklet);
  88. }
  89. return mantis->feeds;
  90. }
  91. static int mantis_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
  92. {
  93. struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
  94. struct mantis_pci *mantis = dvbdmx->priv;
  95. dprintk(MANTIS_DEBUG, 1, "Mantis DVB Stop feed");
  96. if (!dvbdmx->dmx.frontend) {
  97. dprintk(MANTIS_DEBUG, 1, "no frontend ?");
  98. return -EINVAL;
  99. }
  100. mantis->feeds--;
  101. if (mantis->feeds == 0) {
  102. dprintk(MANTIS_DEBUG, 1, "mantis stop feed and dma");
  103. tasklet_disable(&mantis->tasklet);
  104. mantis_dma_stop(mantis);
  105. }
  106. return 0;
  107. }
  108. int mantis_dvb_init(struct mantis_pci *mantis)
  109. {
  110. struct mantis_hwconfig *config = mantis->hwconfig;
  111. int result;
  112. dprintk(MANTIS_DEBUG, 1, "dvb_register_adapter");
  113. result = dvb_register_adapter(&mantis->dvb_adapter,
  114. "Mantis DVB adapter",
  115. THIS_MODULE,
  116. &mantis->pdev->dev,
  117. adapter_nr);
  118. if (result < 0) {
  119. dprintk(MANTIS_ERROR, 1, "Error registering adapter");
  120. return -ENODEV;
  121. }
  122. mantis->dvb_adapter.priv = mantis;
  123. mantis->demux.dmx.capabilities = DMX_TS_FILTERING |
  124. DMX_SECTION_FILTERING |
  125. DMX_MEMORY_BASED_FILTERING;
  126. mantis->demux.priv = mantis;
  127. mantis->demux.filternum = 256;
  128. mantis->demux.feednum = 256;
  129. mantis->demux.start_feed = mantis_dvb_start_feed;
  130. mantis->demux.stop_feed = mantis_dvb_stop_feed;
  131. mantis->demux.write_to_decoder = NULL;
  132. dprintk(MANTIS_DEBUG, 1, "dvb_dmx_init");
  133. result = dvb_dmx_init(&mantis->demux);
  134. if (result < 0) {
  135. dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);
  136. goto err0;
  137. }
  138. mantis->dmxdev.filternum = 256;
  139. mantis->dmxdev.demux = &mantis->demux.dmx;
  140. mantis->dmxdev.capabilities = 0;
  141. dprintk(MANTIS_DEBUG, 1, "dvb_dmxdev_init");
  142. result = dvb_dmxdev_init(&mantis->dmxdev, &mantis->dvb_adapter);
  143. if (result < 0) {
  144. dprintk(MANTIS_ERROR, 1, "dvb_dmxdev_init failed, ERROR=%d", result);
  145. goto err1;
  146. }
  147. mantis->fe_hw.source = DMX_FRONTEND_0;
  148. result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, &mantis->fe_hw);
  149. if (result < 0) {
  150. dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);
  151. goto err2;
  152. }
  153. mantis->fe_mem.source = DMX_MEMORY_FE;
  154. result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, &mantis->fe_mem);
  155. if (result < 0) {
  156. dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);
  157. goto err3;
  158. }
  159. result = mantis->demux.dmx.connect_frontend(&mantis->demux.dmx, &mantis->fe_hw);
  160. if (result < 0) {
  161. dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);
  162. goto err4;
  163. }
  164. dvb_net_init(&mantis->dvb_adapter, &mantis->dvbnet, &mantis->demux.dmx);
  165. tasklet_setup(&mantis->tasklet, mantis_dma_xfer);
  166. tasklet_disable(&mantis->tasklet);
  167. if (mantis->hwconfig) {
  168. result = config->frontend_init(mantis, mantis->fe);
  169. if (result < 0) {
  170. dprintk(MANTIS_ERROR, 1, "!!! NO Frontends found !!!");
  171. goto err5;
  172. } else {
  173. if (mantis->fe == NULL) {
  174. result = -ENOMEM;
  175. dprintk(MANTIS_ERROR, 1, "FE <NULL>");
  176. goto err5;
  177. }
  178. result = dvb_register_frontend(&mantis->dvb_adapter, mantis->fe);
  179. if (result) {
  180. dprintk(MANTIS_ERROR, 1, "ERROR: Frontend registration failed");
  181. if (mantis->fe->ops.release)
  182. mantis->fe->ops.release(mantis->fe);
  183. mantis->fe = NULL;
  184. goto err5;
  185. }
  186. }
  187. }
  188. return 0;
  189. /* Error conditions .. */
  190. err5:
  191. tasklet_kill(&mantis->tasklet);
  192. dvb_net_release(&mantis->dvbnet);
  193. if (mantis->fe) {
  194. dvb_unregister_frontend(mantis->fe);
  195. dvb_frontend_detach(mantis->fe);
  196. }
  197. err4:
  198. mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem);
  199. err3:
  200. mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw);
  201. err2:
  202. dvb_dmxdev_release(&mantis->dmxdev);
  203. err1:
  204. dvb_dmx_release(&mantis->demux);
  205. err0:
  206. dvb_unregister_adapter(&mantis->dvb_adapter);
  207. return result;
  208. }
  209. EXPORT_SYMBOL_GPL(mantis_dvb_init);
  210. int mantis_dvb_exit(struct mantis_pci *mantis)
  211. {
  212. int err;
  213. if (mantis->fe) {
  214. /* mantis_ca_exit(mantis); */
  215. err = mantis_frontend_shutdown(mantis);
  216. if (err != 0)
  217. dprintk(MANTIS_ERROR, 1, "Frontend exit while POWER ON! <%d>", err);
  218. dvb_unregister_frontend(mantis->fe);
  219. dvb_frontend_detach(mantis->fe);
  220. }
  221. tasklet_kill(&mantis->tasklet);
  222. dvb_net_release(&mantis->dvbnet);
  223. mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem);
  224. mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw);
  225. dvb_dmxdev_release(&mantis->dmxdev);
  226. dvb_dmx_release(&mantis->demux);
  227. dprintk(MANTIS_DEBUG, 1, "dvb_unregister_adapter");
  228. dvb_unregister_adapter(&mantis->dvb_adapter);
  229. return 0;
  230. }
  231. EXPORT_SYMBOL_GPL(mantis_dvb_exit);