ddbridge-ci.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. /*
  2. * ddbridge-ci.c: Digital Devices bridge CI (DuoFlex, CI Bridge) support
  3. *
  4. * Copyright (C) 2010-2017 Digital Devices GmbH
  5. * Marcus Metzler <mocm@metzlerbros.de>
  6. * Ralph Metzler <rjkm@metzlerbros.de>
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License
  10. * version 2 only, as published by the Free Software Foundation.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * To obtain the license, point your browser to
  18. * http://www.gnu.org/copyleft/gpl.html
  19. */
  20. #include "ddbridge.h"
  21. #include "ddbridge-regs.h"
  22. #include "ddbridge-ci.h"
  23. #include "ddbridge-io.h"
  24. #include "ddbridge-i2c.h"
  25. #include "cxd2099.h"
  26. /* Octopus CI internal CI interface */
  27. static int wait_ci_ready(struct ddb_ci *ci)
  28. {
  29. u32 count = 10;
  30. ndelay(500);
  31. do {
  32. if (ddbreadl(ci->port->dev,
  33. CI_CONTROL(ci->nr)) & CI_READY)
  34. break;
  35. usleep_range(1, 2);
  36. if ((--count) == 0)
  37. return -1;
  38. } while (1);
  39. return 0;
  40. }
  41. static int read_attribute_mem(struct dvb_ca_en50221 *ca,
  42. int slot, int address)
  43. {
  44. struct ddb_ci *ci = ca->data;
  45. u32 val, off = (address >> 1) & (CI_BUFFER_SIZE - 1);
  46. if (address > CI_BUFFER_SIZE)
  47. return -1;
  48. ddbwritel(ci->port->dev, CI_READ_CMD | (1 << 16) | address,
  49. CI_DO_READ_ATTRIBUTES(ci->nr));
  50. wait_ci_ready(ci);
  51. val = 0xff & ddbreadl(ci->port->dev, CI_BUFFER(ci->nr) + off);
  52. return val;
  53. }
  54. static int write_attribute_mem(struct dvb_ca_en50221 *ca, int slot,
  55. int address, u8 value)
  56. {
  57. struct ddb_ci *ci = ca->data;
  58. ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address,
  59. CI_DO_ATTRIBUTE_RW(ci->nr));
  60. wait_ci_ready(ci);
  61. return 0;
  62. }
  63. static int read_cam_control(struct dvb_ca_en50221 *ca,
  64. int slot, u8 address)
  65. {
  66. u32 count = 100;
  67. struct ddb_ci *ci = ca->data;
  68. u32 res;
  69. ddbwritel(ci->port->dev, CI_READ_CMD | address,
  70. CI_DO_IO_RW(ci->nr));
  71. ndelay(500);
  72. do {
  73. res = ddbreadl(ci->port->dev, CI_READDATA(ci->nr));
  74. if (res & CI_READY)
  75. break;
  76. usleep_range(1, 2);
  77. if ((--count) == 0)
  78. return -1;
  79. } while (1);
  80. return 0xff & res;
  81. }
  82. static int write_cam_control(struct dvb_ca_en50221 *ca, int slot,
  83. u8 address, u8 value)
  84. {
  85. struct ddb_ci *ci = ca->data;
  86. ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address,
  87. CI_DO_IO_RW(ci->nr));
  88. wait_ci_ready(ci);
  89. return 0;
  90. }
  91. static int slot_reset(struct dvb_ca_en50221 *ca, int slot)
  92. {
  93. struct ddb_ci *ci = ca->data;
  94. ddbwritel(ci->port->dev, CI_POWER_ON,
  95. CI_CONTROL(ci->nr));
  96. msleep(100);
  97. ddbwritel(ci->port->dev, CI_POWER_ON | CI_RESET_CAM,
  98. CI_CONTROL(ci->nr));
  99. ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON | CI_RESET_CAM,
  100. CI_CONTROL(ci->nr));
  101. usleep_range(20, 25);
  102. ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON,
  103. CI_CONTROL(ci->nr));
  104. return 0;
  105. }
  106. static int slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
  107. {
  108. struct ddb_ci *ci = ca->data;
  109. ddbwritel(ci->port->dev, 0, CI_CONTROL(ci->nr));
  110. msleep(300);
  111. return 0;
  112. }
  113. static int slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
  114. {
  115. struct ddb_ci *ci = ca->data;
  116. u32 val = ddbreadl(ci->port->dev, CI_CONTROL(ci->nr));
  117. ddbwritel(ci->port->dev, val | CI_BYPASS_DISABLE,
  118. CI_CONTROL(ci->nr));
  119. return 0;
  120. }
  121. static int poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
  122. {
  123. struct ddb_ci *ci = ca->data;
  124. u32 val = ddbreadl(ci->port->dev, CI_CONTROL(ci->nr));
  125. int stat = 0;
  126. if (val & CI_CAM_DETECT)
  127. stat |= DVB_CA_EN50221_POLL_CAM_PRESENT;
  128. if (val & CI_CAM_READY)
  129. stat |= DVB_CA_EN50221_POLL_CAM_READY;
  130. return stat;
  131. }
  132. static struct dvb_ca_en50221 en_templ = {
  133. .read_attribute_mem = read_attribute_mem,
  134. .write_attribute_mem = write_attribute_mem,
  135. .read_cam_control = read_cam_control,
  136. .write_cam_control = write_cam_control,
  137. .slot_reset = slot_reset,
  138. .slot_shutdown = slot_shutdown,
  139. .slot_ts_enable = slot_ts_enable,
  140. .poll_slot_status = poll_slot_status,
  141. };
  142. static void ci_attach(struct ddb_port *port)
  143. {
  144. struct ddb_ci *ci;
  145. ci = kzalloc(sizeof(*ci), GFP_KERNEL);
  146. if (!ci)
  147. return;
  148. memcpy(&ci->en, &en_templ, sizeof(en_templ));
  149. ci->en.data = ci;
  150. port->en = &ci->en;
  151. port->en_freedata = 1;
  152. ci->port = port;
  153. ci->nr = port->nr - 2;
  154. }
  155. /* DuoFlex Dual CI support */
  156. static int write_creg(struct ddb_ci *ci, u8 data, u8 mask)
  157. {
  158. struct i2c_adapter *i2c = &ci->port->i2c->adap;
  159. u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13;
  160. ci->port->creg = (ci->port->creg & ~mask) | data;
  161. return i2c_write_reg(i2c, adr, 0x02, ci->port->creg);
  162. }
  163. static int read_attribute_mem_xo2(struct dvb_ca_en50221 *ca,
  164. int slot, int address)
  165. {
  166. struct ddb_ci *ci = ca->data;
  167. struct i2c_adapter *i2c = &ci->port->i2c->adap;
  168. u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13;
  169. int res;
  170. u8 val;
  171. res = i2c_read_reg16(i2c, adr, 0x8000 | address, &val);
  172. return res ? res : val;
  173. }
  174. static int write_attribute_mem_xo2(struct dvb_ca_en50221 *ca, int slot,
  175. int address, u8 value)
  176. {
  177. struct ddb_ci *ci = ca->data;
  178. struct i2c_adapter *i2c = &ci->port->i2c->adap;
  179. u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13;
  180. return i2c_write_reg16(i2c, adr, 0x8000 | address, value);
  181. }
  182. static int read_cam_control_xo2(struct dvb_ca_en50221 *ca,
  183. int slot, u8 address)
  184. {
  185. struct ddb_ci *ci = ca->data;
  186. struct i2c_adapter *i2c = &ci->port->i2c->adap;
  187. u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13;
  188. u8 val;
  189. int res;
  190. res = i2c_read_reg(i2c, adr, 0x20 | (address & 3), &val);
  191. return res ? res : val;
  192. }
  193. static int write_cam_control_xo2(struct dvb_ca_en50221 *ca, int slot,
  194. u8 address, u8 value)
  195. {
  196. struct ddb_ci *ci = ca->data;
  197. struct i2c_adapter *i2c = &ci->port->i2c->adap;
  198. u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13;
  199. return i2c_write_reg(i2c, adr, 0x20 | (address & 3), value);
  200. }
  201. static int slot_reset_xo2(struct dvb_ca_en50221 *ca, int slot)
  202. {
  203. struct ddb_ci *ci = ca->data;
  204. dev_dbg(ci->port->dev->dev, "%s\n", __func__);
  205. write_creg(ci, 0x01, 0x01);
  206. write_creg(ci, 0x04, 0x04);
  207. msleep(20);
  208. write_creg(ci, 0x02, 0x02);
  209. write_creg(ci, 0x00, 0x04);
  210. write_creg(ci, 0x18, 0x18);
  211. return 0;
  212. }
  213. static int slot_shutdown_xo2(struct dvb_ca_en50221 *ca, int slot)
  214. {
  215. struct ddb_ci *ci = ca->data;
  216. dev_dbg(ci->port->dev->dev, "%s\n", __func__);
  217. write_creg(ci, 0x10, 0xff);
  218. write_creg(ci, 0x08, 0x08);
  219. return 0;
  220. }
  221. static int slot_ts_enable_xo2(struct dvb_ca_en50221 *ca, int slot)
  222. {
  223. struct ddb_ci *ci = ca->data;
  224. dev_dbg(ci->port->dev->dev, "%s\n", __func__);
  225. write_creg(ci, 0x00, 0x10);
  226. return 0;
  227. }
  228. static int poll_slot_status_xo2(struct dvb_ca_en50221 *ca, int slot, int open)
  229. {
  230. struct ddb_ci *ci = ca->data;
  231. struct i2c_adapter *i2c = &ci->port->i2c->adap;
  232. u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13;
  233. u8 val = 0;
  234. int stat = 0;
  235. i2c_read_reg(i2c, adr, 0x01, &val);
  236. if (val & 2)
  237. stat |= DVB_CA_EN50221_POLL_CAM_PRESENT;
  238. if (val & 1)
  239. stat |= DVB_CA_EN50221_POLL_CAM_READY;
  240. return stat;
  241. }
  242. static struct dvb_ca_en50221 en_xo2_templ = {
  243. .read_attribute_mem = read_attribute_mem_xo2,
  244. .write_attribute_mem = write_attribute_mem_xo2,
  245. .read_cam_control = read_cam_control_xo2,
  246. .write_cam_control = write_cam_control_xo2,
  247. .slot_reset = slot_reset_xo2,
  248. .slot_shutdown = slot_shutdown_xo2,
  249. .slot_ts_enable = slot_ts_enable_xo2,
  250. .poll_slot_status = poll_slot_status_xo2,
  251. };
  252. static void ci_xo2_attach(struct ddb_port *port)
  253. {
  254. struct ddb_ci *ci;
  255. ci = kzalloc(sizeof(*ci), GFP_KERNEL);
  256. if (!ci)
  257. return;
  258. memcpy(&ci->en, &en_xo2_templ, sizeof(en_xo2_templ));
  259. ci->en.data = ci;
  260. port->en = &ci->en;
  261. port->en_freedata = 1;
  262. ci->port = port;
  263. ci->nr = port->nr - 2;
  264. ci->port->creg = 0;
  265. write_creg(ci, 0x10, 0xff);
  266. write_creg(ci, 0x08, 0x08);
  267. }
  268. static const struct cxd2099_cfg cxd_cfgtmpl = {
  269. .bitrate = 72000,
  270. .polarity = 1,
  271. .clock_mode = 1,
  272. .max_i2c = 512,
  273. };
  274. static int ci_cxd2099_attach(struct ddb_port *port, u32 bitrate)
  275. {
  276. struct cxd2099_cfg cxd_cfg = cxd_cfgtmpl;
  277. struct i2c_client *client;
  278. cxd_cfg.bitrate = bitrate;
  279. cxd_cfg.en = &port->en;
  280. client = dvb_module_probe("cxd2099", NULL, &port->i2c->adap,
  281. 0x40, &cxd_cfg);
  282. if (!client)
  283. goto err;
  284. port->dvb[0].i2c_client[0] = client;
  285. port->en_freedata = 0;
  286. return 0;
  287. err:
  288. dev_err(port->dev->dev, "CXD2099AR attach failed\n");
  289. return -ENODEV;
  290. }
  291. int ddb_ci_attach(struct ddb_port *port, u32 bitrate)
  292. {
  293. int ret;
  294. switch (port->type) {
  295. case DDB_CI_EXTERNAL_SONY:
  296. ret = ci_cxd2099_attach(port, bitrate);
  297. if (ret)
  298. return -ENODEV;
  299. break;
  300. case DDB_CI_EXTERNAL_XO2:
  301. case DDB_CI_EXTERNAL_XO2_B:
  302. ci_xo2_attach(port);
  303. break;
  304. case DDB_CI_INTERNAL:
  305. ci_attach(port);
  306. break;
  307. default:
  308. return -ENODEV;
  309. }
  310. if (!port->en)
  311. return -ENODEV;
  312. dvb_ca_en50221_init(port->dvb[0].adap, port->en, 0, 1);
  313. return 0;
  314. }
  315. void ddb_ci_detach(struct ddb_port *port)
  316. {
  317. if (port->dvb[0].dev)
  318. dvb_unregister_device(port->dvb[0].dev);
  319. if (port->en) {
  320. dvb_ca_en50221_release(port->en);
  321. dvb_module_release(port->dvb[0].i2c_client[0]);
  322. port->dvb[0].i2c_client[0] = NULL;
  323. /* free alloc'ed memory if needed */
  324. if (port->en_freedata)
  325. kfree(port->en->data);
  326. port->en = NULL;
  327. }
  328. }