firesat_fe.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. /*
  2. * FireDTV driver (formerly known as FireSAT)
  3. *
  4. * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
  5. * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License as
  9. * published by the Free Software Foundation; either version 2 of
  10. * the License, or (at your option) any later version.
  11. */
  12. #include <linux/errno.h>
  13. #include <linux/kernel.h>
  14. #include <linux/string.h>
  15. #include <linux/types.h>
  16. #include <dvb_frontend.h>
  17. #include "avc_api.h"
  18. #include "cmp.h"
  19. #include "firesat.h"
  20. static int firesat_dvb_init(struct dvb_frontend *fe)
  21. {
  22. struct firesat *firesat = fe->sec_priv;
  23. int err;
  24. /* FIXME - allocate free channel at IRM */
  25. firesat->isochannel = firesat->adapter.num;
  26. err = cmp_establish_pp_connection(firesat, firesat->subunit,
  27. firesat->isochannel);
  28. if (err) {
  29. printk(KERN_ERR "Could not establish point to point "
  30. "connection.\n");
  31. return err;
  32. }
  33. return setup_iso_channel(firesat);
  34. }
  35. static int firesat_sleep(struct dvb_frontend *fe)
  36. {
  37. struct firesat *firesat = fe->sec_priv;
  38. tear_down_iso_channel(firesat);
  39. cmp_break_pp_connection(firesat, firesat->subunit, firesat->isochannel);
  40. firesat->isochannel = -1;
  41. return 0;
  42. }
  43. static int firesat_diseqc_send_master_cmd(struct dvb_frontend *fe,
  44. struct dvb_diseqc_master_cmd *cmd)
  45. {
  46. struct firesat *firesat = fe->sec_priv;
  47. return avc_lnb_control(firesat, LNBCONTROL_DONTCARE,
  48. LNBCONTROL_DONTCARE, LNBCONTROL_DONTCARE, 1, cmd);
  49. }
  50. static int firesat_diseqc_send_burst(struct dvb_frontend *fe,
  51. fe_sec_mini_cmd_t minicmd)
  52. {
  53. return 0;
  54. }
  55. static int firesat_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
  56. {
  57. struct firesat *firesat = fe->sec_priv;
  58. firesat->tone = tone;
  59. return 0;
  60. }
  61. static int firesat_set_voltage(struct dvb_frontend *fe,
  62. fe_sec_voltage_t voltage)
  63. {
  64. struct firesat *firesat = fe->sec_priv;
  65. firesat->voltage = voltage;
  66. return 0;
  67. }
  68. static int firesat_read_status(struct dvb_frontend *fe, fe_status_t *status)
  69. {
  70. struct firesat *firesat = fe->sec_priv;
  71. ANTENNA_INPUT_INFO info;
  72. if (avc_tuner_status(firesat, &info))
  73. return -EINVAL;
  74. if (info.NoRF)
  75. *status = 0;
  76. else
  77. *status = FE_HAS_SIGNAL | FE_HAS_VITERBI | FE_HAS_SYNC |
  78. FE_HAS_CARRIER | FE_HAS_LOCK;
  79. return 0;
  80. }
  81. static int firesat_read_ber(struct dvb_frontend *fe, u32 *ber)
  82. {
  83. struct firesat *firesat = fe->sec_priv;
  84. ANTENNA_INPUT_INFO info;
  85. if (avc_tuner_status(firesat, &info))
  86. return -EINVAL;
  87. *ber = info.BER[0] << 24 | info.BER[1] << 16 |
  88. info.BER[2] << 8 | info.BER[3];
  89. return 0;
  90. }
  91. static int firesat_read_signal_strength (struct dvb_frontend *fe, u16 *strength)
  92. {
  93. struct firesat *firesat = fe->sec_priv;
  94. ANTENNA_INPUT_INFO info;
  95. if (avc_tuner_status(firesat, &info))
  96. return -EINVAL;
  97. *strength = info.SignalStrength << 8;
  98. return 0;
  99. }
  100. static int firesat_read_snr(struct dvb_frontend *fe, u16 *snr)
  101. {
  102. struct firesat *firesat = fe->sec_priv;
  103. ANTENNA_INPUT_INFO info;
  104. if (avc_tuner_status(firesat, &info))
  105. return -EINVAL;
  106. /* C/N[dB] = -10 * log10(snr / 65535) */
  107. *snr = (info.CarrierNoiseRatio[0] << 8) + info.CarrierNoiseRatio[1];
  108. *snr *= 257;
  109. return 0;
  110. }
  111. static int firesat_read_uncorrected_blocks(struct dvb_frontend *fe, u32 *ucblocks)
  112. {
  113. return -EOPNOTSUPP;
  114. }
  115. static int firesat_set_frontend(struct dvb_frontend *fe,
  116. struct dvb_frontend_parameters *params)
  117. {
  118. struct firesat *firesat = fe->sec_priv;
  119. /* FIXME: avc_tuner_dsd never returns ACCEPTED. Check status? */
  120. if (avc_tuner_dsd(firesat, params) != ACCEPTED)
  121. return -EINVAL;
  122. else
  123. return 0; /* not sure of this... */
  124. }
  125. static int firesat_get_frontend(struct dvb_frontend *fe,
  126. struct dvb_frontend_parameters *params)
  127. {
  128. return -EOPNOTSUPP;
  129. }
  130. void firesat_frontend_init(struct firesat *firesat)
  131. {
  132. struct dvb_frontend_ops *ops = &firesat->fe.ops;
  133. struct dvb_frontend_info *fi = &ops->info;
  134. ops->init = firesat_dvb_init;
  135. ops->sleep = firesat_sleep;
  136. ops->set_frontend = firesat_set_frontend;
  137. ops->get_frontend = firesat_get_frontend;
  138. ops->read_status = firesat_read_status;
  139. ops->read_ber = firesat_read_ber;
  140. ops->read_signal_strength = firesat_read_signal_strength;
  141. ops->read_snr = firesat_read_snr;
  142. ops->read_ucblocks = firesat_read_uncorrected_blocks;
  143. ops->diseqc_send_master_cmd = firesat_diseqc_send_master_cmd;
  144. ops->diseqc_send_burst = firesat_diseqc_send_burst;
  145. ops->set_tone = firesat_set_tone;
  146. ops->set_voltage = firesat_set_voltage;
  147. switch (firesat->type) {
  148. case FireSAT_DVB_S:
  149. fi->type = FE_QPSK;
  150. fi->frequency_min = 950000;
  151. fi->frequency_max = 2150000;
  152. fi->frequency_stepsize = 125;
  153. fi->symbol_rate_min = 1000000;
  154. fi->symbol_rate_max = 40000000;
  155. fi->caps = FE_CAN_INVERSION_AUTO |
  156. FE_CAN_FEC_1_2 |
  157. FE_CAN_FEC_2_3 |
  158. FE_CAN_FEC_3_4 |
  159. FE_CAN_FEC_5_6 |
  160. FE_CAN_FEC_7_8 |
  161. FE_CAN_FEC_AUTO |
  162. FE_CAN_QPSK;
  163. break;
  164. case FireSAT_DVB_C:
  165. fi->type = FE_QAM;
  166. fi->frequency_min = 47000000;
  167. fi->frequency_max = 866000000;
  168. fi->frequency_stepsize = 62500;
  169. fi->symbol_rate_min = 870000;
  170. fi->symbol_rate_max = 6900000;
  171. fi->caps = FE_CAN_INVERSION_AUTO |
  172. FE_CAN_QAM_16 |
  173. FE_CAN_QAM_32 |
  174. FE_CAN_QAM_64 |
  175. FE_CAN_QAM_128 |
  176. FE_CAN_QAM_256 |
  177. FE_CAN_QAM_AUTO;
  178. break;
  179. case FireSAT_DVB_T:
  180. fi->type = FE_OFDM;
  181. fi->frequency_min = 49000000;
  182. fi->frequency_max = 861000000;
  183. fi->frequency_stepsize = 62500;
  184. fi->caps = FE_CAN_INVERSION_AUTO |
  185. FE_CAN_FEC_2_3 |
  186. FE_CAN_TRANSMISSION_MODE_AUTO |
  187. FE_CAN_GUARD_INTERVAL_AUTO |
  188. FE_CAN_HIERARCHY_AUTO;
  189. break;
  190. default:
  191. printk(KERN_ERR "FireDTV: no frontend for model type %d\n",
  192. firesat->type);
  193. }
  194. strcpy(fi->name, firedtv_model_names[firesat->type]);
  195. firesat->fe.dvb = &firesat->adapter;
  196. firesat->fe.sec_priv = firesat;
  197. }