Advertisement
Guest User

Untitled

a guest
Mar 25th, 2023
30
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 105.01 KB | None | 0 0
  1. diff -uraBN a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
  2. --- a/drivers/i2c/i2c-core-base.c
  3. +++ b/drivers/i2c/i2c-core-base.c
  4. @@ -1018,15 +1018,14 @@
  5. { },
  6. };
  7.  
  8. -static int dummy_probe(struct i2c_client *client,
  9. - const struct i2c_device_id *id)
  10. +static int dummy_probe(struct i2c_client *client)
  11. {
  12. return 0;
  13. }
  14.  
  15. static struct i2c_driver dummy_driver = {
  16. .driver.name = "dummy",
  17. - .probe = dummy_probe,
  18. + .probe_new = dummy_probe,
  19. .id_table = dummy_id,
  20. };
  21.  
  22. @@ -2237,6 +2236,20 @@
  23. }
  24. EXPORT_SYMBOL_GPL(i2c_get_device_id);
  25.  
  26. +/**
  27. + * i2c_client_get_device_id - get the driver match table entry of a device
  28. + * @client: the device to query. The device must be bound to a driver
  29. + *
  30. + * Returns a pointer to the matching entry if found, NULL otherwise.
  31. + */
  32. +const struct i2c_device_id *i2c_client_get_device_id(const struct i2c_client *client)
  33. +{
  34. + const struct i2c_driver *drv = to_i2c_driver(client->dev.driver);
  35. +
  36. + return i2c_match_id(drv->id_table, client);
  37. +}
  38. +EXPORT_SYMBOL_GPL(i2c_client_get_device_id);
  39. +
  40. /* ----------------------------------------------------
  41. * the i2c address scanning function
  42. * Will not work for 10-bit addresses!
  43.  
  44. diff -uraBN a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c
  45. --- a/drivers/media/dvb-core/dvb_frontend.c
  46. +++ b/drivers/media/dvb-core/dvb_frontend.c
  47. @@ -40,7 +40,7 @@
  48. static int dvb_shutdown_timeout;
  49. static int dvb_force_auto_inversion;
  50. static int dvb_override_tune_delay;
  51. -static int dvb_powerdown_on_sleep = 1;
  52. +static int dvb_powerdown_on_sleep;
  53. static int dvb_mfe_wait_time = 5;
  54.  
  55. module_param_named(frontend_debug, dvb_frontend_debug, int, 0644);
  56. @@ -918,6 +918,7 @@
  57.  
  58. /* If the standard is for satellite, convert frequencies to kHz */
  59. switch (c->delivery_system) {
  60. + case SYS_DSS:
  61. case SYS_DVBS:
  62. case SYS_DVBS2:
  63. case SYS_TURBO:
  64. @@ -943,6 +944,7 @@
  65. u32 step = max(fe_step, tuner_step);
  66.  
  67. switch (c->delivery_system) {
  68. + case SYS_DSS:
  69. case SYS_DVBS:
  70. case SYS_DVBS2:
  71. case SYS_TURBO:
  72. @@ -974,6 +976,7 @@
  73.  
  74. /* range check: symbol rate */
  75. switch (c->delivery_system) {
  76. + case SYS_DSS:
  77. case SYS_DVBS:
  78. case SYS_DVBS2:
  79. case SYS_TURBO:
  80. @@ -1037,9 +1040,14 @@
  81. }
  82.  
  83. c->stream_id = NO_STREAM_ID_FILTER;
  84. + c->modcode = MODCODE_ALL;
  85. c->scrambling_sequence_index = 0;/* default sequence */
  86.  
  87. switch (c->delivery_system) {
  88. + case SYS_DSS:
  89. + c->modulation = QPSK;
  90. + c->rolloff = ROLLOFF_20;
  91. + break;
  92. case SYS_DVBS:
  93. case SYS_DVBS2:
  94. case SYS_TURBO:
  95. @@ -1111,7 +1119,7 @@
  96. _DTV_CMD(DTV_ISDBT_LAYERC_TIME_INTERLEAVING),
  97.  
  98. _DTV_CMD(DTV_STREAM_ID),
  99. - _DTV_CMD(DTV_DVBT2_PLP_ID_LEGACY),
  100. + _DTV_CMD(DTV_MODCODE),
  101. _DTV_CMD(DTV_SCRAMBLING_SEQUENCE_INDEX),
  102. _DTV_CMD(DTV_LNA),
  103.  
  104. @@ -1462,8 +1470,12 @@
  105.  
  106. /* Multistream support */
  107. case DTV_STREAM_ID:
  108. - case DTV_DVBT2_PLP_ID_LEGACY:
  109. tvp->u.data = c->stream_id;
  110. + break;
  111. +
  112. + /* Modcode support */
  113. + case DTV_MODCODE:
  114. + tvp->u.data = c->modcode;
  115. break;
  116.  
  117. /* Physical layer scrambling support */
  118. @@ -1821,6 +1833,7 @@
  119. } else {
  120. /* default values */
  121. switch (c->delivery_system) {
  122. + case SYS_DSS:
  123. case SYS_DVBS:
  124. case SYS_DVBS2:
  125. case SYS_ISDBS:
  126. @@ -1883,6 +1896,14 @@
  127. dev_dbg(fe->dvb->device,
  128. "%s: SET cmd 0x%08x (%s) to 0x%08x\n",
  129. __func__, cmd, dtv_cmd_name(cmd), data);
  130. +
  131. + /* Allow the frontend to validate incoming properties */
  132. + if (fe->ops.set_property) {
  133. + r = fe->ops.set_property(fe, cmd, data);
  134. + if (r < 0)
  135. + return r;
  136. + }
  137. +
  138. switch (cmd) {
  139. case DTV_CLEAR:
  140. /*
  141. @@ -2016,8 +2037,12 @@
  142.  
  143. /* Multistream support */
  144. case DTV_STREAM_ID:
  145. - case DTV_DVBT2_PLP_ID_LEGACY:
  146. c->stream_id = data;
  147. + break;
  148. +
  149. + /* Modcode support */
  150. + case DTV_MODCODE:
  151. + c->modcode = data;
  152. break;
  153.  
  154. /* Physical layer scrambling support */
  155. @@ -2288,6 +2313,9 @@
  156. case SYS_DVBC_ANNEX_C:
  157. rolloff = 113;
  158. break;
  159. + case SYS_DSS:
  160. + rolloff = 120;
  161. + break;
  162. case SYS_DVBS:
  163. case SYS_TURBO:
  164. case SYS_ISDBS:
  165. @@ -2422,6 +2450,77 @@
  166. dev_dbg(fe->dvb->device, "%s:\n", __func__);
  167.  
  168. switch (cmd) {
  169. +
  170. + case FE_READ_TEMP:
  171. + if (fe->ops.read_temp) {
  172. + err = fe->ops.read_temp(fe, parg);
  173. + }
  174. + break;
  175. +
  176. + case FE_ECP3FW_READ:
  177. + //printk("FE_ECP3FW_READ *****************");
  178. + if (fe->ops.spi_read) {
  179. + struct ecp3_info *info = parg;
  180. + fe->ops.spi_read(fe, info);
  181. + }
  182. + err = 0;
  183. + break;
  184. + case FE_ECP3FW_WRITE:
  185. + //printk("FE_ECP3FW_WRITE *****************");
  186. + if (fe->ops.spi_write) {
  187. + struct ecp3_info *info = parg;
  188. + fe->ops.spi_write(fe, info);
  189. +
  190. + }
  191. + err = 0;
  192. + break;
  193. +
  194. + case FE_24CXX_READ:
  195. + //printk("FE_24CXX_READ *****************");
  196. + if (fe->ops.mcu_read) {
  197. + struct mcu24cxx_info *info = parg;
  198. + fe->ops.mcu_read(fe, info);
  199. + }
  200. + err = 0;
  201. + break;
  202. + case FE_24CXX_WRITE:
  203. + //printk("FE_24CXX_WRITE *****************");
  204. + if (fe->ops.mcu_write) {
  205. + struct mcu24cxx_info *info = parg;
  206. + fe->ops.mcu_write(fe, info);
  207. +
  208. + }
  209. + err = 0;
  210. + break;
  211. + case FE_REGI2C_READ:
  212. + if (fe->ops.reg_i2cread) {
  213. + struct usbi2c_access *info = parg;
  214. + fe->ops.reg_i2cread(fe, info);
  215. + }
  216. + err = 0;
  217. + break;
  218. + case FE_REGI2C_WRITE:
  219. + if (fe->ops.reg_i2cwrite) {
  220. + struct usbi2c_access *info = parg;
  221. + fe->ops.reg_i2cwrite(fe, info);
  222. + }
  223. + err = 0;
  224. + break;
  225. + case FE_EEPROM_READ:
  226. + if (fe->ops.eeprom_read) {
  227. + struct eeprom_info *info = parg;
  228. + fe->ops.eeprom_read(fe, info);
  229. + }
  230. + err = 0;
  231. + break;
  232. + case FE_EEPROM_WRITE:
  233. + if (fe->ops.eeprom_write) {
  234. + struct eeprom_info *info = parg;
  235. + fe->ops.eeprom_write(fe, info);
  236. + }
  237. + err = 0;
  238. + break;
  239. +
  240. case FE_SET_PROPERTY: {
  241. struct dtv_properties *tvps = parg;
  242. struct dtv_property *tvp = NULL;
  243. @@ -2664,37 +2763,25 @@
  244.  
  245. case FE_READ_BER:
  246. if (fe->ops.read_ber) {
  247. - if (fepriv->thread)
  248. err = fe->ops.read_ber(fe, parg);
  249. - else
  250. - err = -EAGAIN;
  251. }
  252. break;
  253.  
  254. case FE_READ_SIGNAL_STRENGTH:
  255. if (fe->ops.read_signal_strength) {
  256. - if (fepriv->thread)
  257. err = fe->ops.read_signal_strength(fe, parg);
  258. - else
  259. - err = -EAGAIN;
  260. }
  261. break;
  262.  
  263. case FE_READ_SNR:
  264. if (fe->ops.read_snr) {
  265. - if (fepriv->thread)
  266. err = fe->ops.read_snr(fe, parg);
  267. - else
  268. - err = -EAGAIN;
  269. }
  270. break;
  271.  
  272. case FE_READ_UNCORRECTED_BLOCKS:
  273. if (fe->ops.read_ucblocks) {
  274. - if (fepriv->thread)
  275. err = fe->ops.read_ucblocks(fe, parg);
  276. - else
  277. - err = -EAGAIN;
  278. }
  279. break;
  280.  
  281. @@ -2754,7 +2841,17 @@
  282. if (fe->exit == DVB_FE_DEVICE_REMOVED)
  283. return -ENODEV;
  284.  
  285. - if (adapter->mfe_shared) {
  286. + if (adapter->mfe_shared == 2) {
  287. + mutex_lock(&adapter->mfe_lock);
  288. + if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
  289. + if (adapter->mfe_dvbdev &&
  290. + !adapter->mfe_dvbdev->writers) {
  291. + mutex_unlock(&adapter->mfe_lock);
  292. + return -EBUSY;
  293. + }
  294. + adapter->mfe_dvbdev = dvbdev;
  295. + }
  296. + } else if (adapter->mfe_shared) {
  297. mutex_lock(&adapter->mfe_lock);
  298.  
  299. if (!adapter->mfe_dvbdev)
  300.  
  301. diff -uraBN a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig
  302. --- a/drivers/media/dvb-frontends/Kconfig
  303. +++ b/drivers/media/dvb-frontends/Kconfig
  304. @@ -922,6 +922,14 @@
  305.  
  306. source "drivers/media/dvb-frontends/drx39xyj/Kconfig"
  307.  
  308. +config DVB_SI2183
  309. + tristate "Silicon Labs Si2183 DVB-T/T2/C/C2/S/S2/S2X/ISDB-T demodulator"
  310. + depends on DVB_CORE && I2C
  311. + default m if !MEDIA_SUBDRV_AUTOSELECT
  312. + help
  313. + Say Y when you want to support this frontend.
  314. +
  315. +
  316. comment "Common Interface (EN50221) controller drivers"
  317. depends on DVB_CORE
  318.  
  319.  
  320. diff -uraBN a/drivers/media/dvb-frontends/Makefile b/drivers/media/dvb-frontends/Makefile
  321. --- a/drivers/media/dvb-frontends/Makefile
  322. +++ b/drivers/media/dvb-frontends/Makefile
  323. @@ -136,3 +136,4 @@
  324. obj-$(CONFIG_DVB_ZL10036) += zl10036.o
  325. obj-$(CONFIG_DVB_ZL10039) += zl10039.o
  326. obj-$(CONFIG_DVB_ZL10353) += zl10353.o
  327. +obj-$(CONFIG_DVB_SI2183) += si2183.o
  328.  
  329. diff -uraBN a/drivers/media/dvb-frontends/si2183.c b/drivers/media/dvb-frontends/si2183.c
  330. --- a/drivers/media/dvb-frontends/si2183.c
  331. +++ b/drivers/media/dvb-frontends/si2183.c
  332. @@ -0,0 +1,1843 @@
  333. +/*
  334. + * Silicon Labs Si2183(2) DVB-T/T2/C/C2/S/S2 demodulator driver
  335. + *
  336. + * This program is free software; you can redistribute it and/or modify
  337. + * it under the terms of the GNU General Public License as published by
  338. + * the Free Software Foundation; either version 2 of the License, or
  339. + * (at your option) any later version.
  340. + *
  341. + * This program is distributed in the hope that it will be useful,
  342. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  343. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  344. + * GNU General Public License for more details.
  345. + */
  346. +
  347. +#include "si2183.h"
  348. +#include <media/dvb_frontend.h>
  349. +#include <linux/firmware.h>
  350. +#include <linux/i2c-mux.h>
  351. +#include <linux/version.h>
  352. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)
  353. +#define SI2183_USE_I2C_MUX
  354. +#endif
  355. +
  356. +#define SI2183_B60_FIRMWARE "dvb-demod-si2183-b60-01.fw"
  357. +
  358. +#define SI2183_PROP_MODE 0x100a
  359. +#define SI2183_PROP_DVBC_CONST 0x1101
  360. +#define SI2183_PROP_DVBC_SR 0x1102
  361. +#define SI2183_PROP_DVBT_HIER 0x1201
  362. +#define SI2183_PROP_DVBT2_MODE 0x1304
  363. +#define SI2183_PROP_DVBS2_SR 0x1401
  364. +#define SI2183_PROP_DVBS_SR 0x1501
  365. +#define SI2183_PROP_MCNS_CONST 0x1601
  366. +#define SI2183_PROP_MCNS_SR 0x1602
  367. +
  368. +#define SI2183_ARGLEN 30
  369. +struct si2183_cmd {
  370. + u8 args[SI2183_ARGLEN];
  371. + unsigned wlen;
  372. + unsigned rlen;
  373. +};
  374. +
  375. +static const struct dvb_frontend_ops si2183_ops;
  376. +
  377. +LIST_HEAD(silist);
  378. +
  379. +struct si_base {
  380. + struct mutex i2c_mutex;
  381. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)
  382. + struct i2c_mux_core *muxc;
  383. +#endif
  384. + struct list_head silist;
  385. +
  386. + u8 adr;
  387. + struct i2c_adapter *i2c;
  388. + u32 count;
  389. +
  390. + struct i2c_adapter *tuner_adapter;
  391. +
  392. +#ifndef SI2183_USE_I2C_MUX
  393. + struct i2c_client *i2c_gate_client;
  394. +#endif
  395. +};
  396. +
  397. +/* state struct */
  398. +struct si2183_dev {
  399. + struct dvb_frontend fe;
  400. + enum fe_delivery_system delivery_system;
  401. + enum fe_status fe_status;
  402. + u8 stat_resp;
  403. + u16 snr;
  404. + bool fw_loaded;
  405. + u8 ts_mode;
  406. + bool ts_clock_inv;
  407. + bool ts_clock_gapped;
  408. + int start_clk_mode;
  409. + u8 agc_mode;
  410. + struct si_base *base;
  411. + void (*RF_switch)(struct i2c_adapter * i2c,u8 rf_in,u8 flag);
  412. + u8 rf_in;
  413. + u8 active_fe;
  414. + void (*TS_switch)(struct i2c_adapter * i2c,u8 flag);
  415. + void (*LED_switch)(struct i2c_adapter * i2c,u8 flag);
  416. +
  417. + void (*write_properties) (struct i2c_adapter *i2c,u8 reg, u32 buf);
  418. + void (*read_properties) (struct i2c_adapter *i2c,u8 reg, u32 *buf);
  419. +
  420. + void (*write_eeprom) (struct i2c_adapter *i2c,u8 reg, u8 buf);
  421. + void (*read_eeprom) (struct i2c_adapter *i2c,u8 reg, u8 *buf);
  422. +};
  423. +
  424. +/* Own I2C adapter locking is needed because of I2C gate logic. */
  425. +static int si2183_i2c_master_send_unlocked(const struct i2c_client *client,
  426. + const char *buf, int count)
  427. +{
  428. + int ret;
  429. + struct i2c_msg msg = {
  430. + .addr = client->addr,
  431. + .flags = 0,
  432. + .len = count,
  433. + .buf = (char *)buf,
  434. + };
  435. +
  436. + ret = __i2c_transfer(client->adapter, &msg, 1);
  437. + return (ret == 1) ? count : ret;
  438. +}
  439. +
  440. +static int si2183_i2c_master_recv_unlocked(const struct i2c_client *client,
  441. + char *buf, int count)
  442. +{
  443. + int ret;
  444. + struct i2c_msg msg = {
  445. + .addr = client->addr,
  446. + .flags = I2C_M_RD,
  447. + .len = count,
  448. + .buf = buf,
  449. + };
  450. +
  451. + ret = __i2c_transfer(client->adapter, &msg, 1);
  452. + return (ret == 1) ? count : ret;
  453. +}
  454. +
  455. +/* execute firmware command */
  456. +static int si2183_cmd_execute_unlocked(struct i2c_client *client,
  457. + struct si2183_cmd *cmd)
  458. +{
  459. + int ret;
  460. + unsigned long timeout;
  461. +
  462. + if (cmd->wlen) {
  463. + /* write cmd and args for firmware */
  464. + ret = si2183_i2c_master_send_unlocked(client, cmd->args,
  465. + cmd->wlen);
  466. + if (ret < 0) {
  467. + goto err;
  468. + } else if (ret != cmd->wlen) {
  469. + ret = -EREMOTEIO;
  470. + goto err;
  471. + }
  472. + }
  473. +
  474. + if (cmd->rlen) {
  475. + /* wait cmd execution terminate */
  476. + #define TIMEOUT 500
  477. + timeout = jiffies + msecs_to_jiffies(TIMEOUT);
  478. + while (!time_after(jiffies, timeout)) {
  479. + ret = si2183_i2c_master_recv_unlocked(client, cmd->args,
  480. + cmd->rlen);
  481. + if (ret < 0) {
  482. + goto err;
  483. + } else if (ret != cmd->rlen) {
  484. + ret = -EREMOTEIO;
  485. + goto err;
  486. + }
  487. +
  488. + /* firmware ready? */
  489. + if ((cmd->args[0] >> 7) & 0x01)
  490. + break;
  491. + }
  492. +
  493. + dev_dbg(&client->dev, "cmd execution took %d ms\n",
  494. + jiffies_to_msecs(jiffies) -
  495. + (jiffies_to_msecs(timeout) - TIMEOUT));
  496. +
  497. + /* error bit set? */
  498. + if ((cmd->args[0] >> 6) & 0x01) {
  499. + ret = -EREMOTEIO;
  500. + goto err;
  501. + }
  502. +
  503. + if (!((cmd->args[0] >> 7) & 0x01)) {
  504. + ret = -ETIMEDOUT;
  505. + goto err;
  506. + }
  507. + }
  508. +
  509. + return 0;
  510. +err:
  511. + dev_dbg(&client->dev, "failed=%d\n", ret);
  512. + return ret;
  513. +}
  514. +
  515. +static int si2183_cmd_execute(struct i2c_client *client, struct si2183_cmd *cmd)
  516. +{
  517. + struct si2183_dev *dev = i2c_get_clientdata(client);
  518. + int ret;
  519. +
  520. +
  521. + mutex_lock(&dev->base->i2c_mutex);
  522. + ret = si2183_cmd_execute_unlocked(client, cmd);
  523. + mutex_unlock(&dev->base->i2c_mutex);
  524. +
  525. + return ret;
  526. +}
  527. +
  528. +static int si2183_set_prop(struct i2c_client *client, u16 prop, u16 *val)
  529. +{
  530. + struct si2183_cmd cmd;
  531. + int ret;
  532. +
  533. + cmd.args[0] = 0x14;
  534. + cmd.args[1] = 0x00;
  535. + cmd.args[2] = (u8) prop;
  536. + cmd.args[3] = (u8) (prop >> 8);
  537. + cmd.args[4] = (u8) (*val);
  538. + cmd.args[5] = (u8) (*val >> 8);
  539. + cmd.wlen = 6;
  540. + cmd.rlen = 4;
  541. + ret = si2183_cmd_execute(client, &cmd);
  542. + *val = (cmd.args[2] | (cmd.args[3] << 8));
  543. + return ret;
  544. +}
  545. +#if 0
  546. +static int si2183_get_prop(struct i2c_client *client, u16 prop, u16 *val)
  547. +{
  548. + struct si2183_cmd cmd;
  549. + int ret;
  550. +
  551. + cmd.args[0] = 0x15;
  552. + cmd.args[1] = 0x00;
  553. + cmd.args[2] = (u8) prop;
  554. + cmd.args[3] = (u8) (prop >> 8);
  555. + cmd.wlen = 4;
  556. + cmd.rlen = 4;
  557. + ret = si2183_cmd_execute(client, &cmd);
  558. + *val = (cmd.args[2] | (cmd.args[3] << 8));
  559. + return ret;
  560. +}
  561. +#endif
  562. +
  563. +static int si2183_read_status(struct dvb_frontend *fe, enum fe_status *status)
  564. +{
  565. + struct i2c_client *client = fe->demodulator_priv;
  566. + struct si2183_dev *dev = i2c_get_clientdata(client);
  567. + struct dtv_frontend_properties *c = &fe->dtv_property_cache;
  568. + int ret;
  569. + struct si2183_cmd cmd;
  570. + u16 agc;
  571. +
  572. + *status = 0;
  573. +
  574. + if (!dev->active_fe) {
  575. + ret = -EAGAIN;
  576. + goto err;
  577. + }
  578. +
  579. + if ((dev->delivery_system != c->delivery_system) || (dev->delivery_system == 0))
  580. + return 0;
  581. +
  582. + switch (c->delivery_system) {
  583. + case SYS_DVBT:
  584. + memcpy(cmd.args, "\xa0\x01", 2);
  585. + cmd.wlen = 2;
  586. + cmd.rlen = 13;
  587. + dev->snr = 2;
  588. + break;
  589. + case SYS_DVBC_ANNEX_A:
  590. + memcpy(cmd.args, "\x90\x01", 2);
  591. + cmd.wlen = 2;
  592. + cmd.rlen = 9;
  593. + dev->snr = 2;
  594. + break;
  595. + case SYS_DVBC_ANNEX_B:
  596. + memcpy(cmd.args, "\x98\x01", 2);
  597. + cmd.wlen = 2;
  598. + cmd.rlen = 10;
  599. + dev->snr = 2;
  600. + break;
  601. + case SYS_DVBT2:
  602. + memcpy(cmd.args, "\x50\x01", 2);
  603. + cmd.wlen = 2;
  604. + cmd.rlen = 14;
  605. + dev->snr = 2;
  606. + break;
  607. + case SYS_DVBS:
  608. + memcpy(cmd.args, "\x60\x01", 2);
  609. + cmd.wlen = 2;
  610. + cmd.rlen = 10;
  611. + dev->snr = 5;
  612. + break;
  613. + case SYS_DVBS2:
  614. + memcpy(cmd.args, "\x70\x01", 2);
  615. + cmd.wlen = 2;
  616. + cmd.rlen = 13;
  617. + dev->snr = 5;
  618. + break;
  619. + case SYS_ISDBT:
  620. + memcpy(cmd.args, "\xa4\x01", 2);
  621. + cmd.wlen = 2;
  622. + cmd.rlen = 14;
  623. + dev->snr = 2;
  624. + break;
  625. + default:
  626. + ret = -EINVAL;
  627. + goto err;
  628. + }
  629. +
  630. + ret = si2183_cmd_execute(client, &cmd);
  631. + if (ret) {
  632. + dev_err(&client->dev, "read_status fe%d cmd_exec failed=%d\n", fe->id, ret);
  633. + goto err;
  634. + }
  635. +
  636. + dev->stat_resp = cmd.args[2];
  637. + switch ((dev->stat_resp >> 1) & 0x03) {
  638. + case 0x01:
  639. + *status = FE_HAS_SIGNAL | FE_HAS_CARRIER;
  640. + c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
  641. + break;
  642. + case 0x03:
  643. + *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI |
  644. + FE_HAS_SYNC | FE_HAS_LOCK;
  645. + dev->snr *= cmd.args[3] * 164;
  646. + c->cnr.len = 2;
  647. + c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
  648. + c->cnr.stat[0].svalue = (s64) cmd.args[3] * 250;
  649. + c->cnr.stat[1].scale = FE_SCALE_RELATIVE;
  650. + c->cnr.stat[1].svalue = dev->snr;
  651. +
  652. + // writing missing properties
  653. + // CONSTELLATION or modulation
  654. + switch (cmd.args[8] & 0x3f){
  655. + case 0x03:
  656. + c->modulation = QPSK;
  657. + break;
  658. + case 0x07:
  659. + c->modulation = QAM_16;
  660. + break;
  661. + case 0x08:
  662. + c->modulation = QAM_32;
  663. + break;
  664. + case 0x09:
  665. + c->modulation = QAM_64;
  666. + break;
  667. + case 0x0a:
  668. + c->modulation = QAM_128;
  669. + break;
  670. + case 0x0b:
  671. + c->modulation = QAM_256;
  672. + break;
  673. + case 0x0e:
  674. + c->modulation = PSK_8;
  675. + break;
  676. + case 0x14:
  677. + c->modulation = APSK_16;
  678. + break;
  679. + case 0x17:
  680. + c->modulation = APSK_8L;
  681. + break;
  682. + case 0x18:
  683. + c->modulation = APSK_16L;
  684. + break;
  685. + case 0x15:
  686. + c->modulation = APSK_32;
  687. + break;
  688. + case 0x19:
  689. + c->modulation = APSK_32L;
  690. + break;
  691. + case 0x1a:
  692. + c->modulation = APSK_32;
  693. + break;
  694. + default:
  695. + c->modulation = QPSK;
  696. + break;
  697. + }
  698. + // fec_inner
  699. + switch (c->delivery_system) {
  700. + case SYS_DVBT2:
  701. + switch (cmd.args[12] & 0x0f){
  702. + case 0x01:
  703. + c->fec_inner = FEC_1_2;
  704. + break;
  705. + case 0x02:
  706. + c->fec_inner = FEC_2_3;
  707. + break;
  708. + case 0x03:
  709. + c->fec_inner = FEC_3_4;
  710. + break;
  711. + case 0x04:
  712. + c->fec_inner = FEC_4_5;
  713. + break;
  714. + case 0x05:
  715. + c->fec_inner = FEC_5_6;
  716. + break;
  717. + case 0x0a:
  718. + c->fec_inner = FEC_1_3;
  719. + break;
  720. + case 0x0c:
  721. + c->fec_inner = FEC_2_5;
  722. + break;
  723. + case 0x0d:
  724. + c->fec_inner = FEC_3_5;
  725. + break;
  726. + default:
  727. + c->fec_inner = FEC_AUTO;
  728. + break;
  729. + }
  730. + break;
  731. + case SYS_DVBS:
  732. + switch (cmd.args[9] & 0x0f){
  733. + case 0x01:
  734. + c->fec_inner = FEC_1_2;
  735. + break;
  736. + case 0x02:
  737. + c->fec_inner = FEC_2_3;
  738. + break;
  739. + case 0x03:
  740. + c->fec_inner = FEC_3_4;
  741. + break;
  742. + case 0x04:
  743. + c->fec_inner = FEC_4_5;
  744. + break;
  745. + case 0x05:
  746. + c->fec_inner = FEC_5_6;
  747. + break;
  748. + case 0x06:
  749. + c->fec_inner = FEC_6_7;
  750. + break;
  751. + case 0x07:
  752. + c->fec_inner = FEC_7_8;
  753. + break;
  754. + default:
  755. + c->fec_inner = FEC_AUTO;
  756. + break;
  757. + }
  758. + break;
  759. + case SYS_DVBS2:
  760. + switch (cmd.args[9] & 0x1f){
  761. + case 0x01:
  762. + c->fec_inner = FEC_1_2;
  763. + break;
  764. + case 0x02:
  765. + c->fec_inner = FEC_2_3;
  766. + break;
  767. + case 0x03:
  768. + c->fec_inner = FEC_3_4;
  769. + break;
  770. + case 0x04:
  771. + c->fec_inner = FEC_4_5;
  772. + break;
  773. + case 0x05:
  774. + c->fec_inner = FEC_5_6;
  775. + break;
  776. + case 0x08:
  777. + c->fec_inner = FEC_8_9;
  778. + break;
  779. + case 0x09:
  780. + c->fec_inner = FEC_9_10;
  781. + break;
  782. + case 0x0a:
  783. + c->fec_inner = FEC_1_3;
  784. + break;
  785. + case 0x0b:
  786. + c->fec_inner = FEC_1_4;
  787. + break;
  788. + case 0x0c:
  789. + c->fec_inner = FEC_2_5;
  790. + break;
  791. + case 0x0d:
  792. + c->fec_inner = FEC_3_5;
  793. + break;
  794. + default:
  795. + c->fec_inner = FEC_AUTO;
  796. + break;
  797. + }
  798. + break;
  799. + default:
  800. + c->fec_inner = FEC_AUTO;
  801. + break;
  802. + }
  803. + // rolloff and pilot (only available for dvb s2)
  804. + switch (c->delivery_system) {
  805. + case SYS_DVBS2:
  806. + // rolloff
  807. + switch (cmd.args[10] & 0x07){
  808. + case 0x00:
  809. + c->rolloff = ROLLOFF_35;
  810. + break;
  811. + case 0x01:
  812. + c->rolloff = ROLLOFF_25;
  813. + break;
  814. + case 0x02:
  815. + c->rolloff = ROLLOFF_20;
  816. + break;
  817. + case 0x04:
  818. + c->rolloff = ROLLOFF_15;
  819. + break;
  820. + case 0x05:
  821. + c->rolloff = ROLLOFF_10;
  822. + break;
  823. + case 0x06:
  824. + c->rolloff = ROLLOFF_5;
  825. + break;
  826. + default:
  827. + c->rolloff = ROLLOFF_AUTO;
  828. + break;
  829. + }
  830. + // pilot
  831. + switch ((cmd.args[8] >> 7) & 0x01){
  832. + case 0x01:
  833. + c->pilot = PILOT_ON;
  834. + break;
  835. + case 0x00:
  836. + c->pilot = PILOT_OFF;
  837. + break;
  838. + default:
  839. + c->pilot = PILOT_AUTO;
  840. + break;
  841. + }
  842. + break;
  843. + default:
  844. + c->rolloff = ROLLOFF_AUTO;
  845. + c->pilot = PILOT_AUTO;
  846. + break;
  847. + }
  848. + break;
  849. + default:
  850. + c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
  851. + break;
  852. + }
  853. +
  854. + dev->fe_status = *status;
  855. +
  856. + dev_dbg(&client->dev, "status=%02x args=%*ph\n",
  857. + *status, cmd.rlen, cmd.args);
  858. +
  859. + if (fe->ops.tuner_ops.get_rf_strength)
  860. + {
  861. + memcpy(cmd.args, "\x8a\x00\x00\x00\x00\x00", 6);
  862. + cmd.wlen = 6;
  863. + cmd.rlen = 3;
  864. + ret = si2183_cmd_execute(client, &cmd);
  865. + if (ret) {
  866. + dev_err(&client->dev, "read_status fe%d cmd_exec failed=%d\n", fe->id, ret);
  867. + goto err;
  868. + }
  869. + dev_dbg(&client->dev, "status=%02x args=%*ph\n",
  870. + *status, cmd.rlen, cmd.args);
  871. +
  872. + agc = cmd.args[1];
  873. + fe->ops.tuner_ops.get_rf_strength(fe, &agc);
  874. + }
  875. +
  876. + if ( c->strength.len == 1 && c->strength.stat[0].scale == FE_SCALE_DECIBEL) {
  877. + c->strength.len ++;
  878. + c->strength.stat[1].scale = FE_SCALE_RELATIVE;
  879. + c->strength.stat[1].svalue = ((100000 + (s32)c->strength.stat[0].svalue) / 1000) * 656;
  880. + }
  881. +
  882. + return 0;
  883. +err:
  884. + dev_err(&client->dev, "read_status failed=%d\n", ret);
  885. + return ret;
  886. +}
  887. +
  888. +static int si2183_read_snr(struct dvb_frontend *fe, u16 *snr)
  889. +{
  890. + struct i2c_client *client = fe->demodulator_priv;
  891. + struct si2183_dev *dev = i2c_get_clientdata(client);
  892. +
  893. + *snr = (dev->fe_status & FE_HAS_LOCK) ? dev->snr : 0;
  894. +
  895. + return 0;
  896. +}
  897. +
  898. +static int si2183_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
  899. +{
  900. + struct dtv_frontend_properties *c = &fe->dtv_property_cache;
  901. + int i;
  902. +
  903. + *strength = 0;
  904. + for (i=0; i < c->strength.len; i++)
  905. + {
  906. + if (c->strength.stat[i].scale == FE_SCALE_RELATIVE)
  907. + *strength = (u16)c->strength.stat[i].uvalue;
  908. + else if (c->strength.stat[i].scale == FE_SCALE_DECIBEL)
  909. + *strength = ((100000 + (s32)c->strength.stat[i].svalue)/1000) * 656;
  910. + }
  911. +
  912. + return 0;
  913. +}
  914. +
  915. +static int si2183_read_ber(struct dvb_frontend *fe, u32 *ber)
  916. +{
  917. + struct i2c_client *client = fe->demodulator_priv;
  918. + struct si2183_dev *dev = i2c_get_clientdata(client);
  919. + struct si2183_cmd cmd;
  920. + int ret;
  921. +
  922. + if (dev->fe_status & FE_HAS_LOCK) {
  923. + memcpy(cmd.args, "\x82\x00", 2);
  924. + cmd.wlen = 2;
  925. + cmd.rlen = 3;
  926. + ret = si2183_cmd_execute(client, &cmd);
  927. + if (ret) {
  928. + dev_err(&client->dev, "read_ber fe%d cmd_exec failed=%d\n", fe->id, ret);
  929. + goto err;
  930. + }
  931. + *ber = (u32)cmd.args[2] * cmd.args[1] & 0xf;
  932. + } else *ber = 1;
  933. +
  934. + return 0;
  935. +err:
  936. + dev_err(&client->dev, "read_ber failed=%d\n", ret);
  937. + return ret;
  938. +}
  939. +
  940. +static int si2183_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
  941. +{
  942. + struct i2c_client *client = fe->demodulator_priv;
  943. + struct si2183_dev *dev = i2c_get_clientdata(client);
  944. + struct si2183_cmd cmd;
  945. + int ret;
  946. +
  947. + if (dev->stat_resp & 0x10) {
  948. + memcpy(cmd.args, "\x84\x00", 2);
  949. + cmd.wlen = 2;
  950. + cmd.rlen = 3;
  951. + ret = si2183_cmd_execute(client, &cmd);
  952. + if (ret) {
  953. + dev_err(&client->dev, "read_ucblocks fe%d cmd_exec failed=%d\n", fe->id, ret);
  954. + goto err;
  955. + }
  956. +
  957. + *ucblocks = (u16)cmd.args[2] << 8 | cmd.args[1];
  958. + } else *ucblocks = 0;
  959. +
  960. + return 0;
  961. +err:
  962. + dev_err(&client->dev, "read_ucblocks failed=%d\n", ret);
  963. + return ret;
  964. +}
  965. +
  966. +
  967. +static int si2183_set_dvbc(struct dvb_frontend *fe)
  968. +{
  969. + struct dtv_frontend_properties *c = &fe->dtv_property_cache;
  970. + struct i2c_client *client = fe->demodulator_priv;
  971. + struct si2183_dev *dev = i2c_get_clientdata(client);
  972. + struct si2183_cmd cmd;
  973. + int ret;
  974. + u16 prop;
  975. +
  976. + if(dev->LED_switch)
  977. + dev->LED_switch(dev->base->i2c,6);
  978. +
  979. + memcpy(cmd.args, "\x89\x41\x06\x12\x0\x0", 6);
  980. + cmd.args[1]= (dev->agc_mode &0x07)<<4 |0x1;
  981. + cmd.wlen = 6;
  982. + cmd.rlen = 3;
  983. + ret = si2183_cmd_execute(client, &cmd);
  984. + if(ret){
  985. + dev_err(&client->dev, "err set agc mode\n");
  986. + }
  987. + /* dvb-c mode */
  988. + prop = 0x38;
  989. + ret = si2183_set_prop(client, SI2183_PROP_MODE, &prop);
  990. + if (ret) {
  991. + dev_err(&client->dev, "err set dvb-c mode\n");
  992. + return ret;
  993. + }
  994. +
  995. + switch (c->modulation) {
  996. + default:
  997. + case QAM_AUTO:
  998. + prop = 0;
  999. + break;
  1000. + case QAM_16:
  1001. + prop = 7;
  1002. + break;
  1003. + case QAM_32:
  1004. + prop = 8;
  1005. + break;
  1006. + case QAM_64:
  1007. + prop = 9;
  1008. + break;
  1009. + case QAM_128:
  1010. + prop = 10;
  1011. + break;
  1012. + case QAM_256:
  1013. + prop = 11;
  1014. + break;
  1015. + }
  1016. + ret = si2183_set_prop(client, SI2183_PROP_DVBC_CONST, &prop);
  1017. + if (ret) {
  1018. + dev_err(&client->dev, "err set dvb-c constelation\n");
  1019. + return ret;
  1020. + }
  1021. +
  1022. + /* symbol rate */
  1023. + prop = c->symbol_rate / 1000;
  1024. + ret = si2183_set_prop(client, SI2183_PROP_DVBC_SR, &prop);
  1025. + if (ret) {
  1026. + dev_err(&client->dev, "err set dvb-c symbol rate\n");
  1027. + return ret;
  1028. + }
  1029. +
  1030. + return 0;
  1031. +}
  1032. +
  1033. +static int si2183_set_mcns(struct dvb_frontend *fe)
  1034. +{
  1035. + struct dtv_frontend_properties *c = &fe->dtv_property_cache;
  1036. + struct i2c_client *client = fe->demodulator_priv;
  1037. + struct si2183_dev *dev = i2c_get_clientdata(client);
  1038. + struct si2183_cmd cmd;
  1039. + int ret;
  1040. + u16 prop,symb;
  1041. +
  1042. + if(dev->LED_switch)
  1043. + dev->LED_switch(dev->base->i2c,6);
  1044. +
  1045. + memcpy(cmd.args, "\x89\x41\x06\x12\x0\x0", 6);
  1046. + cmd.args[1]= (dev->agc_mode &0x07)<<4 |0x1;
  1047. + cmd.wlen = 6;
  1048. + cmd.rlen = 3;
  1049. + ret = si2183_cmd_execute(client, &cmd);
  1050. + if(ret){
  1051. + dev_err(&client->dev, "err set agc mode\n");
  1052. + }
  1053. + /* mcns mode */
  1054. + prop = 0x18;
  1055. + ret = si2183_set_prop(client, SI2183_PROP_MODE, &prop);
  1056. + if (ret) {
  1057. + dev_err(&client->dev, "err set mcns mode\n");
  1058. + return ret;
  1059. + }
  1060. +
  1061. + switch (c->modulation) {
  1062. + default:
  1063. + case QAM_64:
  1064. + prop = 9;
  1065. + symb = 5057;
  1066. + break;
  1067. + case QAM_256:
  1068. + prop = 11;
  1069. + symb = 5361;
  1070. + break;
  1071. + }
  1072. + ret = si2183_set_prop(client, SI2183_PROP_MCNS_CONST, &prop);
  1073. + if (ret) {
  1074. + dev_err(&client->dev, "err set mcns constelation\n");
  1075. + return ret;
  1076. + }
  1077. +
  1078. + /* symbol rate */
  1079. + ret = si2183_set_prop(client, SI2183_PROP_MCNS_SR, &symb);
  1080. + if (ret) {
  1081. + dev_err(&client->dev, "err set mcns symbol rate\n");
  1082. + return ret;
  1083. + }
  1084. +
  1085. + return 0;
  1086. +}
  1087. +
  1088. +static int gold_code_index (int gold_sequence_index)
  1089. +{
  1090. + unsigned int i, k , x_init;
  1091. + u8 GOLD_PRBS[19] = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  1092. + for (k=0; k<gold_sequence_index; k++) {
  1093. + GOLD_PRBS[18] = (GOLD_PRBS[0] + GOLD_PRBS[7])%2;
  1094. + /* Shifting 18 first values */
  1095. + for (i=0; i<18; i++)
  1096. + GOLD_PRBS[i] = GOLD_PRBS[i+1];
  1097. + }
  1098. + x_init = 0;
  1099. + for (i=0; i<18; i++) { x_init = x_init + GOLD_PRBS[i]*(1<<i); }
  1100. +
  1101. + return x_init;
  1102. +}
  1103. +
  1104. +static int si2183_set_dvbs(struct dvb_frontend *fe)
  1105. +{
  1106. + struct dtv_frontend_properties *c = &fe->dtv_property_cache;
  1107. + struct i2c_client *client = fe->demodulator_priv;
  1108. + struct si2183_dev *dev = i2c_get_clientdata(client);
  1109. + struct si2183_cmd cmd;
  1110. + int ret;
  1111. + u16 prop;
  1112. + u32 pls_mode, pls_code;
  1113. +
  1114. + if(dev->LED_switch)
  1115. + dev->LED_switch(dev->base->i2c,2);
  1116. +
  1117. + /*set SAT agc*/
  1118. + memcpy(cmd.args, "\x8a\x1d\x12\x0\x0\x0", 6);
  1119. + cmd.args[1]= dev->agc_mode|0x18;
  1120. + cmd.wlen = 6;
  1121. + cmd.rlen = 3;
  1122. + ret = si2183_cmd_execute(client, &cmd);
  1123. + if(ret){
  1124. + dev_err(&client->dev, "err set agc mode\n");
  1125. + }
  1126. +
  1127. + /* set mode */
  1128. + prop = 0x8;
  1129. + switch (c->delivery_system) {
  1130. + default:
  1131. + case SYS_DVBS:
  1132. + prop |= 0x80;
  1133. + break;
  1134. + case SYS_DVBS2:
  1135. + prop |= 0x90;
  1136. + break;
  1137. + case SYS_DSS:
  1138. + prop |= 0xa0;
  1139. + break;
  1140. + }
  1141. + if (c->inversion)
  1142. + prop |= 0x100;
  1143. + ret = si2183_set_prop(client, SI2183_PROP_MODE, &prop);
  1144. + if (ret) {
  1145. + dev_err(&client->dev, "err set dvb-s/s2 mode\n");
  1146. + return ret;
  1147. + }
  1148. +
  1149. + /* symbol rate */
  1150. + prop = c->symbol_rate / 1000;
  1151. + switch (c->delivery_system) {
  1152. + default:
  1153. + case SYS_DSS:
  1154. + case SYS_DVBS:
  1155. + ret = si2183_set_prop(client, SI2183_PROP_DVBS_SR, &prop);
  1156. + break;
  1157. + case SYS_DVBS2:
  1158. + ret = si2183_set_prop(client, SI2183_PROP_DVBS2_SR, &prop);
  1159. + /* stream_id selection */
  1160. + cmd.args[0] = 0x71;
  1161. + cmd.args[1] = (u8) c->stream_id;
  1162. + cmd.args[2] = c->stream_id == NO_STREAM_ID_FILTER ? 0 : 1;
  1163. + cmd.wlen = 3;
  1164. + cmd.rlen = 1;
  1165. + ret = si2183_cmd_execute(client, &cmd);
  1166. + if (ret)
  1167. + dev_warn(&client->dev, "dvb-s2: err selecting stream_id\n");
  1168. +
  1169. + /* pls selection */
  1170. + pls_mode = c->stream_id == NO_STREAM_ID_FILTER ? 0 : (c->stream_id >> 26) & 3;
  1171. + pls_code = c->stream_id == NO_STREAM_ID_FILTER ? 0 : (c->stream_id >> 8) & 0x3FFFF;
  1172. + if (pls_mode)
  1173. + pls_code = gold_code_index(pls_code);
  1174. + cmd.args[0] = 0x73;
  1175. + cmd.args[1] = pls_code > 0;
  1176. + cmd.args[2] = cmd.args[3] = 0;
  1177. + cmd.args[4] = (u8) pls_code;
  1178. + cmd.args[5] = (u8) (pls_code >> 8);
  1179. + cmd.args[6] = (u8) (pls_code >> 16);
  1180. + cmd.args[7] = (u8) (pls_code >> 24);
  1181. + cmd.wlen = 8;
  1182. + cmd.rlen = 1;
  1183. + ret = si2183_cmd_execute(client, &cmd);
  1184. + if (ret)
  1185. + dev_warn(&client->dev, "dvb-s2: err set pls\n");
  1186. + }
  1187. +
  1188. + return 0;
  1189. +}
  1190. +
  1191. +static int si2183_set_dvbt(struct dvb_frontend *fe)
  1192. +{
  1193. + struct dtv_frontend_properties *c = &fe->dtv_property_cache;
  1194. + struct i2c_client *client = fe->demodulator_priv;
  1195. + struct si2183_dev *dev = i2c_get_clientdata(client);
  1196. + struct si2183_cmd cmd;
  1197. + int ret;
  1198. + u16 prop;
  1199. +
  1200. + if(dev->LED_switch)
  1201. + dev->LED_switch(dev->base->i2c,1);
  1202. +
  1203. + memcpy(cmd.args, "\x89\x41\x06\x12\x0\x0", 6);
  1204. + cmd.args[1]= (dev->agc_mode &0x07)<<4 |0x1;
  1205. + cmd.wlen = 6;
  1206. + cmd.rlen = 3;
  1207. + ret = si2183_cmd_execute(client, &cmd);
  1208. + if(ret){
  1209. + dev_err(&client->dev, "err set agc mode\n");
  1210. + }
  1211. +
  1212. + if (c->bandwidth_hz == 0) {
  1213. + return -EINVAL;
  1214. + } else if (c->bandwidth_hz <= 2000000)
  1215. + prop = 0x02;
  1216. + else if (c->bandwidth_hz <= 5000000)
  1217. + prop = 0x05;
  1218. + else if (c->bandwidth_hz <= 6000000)
  1219. + prop = 0x06;
  1220. + else if (c->bandwidth_hz <= 7000000)
  1221. + prop = 0x07;
  1222. + else if (c->bandwidth_hz <= 8000000)
  1223. + prop = 0x08;
  1224. + else if (c->bandwidth_hz <= 9000000)
  1225. + prop = 0x09;
  1226. + else if (c->bandwidth_hz <= 10000000)
  1227. + prop = 0x0a;
  1228. + else
  1229. + prop = 0x0f;
  1230. +
  1231. + switch (c->delivery_system) {
  1232. + default:
  1233. + case SYS_DVBT:
  1234. + prop |= 0x20;
  1235. + break;
  1236. + case SYS_DVBT2:
  1237. + prop |= 0x70;
  1238. + break;
  1239. + }
  1240. + ret = si2183_set_prop(client, SI2183_PROP_MODE, &prop);
  1241. + if (ret) {
  1242. + dev_err(&client->dev, "err set dvb-t mode\n");
  1243. + return ret;
  1244. + }
  1245. +
  1246. + /* hierarchy - HP = 0 / LP = 1 */
  1247. + prop = c->hierarchy == HIERARCHY_1 ? 1 : 0;
  1248. + ret = si2183_set_prop(client, SI2183_PROP_DVBT_HIER, &prop);
  1249. + if (ret)
  1250. + dev_warn(&client->dev, "dvb-t: err set hierarchy\n");
  1251. +
  1252. + if (c->delivery_system == SYS_DVBT2) {
  1253. + /* stream_id selection */
  1254. + cmd.args[0] = 0x52;
  1255. + cmd.args[1] = (u8) c->stream_id;
  1256. + cmd.args[2] = c->stream_id == NO_STREAM_ID_FILTER ? 0 : 1;
  1257. + cmd.wlen = 3;
  1258. + cmd.rlen = 1;
  1259. + ret = si2183_cmd_execute(client, &cmd);
  1260. + if (ret)
  1261. + dev_warn(&client->dev, "dvb-t2: err selecting stream_id\n");
  1262. +
  1263. + /* dvb-t2 mode - any=0 / base=1 / lite=2 */
  1264. + prop = 0;
  1265. + ret = si2183_set_prop(client, SI2183_PROP_DVBT2_MODE, &prop);
  1266. + if (ret)
  1267. + dev_warn(&client->dev, "dvb-t2: err set mode\n");
  1268. + }
  1269. +
  1270. + return 0;
  1271. +}
  1272. +
  1273. +static int si2183_set_isdbt(struct dvb_frontend *fe)
  1274. +{
  1275. + struct dtv_frontend_properties *c = &fe->dtv_property_cache;
  1276. + struct i2c_client *client = fe->demodulator_priv;
  1277. + struct si2183_dev *dev = i2c_get_clientdata(client);
  1278. + struct si2183_cmd cmd;
  1279. + int ret;
  1280. + u16 prop;
  1281. +
  1282. + if(dev->LED_switch)
  1283. + dev->LED_switch(dev->base->i2c,5);
  1284. +
  1285. +
  1286. + memcpy(cmd.args, "\x89\x41\x06\x12\x0\x0", 6);
  1287. + cmd.args[1]= (dev->agc_mode &0x07)<<4 |0x1;
  1288. + cmd.wlen = 6;
  1289. + cmd.rlen = 3;
  1290. + ret = si2183_cmd_execute(client, &cmd);
  1291. + if(ret){
  1292. + dev_err(&client->dev, "err set agc mode\n");
  1293. + }
  1294. + if (c->bandwidth_hz == 0) {
  1295. + return -EINVAL;
  1296. + } else if (c->bandwidth_hz <= 2000000)
  1297. + prop = 0x02;
  1298. + else if (c->bandwidth_hz <= 5000000)
  1299. + prop = 0x05;
  1300. + else if (c->bandwidth_hz <= 6000000)
  1301. + prop = 0x06;
  1302. + else if (c->bandwidth_hz <= 7000000)
  1303. + prop = 0x07;
  1304. + else if (c->bandwidth_hz <= 8000000)
  1305. + prop = 0x08;
  1306. + else if (c->bandwidth_hz <= 9000000)
  1307. + prop = 0x09;
  1308. + else if (c->bandwidth_hz <= 10000000)
  1309. + prop = 0x0a;
  1310. + else
  1311. + prop = 0x0f;
  1312. +
  1313. + /* ISDB-T mode */
  1314. + prop |= 0x40;
  1315. + ret = si2183_set_prop(client, SI2183_PROP_MODE, &prop);
  1316. + if (ret) {
  1317. + dev_err(&client->dev, "err set dvb-t mode\n");
  1318. + return ret;
  1319. + }
  1320. + return 0;
  1321. +}
  1322. +
  1323. +static int si2183_set_frontend(struct dvb_frontend *fe)
  1324. +{
  1325. + struct i2c_client *client = fe->demodulator_priv;
  1326. + struct si2183_dev *dev = i2c_get_clientdata(client);
  1327. + struct dtv_frontend_properties *c = &fe->dtv_property_cache;
  1328. + int ret;
  1329. + struct si2183_cmd cmd;
  1330. +
  1331. + dev_dbg(&client->dev,
  1332. + "delivery_system=%u modulation=%u frequency=%u bandwidth_hz=%u symbol_rate=%u inversion=%u stream_id=%d\n",
  1333. + c->delivery_system, c->modulation, c->frequency,
  1334. + c->bandwidth_hz, c->symbol_rate, c->inversion,
  1335. + c->stream_id);
  1336. +
  1337. + if (!dev->active_fe) {
  1338. + ret = -EAGAIN;
  1339. + goto err;
  1340. + }
  1341. + if(dev->RF_switch)
  1342. + {
  1343. + switch (c->delivery_system) {
  1344. + case SYS_DVBT:
  1345. + case SYS_DVBT2:
  1346. + case SYS_DVBC_ANNEX_A:
  1347. + case SYS_DVBC_ANNEX_B:
  1348. + case SYS_ISDBT:
  1349. + dev->RF_switch(dev->base->i2c,dev->rf_in,1);
  1350. +
  1351. + break;
  1352. +
  1353. + case SYS_DVBS:
  1354. + case SYS_DVBS2:
  1355. + case SYS_DSS:
  1356. + default:
  1357. + dev->RF_switch(dev->base->i2c,dev->rf_in,0);
  1358. + break;
  1359. +
  1360. + }
  1361. + }
  1362. +
  1363. + if(dev->TS_switch)
  1364. + dev->TS_switch(dev->base->i2c,1);
  1365. +
  1366. + if (fe->ops.tuner_ops.set_params) {
  1367. +#ifndef SI2183_USE_I2C_MUX
  1368. + if (fe->ops.i2c_gate_ctrl)
  1369. + fe->ops.i2c_gate_ctrl(fe, 1);
  1370. +#endif
  1371. + ret = fe->ops.tuner_ops.set_params(fe);
  1372. +#ifndef SI2183_USE_I2C_MUX
  1373. + if (fe->ops.i2c_gate_ctrl)
  1374. + fe->ops.i2c_gate_ctrl(fe, 0);
  1375. +#endif
  1376. + if (ret) {
  1377. + dev_err(&client->dev, "err setting tuner params\n");
  1378. + goto err;
  1379. + }
  1380. + }
  1381. +
  1382. + switch (c->delivery_system) {
  1383. + case SYS_DVBT:
  1384. + case SYS_DVBT2:
  1385. + ret = si2183_set_dvbt(fe);
  1386. + break;
  1387. + case SYS_DVBC_ANNEX_A:
  1388. + ret = si2183_set_dvbc(fe);
  1389. + break;
  1390. + case SYS_DVBC_ANNEX_B:
  1391. + ret= si2183_set_mcns(fe);
  1392. + break;
  1393. + case SYS_ISDBT:
  1394. + ret = si2183_set_isdbt(fe);
  1395. + break;
  1396. + case SYS_DVBS:
  1397. + case SYS_DVBS2:
  1398. + case SYS_DSS:
  1399. + ret = si2183_set_dvbs(fe);
  1400. + break;
  1401. + default:
  1402. + ret = -EINVAL;
  1403. + goto err;
  1404. + }
  1405. +
  1406. + /* dsp restart */
  1407. + memcpy(cmd.args, "\x85", 1);
  1408. + cmd.wlen = 1;
  1409. + cmd.rlen = 1;
  1410. + ret = si2183_cmd_execute(client, &cmd);
  1411. + if (ret) {
  1412. + dev_err(&client->dev, "err restarting dsp\n");
  1413. + return ret;
  1414. + }
  1415. +
  1416. + dev->delivery_system = c->delivery_system;
  1417. + return 0;
  1418. +err:
  1419. + dev_err(&client->dev, "set_params failed=%d\n", ret);
  1420. + return ret;
  1421. +}
  1422. +
  1423. +static int si2183_init(struct dvb_frontend *fe)
  1424. +{
  1425. + struct i2c_client *client = fe->demodulator_priv;
  1426. + struct si2183_dev *dev = i2c_get_clientdata(client);
  1427. + struct dtv_frontend_properties *c = &fe->dtv_property_cache;
  1428. + int ret = 0, len, remaining;
  1429. + const struct firmware *fw;
  1430. + const char *fw_name;
  1431. + struct si2183_cmd cmd;
  1432. + unsigned int chip_id;
  1433. + u16 prop;
  1434. +
  1435. + dev_dbg(&client->dev, "\n");
  1436. +
  1437. + if (dev->active_fe) {
  1438. + dev->active_fe |= (1 << fe->id);
  1439. + return 0;
  1440. + }
  1441. +
  1442. + c->cnr.len = 1;
  1443. + c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
  1444. +
  1445. + /* initialize */
  1446. + memcpy(cmd.args, "\xc0\x12\x00\x0c\x00\x0d\x16\x00\x00\x00\x00\x00\x00", 13);
  1447. + if(dev->start_clk_mode == 1){
  1448. + cmd.args[3] =0;
  1449. + cmd.args[5] = 0x6;
  1450. + }
  1451. +
  1452. + cmd.wlen = 13;
  1453. + cmd.rlen = 0;
  1454. + ret = si2183_cmd_execute(client, &cmd);
  1455. + if (ret)
  1456. + goto err;
  1457. +
  1458. + if (dev->fw_loaded) {
  1459. + /* resume */
  1460. + memcpy(cmd.args, "\xc0\x06\x08\x0f\x00\x20\x21\x01", 8);
  1461. +
  1462. + if(dev->start_clk_mode==1)
  1463. + cmd.args[6]=0x31;
  1464. + cmd.wlen = 8;
  1465. + cmd.rlen = 1;
  1466. + ret = si2183_cmd_execute(client, &cmd);
  1467. + if (ret)
  1468. + goto err;
  1469. +
  1470. + memcpy(cmd.args, "\x85", 1);
  1471. + cmd.wlen = 1;
  1472. + cmd.rlen = 1;
  1473. + ret = si2183_cmd_execute(client, &cmd);
  1474. + if (ret)
  1475. + goto err;
  1476. +
  1477. + goto warm;
  1478. + }
  1479. +
  1480. + /* power up */
  1481. + memcpy(cmd.args, "\xc0\x06\x01\x0f\x00\x20\x20\x01", 8);
  1482. + if(dev->start_clk_mode ==1 ){
  1483. + cmd.args[6] = 0x30;
  1484. + }
  1485. + cmd.wlen = 8;
  1486. + cmd.rlen = 1;
  1487. + ret = si2183_cmd_execute(client, &cmd);
  1488. + if (ret)
  1489. + goto err;
  1490. +
  1491. + /* query chip revision */
  1492. + memcpy(cmd.args, "\x02", 1);
  1493. + cmd.wlen = 1;
  1494. + cmd.rlen = 13;
  1495. + ret = si2183_cmd_execute(client, &cmd);
  1496. + if (ret)
  1497. + goto err;
  1498. +
  1499. + chip_id = cmd.args[1] << 24 | cmd.args[2] << 16 | cmd.args[3] << 8 |
  1500. + cmd.args[4] << 0;
  1501. +
  1502. + #define SI2183_B60 ('B' << 24 | 83 << 16 | '6' << 8 | '0' << 0)
  1503. +
  1504. + switch (chip_id) {
  1505. + case SI2183_B60:
  1506. + fw_name = SI2183_B60_FIRMWARE;
  1507. + break;
  1508. + default:
  1509. + dev_err(&client->dev, "unknown chip version Si21%d-%c%c%c\n",
  1510. + cmd.args[2], cmd.args[1],
  1511. + cmd.args[3], cmd.args[4]);
  1512. + ret = -EINVAL;
  1513. + goto err;
  1514. + }
  1515. +
  1516. + dev_info(&client->dev, "found a 'Silicon Labs Si21%d-%c%c%c'\n",
  1517. + cmd.args[2], cmd.args[1], cmd.args[3], cmd.args[4]);
  1518. +
  1519. + ret = request_firmware(&fw, fw_name, &client->dev);
  1520. + if (ret) {
  1521. + dev_err(&client->dev,
  1522. + "firmware file '%s' not found\n",
  1523. + fw_name);
  1524. + goto err;
  1525. + }
  1526. +
  1527. + dev_info(&client->dev, "downloading firmware from file '%s'\n",
  1528. + fw_name);
  1529. +
  1530. + for (remaining = fw->size; remaining > 0; remaining -= 17) {
  1531. + len = fw->data[fw->size - remaining];
  1532. + if (len > SI2183_ARGLEN) {
  1533. + ret = -EINVAL;
  1534. + break;
  1535. + }
  1536. + memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len);
  1537. + cmd.wlen = len;
  1538. + cmd.rlen = 1;
  1539. + ret = si2183_cmd_execute(client, &cmd);
  1540. + if (ret)
  1541. + break;
  1542. + }
  1543. + release_firmware(fw);
  1544. +
  1545. + if (ret) {
  1546. + dev_err(&client->dev, "firmware download failed %d\n", ret);
  1547. + goto err;
  1548. + }
  1549. +
  1550. + memcpy(cmd.args, "\x01\x01", 2);
  1551. + cmd.wlen = 2;
  1552. + cmd.rlen = 1;
  1553. + ret = si2183_cmd_execute(client, &cmd);
  1554. + if (ret)
  1555. + goto err;
  1556. +
  1557. + /* query firmware version */
  1558. + memcpy(cmd.args, "\x11", 1);
  1559. + cmd.wlen = 1;
  1560. + cmd.rlen = 10;
  1561. + ret = si2183_cmd_execute(client, &cmd);
  1562. + if (ret)
  1563. + goto err;
  1564. +
  1565. + dev_info(&client->dev, "firmware version: %c.%c.%d\n",
  1566. + cmd.args[6], cmd.args[7], cmd.args[8]);
  1567. +
  1568. + /* set ts mode */
  1569. + prop = 0x10 | dev->ts_mode | (dev->ts_clock_gapped ? 0x40 : 0);
  1570. + ret = si2183_set_prop(client, 0x1001, &prop);
  1571. + if (ret) {
  1572. + dev_err(&client->dev, "err set ts mode\n");
  1573. + }
  1574. +
  1575. + /* FER resol */
  1576. + prop = 0x12;
  1577. + ret = si2183_set_prop(client, 0x100c, &prop);
  1578. + if (ret) {
  1579. + dev_err(&client->dev, "err set FER resol\n");
  1580. + return ret;
  1581. + }
  1582. +
  1583. + /* DD IEN */
  1584. + prop = 0x00;
  1585. + ret = si2183_set_prop(client, 0x1006, &prop);
  1586. + if (ret) {
  1587. + dev_err(&client->dev, "err set dd ien\n");
  1588. + return ret;
  1589. + }
  1590. +
  1591. + /* int sense */
  1592. + prop = 0x2000;
  1593. + ret = si2183_set_prop(client, 0x1007, &prop);
  1594. + if (ret) {
  1595. + dev_err(&client->dev, "err set int sense\n");
  1596. + return ret;
  1597. + }
  1598. +
  1599. + /* Control of SQI computation */
  1600. + prop = 0x1e;
  1601. + ret = si2183_set_prop(client, 0x100f, &prop);
  1602. + if (ret) {
  1603. + dev_err(&client->dev, "err set sqi comp\n");
  1604. + return ret;
  1605. + }
  1606. +
  1607. + /* Transport Stream setting for parallel mode */
  1608. + prop = 0x0104 | (dev->ts_clock_inv ? 0x0000 : 0x1000);
  1609. + ret = si2183_set_prop(client, 0x1009, &prop);
  1610. + if (ret) {
  1611. + dev_err(&client->dev, "err set par_ts\n");
  1612. + return ret;
  1613. + }
  1614. +
  1615. + /* Transport Stream setting for serial mode */
  1616. + prop = 0x230C | (dev->ts_clock_inv ? 0x0000 : 0x1000);
  1617. + ret = si2183_set_prop(client, 0x1008, &prop);
  1618. + if (ret) {
  1619. + dev_err(&client->dev, "err set ser_ts\n");
  1620. + return ret;
  1621. + }
  1622. +
  1623. + /* Transport Stream setting for parallel mode - secondary*/
  1624. + prop = 0x08e3;
  1625. + ret = si2183_set_prop(client, 0x1015, &prop);
  1626. + if (ret) {
  1627. + dev_err(&client->dev, "err set int par_ts_sec\n");
  1628. + return ret;
  1629. + }
  1630. +
  1631. + /* Transport Stream setting for serial mode - secondary*/
  1632. + prop = 0x01c7;
  1633. + ret = si2183_set_prop(client, 0x1016, &prop);
  1634. + if (ret) {
  1635. + dev_err(&client->dev, "err set int ser_ts_sec\n");
  1636. + return ret;
  1637. + }
  1638. +
  1639. + dev->fw_loaded = true;
  1640. +warm:
  1641. + dev->active_fe |= (1 << fe->id);
  1642. + return 0;
  1643. +
  1644. +err:
  1645. + dev_dbg(&client->dev, "init failed=%d\n", ret);
  1646. + return ret;
  1647. +}
  1648. +
  1649. +static int si2183_sleep(struct dvb_frontend *fe)
  1650. +{
  1651. + struct i2c_client *client = fe->demodulator_priv;
  1652. + struct si2183_dev *dev = i2c_get_clientdata(client);
  1653. + int ret;
  1654. + struct si2183_cmd cmd;
  1655. +
  1656. + dev_dbg(&client->dev, "\n");
  1657. +
  1658. + dev->active_fe &= ~(1 << fe->id);
  1659. + if (dev->active_fe)
  1660. + return 0;
  1661. +
  1662. + memcpy(cmd.args, "\x13", 1);
  1663. + cmd.wlen = 1;
  1664. + cmd.rlen = 0;
  1665. + ret = si2183_cmd_execute(client, &cmd);
  1666. + if (ret)
  1667. + goto err;
  1668. +
  1669. + return 0;
  1670. +err:
  1671. + dev_dbg(&client->dev, "failed=%d\n", ret);
  1672. + return ret;
  1673. +}
  1674. +
  1675. +static int si2183_get_tune_settings(struct dvb_frontend *fe,
  1676. + struct dvb_frontend_tune_settings *s)
  1677. +{
  1678. + s->min_delay_ms = 900;
  1679. +
  1680. + return 0;
  1681. +}
  1682. +
  1683. +#ifdef SI2183_USE_I2C_MUX
  1684. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)
  1685. +static int si2183_select(struct i2c_mux_core *muxc, u32 chan)
  1686. +{
  1687. + struct i2c_client *client = i2c_mux_priv(muxc);
  1688. +#else
  1689. +static int si2183_select(struct i2c_adapter *adap, void *mux_priv, u32 chan)
  1690. +{
  1691. + struct i2c_client *client = mux_priv;
  1692. +#endif
  1693. + int ret;
  1694. + struct si2183_cmd cmd;
  1695. +
  1696. + /* open I2C gate */
  1697. + memcpy(cmd.args, "\xc0\x0d\x01", 3);
  1698. + cmd.wlen = 3;
  1699. + cmd.rlen = 0;
  1700. + ret = si2183_cmd_execute_unlocked(client, &cmd);
  1701. + if (ret)
  1702. + goto err;
  1703. +
  1704. + return 0;
  1705. +err:
  1706. + dev_dbg(&client->dev, "failed=%d\n", ret);
  1707. + return ret;
  1708. +}
  1709. +
  1710. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)
  1711. +static int si2183_deselect(struct i2c_mux_core *muxc, u32 chan)
  1712. +{
  1713. + struct i2c_client *client = i2c_mux_priv(muxc);
  1714. +#else
  1715. +static int si2183_deselect(struct i2c_adapter *adap, void *mux_priv, u32 chan)
  1716. +{
  1717. + struct i2c_client *client = mux_priv;
  1718. +#endif
  1719. + int ret;
  1720. + struct si2183_cmd cmd;
  1721. +
  1722. + /* close I2C gate */
  1723. + memcpy(cmd.args, "\xc0\x0d\x00", 3);
  1724. + cmd.wlen = 3;
  1725. + cmd.rlen = 0;
  1726. + ret = si2183_cmd_execute_unlocked(client, &cmd);
  1727. + if (ret)
  1728. + goto err;
  1729. +
  1730. + return 0;
  1731. +err:
  1732. + dev_dbg(&client->dev, "failed=%d\n", ret);
  1733. + return ret;
  1734. +}
  1735. +#else
  1736. +static int i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
  1737. +{
  1738. + struct i2c_client *client = fe->demodulator_priv;
  1739. + struct si2183_dev *dev = i2c_get_clientdata(client);
  1740. + struct si2183_cmd cmd;
  1741. +
  1742. + memcpy(cmd.args, "\xc0\x0d\x00", 3);
  1743. + if (enable)
  1744. + cmd.args[2] = 1;
  1745. + cmd.wlen = 3;
  1746. + cmd.rlen = 0;
  1747. + return si2183_cmd_execute(dev->base->i2c_gate_client, &cmd);
  1748. +}
  1749. +#endif
  1750. +
  1751. +static int si2183_tune(struct dvb_frontend *fe, bool re_tune,
  1752. + unsigned int mode_flags, unsigned int *delay, enum fe_status *status)
  1753. +{
  1754. + *delay = HZ / 5;
  1755. + if (re_tune) {
  1756. + int ret = si2183_set_frontend(fe);
  1757. + if (ret)
  1758. + return ret;
  1759. + }
  1760. + return si2183_read_status(fe, status);
  1761. +}
  1762. +
  1763. +static enum dvbfe_algo si2183_get_algo(struct dvb_frontend *fe)
  1764. +{
  1765. + return DVBFE_ALGO_HW;
  1766. +}
  1767. +
  1768. +static int si2183_set_property(struct dvb_frontend *fe,
  1769. + u32 cmd, u32 data)
  1770. +{
  1771. + int ret = 0;
  1772. +
  1773. + switch (cmd) {
  1774. + case DTV_DELIVERY_SYSTEM:
  1775. + switch (data) {
  1776. + case SYS_DVBS:
  1777. + case SYS_DVBS2:
  1778. + case SYS_DSS:
  1779. + fe->ops.info.frequency_min_hz = 950 * MHz;
  1780. + fe->ops.info.frequency_max_hz = 2150 * MHz;
  1781. + fe->ops.info.frequency_stepsize_hz = 0;
  1782. + break;
  1783. + case SYS_ISDBT:
  1784. + fe->ops.info.frequency_min_hz = 42 * MHz;
  1785. + fe->ops.info.frequency_max_hz = 1002 * MHz;
  1786. + fe->ops.info.frequency_stepsize_hz = 0;
  1787. + break;
  1788. + case SYS_DVBC_ANNEX_A:
  1789. + case SYS_DVBC_ANNEX_B:
  1790. + fe->ops.info.frequency_min_hz = 47 * MHz;
  1791. + fe->ops.info.frequency_max_hz = 862 * MHz;
  1792. + fe->ops.info.frequency_stepsize_hz = 62500;
  1793. + break;
  1794. + case SYS_DVBT:
  1795. + case SYS_DVBT2:
  1796. + default:
  1797. + fe->ops.info.frequency_min_hz = 174 * MHz;
  1798. + fe->ops.info.frequency_max_hz = 862 * MHz;
  1799. + fe->ops.info.frequency_stepsize_hz = 250000;
  1800. + break;
  1801. + }
  1802. + break;
  1803. + default:
  1804. + break;
  1805. + }
  1806. +
  1807. + return ret;
  1808. +}
  1809. +
  1810. +
  1811. +static int send_diseqc_cmd(struct dvb_frontend *fe,
  1812. + u8 cont_tone, u8 tone_burst, u8 burst_sel,
  1813. + u8 end_seq, u8 msg_len, u8 *msg)
  1814. +{
  1815. + struct i2c_client *client = fe->demodulator_priv;
  1816. + struct si2183_cmd cmd;
  1817. + u8 enable = 1;
  1818. +
  1819. + cmd.args[0] = 0x8c;
  1820. + cmd.args[1] = enable | (cont_tone << 1)
  1821. + | (tone_burst << 2) | (burst_sel << 3)
  1822. + | (end_seq << 4) | (msg_len << 5);
  1823. +
  1824. + if (msg_len > 0)
  1825. + memcpy(&cmd.args[2], msg, msg_len);
  1826. +
  1827. + cmd.wlen = 8;
  1828. + cmd.rlen = 1;
  1829. + return si2183_cmd_execute(client, &cmd);
  1830. +}
  1831. +
  1832. +static int si2183_set_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone)
  1833. +{
  1834. + struct i2c_client *client = fe->demodulator_priv;
  1835. + int ret;
  1836. + u8 cont_tone;
  1837. +
  1838. + switch (tone) {
  1839. + case SEC_TONE_ON:
  1840. + cont_tone = 1;
  1841. + break;
  1842. + case SEC_TONE_OFF:
  1843. + cont_tone = 0;
  1844. + break;
  1845. + default:
  1846. + return -EINVAL;
  1847. + }
  1848. +
  1849. + ret = send_diseqc_cmd(fe, cont_tone, 0, 0, 1, 0, NULL);
  1850. + if (ret)
  1851. + goto err;
  1852. +
  1853. + return 0;
  1854. +err:
  1855. + dev_err(&client->dev, "set_tone failed=%d\n", ret);
  1856. + return ret;
  1857. +}
  1858. +
  1859. +static int si2183_diseqc_send_burst(struct dvb_frontend *fe,
  1860. + enum fe_sec_mini_cmd burst)
  1861. +{
  1862. + struct i2c_client *client = fe->demodulator_priv;
  1863. + int ret;
  1864. + u8 burst_sel;
  1865. +
  1866. + switch (burst) {
  1867. + case SEC_MINI_A:
  1868. + burst_sel = 0;
  1869. + break;
  1870. + case SEC_MINI_B:
  1871. + burst_sel = 1;
  1872. + break;
  1873. + default:
  1874. + return -EINVAL;
  1875. + }
  1876. +
  1877. + ret = send_diseqc_cmd(fe, 0, 1, burst_sel, 1, 0, NULL);
  1878. + if (ret)
  1879. + goto err;
  1880. +
  1881. + return 0;
  1882. +err:
  1883. + dev_err(&client->dev, "set_tone failed=%d\n", ret);
  1884. + return ret;
  1885. +}
  1886. +
  1887. +static int si2183_diseqc_send_msg(struct dvb_frontend *fe,
  1888. + struct dvb_diseqc_master_cmd *d)
  1889. +{
  1890. + struct i2c_client *client = fe->demodulator_priv;
  1891. + int ret;
  1892. + u8 remaining = d->msg_len;
  1893. + u8 *p = d->msg;
  1894. + u8 len = 0;
  1895. +
  1896. + while (remaining > 0) {
  1897. + p += len;
  1898. + len = (remaining > 6) ? 6 : remaining;
  1899. + remaining -= len;
  1900. + ret = send_diseqc_cmd(fe, 0, 0, 0,
  1901. + (remaining == 0) ? 1 : 0, len, p);
  1902. + if (ret)
  1903. + goto err;
  1904. + msleep(50);
  1905. + }
  1906. +
  1907. + return 0;
  1908. +err:
  1909. + dev_err(&client->dev, "set_tone failed=%d\n", ret);
  1910. + return ret;
  1911. +}
  1912. +
  1913. +static void spi_read(struct dvb_frontend *fe, struct ecp3_info *ecp3inf)
  1914. +{
  1915. + struct i2c_client *client = fe->demodulator_priv;
  1916. + struct si2183_dev *dev = i2c_get_clientdata(client);
  1917. +
  1918. +
  1919. + if (dev->read_properties)
  1920. + dev->read_properties(client->adapter,ecp3inf->reg, &(ecp3inf->data));
  1921. +
  1922. + return ;
  1923. +}
  1924. +
  1925. +static void spi_write(struct dvb_frontend *fe,struct ecp3_info *ecp3inf)
  1926. +{
  1927. + struct i2c_client *client = fe->demodulator_priv;
  1928. + struct si2183_dev *dev = i2c_get_clientdata(client);
  1929. +
  1930. + if (dev->write_properties)
  1931. + dev->write_properties(client->adapter,ecp3inf->reg, ecp3inf->data);
  1932. + return ;
  1933. +}
  1934. +
  1935. +static void eeprom_read(struct dvb_frontend *fe, struct eeprom_info *eepinf)
  1936. +{
  1937. + struct i2c_client *client = fe->demodulator_priv;
  1938. + struct si2183_dev *dev = i2c_get_clientdata(client);
  1939. +
  1940. + if (dev->read_eeprom)
  1941. + dev->read_eeprom(client->adapter,eepinf->reg, &(eepinf->data));
  1942. + return ;
  1943. +}
  1944. +
  1945. +static void eeprom_write(struct dvb_frontend *fe,struct eeprom_info *eepinf)
  1946. +{
  1947. + struct i2c_client *client = fe->demodulator_priv;
  1948. + struct si2183_dev *dev = i2c_get_clientdata(client);
  1949. +
  1950. + if (dev->write_eeprom)
  1951. + dev->write_eeprom(client->adapter,eepinf->reg, eepinf->data);
  1952. + return ;
  1953. +}
  1954. +
  1955. +static const struct dvb_frontend_ops si2183_ops = {
  1956. + .delsys = {SYS_DVBT, SYS_DVBT2,
  1957. + SYS_ISDBT,
  1958. + SYS_DVBC_ANNEX_A,SYS_DVBC_ANNEX_B,
  1959. + SYS_DVBS, SYS_DVBS2, SYS_DSS},
  1960. + .info = {
  1961. + .name = "Silicon Labs Si2183",
  1962. + .symbol_rate_min = 1000000,
  1963. + .symbol_rate_max = 45000000,
  1964. + .caps = FE_CAN_FEC_1_2 |
  1965. + FE_CAN_FEC_2_3 |
  1966. + FE_CAN_FEC_3_4 |
  1967. + FE_CAN_FEC_5_6 |
  1968. + FE_CAN_FEC_7_8 |
  1969. + FE_CAN_FEC_AUTO |
  1970. + FE_CAN_QPSK |
  1971. + FE_CAN_QAM_16 |
  1972. + FE_CAN_QAM_32 |
  1973. + FE_CAN_QAM_64 |
  1974. + FE_CAN_QAM_128 |
  1975. + FE_CAN_QAM_256 |
  1976. + FE_CAN_QAM_AUTO |
  1977. + FE_CAN_TRANSMISSION_MODE_AUTO |
  1978. + FE_CAN_GUARD_INTERVAL_AUTO |
  1979. + FE_CAN_HIERARCHY_AUTO |
  1980. + FE_CAN_MUTE_TS |
  1981. + FE_CAN_2G_MODULATION |
  1982. + FE_CAN_MULTISTREAM
  1983. + },
  1984. +
  1985. + .get_tune_settings = si2183_get_tune_settings,
  1986. +
  1987. + .init = si2183_init,
  1988. + .sleep = si2183_sleep,
  1989. +
  1990. + .set_frontend = si2183_set_frontend,
  1991. +
  1992. + .read_status = si2183_read_status,
  1993. + .read_signal_strength = si2183_read_signal_strength,
  1994. + .read_snr = si2183_read_snr,
  1995. + .read_ber = si2183_read_ber,
  1996. + .read_ucblocks = si2183_read_ucblocks,
  1997. +
  1998. + .get_frontend_algo = si2183_get_algo,
  1999. + .tune = si2183_tune,
  2000. +
  2001. + .set_property = si2183_set_property,
  2002. +
  2003. + .set_tone = si2183_set_tone,
  2004. + .diseqc_send_burst = si2183_diseqc_send_burst,
  2005. + .diseqc_send_master_cmd = si2183_diseqc_send_msg,
  2006. +#ifndef SI2183_USE_I2C_MUX
  2007. + .i2c_gate_ctrl = i2c_gate_ctrl,
  2008. +#endif
  2009. +
  2010. + .spi_read = spi_read,
  2011. + .spi_write = spi_write,
  2012. + .eeprom_read = eeprom_read,
  2013. + .eeprom_write = eeprom_write,
  2014. +};
  2015. +
  2016. +
  2017. +static struct si_base *match_base(struct i2c_adapter *i2c, u8 adr)
  2018. +{
  2019. + struct si_base *p;
  2020. +
  2021. + list_for_each_entry(p, &silist, silist)
  2022. + if (p->i2c == i2c)// && p->adr == adr) lja: TO FIX
  2023. + return p;
  2024. + return NULL;
  2025. +}
  2026. +
  2027. +static int si2183_probe(struct i2c_client *client,
  2028. + const struct i2c_device_id *id)
  2029. +{
  2030. + struct si2183_config *config = client->dev.platform_data;
  2031. + struct si2183_dev *dev;
  2032. + struct si_base *base;
  2033. + int ret;
  2034. +
  2035. + dev_dbg(&client->dev, "\n");
  2036. +
  2037. + dev = kzalloc(sizeof(*dev), GFP_KERNEL);
  2038. + if (!dev) {
  2039. + ret = -ENOMEM;
  2040. + dev_err(&client->dev, "kzalloc() failed\n");
  2041. + goto err;
  2042. + }
  2043. +
  2044. + base = match_base(client->adapter, client->addr);
  2045. + if (base) {
  2046. + base->count++;
  2047. + dev->base = base;
  2048. + } else {
  2049. + base = kzalloc(sizeof(struct si_base), GFP_KERNEL);
  2050. + if (!base)
  2051. + goto err_kfree;
  2052. + base->i2c = client->adapter;
  2053. + base->adr = client->addr;
  2054. + base->count = 1;
  2055. + dev->base = base;
  2056. + list_add(&base->silist, &silist);
  2057. +
  2058. + mutex_init(&base->i2c_mutex);
  2059. +#ifdef SI2183_USE_I2C_MUX
  2060. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)
  2061. + /* create mux i2c adapter for tuner */
  2062. + base->muxc = i2c_mux_alloc(client->adapter, &client->adapter->dev,
  2063. + 1, 0, I2C_MUX_LOCKED,
  2064. + si2183_select, si2183_deselect);
  2065. + if (!base->muxc) {
  2066. + ret = -ENOMEM;
  2067. + goto err_base_kfree;
  2068. + }
  2069. + base->muxc->priv = client;
  2070. + ret = i2c_mux_add_adapter(base->muxc, 0, 0, 0);
  2071. + if (ret)
  2072. + goto err_base_kfree;
  2073. + base->tuner_adapter = base->muxc->adapter[0];
  2074. +#else
  2075. + /* create mux i2c adapter for tuners */
  2076. + base->tuner_adapter = i2c_add_mux_adapter(client->adapter, &client->adapter->dev,
  2077. + client, 0, 0, 0, si2183_select, si2183_deselect);
  2078. + if (base->tuner_adapter == NULL) {
  2079. + ret = -ENODEV;
  2080. + goto err_base_kfree;
  2081. + }
  2082. +#endif
  2083. +#else
  2084. + base->tuner_adapter = client->adapter;
  2085. + base->i2c_gate_client = client;
  2086. +#endif
  2087. + }
  2088. +
  2089. + /* create dvb_frontend */
  2090. + memcpy(&dev->fe.ops, &si2183_ops, sizeof(struct dvb_frontend_ops));
  2091. + dev->fe.demodulator_priv = client;
  2092. + *config->i2c_adapter = base->tuner_adapter;
  2093. + *config->fe = &dev->fe;
  2094. + dev->ts_mode = config->ts_mode;
  2095. + dev->ts_clock_inv = config->ts_clock_inv;
  2096. + dev->ts_clock_gapped = config->ts_clock_gapped;
  2097. + dev->agc_mode = config->agc_mode;
  2098. + dev->RF_switch = config->RF_switch;
  2099. + dev->rf_in = config->rf_in;
  2100. + dev->fw_loaded = false;
  2101. + dev->delivery_system = 0;
  2102. + dev->snr = 0;
  2103. + dev->stat_resp = 0;
  2104. + dev->active_fe = 0;
  2105. + dev->start_clk_mode = config->start_clk_mode;
  2106. + dev->TS_switch = config->TS_switch;
  2107. + dev->LED_switch = config->LED_switch;
  2108. +
  2109. + dev->write_properties = config->write_properties;
  2110. + dev->read_properties = config->read_properties;
  2111. + dev->write_eeprom = config->write_eeprom;
  2112. + dev->read_eeprom = config->read_eeprom;
  2113. +
  2114. + i2c_set_clientdata(client, dev);
  2115. +
  2116. +#ifndef SI2183_USE_I2C_MUX
  2117. + /* leave gate open for tuner to init */
  2118. + i2c_gate_ctrl(&dev->fe, 1);
  2119. +#endif
  2120. + dev_info(&client->dev, "Silicon Labs Si2183 successfully attached\n");
  2121. + return 0;
  2122. +err_base_kfree:
  2123. + kfree(base);
  2124. +err_kfree:
  2125. + kfree(dev);
  2126. +err:
  2127. + dev_dbg(&client->dev, "probe failed=%d\n", ret);
  2128. + return ret;
  2129. +}
  2130. +
  2131. +static void si2183_remove(struct i2c_client *client)
  2132. +{
  2133. + struct si2183_dev *dev = i2c_get_clientdata(client);
  2134. +
  2135. + dev_dbg(&client->dev, "\n");
  2136. +
  2137. + dev->base->count--;
  2138. + if (dev->base->count == 0) {
  2139. +#ifdef SI2183_USE_I2C_MUX
  2140. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)
  2141. + i2c_mux_del_adapters(dev->base->muxc);
  2142. +#else
  2143. + i2c_del_mux_adapter(dev->base->tuner_adapter);
  2144. +#endif
  2145. +#endif
  2146. + list_del(&dev->base->silist);
  2147. + kfree(dev->base);
  2148. + }
  2149. +
  2150. + dev->fe.ops.release = NULL;
  2151. + dev->fe.demodulator_priv = NULL;
  2152. +
  2153. + kfree(dev);
  2154. +}
  2155. +
  2156. +static const struct i2c_device_id si2183_id_table[] = {
  2157. + {"si2183", 0},
  2158. + {}
  2159. +};
  2160. +MODULE_DEVICE_TABLE(i2c, si2183_id_table);
  2161. +
  2162. +static struct i2c_driver si2183_driver = {
  2163. + .driver = {
  2164. + .name = "si2183",
  2165. + },
  2166. + .probe = si2183_probe,
  2167. + .remove = si2183_remove,
  2168. + .id_table = si2183_id_table,
  2169. +};
  2170. +
  2171. +module_i2c_driver(si2183_driver);
  2172. +
  2173. +MODULE_AUTHOR("Luis Alves <ljalvs@gmail.com>");
  2174. +MODULE_DESCRIPTION("Silicon Labs Si2183 DVB-T/T2/C/C2/S/S2 demodulator driver");
  2175. +MODULE_LICENSE("GPL");
  2176.  
  2177. diff -uraBN a/drivers/media/dvb-frontends/si2183.h b/drivers/media/dvb-frontends/si2183.h
  2178. --- a/drivers/media/dvb-frontends/si2183.h
  2179. +++ b/drivers/media/dvb-frontends/si2183.h
  2180. @@ -0,0 +1,66 @@
  2181. +/*
  2182. + * Silicon Labs Si2183(2) DVB-T/T2/C/C2/S/S2 demodulator driver
  2183. + *
  2184. + * This program is free software; you can redistribute it and/or modify
  2185. + * it under the terms of the GNU General Public License as published by
  2186. + * the Free Software Foundation; either version 2 of the License, or
  2187. + * (at your option) any later version.
  2188. + *
  2189. + * This program is distributed in the hope that it will be useful,
  2190. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  2191. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  2192. + * GNU General Public License for more details.
  2193. + */
  2194. +
  2195. +#ifndef SI2183_H
  2196. +#define SI2183_H
  2197. +
  2198. +#include <linux/dvb/frontend.h>
  2199. +/*
  2200. + * I2C address
  2201. + * 0x64
  2202. + */
  2203. +struct si2183_config {
  2204. + /*
  2205. + * frontend
  2206. + * returned by driver
  2207. + */
  2208. + struct dvb_frontend **fe;
  2209. +
  2210. + /*
  2211. + * tuner I2C adapter
  2212. + * returned by driver
  2213. + */
  2214. + struct i2c_adapter **i2c_adapter;
  2215. +
  2216. + /* TS mode */
  2217. +#define SI2183_TS_PARALLEL 0x06
  2218. +#define SI2183_TS_SERIAL 0x03
  2219. + u8 ts_mode;
  2220. +
  2221. + /* TS clock inverted */
  2222. + bool ts_clock_inv;
  2223. +
  2224. + int start_clk_mode; //0 terrestrial mode 1: satellite mode
  2225. +
  2226. + /* TS clock gapped */
  2227. + bool ts_clock_gapped;
  2228. + /*agc*/
  2229. + u8 agc_mode;
  2230. +
  2231. + /*rf switch*/
  2232. + void (*RF_switch)(struct i2c_adapter * i2c,u8 rf_in,u8 flag);
  2233. + /*rf no.*/
  2234. + u8 rf_in;
  2235. +
  2236. + void (*TS_switch)(struct i2c_adapter * i2c,u8 flag);
  2237. + void (*LED_switch)(struct i2c_adapter * i2c,u8 flag);
  2238. + //update the FW.
  2239. + void (*write_properties) (struct i2c_adapter *i2c,u8 reg, u32 buf);
  2240. + void (*read_properties) (struct i2c_adapter *i2c,u8 reg, u32 *buf);
  2241. + // EEPROM access
  2242. + void (*write_eeprom) (struct i2c_adapter *i2c,u8 reg, u8 buf);
  2243. + void (*read_eeprom) (struct i2c_adapter *i2c,u8 reg, u8 *buf);
  2244. +};
  2245. +
  2246. +#endif
  2247.  
  2248. diff -uraBN a/drivers/media/tuners/av201x.c b/drivers/media/tuners/av201x.c
  2249. --- a/drivers/media/tuners/av201x.c
  2250. +++ b/drivers/media/tuners/av201x.c
  2251. @@ -0,0 +1,302 @@
  2252. +/*
  2253. + * AV201x Airoha Technology silicon tuner driver
  2254. + *
  2255. + * Copyright (C) 2014 Luis Alves <ljalvs@gmail.com>
  2256. + *
  2257. + * This program is free software; you can redistribute it and/or modify
  2258. + * it under the terms of the GNU General Public License as published by
  2259. + * the Free Software Foundation; either version 2 of the License, or
  2260. + * (at your option) any later version.
  2261. + *
  2262. + * This program is distributed in the hope that it will be useful,
  2263. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  2264. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  2265. + * GNU General Public License for more details.
  2266. + *
  2267. + * You should have received a copy of the GNU General Public License along
  2268. + * with this program; if not, write to the Free Software Foundation, Inc.,
  2269. + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  2270. + */
  2271. +
  2272. +#include "av201x.h"
  2273. +#include "av201x_priv.h"
  2274. +
  2275. +/* write multiple (continuous) registers */
  2276. +static int av201x_wrm(struct av201x_priv *priv, u8 *buf, int len)
  2277. +{
  2278. + int ret;
  2279. + struct i2c_msg msg = {
  2280. + .addr = priv->cfg->i2c_address,
  2281. + .flags = 0, .buf = buf, .len = len };
  2282. +
  2283. + dev_dbg(&priv->i2c->dev, "%s() i2c wrm @0x%02x (len=%d) ",
  2284. + __func__, buf[0], len);
  2285. +
  2286. + ret = i2c_transfer(priv->i2c, &msg, 1);
  2287. + if (ret < 0) {
  2288. + dev_warn(&priv->i2c->dev,
  2289. + "%s: i2c wrm err(%i) @0x%02x (len=%d)\n",
  2290. + KBUILD_MODNAME, ret, buf[0], len);
  2291. + return ret;
  2292. + }
  2293. + return 0;
  2294. +}
  2295. +
  2296. +/* write one register */
  2297. +static int av201x_wr(struct av201x_priv *priv, u8 addr, u8 data)
  2298. +{
  2299. + u8 buf[] = { addr, data };
  2300. + return av201x_wrm(priv, buf, 2);
  2301. +}
  2302. +
  2303. +/* read multiple (continuous) registers starting at addr */
  2304. +static int av201x_rdm(struct av201x_priv *priv, u8 addr, u8 *buf, int len)
  2305. +{
  2306. + int ret;
  2307. + struct i2c_msg msg[] = {
  2308. + { .addr = priv->cfg->i2c_address, .flags = 0,
  2309. + .buf = &addr, .len = 1 },
  2310. + { .addr = priv->cfg->i2c_address, .flags = I2C_M_RD,
  2311. + .buf = buf, .len = len }
  2312. + };
  2313. +
  2314. + dev_dbg(&priv->i2c->dev, "%s() i2c rdm @0x%02x (len=%d)\n",
  2315. + __func__, addr, len);
  2316. +
  2317. + ret = i2c_transfer(priv->i2c, msg, 2);
  2318. + if (ret < 0) {
  2319. + dev_warn(&priv->i2c->dev,
  2320. + "%s: i2c rdm err(%i) @0x%02x (len=%d)\n",
  2321. + KBUILD_MODNAME, ret, addr, len);
  2322. + return ret;
  2323. + }
  2324. + return 0;
  2325. +}
  2326. +
  2327. +/* read one register */
  2328. +static int av201x_rd(struct av201x_priv *priv, u8 addr, u8 *data)
  2329. +{
  2330. + return av201x_rdm(priv, addr, data, 1);
  2331. +}
  2332. +
  2333. +/* read register, apply masks, write back */
  2334. +static int av201x_regmask(struct av201x_priv *priv,
  2335. + u8 reg, u8 setmask, u8 clrmask)
  2336. +{
  2337. + int ret;
  2338. + u8 b = 0;
  2339. + if (clrmask != 0xff) {
  2340. + ret = av201x_rd(priv, reg, &b);
  2341. + if (ret)
  2342. + return ret;
  2343. + b &= ~clrmask;
  2344. + }
  2345. + return av201x_wr(priv, reg, b | setmask);
  2346. +}
  2347. +
  2348. +static int av201x_wrtable(struct av201x_priv *priv,
  2349. + struct av201x_regtable *regtable, int len)
  2350. +{
  2351. + int ret, i;
  2352. +
  2353. + for (i = 0; i < len; i++) {
  2354. + ret = av201x_regmask(priv, regtable[i].addr,
  2355. + regtable[i].setmask, regtable[i].clrmask);
  2356. + if (ret)
  2357. + return ret;
  2358. + if (regtable[i].sleep)
  2359. + msleep(regtable[i].sleep);
  2360. + }
  2361. + return 0;
  2362. +}
  2363. +
  2364. +static void av201x_release(struct dvb_frontend *fe)
  2365. +{
  2366. + struct av201x_priv *priv = fe->tuner_priv;
  2367. + dev_dbg(&priv->i2c->dev, "%s()\n", __func__);
  2368. +
  2369. + kfree(fe->tuner_priv);
  2370. + fe->tuner_priv = NULL;
  2371. +}
  2372. +
  2373. +static int av201x_init(struct dvb_frontend *fe)
  2374. +{
  2375. + struct av201x_priv *priv = fe->tuner_priv;
  2376. + int ret;
  2377. + dev_dbg(&priv->i2c->dev, "%s()\n", __func__);
  2378. +
  2379. + ret = av201x_wrtable(priv, av201x_inittuner0,
  2380. + ARRAY_SIZE(av201x_inittuner0));
  2381. +
  2382. + switch (priv->cfg->id) {
  2383. + case ID_AV2011:
  2384. + ret |= av201x_wrtable(priv, av201x_inittuner1a,
  2385. + ARRAY_SIZE(av201x_inittuner1a));
  2386. + break;
  2387. + case ID_AV2012:
  2388. + default:
  2389. + ret |= av201x_wrtable(priv, av201x_inittuner1b,
  2390. + ARRAY_SIZE(av201x_inittuner1b));
  2391. + break;
  2392. + }
  2393. +
  2394. + ret |= av201x_wrtable(priv, av201x_inittuner2,
  2395. + ARRAY_SIZE(av201x_inittuner2));
  2396. +
  2397. + ret |= av201x_wr(priv, REG_TUNER_CTRL, 0x96);
  2398. +
  2399. + msleep(120);
  2400. +
  2401. + if (ret)
  2402. + dev_dbg(&priv->i2c->dev, "%s() failed\n", __func__);
  2403. + return ret;
  2404. +}
  2405. +
  2406. +static int av201x_sleep(struct dvb_frontend *fe)
  2407. +{
  2408. + struct av201x_priv *priv = fe->tuner_priv;
  2409. + int ret;
  2410. + dev_dbg(&priv->i2c->dev, "%s()\n", __func__);
  2411. +
  2412. + ret = av201x_regmask(priv, REG_TUNER_CTRL, AV201X_SLEEP, 0);
  2413. + if (ret)
  2414. + dev_dbg(&priv->i2c->dev, "%s() failed\n", __func__);
  2415. + return ret;
  2416. +}
  2417. +
  2418. +static int av201x_set_params(struct dvb_frontend *fe)
  2419. +{
  2420. + struct av201x_priv *priv = fe->tuner_priv;
  2421. + struct dtv_frontend_properties *c = &fe->dtv_property_cache;
  2422. + u32 n, bw, bf;
  2423. + u8 buf[5];
  2424. + int ret;
  2425. +
  2426. + dev_dbg(&priv->i2c->dev, "%s() delivery_system=%d frequency=%d " \
  2427. + "symbol_rate=%d\n", __func__,
  2428. + c->delivery_system, c->frequency, c->symbol_rate);
  2429. +
  2430. + /*
  2431. + ** PLL setup **
  2432. + RF = (pll_N * ref_freq) / pll_M
  2433. + pll_M = fixed 0x10000
  2434. + PLL output is divided by 2
  2435. + REG_FN = pll_M<24:0>
  2436. + */
  2437. + buf[0] = REG_FN;
  2438. + n = DIV_ROUND_CLOSEST(c->frequency, priv->cfg->xtal_freq);
  2439. + buf[1] = (n > 0xff) ? 0xff : (u8) n;
  2440. + n = DIV_ROUND_CLOSEST((c->frequency / 1000) << 17, priv->cfg->xtal_freq / 1000);
  2441. + buf[2] = (u8) (n >> 9);
  2442. + buf[3] = (u8) (n >> 1);
  2443. + buf[4] = (u8) (((n << 7) & 0x80) | 0x50);
  2444. + ret = av201x_wrm(priv, buf, 5);
  2445. + if (ret)
  2446. + goto exit;
  2447. +
  2448. + msleep(20);
  2449. +
  2450. + /* set bandwidth */
  2451. + bw = (c->symbol_rate / 1000) * 135/200;
  2452. + if (c->symbol_rate < 6500000)
  2453. + bw += 6000;
  2454. + bw += 2000;
  2455. + bw *= 108/100;
  2456. +
  2457. + /* check limits (4MHz < bw < 40MHz) */
  2458. + if (bw > 40000)
  2459. + bw = 40000;
  2460. + else if (bw < 4000)
  2461. + bw = 4000;
  2462. +
  2463. + /* bandwidth step = 211kHz */
  2464. + bf = DIV_ROUND_CLOSEST(bw * 127, 21100);
  2465. + ret = av201x_wr(priv, REG_BWFILTER, (u8) bf);
  2466. +
  2467. + /* enable fine tune agc */
  2468. + ret |= av201x_wr(priv, REG_FT_CTRL, AV201X_FT_EN | AV201X_FT_BLK);
  2469. +
  2470. + ret |= av201x_wr(priv, REG_TUNER_CTRL, 0x96);
  2471. + msleep(20);
  2472. +exit:
  2473. + if (ret)
  2474. + dev_dbg(&priv->i2c->dev, "%s() failed\n", __func__);
  2475. + return ret;
  2476. +}
  2477. +
  2478. +static int AV201x_agc [] = { 0, 82, 100, 116, 140, 162, 173, 187, 210, 223, 254, 255};
  2479. +static int AV201x_level_dBm_10[] = { 90, -50, -263, -361, -463, -563, -661, -761, -861, -891, -904, -910};
  2480. +
  2481. +static int av201x_get_rf_strength(struct dvb_frontend *fe, u16 *st)
  2482. +{
  2483. + struct av201x_priv *priv = fe->tuner_priv;
  2484. + struct dtv_frontend_properties *c = &fe->dtv_property_cache;
  2485. + int if_agc, index, table_length, slope, *x, *y;
  2486. +
  2487. + if_agc = *st;
  2488. + x = AV201x_agc;
  2489. + y = AV201x_level_dBm_10;
  2490. + table_length = sizeof(AV201x_agc)/sizeof(int);
  2491. +
  2492. +
  2493. + /* Finding in which segment the if_agc value is */
  2494. + for (index = 0; index < table_length; index ++)
  2495. + if (x[index] > if_agc ) break;
  2496. +
  2497. + /* Computing segment slope */
  2498. + slope = ((y[index]-y[index-1])*1000)/(x[index]-x[index-1]);
  2499. + /* Linear approximation of rssi value in segment (rssi values will be in 0.1dBm unit: '-523' means -52.3 dBm) */
  2500. + *st = 1000 + ((y[index-1] + ((if_agc - x[index-1])*slope + 500)/1000))/10;
  2501. +
  2502. + c->strength.len = 1;
  2503. + c->strength.stat[0].scale = FE_SCALE_DECIBEL;
  2504. + c->strength.stat[0].svalue = ((y[index-1] + ((if_agc - x[index-1])*slope + 500)/1000)) * 100;
  2505. +
  2506. + return 0;
  2507. +}
  2508. +
  2509. +
  2510. +static const struct dvb_tuner_ops av201x_tuner_ops = {
  2511. + .info = {
  2512. + .name = "Airoha Technology AV201x",
  2513. + .frequency_min_hz = 850 * MHz,
  2514. + .frequency_max_hz = 2300 * MHz,
  2515. + },
  2516. +
  2517. + .release = av201x_release,
  2518. +
  2519. + .init = av201x_init,
  2520. + .sleep = av201x_sleep,
  2521. + .set_params = av201x_set_params,
  2522. + .get_rf_strength = av201x_get_rf_strength,
  2523. +};
  2524. +
  2525. +struct dvb_frontend *av201x_attach(struct dvb_frontend *fe,
  2526. + struct av201x_config *cfg, struct i2c_adapter *i2c)
  2527. +{
  2528. + struct av201x_priv *priv = NULL;
  2529. +
  2530. + priv = kzalloc(sizeof(struct av201x_priv), GFP_KERNEL);
  2531. + if (priv == NULL) {
  2532. + dev_dbg(&i2c->dev, "%s() attach failed\n", __func__);
  2533. + return NULL;
  2534. + }
  2535. +
  2536. + priv->cfg = cfg;
  2537. + priv->i2c = i2c;
  2538. +
  2539. + dev_info(&priv->i2c->dev,
  2540. + "%s: Airoha Technology AV201x successfully attached\n",
  2541. + KBUILD_MODNAME);
  2542. +
  2543. + memcpy(&fe->ops.tuner_ops, &av201x_tuner_ops,
  2544. + sizeof(struct dvb_tuner_ops));
  2545. +
  2546. + fe->tuner_priv = priv;
  2547. + return fe;
  2548. +}
  2549. +EXPORT_SYMBOL(av201x_attach);
  2550. +
  2551. +MODULE_DESCRIPTION("Airoha Technology AV201x silicon tuner driver");
  2552. +MODULE_AUTHOR("Luis Alves <ljalvs@gmail.com>");
  2553. +MODULE_LICENSE("GPL");
  2554.  
  2555. diff -uraBN a/drivers/media/tuners/av201x.h b/drivers/media/tuners/av201x.h
  2556. --- a/drivers/media/tuners/av201x.h
  2557. +++ b/drivers/media/tuners/av201x.h
  2558. @@ -0,0 +1,55 @@
  2559. +/*
  2560. + * AV201x Airoha Technology silicon tuner driver
  2561. + *
  2562. + * Copyright (C) 2014 Luis Alves <ljalvs@gmail.com>
  2563. + *
  2564. + * This program is free software; you can redistribute it and/or modify
  2565. + * it under the terms of the GNU General Public License as published by
  2566. + * the Free Software Foundation; either version 2 of the License, or
  2567. + * (at your option) any later version.
  2568. + *
  2569. + * This program is distributed in the hope that it will be useful,
  2570. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  2571. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  2572. + * GNU General Public License for more details.
  2573. + *
  2574. + * You should have received a copy of the GNU General Public License along
  2575. + * with this program; if not, write to the Free Software Foundation, Inc.,
  2576. + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  2577. + */
  2578. +
  2579. +#ifndef AV201X_H
  2580. +#define AV201X_H
  2581. +
  2582. +#include <linux/kconfig.h>
  2583. +#include <media/dvb_frontend.h>
  2584. +
  2585. +typedef enum av201x_id {
  2586. + ID_AV2011,
  2587. + ID_AV2012,
  2588. + ID_AV2018,
  2589. +} av201x_id_t;
  2590. +
  2591. +struct av201x_config {
  2592. + /* tuner i2c address */
  2593. + u8 i2c_address;
  2594. + /* tuner type */
  2595. + av201x_id_t id;
  2596. +
  2597. + /* crystal freq in kHz */
  2598. + u32 xtal_freq;
  2599. +};
  2600. +
  2601. +#if IS_REACHABLE(CONFIG_MEDIA_TUNER_AV201X)
  2602. +extern struct dvb_frontend *av201x_attach(struct dvb_frontend *fe,
  2603. + struct av201x_config *cfg, struct i2c_adapter *i2c);
  2604. +#else
  2605. +static inline struct dvb_frontend *av201x_attach(struct dvb_frontend *fe,
  2606. + struct av201x_config *cfg, struct i2c_adapter *i2c)
  2607. +{
  2608. + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
  2609. + return NULL;
  2610. +}
  2611. +#endif
  2612. +
  2613. +#endif /* AV201X_H */
  2614.  
  2615. diff -uraBN a/drivers/media/tuners/av201x_priv.h b/drivers/media/tuners/av201x_priv.h
  2616. --- a/drivers/media/tuners/av201x_priv.h
  2617. +++ b/drivers/media/tuners/av201x_priv.h
  2618. @@ -0,0 +1,110 @@
  2619. +/*
  2620. + * AV201x Airoha Technology silicon tuner driver
  2621. + *
  2622. + * Copyright (C) 2014 Luis Alves <ljalvs@gmail.com>
  2623. + *
  2624. + * This program is free software; you can redistribute it and/or modify
  2625. + * it under the terms of the GNU General Public License as published by
  2626. + * the Free Software Foundation; either version 2 of the License, or
  2627. + * (at your option) any later version.
  2628. + *
  2629. + * This program is distributed in the hope that it will be useful,
  2630. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  2631. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  2632. + * GNU General Public License for more details.
  2633. + *
  2634. + * You should have received a copy of the GNU General Public License along
  2635. + * with this program; if not, write to the Free Software Foundation, Inc.,
  2636. + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  2637. + */
  2638. +
  2639. +#ifndef AV201X_PRIV_H
  2640. +#define AV201X_PRIV_H
  2641. +
  2642. +struct av201x_priv {
  2643. + struct av201x_config *cfg;
  2644. + struct i2c_adapter *i2c;
  2645. +};
  2646. +
  2647. +enum av201x_regs_addr {
  2648. + REG_FN = 0x00,
  2649. + REG_BWFILTER = 0x05,
  2650. + REG_TUNER_STAT = 0x0b,
  2651. + REG_TUNER_CTRL = 0x0c,
  2652. + REG_FT_CTRL = 0x25,
  2653. +};
  2654. +
  2655. +/* REG_TUNER_STAT */
  2656. +#define AV201X_PLLLOCK (1<<0)
  2657. +
  2658. +/* REG_TUNER_CTRL */
  2659. +#define AV201X_SLEEP (1<<5)
  2660. +#define AV201X_RFLP (1<<6)
  2661. +
  2662. +/* REG_FT_CTRL */
  2663. +#define AV201X_FT_EN (1<<1)
  2664. +#define AV201X_FT_BLK (1<<2)
  2665. +
  2666. +struct av201x_regtable {
  2667. + u8 addr;
  2668. + u8 setmask;
  2669. + u8 clrmask;
  2670. + int sleep;
  2671. +};
  2672. +
  2673. +static struct av201x_regtable av201x_inittuner0[] = {
  2674. + {0x00, 0x38, 0xff, 0},
  2675. + {0x01, 0x00, 0xff, 0},
  2676. + {0x02, 0x00, 0xff, 0},
  2677. + {0x03, 0x50, 0xff, 0},
  2678. + {0x04, 0x1f, 0xff, 0},
  2679. + {0x05, 0xa3, 0xff, 0},
  2680. + {0x06, 0xfd, 0xff, 0},
  2681. + {0x07, 0x58, 0xff, 0},
  2682. + {0x08, 0x36, 0xff, 0},
  2683. + {0x09, 0xc2, 0xff, 0},
  2684. + {0x0a, 0x88, 0xff, 0},
  2685. + {0x0b, 0xb4, 0xff, 20},
  2686. + {0x0d, 0x40, 0xff, 0},
  2687. +};
  2688. +
  2689. +static struct av201x_regtable av201x_inittuner1a[] = {
  2690. + {0x0e, 0x94, 0xff, 0},
  2691. + {0x0f, 0x9a, 0xff, 0},
  2692. +};
  2693. +
  2694. +static struct av201x_regtable av201x_inittuner1b[] = {
  2695. + {0x0e, 0x5b, 0xff, 0},
  2696. + {0x0f, 0x6a, 0xff, 0},
  2697. +};
  2698. +
  2699. +static struct av201x_regtable av201x_inittuner2[] = {
  2700. + {0x10, 0x66, 0xff, 0},
  2701. + {0x11, 0x40, 0xff, 0},
  2702. + {0x12, 0x80, 0xff, 0},
  2703. + {0x13, 0x2b, 0xff, 0},
  2704. + {0x14, 0x6a, 0xff, 0},
  2705. + {0x15, 0x50, 0xff, 0},
  2706. + {0x16, 0x91, 0xff, 0},
  2707. + {0x17, 0x27, 0xff, 0},
  2708. + {0x18, 0x8f, 0xff, 0},
  2709. + {0x19, 0xcc, 0xff, 0},
  2710. + {0x1a, 0x21, 0xff, 0},
  2711. + {0x1b, 0x10, 0xff, 0},
  2712. + {0x1c, 0x80, 0xff, 0},
  2713. + {0x1d, 0x02, 0xff, 0},
  2714. + {0x1e, 0xf5, 0xff, 0},
  2715. + {0x1f, 0x7f, 0xff, 0},
  2716. + {0x20, 0x4a, 0xff, 0},
  2717. + {0x21, 0x9b, 0xff, 0},
  2718. + {0x22, 0xe0, 0xff, 0},
  2719. + {0x23, 0xe0, 0xff, 0},
  2720. + {0x24, 0x36, 0xff, 0},
  2721. + {0x25, 0x00, 0xff, 0},
  2722. + {0x26, 0xab, 0xff, 0},
  2723. + {0x27, 0x97, 0xff, 0},
  2724. + {0x28, 0xc5, 0xff, 0},
  2725. + {0x29, 0xa8, 0xff, 20},
  2726. +};
  2727. +
  2728. +#endif /* AV201X_PRIV_H */
  2729.  
  2730. diff -uraBN a/drivers/media/tuners/Kconfig b/drivers/media/tuners/Kconfig
  2731. --- a/drivers/media/tuners/Kconfig
  2732. +++ b/drivers/media/tuners/Kconfig
  2733. @@ -297,4 +297,11 @@
  2734. This device is only used inside a SiP called together with a
  2735. demodulator for now.
  2736.  
  2737. +config MEDIA_TUNER_AV201X
  2738. + tristate "Airoha Technology AV201x silicon tuner"
  2739. + depends on MEDIA_SUPPORT && I2C
  2740. + default m if !MEDIA_SUBDRV_AUTOSELECT
  2741. + help
  2742. + Airoha Technology AV201x silicon tuner driver.
  2743. +
  2744. endmenu
  2745.  
  2746. diff -uraBN a/drivers/media/tuners/Makefile b/drivers/media/tuners/Makefile
  2747. --- a/drivers/media/tuners/Makefile
  2748. +++ b/drivers/media/tuners/Makefile
  2749. @@ -46,3 +46,4 @@
  2750. obj-$(CONFIG_MEDIA_TUNER_XC2028) += xc2028.o
  2751. obj-$(CONFIG_MEDIA_TUNER_XC4000) += xc4000.o
  2752. obj-$(CONFIG_MEDIA_TUNER_XC5000) += xc5000.o
  2753. +obj-$(CONFIG_MEDIA_TUNER_AV201X) += av201x.o
  2754.  
  2755. diff -uraBN a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c
  2756. --- a/drivers/media/tuners/si2157.c
  2757. +++ b/drivers/media/tuners/si2157.c
  2758. @@ -1,4 +1,4 @@
  2759. -// SPDX-License-Identifier: GPL-2.0-or-later
  2760. +// // SPDX-License-Identifier: GPL-2.0-or-later
  2761. /*
  2762. * Silicon Labs Si2146/2147/2148/2157/2158 silicon tuner driver
  2763. *
  2764. @@ -35,7 +35,7 @@
  2765.  
  2766. if (cmd->rlen) {
  2767. /* wait cmd execution terminate */
  2768. - #define TIMEOUT 80
  2769. + #define TIMEOUT 500
  2770. timeout = jiffies + msecs_to_jiffies(TIMEOUT);
  2771. while (!time_after(jiffies, timeout)) {
  2772. ret = i2c_master_recv(client, cmd->args, cmd->rlen);
  2773. @@ -188,9 +188,9 @@
  2774. /* Update the part id based on device's report */
  2775. dev->part_id = part_id;
  2776.  
  2777. - dev_info(&client->dev,
  2778. - "found a 'Silicon Labs Si21%d-%c%c%c ROM 0x%02x'\n",
  2779. - part_id, cmd.args[1], cmd.args[3], cmd.args[4], rom_id);
  2780. + //dev_info(&client->dev,
  2781. + // "found a 'Silicon Labs Si21%d-%c%c%c ROM 0x%02x'\n",
  2782. + // part_id, cmd.args[1], cmd.args[3], cmd.args[4], rom_id);
  2783.  
  2784. if (fw_name)
  2785. ret = si2157_load_firmware(fe, fw_name);
  2786. @@ -223,6 +223,9 @@
  2787. int ret;
  2788.  
  2789. dev_dbg(&client->dev, "\n");
  2790. +
  2791. + if (dev->active)
  2792. + return 0;
  2793.  
  2794. /* Try to get Xtal trim property, to verify tuner still running */
  2795. memcpy(cmd.args, "\x15\x00\x02\x04", 4);
  2796. @@ -285,8 +288,8 @@
  2797. if (ret)
  2798. goto err;
  2799.  
  2800. - dev_info(&client->dev, "firmware version: %c.%c.%d\n",
  2801. - cmd.args[6], cmd.args[7], cmd.args[8]);
  2802. + //dev_info(&client->dev, "firmware version: %c.%c.%d\n",
  2803. + // cmd.args[6], cmd.args[7], cmd.args[8]);
  2804.  
  2805. /* enable tuner status flags */
  2806. memcpy(cmd.args, "\x14\x00\x01\x05\x01\x00", 6);
  2807. @@ -478,30 +481,27 @@
  2808.  
  2809. switch (c->delivery_system) {
  2810. case SYS_ATSC:
  2811. - delivery_system = 0x00;
  2812. - if_frequency = 3250000;
  2813. - break;
  2814. - case SYS_DVBC_ANNEX_B:
  2815. - delivery_system = 0x10;
  2816. - if_frequency = 4000000;
  2817. - break;
  2818. + delivery_system = 0x00;
  2819. + if_frequency = 3250000;
  2820. + break;
  2821. case SYS_DVBT:
  2822. case SYS_DVBT2: /* it seems DVB-T and DVB-T2 both are 0x20 here */
  2823. - delivery_system = 0x20;
  2824. - break;
  2825. + delivery_system = 0x20;
  2826. + break;
  2827. case SYS_DVBC_ANNEX_A:
  2828. + case SYS_DVBC_ANNEX_B:
  2829. case SYS_DVBC_ANNEX_C:
  2830. - delivery_system = 0x30;
  2831. - break;
  2832. + delivery_system = 0x30;
  2833. + break;
  2834. case SYS_ISDBT:
  2835. - delivery_system = 0x40;
  2836. - break;
  2837. + delivery_system = 0x40;
  2838. + break;
  2839. case SYS_DTMB:
  2840. - delivery_system = 0x60;
  2841. - break;
  2842. + delivery_system = 0x60;
  2843. + break;
  2844. default:
  2845. - ret = -EINVAL;
  2846. - goto err;
  2847. + ret = -EINVAL;
  2848. + goto err;
  2849. }
  2850.  
  2851. memcpy(cmd.args, "\x14\x00\x03\x07\x00\x00", 6);
  2852. @@ -525,6 +525,16 @@
  2853. ret = si2157_cmd_execute(client, &cmd);
  2854. if (ret)
  2855. goto err;
  2856. +
  2857. +#if 0 /* set LIF out amp */
  2858. + memcpy(cmd.args, "\x14\x00\x07\x07\x94\x20", 6);
  2859. + cmd.args[5] = delivery_system == 0x30 ? 0x2B : 0x20;
  2860. + cmd.wlen = 6;
  2861. + cmd.rlen = 4;
  2862. + ret = si2157_cmd_execute(client, &cmd);
  2863. + if (ret)
  2864. + goto err;
  2865. +#endif
  2866.  
  2867. /* set digital if frequency if needed */
  2868. if (if_frequency != dev->if_frequency) {
  2869. @@ -865,19 +875,24 @@
  2870. if (ret)
  2871. goto err;
  2872.  
  2873. + c->strength.len = 2;
  2874. c->strength.stat[0].scale = FE_SCALE_DECIBEL;
  2875. - c->strength.stat[0].svalue = (s8) cmd.args[3] * 1000;
  2876. + c->strength.stat[0].svalue = (s8)cmd.args[3] * 1000;
  2877. +
  2878. + c->strength.stat[1].scale = FE_SCALE_RELATIVE;
  2879. + c->strength.stat[1].uvalue = (100 + (s8)cmd.args[3]) * 656;
  2880.  
  2881. schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(2000));
  2882. return;
  2883. err:
  2884. + c->strength.len = 1;
  2885. c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
  2886. dev_dbg(&client->dev, "failed=%d\n", ret);
  2887. }
  2888.  
  2889. -static int si2157_probe(struct i2c_client *client,
  2890. - const struct i2c_device_id *id)
  2891. -{
  2892. +static int si2157_probe(struct i2c_client *client)
  2893. +{
  2894. + const struct i2c_device_id *id = i2c_client_get_device_id(client);
  2895. struct si2157_config *cfg = client->dev.platform_data;
  2896. struct dvb_frontend *fe = cfg->fe;
  2897. struct si2157_dev *dev;
  2898. @@ -990,7 +1005,7 @@
  2899. .name = "si2157",
  2900. .suppress_bind_attrs = true,
  2901. },
  2902. - .probe = si2157_probe,
  2903. + .probe_new = si2157_probe,
  2904. .remove = si2157_remove,
  2905. .id_table = si2157_id_table,
  2906. };
  2907. @@ -1000,6 +1015,7 @@
  2908. MODULE_DESCRIPTION("Silicon Labs Si2141/Si2146/2147/2148/2157/2158 silicon tuner driver");
  2909. MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
  2910. MODULE_LICENSE("GPL");
  2911. +MODULE_FIRMWARE(SI2157_A30_FIRMWARE);
  2912. MODULE_FIRMWARE(SI2158_A20_FIRMWARE);
  2913. MODULE_FIRMWARE(SI2141_A10_FIRMWARE);
  2914. MODULE_FIRMWARE(SI2157_A30_FIRMWARE);
  2915.  
  2916. diff -uraBN a/drivers/media/usb/dvb-usb/dvb-usb-dvb.c b/drivers/media/usb/dvb-usb/dvb-usb-dvb.c
  2917. --- a/drivers/media/usb/dvb-usb/dvb-usb-dvb.c
  2918. +++ b/drivers/media/usb/dvb-usb/dvb-usb-dvb.c
  2919. @@ -9,6 +9,8 @@
  2920. */
  2921. #include "dvb-usb-common.h"
  2922. #include <media/media-device.h>
  2923. +
  2924. +#undef CONFIG_MEDIA_CONTROLLER_DVB
  2925.  
  2926. /* does the complete input transfer handling */
  2927. static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
  2928. @@ -317,6 +319,22 @@
  2929. return 0;
  2930. }
  2931.  
  2932. + if(adap->fe_adap[i].fe2!=NULL){
  2933. + if (dvb_register_frontend(&adap->dvb_adap, adap->fe_adap[i].fe2)) {
  2934. + err("Frontend %d registration failed.", i);
  2935. + dvb_frontend_detach(adap->fe_adap[i].fe2);
  2936. + adap->fe_adap[i].fe2 = NULL;
  2937. + /* In error case, do not try register more FEs,
  2938. + * still leaving already registered FEs alive. */
  2939. + if (i == 0)
  2940. + return -ENODEV;
  2941. + else
  2942. + return 0;
  2943. + }
  2944. +
  2945. +
  2946. + }
  2947. +
  2948. /* only attach the tuner if the demod is there */
  2949. if (adap->props.fe[i].tuner_attach != NULL)
  2950. adap->props.fe[i].tuner_attach(adap);
  2951. @@ -343,6 +361,10 @@
  2952. dvb_unregister_frontend(adap->fe_adap[i].fe);
  2953. dvb_frontend_detach(adap->fe_adap[i].fe);
  2954. }
  2955. + if (adap->fe_adap[i].fe2 != NULL) {
  2956. + dvb_unregister_frontend(adap->fe_adap[i].fe2);
  2957. + dvb_frontend_detach(adap->fe_adap[i].fe2);
  2958. + }
  2959. }
  2960. adap->num_frontends_initialized = 0;
  2961.  
  2962.  
  2963. diff -uraBN a/drivers/media/usb/dvb-usb/dvb-usb.h b/drivers/media/usb/dvb-usb/dvb-usb.h
  2964. --- a/drivers/media/usb/dvb-usb/dvb-usb.h
  2965. +++ b/drivers/media/usb/dvb-usb/dvb-usb.h
  2966. @@ -372,7 +372,8 @@
  2967. */
  2968. struct dvb_usb_fe_adapter {
  2969. struct dvb_frontend *fe;
  2970. -
  2971. + struct dvb_frontend *fe2;
  2972. + struct dvb_frontend _fe2;
  2973. int (*fe_init) (struct dvb_frontend *);
  2974. int (*fe_sleep) (struct dvb_frontend *);
  2975.  
  2976.  
  2977. diff -uraBN a/drivers/media/usb/dvb-usb/Kconfig b/drivers/media/usb/dvb-usb/Kconfig
  2978. --- a/drivers/media/usb/dvb-usb/Kconfig
  2979. +++ b/drivers/media/usb/dvb-usb/Kconfig
  2980. @@ -346,4 +346,13 @@
  2981.  
  2982. DVB-T USB2.0 receivers.
  2983.  
  2984. +config DVB_USB_TBS5580
  2985. + tristate "Turbosight TBS5580 CI support"
  2986. + depends on DVB_USB
  2987. + select DVB_SI2183 if MEDIA_SUBDRV_AUTOSELECT
  2988. + select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT
  2989. + select MEDIA_TUNER_AV201X if MEDIA_SUBDRV_AUTOSELECT
  2990. + help
  2991. + Say Y here to support the Turbosight TBS5580 CI USB2 DVB-T/T2/C/C2/S/S2/S2x device
  2992. +
  2993. endif
  2994.  
  2995. diff -uraBN a/drivers/media/usb/dvb-usb/Makefile b/drivers/media/usb/dvb-usb/Makefile
  2996. --- a/drivers/media/usb/dvb-usb/Makefile
  2997. +++ b/drivers/media/usb/dvb-usb/Makefile
  2998. @@ -80,6 +80,9 @@
  2999. dvb-usb-technisat-usb2-objs := technisat-usb2.o
  3000. obj-$(CONFIG_DVB_USB_TECHNISAT_USB2) += dvb-usb-technisat-usb2.o
  3001.  
  3002. +dvb-usb-tbs5580-objs = tbs5580.o
  3003. +obj-$(CONFIG_DVB_USB_TBS5580) += dvb-usb-tbs5580.o
  3004. +
  3005. ccflags-y += -I$(srctree)/drivers/media/dvb-frontends/
  3006. # due to tuner-xc3028
  3007. ccflags-y += -I$(srctree)/drivers/media/tuners
  3008.  
  3009. diff -uraBN a/drivers/media/usb/dvb-usb/tbs5580.c b/drivers/media/usb/dvb-usb/tbs5580.c
  3010. --- a/drivers/media/usb/dvb-usb/tbs5580.c
  3011. +++ b/drivers/media/usb/dvb-usb/tbs5580.c
  3012. @@ -0,0 +1,793 @@
  3013. +/*
  3014. + * TurboSight TBS 5580se driver
  3015. + *
  3016. + * Copyright (c) 2017 Davin zhang <smiledavin@gmail.com>
  3017. + *
  3018. + * This program is free software; you can redistribute it and/or modify it
  3019. + * under the terms of the GNU General Public License as published by the
  3020. + * Free Software Foundation, version 2.
  3021. + *
  3022. + */
  3023. +
  3024. +#include <linux/version.h>
  3025. +#include "tbs5580.h"
  3026. +#include "si2183.h"
  3027. +#include "si2157.h"
  3028. +#include "av201x.h"
  3029. +#include <media/dvb_ca_en50221.h>
  3030. +
  3031. +#define TBS5580_READ_MSG 0
  3032. +#define TBS5580_WRITE_MSG 1
  3033. +
  3034. +#define TBS5580_VOLTAGE_CTRL (0x1800)
  3035. +
  3036. +
  3037. +struct tbs5580_state {
  3038. + struct i2c_client *i2c_client_demod;
  3039. + struct i2c_client *i2c_client_tuner;
  3040. + struct dvb_ca_en50221 ca;
  3041. + struct mutex ca_mutex;
  3042. +};
  3043. +
  3044. +static struct av201x_config tbs5580_av201x_cfg = {
  3045. + .i2c_address = 0x62,
  3046. + .id = ID_AV2018,
  3047. + .xtal_freq = 27000,
  3048. +};
  3049. +
  3050. +/* debug */
  3051. +static int dvb_usb_tbs5580_debug;
  3052. +module_param_named(debug, dvb_usb_tbs5580_debug, int, 0644);
  3053. +MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))."
  3054. + DVB_USB_DEBUG_STATUS);
  3055. +
  3056. +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
  3057. +
  3058. +static int tbs5580_op_rw(struct usb_device *dev, u8 request, u16 value,
  3059. + u16 index, u8 * data, u16 len, int flags)
  3060. +{
  3061. + int ret;
  3062. + void *u8buf;
  3063. +
  3064. + unsigned int pipe = (flags == TBS5580_READ_MSG) ?
  3065. + usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0);
  3066. + u8 request_type = (flags == TBS5580_READ_MSG) ? USB_DIR_IN :
  3067. + USB_DIR_OUT;
  3068. + u8buf = kmalloc(len, GFP_KERNEL);
  3069. + if (!u8buf)
  3070. + return -ENOMEM;
  3071. +
  3072. + if (flags == TBS5580_WRITE_MSG)
  3073. + memcpy(u8buf, data, len);
  3074. + ret = usb_control_msg(dev, pipe, request, request_type |
  3075. + USB_TYPE_VENDOR, value, index , u8buf, len, 2000);
  3076. +
  3077. + if (flags == TBS5580_READ_MSG)
  3078. + memcpy(data, u8buf, len);
  3079. + kfree(u8buf);
  3080. + return ret;
  3081. +}
  3082. +
  3083. +static int tbs5580_read_attribute_mem(struct dvb_ca_en50221 *ca,
  3084. + int slot, int address)
  3085. +{
  3086. + struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
  3087. + struct tbs5580_state *state = (struct tbs5580_state *)d->priv;
  3088. + u8 buf[4], rbuf[3];
  3089. + int ret;
  3090. +
  3091. + if (0 != slot)
  3092. + return -EINVAL;
  3093. +
  3094. + buf[0] = 1;
  3095. + buf[1] = 0;
  3096. + buf[2] = (address >> 8) & 0x0f;
  3097. + buf[3] = address;
  3098. +
  3099. + //msleep(10);
  3100. +
  3101. + mutex_lock(&state->ca_mutex);
  3102. +
  3103. + ret = tbs5580_op_rw(d->udev, 0xa4, 0, 0,
  3104. + buf, 4, TBS5580_WRITE_MSG);
  3105. +
  3106. + //msleep(1);
  3107. +
  3108. + ret = tbs5580_op_rw(d->udev, 0xa5, 0, 0,
  3109. + rbuf, 1, TBS5580_READ_MSG);
  3110. +
  3111. + mutex_unlock(&state->ca_mutex);
  3112. +
  3113. + if (ret < 0)
  3114. + return ret;
  3115. +
  3116. + return rbuf[0];
  3117. +}
  3118. +
  3119. +static int tbs5580_write_attribute_mem(struct dvb_ca_en50221 *ca,
  3120. + int slot, int address, u8 value)
  3121. +{
  3122. + struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
  3123. + struct tbs5580_state *state = (struct tbs5580_state *)d->priv;
  3124. + u8 buf[5];//, rbuf[1];
  3125. + int ret;
  3126. +
  3127. + if (0 != slot)
  3128. + return -EINVAL;
  3129. +
  3130. + buf[0] = 1;
  3131. + buf[1] = 0;
  3132. + buf[2] = (address >> 8) & 0x0f;
  3133. + buf[3] = address;
  3134. + buf[4] = value;
  3135. +
  3136. + mutex_lock(&state->ca_mutex);
  3137. +
  3138. + ret = tbs5580_op_rw(d->udev, 0xa2, 0, 0,
  3139. + buf, 5, TBS5580_WRITE_MSG);
  3140. +
  3141. + //msleep(1);
  3142. +
  3143. + //ret = tbs5580_op_rw(d->udev, 0xa5, 0, 0,
  3144. + // rbuf, 1, TBS5580_READ_MSG);
  3145. +
  3146. + mutex_unlock(&state->ca_mutex);
  3147. +
  3148. + if (ret < 0)
  3149. + return ret;
  3150. +
  3151. + return 0;
  3152. +}
  3153. +
  3154. +static int tbs5580_read_cam_control(struct dvb_ca_en50221 *ca, int slot,
  3155. + u8 address)
  3156. +{
  3157. + struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
  3158. + struct tbs5580_state *state = (struct tbs5580_state *)d->priv;
  3159. + u8 buf[4], rbuf[1];
  3160. + int ret;
  3161. +
  3162. + if (0 != slot)
  3163. + return -EINVAL;
  3164. +
  3165. + buf[0] = 1;
  3166. + buf[1] = 1;
  3167. + buf[2] = (address >> 8) & 0x0f;
  3168. + buf[3] = address;
  3169. +
  3170. + mutex_lock(&state->ca_mutex);
  3171. +
  3172. + ret = tbs5580_op_rw(d->udev, 0xa4, 0, 0,
  3173. + buf, 4, TBS5580_WRITE_MSG);
  3174. +
  3175. + //msleep(10);
  3176. +
  3177. + ret = tbs5580_op_rw(d->udev, 0xa5, 0, 0,
  3178. + rbuf, 1, TBS5580_READ_MSG);
  3179. +
  3180. + mutex_unlock(&state->ca_mutex);
  3181. +
  3182. + if (ret < 0)
  3183. + return ret;
  3184. +
  3185. + return rbuf[0];
  3186. +}
  3187. +
  3188. +static int tbs5580_write_cam_control(struct dvb_ca_en50221 *ca, int slot,
  3189. + u8 address, u8 value)
  3190. +{
  3191. + struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
  3192. + struct tbs5580_state *state = (struct tbs5580_state *)d->priv;
  3193. + u8 buf[5];//, rbuf[1];
  3194. + int ret;
  3195. +
  3196. + if (0 != slot)
  3197. + return -EINVAL;
  3198. +
  3199. + buf[0] = 1;
  3200. + buf[1] = 1;
  3201. + buf[2] = (address >> 8) & 0x0f;
  3202. + buf[3] = address;
  3203. + buf[4] = value;
  3204. +
  3205. + mutex_lock(&state->ca_mutex);
  3206. +
  3207. + ret = tbs5580_op_rw(d->udev, 0xa2, 0, 0,
  3208. + buf, 5, TBS5580_WRITE_MSG);
  3209. +
  3210. + //msleep(1);
  3211. +
  3212. + //ret = tbs5580_op_rw(d->udev, 0xa5, 0, 0,
  3213. + // rbuf, 1, TBS5580_READ_MSG);
  3214. +
  3215. + mutex_unlock(&state->ca_mutex);
  3216. +
  3217. + if (ret < 0)
  3218. + return ret;
  3219. +
  3220. + return 0;
  3221. +}
  3222. +
  3223. +static int tbs5580_set_video_port(struct dvb_ca_en50221 *ca,
  3224. + int slot, int enable)
  3225. +{
  3226. + struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
  3227. + struct tbs5580_state *state = (struct tbs5580_state *)d->priv;
  3228. + u8 buf[2];
  3229. + int ret;
  3230. +
  3231. + if (0 != slot)
  3232. + return -EINVAL;
  3233. +
  3234. + buf[0] = 2;
  3235. + buf[1] = enable;
  3236. +
  3237. + mutex_lock(&state->ca_mutex);
  3238. +
  3239. + ret = tbs5580_op_rw(d->udev, 0xa6, 0, 0,
  3240. + buf, 2, TBS5580_WRITE_MSG);
  3241. +
  3242. + mutex_unlock(&state->ca_mutex);
  3243. +
  3244. + if (ret < 0)
  3245. + return ret;
  3246. +
  3247. + if (enable != buf[1]) {
  3248. + err("CI not %sabled.", enable ? "en" : "dis");
  3249. + return -EIO;
  3250. + }
  3251. +
  3252. + info("CI %sabled.", enable ? "en" : "dis");
  3253. + return 0;
  3254. +}
  3255. +
  3256. +static int tbs5580_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
  3257. +{
  3258. + return tbs5580_set_video_port(ca, slot, /* enable */ 0);
  3259. +}
  3260. +
  3261. +static int tbs5580_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
  3262. +{
  3263. + return tbs5580_set_video_port(ca, slot, /* enable */ 1);
  3264. +}
  3265. +
  3266. +static int tbs5580_slot_reset(struct dvb_ca_en50221 *ca, int slot)
  3267. +{
  3268. + struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
  3269. + struct tbs5580_state *state = (struct tbs5580_state *)d->priv;
  3270. + u8 buf[2];
  3271. + int ret;
  3272. +
  3273. + if (0 != slot) {
  3274. + return -EINVAL;
  3275. + }
  3276. +
  3277. + buf[0] = 1;
  3278. + buf[1] = 0;
  3279. +
  3280. + mutex_lock (&state->ca_mutex);
  3281. +
  3282. + ret = tbs5580_op_rw(d->udev, 0xa6, 0, 0,
  3283. + buf, 2, TBS5580_WRITE_MSG);
  3284. +
  3285. + msleep (5);
  3286. +
  3287. + buf[1] = 1;
  3288. +
  3289. + ret = tbs5580_op_rw(d->udev, 0xa6, 0, 0,
  3290. + buf, 2, TBS5580_WRITE_MSG);
  3291. +
  3292. + msleep (1400);
  3293. +
  3294. + mutex_unlock (&state->ca_mutex);
  3295. +
  3296. + if (ret < 0)
  3297. + return ret;
  3298. +
  3299. + return 0;
  3300. +}
  3301. +
  3302. +static int tbs5580_poll_slot_status(struct dvb_ca_en50221 *ca,
  3303. + int slot, int open)
  3304. +{
  3305. + struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
  3306. + struct tbs5580_state *state = (struct tbs5580_state *)d->priv;
  3307. + u8 buf[3];
  3308. +
  3309. + if (0 != slot)
  3310. + return -EINVAL;
  3311. +
  3312. + mutex_lock(&state->ca_mutex);
  3313. +
  3314. + tbs5580_op_rw(d->udev, 0xa8, 0, 0,
  3315. + buf, 3, TBS5580_READ_MSG);
  3316. +
  3317. + mutex_unlock(&state->ca_mutex);
  3318. +
  3319. + if ((1 == buf[2]) && (1 == buf[1]) && (0xa9 == buf[0])) {
  3320. + return (DVB_CA_EN50221_POLL_CAM_PRESENT |
  3321. + DVB_CA_EN50221_POLL_CAM_READY);
  3322. + } else {
  3323. + return 0;
  3324. + }
  3325. +}
  3326. +
  3327. +static void tbs5580_uninit(struct dvb_usb_device *d)
  3328. +{
  3329. + struct tbs5580_state *state;
  3330. +
  3331. + if (NULL == d)
  3332. + return;
  3333. +
  3334. + state = (struct tbs5580_state *)d->priv;
  3335. + if (NULL == state)
  3336. + return;
  3337. +
  3338. + if (NULL == state->ca.data)
  3339. + return;
  3340. +
  3341. + /* Error ignored. */
  3342. + tbs5580_set_video_port(&state->ca, /* slot */ 0, /* enable */ 0);
  3343. +
  3344. + dvb_ca_en50221_release(&state->ca);
  3345. +
  3346. + memset(&state->ca, 0, sizeof(state->ca));
  3347. +}
  3348. +
  3349. +static int tbs5580_init(struct dvb_usb_adapter *a)
  3350. +{
  3351. +
  3352. + struct dvb_usb_device *d = a->dev;
  3353. + struct tbs5580_state *state = (struct tbs5580_state *)d->priv;
  3354. + int ret;
  3355. +
  3356. + state->ca.owner = THIS_MODULE;
  3357. + state->ca.read_attribute_mem = tbs5580_read_attribute_mem;
  3358. + state->ca.write_attribute_mem = tbs5580_write_attribute_mem;
  3359. + state->ca.read_cam_control = tbs5580_read_cam_control;
  3360. + state->ca.write_cam_control = tbs5580_write_cam_control;
  3361. + state->ca.slot_reset = tbs5580_slot_reset;
  3362. + state->ca.slot_shutdown = tbs5580_slot_shutdown;
  3363. + state->ca.slot_ts_enable = tbs5580_slot_ts_enable;
  3364. + state->ca.poll_slot_status = tbs5580_poll_slot_status;
  3365. + state->ca.data = d;
  3366. +
  3367. + ret = dvb_ca_en50221_init (&a->dvb_adap, &state->ca,
  3368. + /* flags */ 0, /* n_slots */ 1);
  3369. +
  3370. + if (0 != ret) {
  3371. + err ("Cannot initialize CI: Error %d.", ret);
  3372. + memset (&state->ca, 0, sizeof (state->ca));
  3373. + return ret;
  3374. + }
  3375. +
  3376. + info ("CI initialized.");
  3377. +
  3378. + ret = tbs5580_poll_slot_status(&state->ca, 0, 0);
  3379. + if (0 == ret)
  3380. + tbs5580_set_video_port(&state->ca, /* slot */ 0, /* enable */ 0);
  3381. +
  3382. + return 0;
  3383. +}
  3384. +
  3385. +/* I2C */
  3386. +static int tbs5580_i2c_transfer(struct i2c_adapter *adap,
  3387. + struct i2c_msg msg[], int num)
  3388. +{
  3389. + struct dvb_usb_device *d = i2c_get_adapdata(adap);
  3390. + struct tbs5580_state *state = (struct tbs5580_state *)d->priv;
  3391. + int i = 0;
  3392. + u8 buf6[20];
  3393. + u8 inbuf[20];
  3394. +
  3395. + if (!d)
  3396. + return -ENODEV;
  3397. + mutex_lock(&state->ca_mutex);
  3398. + if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
  3399. + return -EAGAIN;
  3400. +
  3401. + switch (num) {
  3402. + case 2:
  3403. + buf6[0]=msg[1].len;//lenth
  3404. + buf6[1]=msg[0].addr<<1;//demod addr
  3405. + //register
  3406. + buf6[2] = msg[0].buf[0];
  3407. +
  3408. + tbs5580_op_rw(d->udev, 0x90, 0, 0,
  3409. + buf6, 3, TBS5580_WRITE_MSG);
  3410. + //msleep(5);
  3411. + tbs5580_op_rw(d->udev, 0x91, 0, 0,
  3412. + inbuf, buf6[0], TBS5580_READ_MSG);
  3413. + memcpy(msg[1].buf, inbuf, msg[1].len);
  3414. + break;
  3415. + case 1:
  3416. + switch (msg[0].addr) {
  3417. + case 0x67:
  3418. + case 0x62:
  3419. + case 0x61:
  3420. + if (msg[0].flags == 0) {
  3421. + buf6[0] = msg[0].len+1;//lenth
  3422. + buf6[1] = msg[0].addr<<1;//addr
  3423. + for(i=0;i<msg[0].len;i++) {
  3424. + buf6[2+i] = msg[0].buf[i];//register
  3425. + }
  3426. + tbs5580_op_rw(d->udev, 0x80, 0, 0,
  3427. + buf6, msg[0].len+2, TBS5580_WRITE_MSG);
  3428. + } else {
  3429. + buf6[0] = msg[0].len;//length
  3430. + buf6[1] = (msg[0].addr<<1) | 0x01;//addr
  3431. + tbs5580_op_rw(d->udev, 0x93, 0, 0,
  3432. + buf6, 2, TBS5580_WRITE_MSG);
  3433. + //msleep(5);
  3434. + tbs5580_op_rw(d->udev, 0x91, 0, 0,
  3435. + inbuf, buf6[0], TBS5580_READ_MSG);
  3436. + memcpy(msg[0].buf, inbuf, msg[0].len);
  3437. + }
  3438. + //msleep(3);
  3439. + break;
  3440. + case (TBS5580_VOLTAGE_CTRL):
  3441. + buf6[0] = 3;
  3442. + buf6[1] = msg[0].buf[0];
  3443. + tbs5580_op_rw(d->udev, 0x8a, 0, 0,
  3444. + buf6, 2, TBS5580_WRITE_MSG);
  3445. + break;
  3446. + }
  3447. +
  3448. + break;
  3449. + }
  3450. +
  3451. + mutex_unlock(&d->i2c_mutex);
  3452. + mutex_unlock(&state->ca_mutex);
  3453. + return num;
  3454. +}
  3455. +
  3456. +static u32 tbs5580_i2c_func(struct i2c_adapter *adapter)
  3457. +{
  3458. + return I2C_FUNC_I2C;
  3459. +}
  3460. +
  3461. +static struct i2c_algorithm tbs5580_i2c_algo = {
  3462. + .master_xfer = tbs5580_i2c_transfer,
  3463. + .functionality = tbs5580_i2c_func,
  3464. +};
  3465. +
  3466. +static int tbs5580_set_voltage(struct dvb_frontend *fe,
  3467. + enum fe_sec_voltage voltage)
  3468. +{
  3469. + static u8 command_13v[1] = {0x00};
  3470. + static u8 command_18v[1] = {0x01};
  3471. + struct i2c_msg msg[] = {
  3472. + {.addr = TBS5580_VOLTAGE_CTRL, .flags = 0,
  3473. + .buf = command_13v, .len = 1},
  3474. + };
  3475. +
  3476. + struct dvb_usb_adapter *udev_adap =
  3477. + (struct dvb_usb_adapter *)(fe->dvb->priv);
  3478. + if (voltage == SEC_VOLTAGE_18)
  3479. + msg[0].buf = command_18v;
  3480. +
  3481. +
  3482. + i2c_transfer(&udev_adap->dev->i2c_adap, msg, 1);
  3483. +
  3484. + return 0;
  3485. +}
  3486. +
  3487. +static int tbs5580_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
  3488. +{
  3489. + int i,ret;
  3490. + u8 ibuf[3] = {0, 0,0};
  3491. + u8 eeprom[256], eepromline[16];
  3492. +
  3493. + for (i = 0; i < 256; i++) {
  3494. + ibuf[0]=1;//lenth
  3495. + ibuf[1]=0xa0;//eeprom addr
  3496. + ibuf[2]=i;//register
  3497. + ret = tbs5580_op_rw(d->udev, 0x90, 0, 0,
  3498. + ibuf, 3, TBS5580_WRITE_MSG);
  3499. + ret = tbs5580_op_rw(d->udev, 0x91, 0, 0,
  3500. + ibuf, 1, TBS5580_READ_MSG);
  3501. + if (ret < 0) {
  3502. + err("read eeprom failed.");
  3503. + return -1;
  3504. + } else {
  3505. + eepromline[i%16] = ibuf[0];
  3506. + eeprom[i] = ibuf[0];
  3507. + }
  3508. +
  3509. + if ((i % 16) == 15) {
  3510. + deb_xfer("%02x: ", i - 15);
  3511. + debug_dump(eepromline, 16, deb_xfer);
  3512. + }
  3513. + }
  3514. + memcpy(mac, eeprom + 16, 6);
  3515. + return 0;
  3516. +};
  3517. +
  3518. +static struct dvb_usb_device_properties tbs5580_properties;
  3519. +
  3520. +static int tbs5580_frontend_attach(struct dvb_usb_adapter *adap)
  3521. +{
  3522. + struct dvb_usb_device *d = adap->dev;
  3523. + struct tbs5580_state *st = d->priv;
  3524. + struct i2c_adapter *adapter;
  3525. + struct i2c_client *client_demod;
  3526. + struct i2c_client *client_tuner;
  3527. + struct i2c_board_info info;
  3528. + struct si2183_config si2183_config;
  3529. + struct si2157_config si2157_config;
  3530. + u8 buf[20];
  3531. +
  3532. + mutex_init(&st->ca_mutex);
  3533. + /* attach frontend */
  3534. + memset(&si2183_config,0,sizeof(si2183_config));
  3535. + si2183_config.i2c_adapter = &adapter;
  3536. + si2183_config.fe = &adap->fe_adap[0].fe;
  3537. + si2183_config.ts_mode = SI2183_TS_PARALLEL;
  3538. + si2183_config.ts_clock_gapped = true;
  3539. + si2183_config.rf_in = 0;
  3540. + si2183_config.RF_switch = NULL;
  3541. + si2183_config.agc_mode = 0x5 ;
  3542. + memset(&info, 0, sizeof(struct i2c_board_info));
  3543. + strlcpy(info.type, "si2183", I2C_NAME_SIZE);
  3544. + info.addr = 0x67;
  3545. + info.platform_data = &si2183_config;
  3546. + request_module(info.type);
  3547. + client_demod = i2c_new_client_device(&d->i2c_adap, &info);
  3548. + if (!i2c_client_has_driver(client_demod))
  3549. + return -ENODEV;
  3550. +
  3551. + if (!try_module_get(client_demod->dev.driver->owner)) {
  3552. + i2c_unregister_device(client_demod);
  3553. + return -ENODEV;
  3554. + }
  3555. + st->i2c_client_demod = client_demod;
  3556. +
  3557. + /* dvb core doesn't support 2 tuners for 1 demod so
  3558. + we split the adapter in 2 frontends */
  3559. +
  3560. + adap->fe_adap[0].fe2 = &adap->fe_adap[0]._fe2;
  3561. + memcpy(adap->fe_adap[0].fe2, adap->fe_adap[0].fe, sizeof(struct dvb_frontend));
  3562. +
  3563. + /* terrestrial tuner */
  3564. + memset(adap->fe_adap[0].fe->ops.delsys, 0, MAX_DELSYS);
  3565. + adap->fe_adap[0].fe->ops.delsys[0] = SYS_DVBT;
  3566. + adap->fe_adap[0].fe->ops.delsys[1] = SYS_DVBT2;
  3567. + adap->fe_adap[0].fe->ops.delsys[2] = SYS_DVBC_ANNEX_A;
  3568. + adap->fe_adap[0].fe->ops.delsys[3] = SYS_ISDBT;
  3569. + adap->fe_adap[0].fe->ops.delsys[4] = SYS_DVBC_ANNEX_B;
  3570. +
  3571. + /* attach ter tuner */
  3572. + memset(&si2157_config, 0, sizeof(si2157_config));
  3573. + si2157_config.fe = adap->fe_adap[0].fe;
  3574. + si2157_config.if_port = 1;
  3575. + memset(&info, 0, sizeof(struct i2c_board_info));
  3576. + strlcpy(info.type, "si2157", I2C_NAME_SIZE);
  3577. + info.addr = 0x61;
  3578. + info.platform_data = &si2157_config;
  3579. + request_module(info.type);
  3580. + client_tuner = i2c_new_client_device(adapter, &info);
  3581. + if (!i2c_client_has_driver(client_tuner)) {
  3582. + module_put(client_demod->dev.driver->owner);
  3583. + i2c_unregister_device(client_demod);
  3584. + return -ENODEV;
  3585. + }
  3586. + if (!try_module_get(client_tuner->dev.driver->owner)) {
  3587. + i2c_unregister_device(client_tuner);
  3588. + module_put(client_demod->dev.driver->owner);
  3589. + i2c_unregister_device(client_demod);
  3590. + return -ENODEV;
  3591. + }
  3592. +
  3593. + st->i2c_client_tuner = client_tuner;
  3594. +
  3595. + /*attach SAT tuner*/
  3596. + memset(adap->fe_adap[0].fe2->ops.delsys, 0, MAX_DELSYS);
  3597. + adap->fe_adap[0].fe2->ops.delsys[0] = SYS_DVBS;
  3598. + adap->fe_adap[0].fe2->ops.delsys[1] = SYS_DVBS2;
  3599. + adap->fe_adap[0].fe2->ops.delsys[2] = SYS_DSS;
  3600. + adap->fe_adap[0].fe2->id = 1;
  3601. +
  3602. + if (dvb_attach(av201x_attach, adap->fe_adap[0].fe2, &tbs5580_av201x_cfg,
  3603. + adapter) == NULL) {
  3604. + return -ENODEV;
  3605. + }
  3606. + else {
  3607. + buf[0] = 1;
  3608. + buf[1] = 0;
  3609. + tbs5580_op_rw(d->udev, 0x8a, 0, 0,
  3610. + buf, 2, TBS5580_WRITE_MSG);
  3611. +
  3612. + adap->fe_adap[0].fe2->ops.set_voltage = tbs5580_set_voltage;
  3613. +
  3614. + }
  3615. +
  3616. + buf[0] = 0;
  3617. + buf[1] = 0;
  3618. + tbs5580_op_rw(d->udev, 0xb7, 0, 0,
  3619. + buf, 2, TBS5580_WRITE_MSG);
  3620. + buf[0] = 8;
  3621. + buf[1] = 1;
  3622. + tbs5580_op_rw(d->udev, 0x8a, 0, 0,
  3623. + buf, 2, TBS5580_WRITE_MSG);
  3624. +
  3625. + tbs5580_init(adap);
  3626. +
  3627. + strlcpy(adap->fe_adap[0].fe->ops.info.name,d->props.devices[0].name,52);
  3628. + strcat(adap->fe_adap[0].fe->ops.info.name," DVB-T/T2/C/C2/ISDB-T");
  3629. + strlcpy(adap->fe_adap[0].fe2->ops.info.name,d->props.devices[0].name,52);
  3630. + strcat(adap->fe_adap[0].fe2->ops.info.name," DVB-S/S2/S2X");
  3631. +
  3632. + return 0;
  3633. +}
  3634. +
  3635. +static struct usb_device_id tbs5580_table[] = {
  3636. + {USB_DEVICE(0x734c, 0x5580)},
  3637. + { }
  3638. +};
  3639. +
  3640. +MODULE_DEVICE_TABLE(usb, tbs5580_table);
  3641. +
  3642. +static int tbs5580_load_firmware(struct usb_device *dev,
  3643. + const struct firmware *frmwr)
  3644. +{
  3645. + u8 *b, *p;
  3646. + int ret = 0, i;
  3647. + u8 reset;
  3648. + const struct firmware *fw;
  3649. + switch (dev->descriptor.idProduct) {
  3650. + case 0x5580:
  3651. + ret = request_firmware(&fw, tbs5580_properties.firmware, &dev->dev);
  3652. + if (ret != 0) {
  3653. + err("did not find the firmware file. (%s) "
  3654. + "Please see linux/Documentation/dvb/ for more details "
  3655. + "on firmware-problems.", tbs5580_properties.firmware);
  3656. + return ret;
  3657. + }
  3658. + break;
  3659. + default:
  3660. + fw = frmwr;
  3661. + break;
  3662. + }
  3663. + info("start downloading TBS5580 firmware");
  3664. + p = kmalloc(fw->size, GFP_KERNEL);
  3665. + reset = 1;
  3666. + /*stop the CPU*/
  3667. + tbs5580_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, TBS5580_WRITE_MSG);
  3668. + tbs5580_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, TBS5580_WRITE_MSG);
  3669. +
  3670. + if (p != NULL) {
  3671. + memcpy(p, fw->data, fw->size);
  3672. + for (i = 0; i < fw->size; i += 0x40) {
  3673. + b = (u8 *) p + i;
  3674. + if (tbs5580_op_rw(dev, 0xa0, i, 0, b , 0x40,
  3675. + TBS5580_WRITE_MSG) != 0x40) {
  3676. + err("error while transferring firmware");
  3677. + ret = -EINVAL;
  3678. + break;
  3679. + }
  3680. + }
  3681. + /* restart the CPU */
  3682. + reset = 0;
  3683. + if (ret || tbs5580_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1,
  3684. + TBS5580_WRITE_MSG) != 1) {
  3685. + err("could not restart the USB controller CPU.");
  3686. + ret = -EINVAL;
  3687. + }
  3688. + if (ret || tbs5580_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1,
  3689. + TBS5580_WRITE_MSG) != 1) {
  3690. + err("could not restart the USB controller CPU.");
  3691. + ret = -EINVAL;
  3692. + }
  3693. +
  3694. + msleep(100);
  3695. + kfree(p);
  3696. + }
  3697. + return ret;
  3698. +}
  3699. +
  3700. +static struct dvb_usb_device_properties tbs5580_properties = {
  3701. + .caps = DVB_USB_IS_AN_I2C_ADAPTER,
  3702. + .usb_ctrl = DEVICE_SPECIFIC,
  3703. + .firmware = "dvb-usb-id5580.fw",
  3704. + .size_of_priv = sizeof(struct tbs5580_state),
  3705. + .no_reconnect = 1,
  3706. +
  3707. + .i2c_algo = &tbs5580_i2c_algo,
  3708. +
  3709. + .generic_bulk_ctrl_endpoint = 0x81,
  3710. + /* parameter for the MPEG2-data transfer */
  3711. + .num_adapters = 1,
  3712. + .download_firmware = tbs5580_load_firmware,
  3713. + .read_mac_address = tbs5580_read_mac_address,
  3714. + .adapter = {{
  3715. + .num_frontends = 1,
  3716. + .fe = {{
  3717. + .frontend_attach = tbs5580_frontend_attach,
  3718. + .streaming_ctrl = NULL,
  3719. + .tuner_attach = NULL,
  3720. + .stream = {
  3721. + .type = USB_BULK,
  3722. + .count = 8,
  3723. + .endpoint = 0x82,
  3724. + .u = {
  3725. + .bulk = {
  3726. + .buffersize = 4096,
  3727. + }
  3728. + }
  3729. + },
  3730. + }},
  3731. + }},
  3732. +
  3733. + .num_device_descs = 1,
  3734. + .devices = {
  3735. + {"TBS 5580 CI USB2.0",
  3736. + {&tbs5580_table[0], NULL},
  3737. + {NULL},
  3738. + }
  3739. + }
  3740. +};
  3741. +
  3742. +static int tbs5580_probe(struct usb_interface *intf,
  3743. + const struct usb_device_id *id)
  3744. +{
  3745. + if (0 == dvb_usb_device_init(intf, &tbs5580_properties,
  3746. + THIS_MODULE, NULL, adapter_nr)) {
  3747. + return 0;
  3748. + }
  3749. + return -ENODEV;
  3750. +}
  3751. +
  3752. +static void tbs5580_disconnect(struct usb_interface *intf)
  3753. +{
  3754. +
  3755. + struct dvb_usb_device *d = usb_get_intfdata(intf);
  3756. +#if 0
  3757. + struct tbs5580_state *st = d->priv;
  3758. + struct i2c_client *client;
  3759. +
  3760. + /* remove I2C client for tuner */
  3761. + client = st->i2c_client_tuner;
  3762. + if (client) {
  3763. + module_put(client->dev.driver->owner);
  3764. + i2c_unregister_device(client);
  3765. + }
  3766. +
  3767. + /* remove I2C client for demodulator */
  3768. + client = st->i2c_client_demod;
  3769. + if (client) {
  3770. + module_put(client->dev.driver->owner);
  3771. + i2c_unregister_device(client);
  3772. + }
  3773. +#endif
  3774. + tbs5580_uninit(d);
  3775. + dvb_usb_device_exit(intf);
  3776. +}
  3777. +
  3778. +static struct usb_driver tbs5580_driver = {
  3779. + .name = "tbs5580",
  3780. + .probe = tbs5580_probe,
  3781. + .disconnect = tbs5580_disconnect,
  3782. + .id_table = tbs5580_table,
  3783. +};
  3784. +
  3785. +static int __init tbs5580_module_init(void)
  3786. +{
  3787. + int ret = usb_register(&tbs5580_driver);
  3788. + if (ret)
  3789. + err("usb_register failed. Error number %d", ret);
  3790. +
  3791. + return ret;
  3792. +}
  3793. +
  3794. +static void __exit tbs5580_module_exit(void)
  3795. +{
  3796. + usb_deregister(&tbs5580_driver);
  3797. +}
  3798. +
  3799. +module_init(tbs5580_module_init);
  3800. +module_exit(tbs5580_module_exit);
  3801. +
  3802. +MODULE_AUTHOR("Davin zhang <smiledavin@gmail.com>");
  3803. +MODULE_DESCRIPTION("TurboSight TBS 5580 driver");
  3804. +MODULE_VERSION("1.0");
  3805. +MODULE_LICENSE("GPL");
  3806.  
  3807. diff -uraBN a/drivers/media/usb/dvb-usb/tbs5580.h b/drivers/media/usb/dvb-usb/tbs5580.h
  3808. --- a/drivers/media/usb/dvb-usb/tbs5580.h
  3809. +++ b/drivers/media/usb/dvb-usb/tbs5580.h
  3810. @@ -0,0 +1,8 @@
  3811. +#ifndef _TBS5580_H_
  3812. +#define _TBS5580_H_
  3813. +
  3814. +#define DVB_USB_LOG_PREFIX "tbs5580"
  3815. +#include "dvb-usb.h"
  3816. +
  3817. +#define deb_xfer(args...) dprintk(dvb_usb_tbs5580_debug, 0x02, args)
  3818. +#endif
  3819.  
  3820. diff -uraBN a/include/linux/i2c.h b/include/linux/i2c.h
  3821. --- a/include/linux/i2c.h
  3822. +++ b/include/linux/i2c.h
  3823. @@ -189,6 +189,7 @@
  3824. u8 *values);
  3825. int i2c_get_device_id(const struct i2c_client *client,
  3826. struct i2c_device_identity *id);
  3827. +const struct i2c_device_id *i2c_client_get_device_id(const struct i2c_client *client);
  3828. #endif /* I2C */
  3829.  
  3830. /**
  3831.  
  3832. diff -uraBN a/include/media/dvb_frontend.h b/include/media/dvb_frontend.h
  3833. --- a/include/media/dvb_frontend.h
  3834. +++ b/include/media/dvb_frontend.h
  3835. @@ -433,8 +433,10 @@
  3836. * @ts_bus_ctrl: callback function used to take control of the TS bus.
  3837. * @set_lna: callback function to power on/off/auto the LNA.
  3838. * @search: callback function used on some custom algo search algos.
  3839. - * @tuner_ops: pointer to &struct dvb_tuner_ops
  3840. - * @analog_ops: pointer to &struct analog_demod_ops
  3841. + * @tuner_ops: pointer to struct dvb_tuner_ops
  3842. + * @analog_ops: pointer to struct analog_demod_ops
  3843. + * @set_property: callback function to allow the frontend to validade
  3844. + * incoming properties. Should not be used on new drivers.
  3845. */
  3846. struct dvb_frontend_ops {
  3847. struct dvb_frontend_internal_info info;
  3848. @@ -497,6 +499,22 @@
  3849.  
  3850. struct dvb_tuner_ops tuner_ops;
  3851. struct analog_demod_ops analog_ops;
  3852. +
  3853. + int (*set_property)(struct dvb_frontend* fe, u32 cmd, u32 data);
  3854. +
  3855. + void(*spi_read)( struct dvb_frontend *fe,struct ecp3_info *ecp3inf);
  3856. + void(*spi_write)( struct dvb_frontend *fe,struct ecp3_info *ecp3inf);
  3857. +
  3858. + void(*mcu_read)( struct dvb_frontend *fe,struct mcu24cxx_info *mcu24cxxinf);
  3859. + void(*mcu_write)( struct dvb_frontend *fe,struct mcu24cxx_info *mcu24cxxinf);
  3860. +
  3861. + void(*reg_i2cread)( struct dvb_frontend *fe,struct usbi2c_access *pi2cinf);
  3862. + void(*reg_i2cwrite)( struct dvb_frontend *fe,struct usbi2c_access *pi2cinf);
  3863. +
  3864. + void(*eeprom_read)( struct dvb_frontend *fe,struct eeprom_info *peepinf);
  3865. + void(*eeprom_write)( struct dvb_frontend *fe,struct eeprom_info *peepinf);
  3866. +
  3867. + int (*read_temp)(struct dvb_frontend* fe, s16* temp);
  3868. };
  3869.  
  3870. #ifdef __DVB_CORE__
  3871. @@ -628,8 +646,9 @@
  3872.  
  3873. /* Multistream specifics */
  3874. u32 stream_id;
  3875. -
  3876. - /* Physical Layer Scrambling specifics */
  3877. + u32 modcode;
  3878. +
  3879. + /* Physical Layer Scrambling specifics */
  3880. u32 scrambling_sequence_index;
  3881.  
  3882. /* ATSC-MH specifics */
  3883.  
  3884. diff -uraBN a/include/uapi/linux/dvb/frontend.h b/include/uapi/linux/dvb/frontend.h
  3885. --- a/include/uapi/linux/dvb/frontend.h
  3886. +++ b/include/uapi/linux/dvb/frontend.h
  3887. @@ -7,21 +7,6 @@
  3888. * Holger Waechtler <holger@convergence.de>
  3889. * Andre Draszik <ad@convergence.de>
  3890. * for convergence integrated media GmbH
  3891. - *
  3892. - * This program is free software; you can redistribute it and/or
  3893. - * modify it under the terms of the GNU Lesser General Public License
  3894. - * as published by the Free Software Foundation; either version 2.1
  3895. - * of the License, or (at your option) any later version.
  3896. - *
  3897. - * This program is distributed in the hope that it will be useful,
  3898. - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  3899. - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  3900. - * GNU General Public License for more details.
  3901. - *
  3902. - * You should have received a copy of the GNU Lesser General Public License
  3903. - * along with this program; if not, write to the Free Software
  3904. - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  3905. - *
  3906. */
  3907.  
  3908. #ifndef _DVBFRONTEND_H_
  3909. @@ -69,6 +54,7 @@
  3910. * automatically
  3911. * @FE_CAN_MUTE_TS: Can stop spurious TS data output
  3912. */
  3913. +
  3914. enum fe_caps {
  3915. FE_IS_STUPID = 0,
  3916. FE_CAN_INVERSION_AUTO = 0x1,
  3917. @@ -282,7 +268,6 @@
  3918. /**
  3919. * enum fe_code_rate - Type of Forward Error Correction (FEC)
  3920. *
  3921. - *
  3922. * @FEC_NONE: No Forward Error Correction Code
  3923. * @FEC_1_2: Forward Error Correction Code 1/2
  3924. * @FEC_2_3: Forward Error Correction Code 2/3
  3925. @@ -296,6 +281,22 @@
  3926. * @FEC_3_5: Forward Error Correction Code 3/5
  3927. * @FEC_9_10: Forward Error Correction Code 9/10
  3928. * @FEC_2_5: Forward Error Correction Code 2/5
  3929. + * @FEC_1_3: Forward Error Correction Code 1/3
  3930. + * @FEC_1_4: Forward Error Correction Code 1/4
  3931. + * @FEC_5_9: Forward Error Correction Code 5/9
  3932. + * @FEC_7_9: Forward Error Correction Code 7/9
  3933. + * @FEC_8_15: Forward Error Correction Code 8/15
  3934. + * @FEC_11_15: Forward Error Correction Code 11/15
  3935. + * @FEC_13_18: Forward Error Correction Code 13/18
  3936. + * @FEC_9_20: Forward Error Correction Code 9/20
  3937. + * @FEC_11_20: Forward Error Correction Code 11/20
  3938. + * @FEC_23_36: Forward Error Correction Code 23/36
  3939. + * @FEC_25_36: Forward Error Correction Code 25/36
  3940. + * @FEC_13_45: Forward Error Correction Code 13/45
  3941. + * @FEC_26_45: Forward Error Correction Code 26/45
  3942. + * @FEC_28_45: Forward Error Correction Code 28/45
  3943. + * @FEC_32_45: Forward Error Correction Code 32/45
  3944. + * @FEC_77_90: Forward Error Correction Code 77/90
  3945. *
  3946. * Please note that not all FEC types are supported by a given standard.
  3947. */
  3948. @@ -313,6 +314,32 @@
  3949. FEC_3_5,
  3950. FEC_9_10,
  3951. FEC_2_5,
  3952. + FEC_1_3,
  3953. + FEC_1_4,
  3954. + FEC_5_9,
  3955. + FEC_7_9,
  3956. + FEC_4_15,
  3957. + FEC_7_15,
  3958. + FEC_8_15,
  3959. + FEC_11_15,
  3960. + FEC_13_18,
  3961. + FEC_9_20,
  3962. + FEC_11_20,
  3963. + FEC_23_36,
  3964. + FEC_25_36,
  3965. + FEC_11_45,
  3966. + FEC_13_45,
  3967. + FEC_14_45,
  3968. + FEC_26_45,
  3969. + FEC_28_45,
  3970. + FEC_29_45,
  3971. + FEC_31_45,
  3972. + FEC_32_45,
  3973. + FEC_77_90,
  3974. + FEC_R_58,
  3975. + FEC_R_60,
  3976. + FEC_R_62,
  3977. + FEC_R_5E,
  3978. };
  3979.  
  3980. /**
  3981. @@ -331,6 +358,13 @@
  3982. * @APSK_32: 32-APSK modulation
  3983. * @DQPSK: DQPSK modulation
  3984. * @QAM_4_NR: 4-QAM-NR modulation
  3985. + * @QAM_1024: 1024-QAM modulation
  3986. + * @QAM_4096: 4096-QAM modulation
  3987. + * @APSK_8_L: 8APSK-L modulation
  3988. + * @APSK_16_L: 16APSK-L modulation
  3989. + * @APSK_32_L: 32APSK-L modulation
  3990. + * @APSK_64: 64APSK modulation
  3991. + * @APSK_64_L: 64APSK-L modulation
  3992. *
  3993. * Please note that not all modulations are supported by a given standard.
  3994. *
  3995. @@ -350,6 +384,19 @@
  3996. APSK_32,
  3997. DQPSK,
  3998. QAM_4_NR,
  3999. + QAM_512,
  4000. + QAM_1024,
  4001. + QAM_4096,
  4002. + APSK_64,
  4003. + APSK_128,
  4004. + APSK_256,
  4005. + APSK_8L,
  4006. + APSK_16L,
  4007. + APSK_32L,
  4008. + APSK_64L,
  4009. + APSK_128L,
  4010. + APSK_256L,
  4011. + APSK_1024,
  4012. };
  4013.  
  4014. /**
  4015. @@ -404,6 +451,7 @@
  4016. * @GUARD_INTERVAL_PN420: PN length 420 (1/4)
  4017. * @GUARD_INTERVAL_PN595: PN length 595 (1/6)
  4018. * @GUARD_INTERVAL_PN945: PN length 945 (1/9)
  4019. + * @GUARD_INTERVAL_1_64: Guard interval 1/64
  4020. *
  4021. * Please note that not all guard intervals are supported by a given standard.
  4022. */
  4023. @@ -419,6 +467,7 @@
  4024. GUARD_INTERVAL_PN420,
  4025. GUARD_INTERVAL_PN595,
  4026. GUARD_INTERVAL_PN945,
  4027. + GUARD_INTERVAL_1_64,
  4028. };
  4029.  
  4030. /**
  4031. @@ -513,7 +562,8 @@
  4032.  
  4033. #define DTV_STREAM_ID 42
  4034. #define DTV_ISDBS_TS_ID_LEGACY DTV_STREAM_ID
  4035. -#define DTV_DVBT2_PLP_ID_LEGACY 43
  4036. +#define DTV_DVBT2_PLP_ID_LEGACY DTV_STREAM_ID
  4037. +#define DTV_MODCODE 43
  4038.  
  4039. #define DTV_ENUM_DELSYS 44
  4040.  
  4041. @@ -571,6 +621,9 @@
  4042. * @ROLLOFF_20: Roloff factor: α=20%
  4043. * @ROLLOFF_25: Roloff factor: α=25%
  4044. * @ROLLOFF_AUTO: Auto-detect the roloff factor.
  4045. + * @ROLLOFF_15: Rolloff factor: α=15%
  4046. + * @ROLLOFF_10: Rolloff factor: α=10%
  4047. + * @ROLLOFF_5: Rolloff factor: α=5%
  4048. *
  4049. * .. note:
  4050. *
  4051. @@ -581,6 +634,9 @@
  4052. ROLLOFF_20,
  4053. ROLLOFF_25,
  4054. ROLLOFF_AUTO,
  4055. + ROLLOFF_15,
  4056. + ROLLOFF_10,
  4057. + ROLLOFF_5,
  4058. };
  4059.  
  4060. /**
  4061. @@ -594,6 +650,8 @@
  4062. * Cable TV: DVB-C following ITU-T J.83 Annex B spec (ClearQAM)
  4063. * @SYS_DVBC_ANNEX_C:
  4064. * Cable TV: DVB-C following ITU-T J.83 Annex C spec
  4065. + * @SYS_DVBC2:
  4066. + * Cable TV: DVB-C2
  4067. * @SYS_ISDBC:
  4068. * Cable TV: ISDB-C (no drivers yet)
  4069. * @SYS_DVBT:
  4070. @@ -611,7 +669,7 @@
  4071. * @SYS_DVBS:
  4072. * Satellite TV: DVB-S
  4073. * @SYS_DVBS2:
  4074. - * Satellite TV: DVB-S2
  4075. + * Satellite TV: DVB-S2 and DVB-S2X
  4076. * @SYS_TURBO:
  4077. * Satellite TV: DVB-S Turbo
  4078. * @SYS_ISDBS:
  4079. @@ -645,6 +703,7 @@
  4080. SYS_DVBT2,
  4081. SYS_TURBO,
  4082. SYS_DVBC_ANNEX_C,
  4083. + SYS_DVBC2,
  4084. };
  4085.  
  4086. /* backward compatibility definitions for delivery systems */
  4087. @@ -720,7 +779,7 @@
  4088. };
  4089.  
  4090. /**
  4091. - * enum atscmh_rs_code_mode
  4092. + * enum atscmh_rs_code_mode - ATSC-M/H Reed Solomon modes
  4093. * @ATSCMH_RSCODE_211_187: Reed Solomon code (211,187).
  4094. * @ATSCMH_RSCODE_223_187: Reed Solomon code (223,187).
  4095. * @ATSCMH_RSCODE_235_187: Reed Solomon code (235,187).
  4096. @@ -734,7 +793,8 @@
  4097. };
  4098.  
  4099. #define NO_STREAM_ID_FILTER (~0U)
  4100. -#define LNA_AUTO (~0U)
  4101. +#define LNA_AUTO (~0U)
  4102. +#define MODCODE_ALL (~0U)
  4103.  
  4104. /**
  4105. * enum fecap_scale_params - scale types for the quality parameters.
  4106. @@ -1008,4 +1068,45 @@
  4107.  
  4108. #endif
  4109.  
  4110. -#endif /*_DVBFRONTEND_H_*/
  4111. +struct ecp3_info
  4112. +{
  4113. + __u8 reg;
  4114. + __u32 data;
  4115. +};
  4116. +
  4117. +struct mcu24cxx_info
  4118. +{
  4119. + __u32 bassaddr;
  4120. + __u8 reg;
  4121. + __u32 data;
  4122. +};
  4123. +
  4124. +struct usbi2c_access
  4125. +{
  4126. + __u8 chip_addr;
  4127. + __u8 reg;
  4128. + __u8 num;
  4129. + __u8 buf[8];
  4130. +};
  4131. +
  4132. +struct eeprom_info
  4133. +{
  4134. + __u8 reg;
  4135. + __u8 data;
  4136. +};
  4137. +
  4138. +#define FE_ECP3FW_READ _IOR('o', 90, struct ecp3_info)
  4139. +#define FE_ECP3FW_WRITE _IOW('o', 91, struct ecp3_info)
  4140. +
  4141. +#define FE_24CXX_READ _IOR('o', 92, struct mcu24cxx_info)
  4142. +#define FE_24CXX_WRITE _IOW('o', 93, struct mcu24cxx_info)
  4143. +
  4144. +#define FE_REGI2C_READ _IOR('o', 94, struct usbi2c_access)
  4145. +#define FE_REGI2C_WRITE _IOW('o', 95, struct usbi2c_access)
  4146. +
  4147. +#define FE_EEPROM_READ _IOR('o', 96, struct eeprom_info)
  4148. +#define FE_EEPROM_WRITE _IOW('o', 97, struct eeprom_info)
  4149. +
  4150. +#define FE_READ_TEMP _IOR('o', 98, __s16)
  4151. +
  4152. +#endif /* _DVBFRONTEND_H_ */
  4153.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement