dtt200u-fe.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. /* Frontend part of the Linux driver for the WideView/ Yakumo/ Hama/
  2. * Typhoon/ Yuan DVB-T USB2.0 receiver.
  3. *
  4. * Copyright (C) 2005 Patrick Boettcher <patrick.boettcher@posteo.de>
  5. *
  6. * This program is free software; you can redistribute it and/or modify it
  7. * under the terms of the GNU General Public License as published by the Free
  8. * Software Foundation, version 2.
  9. *
  10. * see Documentation/dvb/README.dvb-usb for more information
  11. */
  12. #include "dtt200u.h"
  13. struct dtt200u_fe_state {
  14. struct dvb_usb_device *d;
  15. enum fe_status stat;
  16. struct dtv_frontend_properties fep;
  17. struct dvb_frontend frontend;
  18. unsigned char data[80];
  19. struct mutex data_mutex;
  20. };
  21. static int dtt200u_fe_read_status(struct dvb_frontend *fe,
  22. enum fe_status *stat)
  23. {
  24. struct dtt200u_fe_state *state = fe->demodulator_priv;
  25. int ret;
  26. mutex_lock(&state->data_mutex);
  27. state->data[0] = GET_TUNE_STATUS;
  28. ret = dvb_usb_generic_rw(state->d, state->data, 1, state->data, 3, 0);
  29. if (ret < 0) {
  30. *stat = 0;
  31. mutex_unlock(&state->data_mutex);
  32. return ret;
  33. }
  34. switch (state->data[0]) {
  35. case 0x01:
  36. *stat = FE_HAS_SIGNAL | FE_HAS_CARRIER |
  37. FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
  38. break;
  39. case 0x00: /* pending */
  40. *stat = FE_TIMEDOUT; /* during set_frontend */
  41. break;
  42. default:
  43. case 0x02: /* failed */
  44. *stat = 0;
  45. break;
  46. }
  47. mutex_unlock(&state->data_mutex);
  48. return 0;
  49. }
  50. static int dtt200u_fe_read_ber(struct dvb_frontend* fe, u32 *ber)
  51. {
  52. struct dtt200u_fe_state *state = fe->demodulator_priv;
  53. int ret;
  54. mutex_lock(&state->data_mutex);
  55. state->data[0] = GET_VIT_ERR_CNT;
  56. ret = dvb_usb_generic_rw(state->d, state->data, 1, state->data, 3, 0);
  57. if (ret >= 0)
  58. *ber = (state->data[0] << 16) | (state->data[1] << 8) | state->data[2];
  59. mutex_unlock(&state->data_mutex);
  60. return ret;
  61. }
  62. static int dtt200u_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
  63. {
  64. struct dtt200u_fe_state *state = fe->demodulator_priv;
  65. int ret;
  66. mutex_lock(&state->data_mutex);
  67. state->data[0] = GET_RS_UNCOR_BLK_CNT;
  68. ret = dvb_usb_generic_rw(state->d, state->data, 1, state->data, 2, 0);
  69. if (ret >= 0)
  70. *unc = (state->data[0] << 8) | state->data[1];
  71. mutex_unlock(&state->data_mutex);
  72. return ret;
  73. }
  74. static int dtt200u_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
  75. {
  76. struct dtt200u_fe_state *state = fe->demodulator_priv;
  77. int ret;
  78. mutex_lock(&state->data_mutex);
  79. state->data[0] = GET_AGC;
  80. ret = dvb_usb_generic_rw(state->d, state->data, 1, state->data, 1, 0);
  81. if (ret >= 0)
  82. *strength = (state->data[0] << 8) | state->data[0];
  83. mutex_unlock(&state->data_mutex);
  84. return ret;
  85. }
  86. static int dtt200u_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
  87. {
  88. struct dtt200u_fe_state *state = fe->demodulator_priv;
  89. int ret;
  90. mutex_lock(&state->data_mutex);
  91. state->data[0] = GET_SNR;
  92. ret = dvb_usb_generic_rw(state->d, state->data, 1, state->data, 1, 0);
  93. if (ret >= 0)
  94. *snr = ~((state->data[0] << 8) | state->data[0]);
  95. mutex_unlock(&state->data_mutex);
  96. return ret;
  97. }
  98. static int dtt200u_fe_init(struct dvb_frontend* fe)
  99. {
  100. struct dtt200u_fe_state *state = fe->demodulator_priv;
  101. int ret;
  102. mutex_lock(&state->data_mutex);
  103. state->data[0] = SET_INIT;
  104. ret = dvb_usb_generic_write(state->d, state->data, 1);
  105. mutex_unlock(&state->data_mutex);
  106. return ret;
  107. }
  108. static int dtt200u_fe_sleep(struct dvb_frontend* fe)
  109. {
  110. return dtt200u_fe_init(fe);
  111. }
  112. static int dtt200u_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
  113. {
  114. tune->min_delay_ms = 1500;
  115. tune->step_size = 0;
  116. tune->max_drift = 0;
  117. return 0;
  118. }
  119. static int dtt200u_fe_set_frontend(struct dvb_frontend *fe)
  120. {
  121. struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
  122. struct dtt200u_fe_state *state = fe->demodulator_priv;
  123. int ret;
  124. u16 freq = fep->frequency / 250000;
  125. mutex_lock(&state->data_mutex);
  126. state->data[0] = SET_BANDWIDTH;
  127. switch (fep->bandwidth_hz) {
  128. case 8000000:
  129. state->data[1] = 8;
  130. break;
  131. case 7000000:
  132. state->data[1] = 7;
  133. break;
  134. case 6000000:
  135. state->data[1] = 6;
  136. break;
  137. default:
  138. ret = -EINVAL;
  139. goto ret;
  140. }
  141. ret = dvb_usb_generic_write(state->d, state->data, 2);
  142. if (ret < 0)
  143. goto ret;
  144. state->data[0] = SET_RF_FREQ;
  145. state->data[1] = freq & 0xff;
  146. state->data[2] = (freq >> 8) & 0xff;
  147. ret = dvb_usb_generic_write(state->d, state->data, 3);
  148. if (ret < 0)
  149. goto ret;
  150. ret:
  151. mutex_unlock(&state->data_mutex);
  152. return ret;
  153. }
  154. static int dtt200u_fe_get_frontend(struct dvb_frontend* fe,
  155. struct dtv_frontend_properties *fep)
  156. {
  157. struct dtt200u_fe_state *state = fe->demodulator_priv;
  158. memcpy(fep, &state->fep, sizeof(struct dtv_frontend_properties));
  159. return 0;
  160. }
  161. static void dtt200u_fe_release(struct dvb_frontend* fe)
  162. {
  163. struct dtt200u_fe_state *state = (struct dtt200u_fe_state*) fe->demodulator_priv;
  164. kfree(state);
  165. }
  166. static struct dvb_frontend_ops dtt200u_fe_ops;
  167. struct dvb_frontend* dtt200u_fe_attach(struct dvb_usb_device *d)
  168. {
  169. struct dtt200u_fe_state* state = NULL;
  170. /* allocate memory for the internal state */
  171. state = kzalloc(sizeof(struct dtt200u_fe_state), GFP_KERNEL);
  172. if (state == NULL)
  173. goto error;
  174. deb_info("attaching frontend dtt200u\n");
  175. state->d = d;
  176. mutex_init(&state->data_mutex);
  177. memcpy(&state->frontend.ops,&dtt200u_fe_ops,sizeof(struct dvb_frontend_ops));
  178. state->frontend.demodulator_priv = state;
  179. return &state->frontend;
  180. error:
  181. return NULL;
  182. }
  183. static struct dvb_frontend_ops dtt200u_fe_ops = {
  184. .delsys = { SYS_DVBT },
  185. .info = {
  186. .name = "WideView USB DVB-T",
  187. .frequency_min = 44250000,
  188. .frequency_max = 867250000,
  189. .frequency_stepsize = 250000,
  190. .caps = FE_CAN_INVERSION_AUTO |
  191. FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
  192. FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
  193. FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
  194. FE_CAN_TRANSMISSION_MODE_AUTO |
  195. FE_CAN_GUARD_INTERVAL_AUTO |
  196. FE_CAN_RECOVER |
  197. FE_CAN_HIERARCHY_AUTO,
  198. },
  199. .release = dtt200u_fe_release,
  200. .init = dtt200u_fe_init,
  201. .sleep = dtt200u_fe_sleep,
  202. .set_frontend = dtt200u_fe_set_frontend,
  203. .get_frontend = dtt200u_fe_get_frontend,
  204. .get_tune_settings = dtt200u_fe_get_tune_settings,
  205. .read_status = dtt200u_fe_read_status,
  206. .read_ber = dtt200u_fe_read_ber,
  207. .read_signal_strength = dtt200u_fe_read_signal_strength,
  208. .read_snr = dtt200u_fe_read_snr,
  209. .read_ucblocks = dtt200u_fe_read_unc_blocks,
  210. };