va1j5jf8007s.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658
  1. /*
  2. * ISDB-S driver for VA1J5JF8007
  3. *
  4. * Copyright (C) 2009 HIRANO Takahito <hiranotaka@zng.info>
  5. *
  6. * based on pt1dvr - http://pt1dvr.sourceforge.jp/
  7. * by Tomoaki Ishikawa <tomy@users.sourceforge.jp>
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22. */
  23. #include <linux/kernel.h>
  24. #include <linux/module.h>
  25. #include <linux/slab.h>
  26. #include <linux/i2c.h>
  27. #include "dvb_frontend.h"
  28. #include "va1j5jf8007s.h"
  29. enum va1j5jf8007s_tune_state {
  30. VA1J5JF8007S_IDLE,
  31. VA1J5JF8007S_SET_FREQUENCY_1,
  32. VA1J5JF8007S_SET_FREQUENCY_2,
  33. VA1J5JF8007S_SET_FREQUENCY_3,
  34. VA1J5JF8007S_CHECK_FREQUENCY,
  35. VA1J5JF8007S_SET_MODULATION,
  36. VA1J5JF8007S_CHECK_MODULATION,
  37. VA1J5JF8007S_SET_TS_ID,
  38. VA1J5JF8007S_CHECK_TS_ID,
  39. VA1J5JF8007S_TRACK,
  40. };
  41. struct va1j5jf8007s_state {
  42. const struct va1j5jf8007s_config *config;
  43. struct i2c_adapter *adap;
  44. struct dvb_frontend fe;
  45. enum va1j5jf8007s_tune_state tune_state;
  46. };
  47. static int va1j5jf8007s_get_frontend_algo(struct dvb_frontend *fe)
  48. {
  49. return DVBFE_ALGO_HW;
  50. }
  51. static int
  52. va1j5jf8007s_read_status(struct dvb_frontend *fe, fe_status_t *status)
  53. {
  54. struct va1j5jf8007s_state *state;
  55. state = fe->demodulator_priv;
  56. switch (state->tune_state) {
  57. case VA1J5JF8007S_IDLE:
  58. case VA1J5JF8007S_SET_FREQUENCY_1:
  59. case VA1J5JF8007S_SET_FREQUENCY_2:
  60. case VA1J5JF8007S_SET_FREQUENCY_3:
  61. case VA1J5JF8007S_CHECK_FREQUENCY:
  62. *status = 0;
  63. return 0;
  64. case VA1J5JF8007S_SET_MODULATION:
  65. case VA1J5JF8007S_CHECK_MODULATION:
  66. *status |= FE_HAS_SIGNAL;
  67. return 0;
  68. case VA1J5JF8007S_SET_TS_ID:
  69. case VA1J5JF8007S_CHECK_TS_ID:
  70. *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
  71. return 0;
  72. case VA1J5JF8007S_TRACK:
  73. *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_LOCK;
  74. return 0;
  75. }
  76. BUG();
  77. }
  78. struct va1j5jf8007s_cb_map {
  79. u32 frequency;
  80. u8 cb;
  81. };
  82. static const struct va1j5jf8007s_cb_map va1j5jf8007s_cb_maps[] = {
  83. { 986000, 0xb2 },
  84. { 1072000, 0xd2 },
  85. { 1154000, 0xe2 },
  86. { 1291000, 0x20 },
  87. { 1447000, 0x40 },
  88. { 1615000, 0x60 },
  89. { 1791000, 0x80 },
  90. { 1972000, 0xa0 },
  91. };
  92. static u8 va1j5jf8007s_lookup_cb(u32 frequency)
  93. {
  94. int i;
  95. const struct va1j5jf8007s_cb_map *map;
  96. for (i = 0; i < ARRAY_SIZE(va1j5jf8007s_cb_maps); i++) {
  97. map = &va1j5jf8007s_cb_maps[i];
  98. if (frequency < map->frequency)
  99. return map->cb;
  100. }
  101. return 0xc0;
  102. }
  103. static int va1j5jf8007s_set_frequency_1(struct va1j5jf8007s_state *state)
  104. {
  105. u32 frequency;
  106. u16 word;
  107. u8 buf[6];
  108. struct i2c_msg msg;
  109. frequency = state->fe.dtv_property_cache.frequency;
  110. word = (frequency + 500) / 1000;
  111. if (frequency < 1072000)
  112. word = (word << 1 & ~0x1f) | (word & 0x0f);
  113. buf[0] = 0xfe;
  114. buf[1] = 0xc0;
  115. buf[2] = 0x40 | word >> 8;
  116. buf[3] = word;
  117. buf[4] = 0xe0;
  118. buf[5] = va1j5jf8007s_lookup_cb(frequency);
  119. msg.addr = state->config->demod_address;
  120. msg.flags = 0;
  121. msg.len = sizeof(buf);
  122. msg.buf = buf;
  123. if (i2c_transfer(state->adap, &msg, 1) != 1)
  124. return -EREMOTEIO;
  125. return 0;
  126. }
  127. static int va1j5jf8007s_set_frequency_2(struct va1j5jf8007s_state *state)
  128. {
  129. u8 buf[3];
  130. struct i2c_msg msg;
  131. buf[0] = 0xfe;
  132. buf[1] = 0xc0;
  133. buf[2] = 0xe4;
  134. msg.addr = state->config->demod_address;
  135. msg.flags = 0;
  136. msg.len = sizeof(buf);
  137. msg.buf = buf;
  138. if (i2c_transfer(state->adap, &msg, 1) != 1)
  139. return -EREMOTEIO;
  140. return 0;
  141. }
  142. static int va1j5jf8007s_set_frequency_3(struct va1j5jf8007s_state *state)
  143. {
  144. u32 frequency;
  145. u8 buf[4];
  146. struct i2c_msg msg;
  147. frequency = state->fe.dtv_property_cache.frequency;
  148. buf[0] = 0xfe;
  149. buf[1] = 0xc0;
  150. buf[2] = 0xf4;
  151. buf[3] = va1j5jf8007s_lookup_cb(frequency) | 0x4;
  152. msg.addr = state->config->demod_address;
  153. msg.flags = 0;
  154. msg.len = sizeof(buf);
  155. msg.buf = buf;
  156. if (i2c_transfer(state->adap, &msg, 1) != 1)
  157. return -EREMOTEIO;
  158. return 0;
  159. }
  160. static int
  161. va1j5jf8007s_check_frequency(struct va1j5jf8007s_state *state, int *lock)
  162. {
  163. u8 addr;
  164. u8 write_buf[2], read_buf[1];
  165. struct i2c_msg msgs[2];
  166. addr = state->config->demod_address;
  167. write_buf[0] = 0xfe;
  168. write_buf[1] = 0xc1;
  169. msgs[0].addr = addr;
  170. msgs[0].flags = 0;
  171. msgs[0].len = sizeof(write_buf);
  172. msgs[0].buf = write_buf;
  173. msgs[1].addr = addr;
  174. msgs[1].flags = I2C_M_RD;
  175. msgs[1].len = sizeof(read_buf);
  176. msgs[1].buf = read_buf;
  177. if (i2c_transfer(state->adap, msgs, 2) != 2)
  178. return -EREMOTEIO;
  179. *lock = read_buf[0] & 0x40;
  180. return 0;
  181. }
  182. static int va1j5jf8007s_set_modulation(struct va1j5jf8007s_state *state)
  183. {
  184. u8 buf[2];
  185. struct i2c_msg msg;
  186. buf[0] = 0x03;
  187. buf[1] = 0x01;
  188. msg.addr = state->config->demod_address;
  189. msg.flags = 0;
  190. msg.len = sizeof(buf);
  191. msg.buf = buf;
  192. if (i2c_transfer(state->adap, &msg, 1) != 1)
  193. return -EREMOTEIO;
  194. return 0;
  195. }
  196. static int
  197. va1j5jf8007s_check_modulation(struct va1j5jf8007s_state *state, int *lock)
  198. {
  199. u8 addr;
  200. u8 write_buf[1], read_buf[1];
  201. struct i2c_msg msgs[2];
  202. addr = state->config->demod_address;
  203. write_buf[0] = 0xc3;
  204. msgs[0].addr = addr;
  205. msgs[0].flags = 0;
  206. msgs[0].len = sizeof(write_buf);
  207. msgs[0].buf = write_buf;
  208. msgs[1].addr = addr;
  209. msgs[1].flags = I2C_M_RD;
  210. msgs[1].len = sizeof(read_buf);
  211. msgs[1].buf = read_buf;
  212. if (i2c_transfer(state->adap, msgs, 2) != 2)
  213. return -EREMOTEIO;
  214. *lock = !(read_buf[0] & 0x10);
  215. return 0;
  216. }
  217. static int
  218. va1j5jf8007s_set_ts_id(struct va1j5jf8007s_state *state)
  219. {
  220. u32 ts_id;
  221. u8 buf[3];
  222. struct i2c_msg msg;
  223. ts_id = state->fe.dtv_property_cache.isdbs_ts_id;
  224. if (!ts_id)
  225. return 0;
  226. buf[0] = 0x8f;
  227. buf[1] = ts_id >> 8;
  228. buf[2] = ts_id;
  229. msg.addr = state->config->demod_address;
  230. msg.flags = 0;
  231. msg.len = sizeof(buf);
  232. msg.buf = buf;
  233. if (i2c_transfer(state->adap, &msg, 1) != 1)
  234. return -EREMOTEIO;
  235. return 0;
  236. }
  237. static int
  238. va1j5jf8007s_check_ts_id(struct va1j5jf8007s_state *state, int *lock)
  239. {
  240. u8 addr;
  241. u8 write_buf[1], read_buf[2];
  242. struct i2c_msg msgs[2];
  243. u32 ts_id;
  244. ts_id = state->fe.dtv_property_cache.isdbs_ts_id;
  245. if (!ts_id) {
  246. *lock = 1;
  247. return 0;
  248. }
  249. addr = state->config->demod_address;
  250. write_buf[0] = 0xe6;
  251. msgs[0].addr = addr;
  252. msgs[0].flags = 0;
  253. msgs[0].len = sizeof(write_buf);
  254. msgs[0].buf = write_buf;
  255. msgs[1].addr = addr;
  256. msgs[1].flags = I2C_M_RD;
  257. msgs[1].len = sizeof(read_buf);
  258. msgs[1].buf = read_buf;
  259. if (i2c_transfer(state->adap, msgs, 2) != 2)
  260. return -EREMOTEIO;
  261. *lock = (read_buf[0] << 8 | read_buf[1]) == ts_id;
  262. return 0;
  263. }
  264. static int
  265. va1j5jf8007s_tune(struct dvb_frontend *fe,
  266. struct dvb_frontend_parameters *params,
  267. unsigned int mode_flags, unsigned int *delay,
  268. fe_status_t *status)
  269. {
  270. struct va1j5jf8007s_state *state;
  271. int ret;
  272. int lock;
  273. state = fe->demodulator_priv;
  274. if (params != NULL)
  275. state->tune_state = VA1J5JF8007S_SET_FREQUENCY_1;
  276. switch (state->tune_state) {
  277. case VA1J5JF8007S_IDLE:
  278. *delay = 3 * HZ;
  279. *status = 0;
  280. return 0;
  281. case VA1J5JF8007S_SET_FREQUENCY_1:
  282. ret = va1j5jf8007s_set_frequency_1(state);
  283. if (ret < 0)
  284. return ret;
  285. state->tune_state = VA1J5JF8007S_SET_FREQUENCY_2;
  286. *delay = 0;
  287. *status = 0;
  288. return 0;
  289. case VA1J5JF8007S_SET_FREQUENCY_2:
  290. ret = va1j5jf8007s_set_frequency_2(state);
  291. if (ret < 0)
  292. return ret;
  293. state->tune_state = VA1J5JF8007S_SET_FREQUENCY_3;
  294. *delay = (HZ + 99) / 100;
  295. *status = 0;
  296. return 0;
  297. case VA1J5JF8007S_SET_FREQUENCY_3:
  298. ret = va1j5jf8007s_set_frequency_3(state);
  299. if (ret < 0)
  300. return ret;
  301. state->tune_state = VA1J5JF8007S_CHECK_FREQUENCY;
  302. *delay = 0;
  303. *status = 0;
  304. return 0;
  305. case VA1J5JF8007S_CHECK_FREQUENCY:
  306. ret = va1j5jf8007s_check_frequency(state, &lock);
  307. if (ret < 0)
  308. return ret;
  309. if (!lock) {
  310. *delay = (HZ + 999) / 1000;
  311. *status = 0;
  312. return 0;
  313. }
  314. state->tune_state = VA1J5JF8007S_SET_MODULATION;
  315. *delay = 0;
  316. *status = FE_HAS_SIGNAL;
  317. return 0;
  318. case VA1J5JF8007S_SET_MODULATION:
  319. ret = va1j5jf8007s_set_modulation(state);
  320. if (ret < 0)
  321. return ret;
  322. state->tune_state = VA1J5JF8007S_CHECK_MODULATION;
  323. *delay = 0;
  324. *status = FE_HAS_SIGNAL;
  325. return 0;
  326. case VA1J5JF8007S_CHECK_MODULATION:
  327. ret = va1j5jf8007s_check_modulation(state, &lock);
  328. if (ret < 0)
  329. return ret;
  330. if (!lock) {
  331. *delay = (HZ + 49) / 50;
  332. *status = FE_HAS_SIGNAL;
  333. return 0;
  334. }
  335. state->tune_state = VA1J5JF8007S_SET_TS_ID;
  336. *delay = 0;
  337. *status = FE_HAS_SIGNAL | FE_HAS_CARRIER;
  338. return 0;
  339. case VA1J5JF8007S_SET_TS_ID:
  340. ret = va1j5jf8007s_set_ts_id(state);
  341. if (ret < 0)
  342. return ret;
  343. state->tune_state = VA1J5JF8007S_CHECK_TS_ID;
  344. return 0;
  345. case VA1J5JF8007S_CHECK_TS_ID:
  346. ret = va1j5jf8007s_check_ts_id(state, &lock);
  347. if (ret < 0)
  348. return ret;
  349. if (!lock) {
  350. *delay = (HZ + 99) / 100;
  351. *status = FE_HAS_SIGNAL | FE_HAS_CARRIER;
  352. return 0;
  353. }
  354. state->tune_state = VA1J5JF8007S_TRACK;
  355. /* fall through */
  356. case VA1J5JF8007S_TRACK:
  357. *delay = 3 * HZ;
  358. *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_LOCK;
  359. return 0;
  360. }
  361. BUG();
  362. }
  363. static int va1j5jf8007s_init_frequency(struct va1j5jf8007s_state *state)
  364. {
  365. u8 buf[4];
  366. struct i2c_msg msg;
  367. buf[0] = 0xfe;
  368. buf[1] = 0xc0;
  369. buf[2] = 0xf0;
  370. buf[3] = 0x04;
  371. msg.addr = state->config->demod_address;
  372. msg.flags = 0;
  373. msg.len = sizeof(buf);
  374. msg.buf = buf;
  375. if (i2c_transfer(state->adap, &msg, 1) != 1)
  376. return -EREMOTEIO;
  377. return 0;
  378. }
  379. static int va1j5jf8007s_set_sleep(struct va1j5jf8007s_state *state, int sleep)
  380. {
  381. u8 buf[2];
  382. struct i2c_msg msg;
  383. buf[0] = 0x17;
  384. buf[1] = sleep ? 0x01 : 0x00;
  385. msg.addr = state->config->demod_address;
  386. msg.flags = 0;
  387. msg.len = sizeof(buf);
  388. msg.buf = buf;
  389. if (i2c_transfer(state->adap, &msg, 1) != 1)
  390. return -EREMOTEIO;
  391. return 0;
  392. }
  393. static int va1j5jf8007s_sleep(struct dvb_frontend *fe)
  394. {
  395. struct va1j5jf8007s_state *state;
  396. int ret;
  397. state = fe->demodulator_priv;
  398. ret = va1j5jf8007s_init_frequency(state);
  399. if (ret < 0)
  400. return ret;
  401. return va1j5jf8007s_set_sleep(state, 1);
  402. }
  403. static int va1j5jf8007s_init(struct dvb_frontend *fe)
  404. {
  405. struct va1j5jf8007s_state *state;
  406. state = fe->demodulator_priv;
  407. state->tune_state = VA1J5JF8007S_IDLE;
  408. return va1j5jf8007s_set_sleep(state, 0);
  409. }
  410. static void va1j5jf8007s_release(struct dvb_frontend *fe)
  411. {
  412. struct va1j5jf8007s_state *state;
  413. state = fe->demodulator_priv;
  414. kfree(state);
  415. }
  416. static struct dvb_frontend_ops va1j5jf8007s_ops = {
  417. .info = {
  418. .name = "VA1J5JF8007 ISDB-S",
  419. .type = FE_QPSK,
  420. .frequency_min = 950000,
  421. .frequency_max = 2150000,
  422. .frequency_stepsize = 1000,
  423. .caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_AUTO |
  424. FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
  425. FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO,
  426. },
  427. .get_frontend_algo = va1j5jf8007s_get_frontend_algo,
  428. .read_status = va1j5jf8007s_read_status,
  429. .tune = va1j5jf8007s_tune,
  430. .sleep = va1j5jf8007s_sleep,
  431. .init = va1j5jf8007s_init,
  432. .release = va1j5jf8007s_release,
  433. };
  434. static int va1j5jf8007s_prepare_1(struct va1j5jf8007s_state *state)
  435. {
  436. u8 addr;
  437. u8 write_buf[1], read_buf[1];
  438. struct i2c_msg msgs[2];
  439. addr = state->config->demod_address;
  440. write_buf[0] = 0x07;
  441. msgs[0].addr = addr;
  442. msgs[0].flags = 0;
  443. msgs[0].len = sizeof(write_buf);
  444. msgs[0].buf = write_buf;
  445. msgs[1].addr = addr;
  446. msgs[1].flags = I2C_M_RD;
  447. msgs[1].len = sizeof(read_buf);
  448. msgs[1].buf = read_buf;
  449. if (i2c_transfer(state->adap, msgs, 2) != 2)
  450. return -EREMOTEIO;
  451. if (read_buf[0] != 0x41)
  452. return -EIO;
  453. return 0;
  454. }
  455. static const u8 va1j5jf8007s_prepare_bufs[][2] = {
  456. {0x04, 0x02}, {0x0d, 0x55}, {0x11, 0x40}, {0x13, 0x80}, {0x17, 0x01},
  457. {0x1c, 0x0a}, {0x1d, 0xaa}, {0x1e, 0x20}, {0x1f, 0x88}, {0x51, 0xb0},
  458. {0x52, 0x89}, {0x53, 0xb3}, {0x5a, 0x2d}, {0x5b, 0xd3}, {0x85, 0x69},
  459. {0x87, 0x04}, {0x8e, 0x02}, {0xa3, 0xf7}, {0xa5, 0xc0},
  460. };
  461. static int va1j5jf8007s_prepare_2(struct va1j5jf8007s_state *state)
  462. {
  463. u8 addr;
  464. u8 buf[2];
  465. struct i2c_msg msg;
  466. int i;
  467. addr = state->config->demod_address;
  468. msg.addr = addr;
  469. msg.flags = 0;
  470. msg.len = 2;
  471. msg.buf = buf;
  472. for (i = 0; i < ARRAY_SIZE(va1j5jf8007s_prepare_bufs); i++) {
  473. memcpy(buf, va1j5jf8007s_prepare_bufs[i], sizeof(buf));
  474. if (i2c_transfer(state->adap, &msg, 1) != 1)
  475. return -EREMOTEIO;
  476. }
  477. return 0;
  478. }
  479. /* must be called after va1j5jf8007t_attach */
  480. int va1j5jf8007s_prepare(struct dvb_frontend *fe)
  481. {
  482. struct va1j5jf8007s_state *state;
  483. int ret;
  484. state = fe->demodulator_priv;
  485. ret = va1j5jf8007s_prepare_1(state);
  486. if (ret < 0)
  487. return ret;
  488. ret = va1j5jf8007s_prepare_2(state);
  489. if (ret < 0)
  490. return ret;
  491. return va1j5jf8007s_init_frequency(state);
  492. }
  493. struct dvb_frontend *
  494. va1j5jf8007s_attach(const struct va1j5jf8007s_config *config,
  495. struct i2c_adapter *adap)
  496. {
  497. struct va1j5jf8007s_state *state;
  498. struct dvb_frontend *fe;
  499. u8 buf[2];
  500. struct i2c_msg msg;
  501. state = kzalloc(sizeof(struct va1j5jf8007s_state), GFP_KERNEL);
  502. if (!state)
  503. return NULL;
  504. state->config = config;
  505. state->adap = adap;
  506. fe = &state->fe;
  507. memcpy(&fe->ops, &va1j5jf8007s_ops, sizeof(struct dvb_frontend_ops));
  508. fe->demodulator_priv = state;
  509. buf[0] = 0x01;
  510. buf[1] = 0x80;
  511. msg.addr = state->config->demod_address;
  512. msg.flags = 0;
  513. msg.len = sizeof(buf);
  514. msg.buf = buf;
  515. if (i2c_transfer(state->adap, &msg, 1) != 1) {
  516. kfree(state);
  517. return NULL;
  518. }
  519. return fe;
  520. }