sms-cards.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Card-specific functions for the Siano SMS1xxx USB dongle
  4. *
  5. * Copyright (c) 2008 Michael Krufky <[email protected]>
  6. */
  7. #include "sms-cards.h"
  8. #include "smsir.h"
  9. #include <linux/module.h>
  10. static struct sms_board sms_boards[] = {
  11. [SMS_BOARD_UNKNOWN] = {
  12. .name = "Unknown board",
  13. .type = SMS_UNKNOWN_TYPE,
  14. .default_mode = DEVICE_MODE_NONE,
  15. },
  16. [SMS1XXX_BOARD_SIANO_STELLAR] = {
  17. .name = "Siano Stellar Digital Receiver",
  18. .type = SMS_STELLAR,
  19. .default_mode = DEVICE_MODE_DVBT_BDA,
  20. },
  21. [SMS1XXX_BOARD_SIANO_NOVA_A] = {
  22. .name = "Siano Nova A Digital Receiver",
  23. .type = SMS_NOVA_A0,
  24. .default_mode = DEVICE_MODE_DVBT_BDA,
  25. },
  26. [SMS1XXX_BOARD_SIANO_NOVA_B] = {
  27. .name = "Siano Nova B Digital Receiver",
  28. .type = SMS_NOVA_B0,
  29. .default_mode = DEVICE_MODE_DVBT_BDA,
  30. },
  31. [SMS1XXX_BOARD_SIANO_VEGA] = {
  32. .name = "Siano Vega Digital Receiver",
  33. .type = SMS_VEGA,
  34. .default_mode = DEVICE_MODE_CMMB,
  35. },
  36. [SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT] = {
  37. .name = "Hauppauge Catamount",
  38. .type = SMS_STELLAR,
  39. .fw[DEVICE_MODE_DVBT_BDA] = SMS_FW_DVBT_STELLAR,
  40. .default_mode = DEVICE_MODE_DVBT_BDA,
  41. },
  42. [SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A] = {
  43. .name = "Hauppauge Okemo-A",
  44. .type = SMS_NOVA_A0,
  45. .fw[DEVICE_MODE_DVBT_BDA] = SMS_FW_DVBT_NOVA_A,
  46. .default_mode = DEVICE_MODE_DVBT_BDA,
  47. },
  48. [SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B] = {
  49. .name = "Hauppauge Okemo-B",
  50. .type = SMS_NOVA_B0,
  51. .fw[DEVICE_MODE_DVBT_BDA] = SMS_FW_DVBT_NOVA_B,
  52. .default_mode = DEVICE_MODE_DVBT_BDA,
  53. },
  54. [SMS1XXX_BOARD_HAUPPAUGE_WINDHAM] = {
  55. .name = "Hauppauge WinTV MiniStick",
  56. .type = SMS_NOVA_B0,
  57. .fw[DEVICE_MODE_ISDBT_BDA] = SMS_FW_ISDBT_HCW_55XXX,
  58. .fw[DEVICE_MODE_DVBT_BDA] = SMS_FW_DVBT_HCW_55XXX,
  59. .default_mode = DEVICE_MODE_DVBT_BDA,
  60. .rc_codes = RC_MAP_HAUPPAUGE,
  61. .board_cfg.leds_power = 26,
  62. .board_cfg.led0 = 27,
  63. .board_cfg.led1 = 28,
  64. .board_cfg.ir = 9,
  65. .led_power = 26,
  66. .led_lo = 27,
  67. .led_hi = 28,
  68. },
  69. [SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD] = {
  70. .name = "Hauppauge WinTV MiniCard",
  71. .type = SMS_NOVA_B0,
  72. .fw[DEVICE_MODE_DVBT_BDA] = SMS_FW_DVBT_HCW_55XXX,
  73. .default_mode = DEVICE_MODE_DVBT_BDA,
  74. .lna_ctrl = 29,
  75. .board_cfg.foreign_lna0_ctrl = 29,
  76. .rf_switch = 17,
  77. .board_cfg.rf_switch_uhf = 17,
  78. },
  79. [SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2] = {
  80. .name = "Hauppauge WinTV MiniCard Rev 2",
  81. .type = SMS_NOVA_B0,
  82. .fw[DEVICE_MODE_DVBT_BDA] = SMS_FW_DVBT_HCW_55XXX,
  83. .default_mode = DEVICE_MODE_DVBT_BDA,
  84. .lna_ctrl = -1,
  85. },
  86. [SMS1XXX_BOARD_SIANO_NICE] = {
  87. .name = "Siano Nice Digital Receiver",
  88. .type = SMS_NOVA_B0,
  89. .default_mode = DEVICE_MODE_DVBT_BDA,
  90. },
  91. [SMS1XXX_BOARD_SIANO_VENICE] = {
  92. .name = "Siano Venice Digital Receiver",
  93. .type = SMS_VEGA,
  94. .default_mode = DEVICE_MODE_CMMB,
  95. },
  96. [SMS1XXX_BOARD_SIANO_STELLAR_ROM] = {
  97. .name = "Siano Stellar Digital Receiver ROM",
  98. .type = SMS_STELLAR,
  99. .default_mode = DEVICE_MODE_DVBT_BDA,
  100. .intf_num = 1,
  101. },
  102. [SMS1XXX_BOARD_ZTE_DVB_DATA_CARD] = {
  103. .name = "ZTE Data Card Digital Receiver",
  104. .type = SMS_NOVA_B0,
  105. .default_mode = DEVICE_MODE_DVBT_BDA,
  106. .intf_num = 5,
  107. .mtu = 15792,
  108. },
  109. [SMS1XXX_BOARD_ONDA_MDTV_DATA_CARD] = {
  110. .name = "ONDA Data Card Digital Receiver",
  111. .type = SMS_NOVA_B0,
  112. .default_mode = DEVICE_MODE_DVBT_BDA,
  113. .intf_num = 6,
  114. .mtu = 15792,
  115. },
  116. [SMS1XXX_BOARD_SIANO_MING] = {
  117. .name = "Siano Ming Digital Receiver",
  118. .type = SMS_MING,
  119. .default_mode = DEVICE_MODE_CMMB,
  120. },
  121. [SMS1XXX_BOARD_SIANO_PELE] = {
  122. .name = "Siano Pele Digital Receiver",
  123. .type = SMS_PELE,
  124. .default_mode = DEVICE_MODE_ISDBT_BDA,
  125. },
  126. [SMS1XXX_BOARD_SIANO_RIO] = {
  127. .name = "Siano Rio Digital Receiver",
  128. .type = SMS_RIO,
  129. .default_mode = DEVICE_MODE_ISDBT_BDA,
  130. },
  131. [SMS1XXX_BOARD_SIANO_DENVER_1530] = {
  132. .name = "Siano Denver (ATSC-M/H) Digital Receiver",
  133. .type = SMS_DENVER_1530,
  134. .default_mode = DEVICE_MODE_ATSC,
  135. .crystal = 2400,
  136. },
  137. [SMS1XXX_BOARD_SIANO_DENVER_2160] = {
  138. .name = "Siano Denver (TDMB) Digital Receiver",
  139. .type = SMS_DENVER_2160,
  140. .default_mode = DEVICE_MODE_DAB_TDMB,
  141. },
  142. [SMS1XXX_BOARD_PCTV_77E] = {
  143. .name = "Hauppauge microStick 77e",
  144. .type = SMS_NOVA_B0,
  145. .fw[DEVICE_MODE_DVBT_BDA] = SMS_FW_DVB_NOVA_12MHZ_B0,
  146. .default_mode = DEVICE_MODE_DVBT_BDA,
  147. },
  148. };
  149. struct sms_board *sms_get_board(unsigned id)
  150. {
  151. BUG_ON(id >= ARRAY_SIZE(sms_boards));
  152. return &sms_boards[id];
  153. }
  154. EXPORT_SYMBOL_GPL(sms_get_board);
  155. static inline void sms_gpio_assign_11xx_default_led_config(
  156. struct smscore_config_gpio *p_gpio_config) {
  157. p_gpio_config->direction = SMS_GPIO_DIRECTION_OUTPUT;
  158. p_gpio_config->inputcharacteristics =
  159. SMS_GPIO_INPUTCHARACTERISTICS_NORMAL;
  160. p_gpio_config->outputdriving = SMS_GPIO_OUTPUTDRIVING_4mA;
  161. p_gpio_config->outputslewrate = SMS_GPIO_OUTPUT_SLEW_RATE_0_45_V_NS;
  162. p_gpio_config->pullupdown = SMS_GPIO_PULLUPDOWN_NONE;
  163. }
  164. int sms_board_event(struct smscore_device_t *coredev,
  165. enum SMS_BOARD_EVENTS gevent)
  166. {
  167. struct smscore_config_gpio my_gpio_config;
  168. sms_gpio_assign_11xx_default_led_config(&my_gpio_config);
  169. switch (gevent) {
  170. case BOARD_EVENT_POWER_INIT: /* including hotplug */
  171. break; /* BOARD_EVENT_BIND */
  172. case BOARD_EVENT_POWER_SUSPEND:
  173. break; /* BOARD_EVENT_POWER_SUSPEND */
  174. case BOARD_EVENT_POWER_RESUME:
  175. break; /* BOARD_EVENT_POWER_RESUME */
  176. case BOARD_EVENT_BIND:
  177. break; /* BOARD_EVENT_BIND */
  178. case BOARD_EVENT_SCAN_PROG:
  179. break; /* BOARD_EVENT_SCAN_PROG */
  180. case BOARD_EVENT_SCAN_COMP:
  181. break; /* BOARD_EVENT_SCAN_COMP */
  182. case BOARD_EVENT_EMERGENCY_WARNING_SIGNAL:
  183. break; /* BOARD_EVENT_EMERGENCY_WARNING_SIGNAL */
  184. case BOARD_EVENT_FE_LOCK:
  185. break; /* BOARD_EVENT_FE_LOCK */
  186. case BOARD_EVENT_FE_UNLOCK:
  187. break; /* BOARD_EVENT_FE_UNLOCK */
  188. case BOARD_EVENT_DEMOD_LOCK:
  189. break; /* BOARD_EVENT_DEMOD_LOCK */
  190. case BOARD_EVENT_DEMOD_UNLOCK:
  191. break; /* BOARD_EVENT_DEMOD_UNLOCK */
  192. case BOARD_EVENT_RECEPTION_MAX_4:
  193. break; /* BOARD_EVENT_RECEPTION_MAX_4 */
  194. case BOARD_EVENT_RECEPTION_3:
  195. break; /* BOARD_EVENT_RECEPTION_3 */
  196. case BOARD_EVENT_RECEPTION_2:
  197. break; /* BOARD_EVENT_RECEPTION_2 */
  198. case BOARD_EVENT_RECEPTION_1:
  199. break; /* BOARD_EVENT_RECEPTION_1 */
  200. case BOARD_EVENT_RECEPTION_LOST_0:
  201. break; /* BOARD_EVENT_RECEPTION_LOST_0 */
  202. case BOARD_EVENT_MULTIPLEX_OK:
  203. break; /* BOARD_EVENT_MULTIPLEX_OK */
  204. case BOARD_EVENT_MULTIPLEX_ERRORS:
  205. break; /* BOARD_EVENT_MULTIPLEX_ERRORS */
  206. default:
  207. pr_err("Unknown SMS board event\n");
  208. break;
  209. }
  210. return 0;
  211. }
  212. EXPORT_SYMBOL_GPL(sms_board_event);
  213. static int sms_set_gpio(struct smscore_device_t *coredev, int pin, int enable)
  214. {
  215. int lvl, ret;
  216. u32 gpio;
  217. struct smscore_config_gpio gpioconfig = {
  218. .direction = SMS_GPIO_DIRECTION_OUTPUT,
  219. .pullupdown = SMS_GPIO_PULLUPDOWN_NONE,
  220. .inputcharacteristics = SMS_GPIO_INPUTCHARACTERISTICS_NORMAL,
  221. .outputslewrate = SMS_GPIO_OUTPUT_SLEW_RATE_FAST,
  222. .outputdriving = SMS_GPIO_OUTPUTDRIVING_S_4mA,
  223. };
  224. if (pin == 0)
  225. return -EINVAL;
  226. if (pin < 0) {
  227. /* inverted gpio */
  228. gpio = pin * -1;
  229. lvl = enable ? 0 : 1;
  230. } else {
  231. gpio = pin;
  232. lvl = enable ? 1 : 0;
  233. }
  234. ret = smscore_configure_gpio(coredev, gpio, &gpioconfig);
  235. if (ret < 0)
  236. return ret;
  237. return smscore_set_gpio(coredev, gpio, lvl);
  238. }
  239. int sms_board_setup(struct smscore_device_t *coredev)
  240. {
  241. int board_id = smscore_get_board_id(coredev);
  242. struct sms_board *board = sms_get_board(board_id);
  243. switch (board_id) {
  244. case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
  245. /* turn off all LEDs */
  246. sms_set_gpio(coredev, board->led_power, 0);
  247. sms_set_gpio(coredev, board->led_hi, 0);
  248. sms_set_gpio(coredev, board->led_lo, 0);
  249. break;
  250. case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2:
  251. case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD:
  252. /* turn off LNA */
  253. sms_set_gpio(coredev, board->lna_ctrl, 0);
  254. break;
  255. }
  256. return 0;
  257. }
  258. EXPORT_SYMBOL_GPL(sms_board_setup);
  259. int sms_board_power(struct smscore_device_t *coredev, int onoff)
  260. {
  261. int board_id = smscore_get_board_id(coredev);
  262. struct sms_board *board = sms_get_board(board_id);
  263. switch (board_id) {
  264. case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
  265. /* power LED */
  266. sms_set_gpio(coredev,
  267. board->led_power, onoff ? 1 : 0);
  268. break;
  269. case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2:
  270. case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD:
  271. /* LNA */
  272. if (!onoff)
  273. sms_set_gpio(coredev, board->lna_ctrl, 0);
  274. break;
  275. }
  276. return 0;
  277. }
  278. EXPORT_SYMBOL_GPL(sms_board_power);
  279. int sms_board_led_feedback(struct smscore_device_t *coredev, int led)
  280. {
  281. int board_id = smscore_get_board_id(coredev);
  282. struct sms_board *board = sms_get_board(board_id);
  283. /* don't touch GPIO if LEDs are already set */
  284. if (smscore_led_state(coredev, -1) == led)
  285. return 0;
  286. switch (board_id) {
  287. case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
  288. sms_set_gpio(coredev,
  289. board->led_lo, (led & SMS_LED_LO) ? 1 : 0);
  290. sms_set_gpio(coredev,
  291. board->led_hi, (led & SMS_LED_HI) ? 1 : 0);
  292. smscore_led_state(coredev, led);
  293. break;
  294. }
  295. return 0;
  296. }
  297. EXPORT_SYMBOL_GPL(sms_board_led_feedback);
  298. int sms_board_lna_control(struct smscore_device_t *coredev, int onoff)
  299. {
  300. int board_id = smscore_get_board_id(coredev);
  301. struct sms_board *board = sms_get_board(board_id);
  302. pr_debug("%s: LNA %s\n", __func__, onoff ? "enabled" : "disabled");
  303. switch (board_id) {
  304. case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2:
  305. case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD:
  306. sms_set_gpio(coredev,
  307. board->rf_switch, onoff ? 1 : 0);
  308. return sms_set_gpio(coredev,
  309. board->lna_ctrl, onoff ? 1 : 0);
  310. }
  311. return -EINVAL;
  312. }
  313. EXPORT_SYMBOL_GPL(sms_board_lna_control);
  314. int sms_board_load_modules(int id)
  315. {
  316. request_module("smsdvb");
  317. return 0;
  318. }
  319. EXPORT_SYMBOL_GPL(sms_board_load_modules);