c8sectpfe-dvb.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. /*
  2. * c8sectpfe-dvb.c - C8SECTPFE STi DVB driver
  3. *
  4. * Copyright (c) STMicroelectronics 2015
  5. *
  6. * Author Peter Griffin <peter.griffin@linaro.org>
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. *
  17. * GNU General Public License for more details.
  18. */
  19. #include <linux/completion.h>
  20. #include <linux/delay.h>
  21. #include <linux/i2c.h>
  22. #include <linux/interrupt.h>
  23. #include <linux/version.h>
  24. #include <dt-bindings/media/c8sectpfe.h>
  25. #include "c8sectpfe-common.h"
  26. #include "c8sectpfe-core.h"
  27. #include "c8sectpfe-dvb.h"
  28. #include "dvb-pll.h"
  29. #include "lnbh24.h"
  30. #include "stv0367.h"
  31. #include "stv0367_priv.h"
  32. #include "stv6110x.h"
  33. #include "stv090x.h"
  34. #include "tda18212.h"
  35. static inline const char *dvb_card_str(unsigned int c)
  36. {
  37. switch (c) {
  38. case STV0367_TDA18212_NIMA_1: return "STV0367_TDA18212_NIMA_1";
  39. case STV0367_TDA18212_NIMA_2: return "STV0367_TDA18212_NIMA_2";
  40. case STV0367_TDA18212_NIMB_1: return "STV0367_TDA18212_NIMB_1";
  41. case STV0367_TDA18212_NIMB_2: return "STV0367_TDA18212_NIMB_2";
  42. case STV0903_6110_LNB24_NIMA: return "STV0903_6110_LNB24_NIMA";
  43. case STV0903_6110_LNB24_NIMB: return "STV0903_6110_LNB24_NIMB";
  44. default: return "unknown dvb frontend card";
  45. }
  46. }
  47. static struct stv090x_config stv090x_config = {
  48. .device = STV0903,
  49. .demod_mode = STV090x_SINGLE,
  50. .clk_mode = STV090x_CLK_EXT,
  51. .xtal = 16000000,
  52. .address = 0x69,
  53. .ts1_mode = STV090x_TSMODE_SERIAL_CONTINUOUS,
  54. .ts2_mode = STV090x_TSMODE_SERIAL_CONTINUOUS,
  55. .repeater_level = STV090x_RPTLEVEL_64,
  56. .tuner_init = NULL,
  57. .tuner_set_mode = NULL,
  58. .tuner_set_frequency = NULL,
  59. .tuner_get_frequency = NULL,
  60. .tuner_set_bandwidth = NULL,
  61. .tuner_get_bandwidth = NULL,
  62. .tuner_set_bbgain = NULL,
  63. .tuner_get_bbgain = NULL,
  64. .tuner_set_refclk = NULL,
  65. .tuner_get_status = NULL,
  66. };
  67. static struct stv6110x_config stv6110x_config = {
  68. .addr = 0x60,
  69. .refclk = 16000000,
  70. };
  71. #define NIMA 0
  72. #define NIMB 1
  73. static struct stv0367_config stv0367_tda18212_config[] = {
  74. {
  75. .demod_address = 0x1c,
  76. .xtal = 16000000,
  77. .if_khz = 4500,
  78. .if_iq_mode = FE_TER_NORMAL_IF_TUNER,
  79. .ts_mode = STV0367_SERIAL_PUNCT_CLOCK,
  80. .clk_pol = STV0367_CLOCKPOLARITY_DEFAULT,
  81. }, {
  82. .demod_address = 0x1d,
  83. .xtal = 16000000,
  84. .if_khz = 4500,
  85. .if_iq_mode = FE_TER_NORMAL_IF_TUNER,
  86. .ts_mode = STV0367_SERIAL_PUNCT_CLOCK,
  87. .clk_pol = STV0367_CLOCKPOLARITY_DEFAULT,
  88. }, {
  89. .demod_address = 0x1e,
  90. .xtal = 16000000,
  91. .if_khz = 4500,
  92. .if_iq_mode = FE_TER_NORMAL_IF_TUNER,
  93. .ts_mode = STV0367_SERIAL_PUNCT_CLOCK,
  94. .clk_pol = STV0367_CLOCKPOLARITY_DEFAULT,
  95. },
  96. };
  97. static struct tda18212_config tda18212_conf = {
  98. .if_dvbt_6 = 4150,
  99. .if_dvbt_7 = 4150,
  100. .if_dvbt_8 = 4500,
  101. .if_dvbc = 5000,
  102. };
  103. int c8sectpfe_frontend_attach(struct dvb_frontend **fe,
  104. struct c8sectpfe *c8sectpfe,
  105. struct channel_info *tsin, int chan_num)
  106. {
  107. struct tda18212_config *tda18212;
  108. struct stv6110x_devctl *fe2;
  109. struct i2c_client *client;
  110. struct i2c_board_info tda18212_info = {
  111. .type = "tda18212",
  112. .addr = 0x60,
  113. };
  114. if (!tsin)
  115. return -EINVAL;
  116. switch (tsin->dvb_card) {
  117. case STV0367_TDA18212_NIMA_1:
  118. case STV0367_TDA18212_NIMA_2:
  119. case STV0367_TDA18212_NIMB_1:
  120. case STV0367_TDA18212_NIMB_2:
  121. if (tsin->dvb_card == STV0367_TDA18212_NIMA_1)
  122. *fe = dvb_attach(stv0367ter_attach,
  123. &stv0367_tda18212_config[0],
  124. tsin->i2c_adapter);
  125. else if (tsin->dvb_card == STV0367_TDA18212_NIMB_1)
  126. *fe = dvb_attach(stv0367ter_attach,
  127. &stv0367_tda18212_config[1],
  128. tsin->i2c_adapter);
  129. else
  130. *fe = dvb_attach(stv0367ter_attach,
  131. &stv0367_tda18212_config[2],
  132. tsin->i2c_adapter);
  133. if (!*fe) {
  134. dev_err(c8sectpfe->device,
  135. "%s: stv0367ter_attach failed for NIM card %s\n"
  136. , __func__, dvb_card_str(tsin->dvb_card));
  137. return -ENODEV;
  138. };
  139. /*
  140. * init the demod so that i2c gate_ctrl
  141. * to the tuner works correctly
  142. */
  143. (*fe)->ops.init(*fe);
  144. /* Allocate the tda18212 structure */
  145. tda18212 = devm_kzalloc(c8sectpfe->device,
  146. sizeof(struct tda18212_config),
  147. GFP_KERNEL);
  148. if (!tda18212) {
  149. dev_err(c8sectpfe->device,
  150. "%s: devm_kzalloc failed\n", __func__);
  151. return -ENOMEM;
  152. }
  153. memcpy(tda18212, &tda18212_conf,
  154. sizeof(struct tda18212_config));
  155. tda18212->fe = (*fe);
  156. tda18212_info.platform_data = tda18212;
  157. /* attach tuner */
  158. request_module("tda18212");
  159. client = i2c_new_device(tsin->i2c_adapter, &tda18212_info);
  160. if (!client || !client->dev.driver) {
  161. dvb_frontend_detach(*fe);
  162. return -ENODEV;
  163. }
  164. if (!try_module_get(client->dev.driver->owner)) {
  165. i2c_unregister_device(client);
  166. dvb_frontend_detach(*fe);
  167. return -ENODEV;
  168. }
  169. tsin->i2c_client = client;
  170. break;
  171. case STV0903_6110_LNB24_NIMA:
  172. *fe = dvb_attach(stv090x_attach, &stv090x_config,
  173. tsin->i2c_adapter, STV090x_DEMODULATOR_0);
  174. if (!*fe) {
  175. dev_err(c8sectpfe->device, "%s: stv090x_attach failed\n"
  176. "\tfor NIM card %s\n",
  177. __func__, dvb_card_str(tsin->dvb_card));
  178. return -ENODEV;
  179. }
  180. fe2 = dvb_attach(stv6110x_attach, *fe,
  181. &stv6110x_config, tsin->i2c_adapter);
  182. if (!fe2) {
  183. dev_err(c8sectpfe->device,
  184. "%s: stv6110x_attach failed for NIM card %s\n"
  185. , __func__, dvb_card_str(tsin->dvb_card));
  186. return -ENODEV;
  187. };
  188. stv090x_config.tuner_init = fe2->tuner_init;
  189. stv090x_config.tuner_set_mode = fe2->tuner_set_mode;
  190. stv090x_config.tuner_set_frequency = fe2->tuner_set_frequency;
  191. stv090x_config.tuner_get_frequency = fe2->tuner_get_frequency;
  192. stv090x_config.tuner_set_bandwidth = fe2->tuner_set_bandwidth;
  193. stv090x_config.tuner_get_bandwidth = fe2->tuner_get_bandwidth;
  194. stv090x_config.tuner_set_bbgain = fe2->tuner_set_bbgain;
  195. stv090x_config.tuner_get_bbgain = fe2->tuner_get_bbgain;
  196. stv090x_config.tuner_set_refclk = fe2->tuner_set_refclk;
  197. stv090x_config.tuner_get_status = fe2->tuner_get_status;
  198. dvb_attach(lnbh24_attach, *fe, tsin->i2c_adapter, 0, 0, 0x9);
  199. break;
  200. default:
  201. dev_err(c8sectpfe->device,
  202. "%s: DVB frontend card %s not yet supported\n",
  203. __func__, dvb_card_str(tsin->dvb_card));
  204. return -ENODEV;
  205. }
  206. (*fe)->id = chan_num;
  207. dev_info(c8sectpfe->device,
  208. "DVB frontend card %s successfully attached",
  209. dvb_card_str(tsin->dvb_card));
  210. return 0;
  211. }