cxd2880_tnrdmd_dvbt2.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * cxd2880_tnrdmd_dvbt2.c
  4. * Sony CXD2880 DVB-T2/T tuner + demodulator driver
  5. * control functions for DVB-T2
  6. *
  7. * Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
  8. */
  9. #include <media/dvb_frontend.h>
  10. #include "cxd2880_tnrdmd_dvbt2.h"
  11. #include "cxd2880_tnrdmd_dvbt2_mon.h"
  12. static const struct cxd2880_reg_value tune_dmd_setting_seq1[] = {
  13. {0x00, 0x00}, {0x31, 0x02},
  14. };
  15. static const struct cxd2880_reg_value tune_dmd_setting_seq2[] = {
  16. {0x00, 0x04}, {0x5d, 0x0b},
  17. };
  18. static int x_tune_dvbt2_demod_setting(struct cxd2880_tnrdmd
  19. *tnr_dmd,
  20. enum cxd2880_dtv_bandwidth
  21. bandwidth,
  22. enum cxd2880_tnrdmd_clockmode
  23. clk_mode)
  24. {
  25. static const u8 tsif_settings[2] = { 0x01, 0x01 };
  26. static const u8 init_settings[14] = {
  27. 0x07, 0x06, 0x01, 0xf0, 0x00, 0x00, 0x04, 0xb0, 0x00, 0x00,
  28. 0x09, 0x9c, 0x0e, 0x4c
  29. };
  30. static const u8 clk_mode_settings_a1[9] = {
  31. 0x52, 0x49, 0x2c, 0x51, 0x51, 0x3d, 0x15, 0x29, 0x0c
  32. };
  33. static const u8 clk_mode_settings_b1[9] = {
  34. 0x5d, 0x55, 0x32, 0x5c, 0x5c, 0x45, 0x17, 0x2e, 0x0d
  35. };
  36. static const u8 clk_mode_settings_c1[9] = {
  37. 0x60, 0x00, 0x34, 0x5e, 0x5e, 0x47, 0x18, 0x2f, 0x0e
  38. };
  39. static const u8 clk_mode_settings_a2[13] = {
  40. 0x04, 0xe7, 0x94, 0x92, 0x09, 0xcf, 0x7e, 0xd0, 0x49,
  41. 0xcd, 0xcd, 0x1f, 0x5b
  42. };
  43. static const u8 clk_mode_settings_b2[13] = {
  44. 0x05, 0x90, 0x27, 0x55, 0x0b, 0x20, 0x8f, 0xd6, 0xea,
  45. 0xc8, 0xc8, 0x23, 0x91
  46. };
  47. static const u8 clk_mode_settings_c2[13] = {
  48. 0x05, 0xb8, 0xd8, 0x00, 0x0b, 0x72, 0x93, 0xf3, 0x00,
  49. 0xcd, 0xcd, 0x24, 0x95
  50. };
  51. static const u8 clk_mode_settings_a3[5] = {
  52. 0x0b, 0x6a, 0xc9, 0x03, 0x33
  53. };
  54. static const u8 clk_mode_settings_b3[5] = {
  55. 0x01, 0x02, 0xe4, 0x03, 0x39
  56. };
  57. static const u8 clk_mode_settings_c3[5] = {
  58. 0x01, 0x02, 0xeb, 0x03, 0x3b
  59. };
  60. static const u8 gtdofst[2] = { 0x3f, 0xff };
  61. static const u8 bw8_gtdofst_a[2] = { 0x19, 0xd2 };
  62. static const u8 bw8_nomi_ac[6] = { 0x15, 0x00, 0x00, 0x00, 0x00, 0x00 };
  63. static const u8 bw8_nomi_b[6] = { 0x14, 0x6a, 0xaa, 0xaa, 0xab, 0x00 };
  64. static const u8 bw8_sst_a[2] = { 0x06, 0x2a };
  65. static const u8 bw8_sst_b[2] = { 0x06, 0x29 };
  66. static const u8 bw8_sst_c[2] = { 0x06, 0x28 };
  67. static const u8 bw8_mrc_a[9] = {
  68. 0x28, 0x00, 0x50, 0x00, 0x60, 0x00, 0x00, 0x90, 0x00
  69. };
  70. static const u8 bw8_mrc_b[9] = {
  71. 0x2d, 0x5e, 0x5a, 0xbd, 0x6c, 0xe3, 0x00, 0xa3, 0x55
  72. };
  73. static const u8 bw8_mrc_c[9] = {
  74. 0x2e, 0xaa, 0x5d, 0x55, 0x70, 0x00, 0x00, 0xa8, 0x00
  75. };
  76. static const u8 bw7_nomi_ac[6] = { 0x18, 0x00, 0x00, 0x00, 0x00, 0x00 };
  77. static const u8 bw7_nomi_b[6] = { 0x17, 0x55, 0x55, 0x55, 0x55, 0x00 };
  78. static const u8 bw7_sst_a[2] = { 0x06, 0x23 };
  79. static const u8 bw7_sst_b[2] = { 0x06, 0x22 };
  80. static const u8 bw7_sst_c[2] = { 0x06, 0x21 };
  81. static const u8 bw7_mrc_a[9] = {
  82. 0x2d, 0xb6, 0x5b, 0x6d, 0x6d, 0xb6, 0x00, 0xa4, 0x92
  83. };
  84. static const u8 bw7_mrc_b[9] = {
  85. 0x33, 0xda, 0x67, 0xb4, 0x7c, 0x71, 0x00, 0xba, 0xaa
  86. };
  87. static const u8 bw7_mrc_c[9] = {
  88. 0x35, 0x55, 0x6a, 0xaa, 0x80, 0x00, 0x00, 0xc0, 0x00
  89. };
  90. static const u8 bw6_nomi_ac[6] = { 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00 };
  91. static const u8 bw6_nomi_b[6] = { 0x1b, 0x38, 0xe3, 0x8e, 0x39, 0x00 };
  92. static const u8 bw6_sst_a[2] = { 0x06, 0x1c };
  93. static const u8 bw6_sst_b[2] = { 0x06, 0x1b };
  94. static const u8 bw6_sst_c[2] = { 0x06, 0x1a };
  95. static const u8 bw6_mrc_a[9] = {
  96. 0x35, 0x55, 0x6a, 0xaa, 0x80, 0x00, 0x00, 0xc0, 0x00
  97. };
  98. static const u8 bw6_mrc_b[9] = {
  99. 0x3c, 0x7e, 0x78, 0xfc, 0x91, 0x2f, 0x00, 0xd9, 0xc7
  100. };
  101. static const u8 bw6_mrc_c[9] = {
  102. 0x3e, 0x38, 0x7c, 0x71, 0x95, 0x55, 0x00, 0xdf, 0xff
  103. };
  104. static const u8 bw5_nomi_ac[6] = { 0x21, 0x99, 0x99, 0x99, 0x9a, 0x00 };
  105. static const u8 bw5_nomi_b[6] = { 0x20, 0xaa, 0xaa, 0xaa, 0xab, 0x00 };
  106. static const u8 bw5_sst_a[2] = { 0x06, 0x15 };
  107. static const u8 bw5_sst_b[2] = { 0x06, 0x15 };
  108. static const u8 bw5_sst_c[2] = { 0x06, 0x14 };
  109. static const u8 bw5_mrc_a[9] = {
  110. 0x40, 0x00, 0x6a, 0xaa, 0x80, 0x00, 0x00, 0xe6, 0x66
  111. };
  112. static const u8 bw5_mrc_b[9] = {
  113. 0x48, 0x97, 0x78, 0xfc, 0x91, 0x2f, 0x01, 0x05, 0x55
  114. };
  115. static const u8 bw5_mrc_c[9] = {
  116. 0x4a, 0xaa, 0x7c, 0x71, 0x95, 0x55, 0x01, 0x0c, 0xcc
  117. };
  118. static const u8 bw1_7_nomi_a[6] = {
  119. 0x68, 0x0f, 0xa2, 0x32, 0xcf, 0x03
  120. };
  121. static const u8 bw1_7_nomi_c[6] = {
  122. 0x68, 0x0f, 0xa2, 0x32, 0xcf, 0x03
  123. };
  124. static const u8 bw1_7_nomi_b[6] = {
  125. 0x65, 0x2b, 0xa4, 0xcd, 0xd8, 0x03
  126. };
  127. static const u8 bw1_7_sst_a[2] = { 0x06, 0x0c };
  128. static const u8 bw1_7_sst_b[2] = { 0x06, 0x0c };
  129. static const u8 bw1_7_sst_c[2] = { 0x06, 0x0b };
  130. static const u8 bw1_7_mrc_a[9] = {
  131. 0x40, 0x00, 0x6a, 0xaa, 0x80, 0x00, 0x02, 0xc9, 0x8f
  132. };
  133. static const u8 bw1_7_mrc_b[9] = {
  134. 0x48, 0x97, 0x78, 0xfc, 0x91, 0x2f, 0x03, 0x29, 0x5d
  135. };
  136. static const u8 bw1_7_mrc_c[9] = {
  137. 0x4a, 0xaa, 0x7c, 0x71, 0x95, 0x55, 0x03, 0x40, 0x7d
  138. };
  139. const u8 *data = NULL;
  140. const u8 *data2 = NULL;
  141. const u8 *data3 = NULL;
  142. int ret;
  143. if (!tnr_dmd)
  144. return -EINVAL;
  145. ret = cxd2880_io_write_multi_regs(tnr_dmd->io,
  146. CXD2880_IO_TGT_SYS,
  147. tune_dmd_setting_seq1,
  148. ARRAY_SIZE(tune_dmd_setting_seq1));
  149. if (ret)
  150. return ret;
  151. ret = cxd2880_io_write_multi_regs(tnr_dmd->io,
  152. CXD2880_IO_TGT_DMD,
  153. tune_dmd_setting_seq2,
  154. ARRAY_SIZE(tune_dmd_setting_seq2));
  155. if (ret)
  156. return ret;
  157. if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_SUB) {
  158. ret = tnr_dmd->io->write_reg(tnr_dmd->io,
  159. CXD2880_IO_TGT_DMD,
  160. 0x00, 0x00);
  161. if (ret)
  162. return ret;
  163. ret = tnr_dmd->io->write_regs(tnr_dmd->io,
  164. CXD2880_IO_TGT_DMD,
  165. 0xce, tsif_settings, 2);
  166. if (ret)
  167. return ret;
  168. }
  169. ret = tnr_dmd->io->write_reg(tnr_dmd->io,
  170. CXD2880_IO_TGT_DMD,
  171. 0x00, 0x20);
  172. if (ret)
  173. return ret;
  174. ret = tnr_dmd->io->write_reg(tnr_dmd->io,
  175. CXD2880_IO_TGT_DMD,
  176. 0x8a, init_settings[0]);
  177. if (ret)
  178. return ret;
  179. ret = tnr_dmd->io->write_reg(tnr_dmd->io,
  180. CXD2880_IO_TGT_DMD,
  181. 0x90, init_settings[1]);
  182. if (ret)
  183. return ret;
  184. ret = tnr_dmd->io->write_reg(tnr_dmd->io,
  185. CXD2880_IO_TGT_DMD,
  186. 0x00, 0x25);
  187. if (ret)
  188. return ret;
  189. ret = tnr_dmd->io->write_regs(tnr_dmd->io,
  190. CXD2880_IO_TGT_DMD,
  191. 0xf0, &init_settings[2], 2);
  192. if (ret)
  193. return ret;
  194. ret = tnr_dmd->io->write_reg(tnr_dmd->io,
  195. CXD2880_IO_TGT_DMD,
  196. 0x00, 0x2a);
  197. if (ret)
  198. return ret;
  199. ret = tnr_dmd->io->write_reg(tnr_dmd->io,
  200. CXD2880_IO_TGT_DMD,
  201. 0xdc, init_settings[4]);
  202. if (ret)
  203. return ret;
  204. ret = tnr_dmd->io->write_reg(tnr_dmd->io,
  205. CXD2880_IO_TGT_DMD,
  206. 0xde, init_settings[5]);
  207. if (ret)
  208. return ret;
  209. ret = tnr_dmd->io->write_reg(tnr_dmd->io,
  210. CXD2880_IO_TGT_DMD,
  211. 0x00, 0x2d);
  212. if (ret)
  213. return ret;
  214. ret = tnr_dmd->io->write_regs(tnr_dmd->io,
  215. CXD2880_IO_TGT_DMD,
  216. 0x73, &init_settings[6], 4);
  217. if (ret)
  218. return ret;
  219. ret = tnr_dmd->io->write_regs(tnr_dmd->io,
  220. CXD2880_IO_TGT_DMD,
  221. 0x8f, &init_settings[10], 4);
  222. if (ret)
  223. return ret;
  224. switch (clk_mode) {
  225. case CXD2880_TNRDMD_CLOCKMODE_A:
  226. data = clk_mode_settings_a1;
  227. data2 = clk_mode_settings_a2;
  228. data3 = clk_mode_settings_a3;
  229. break;
  230. case CXD2880_TNRDMD_CLOCKMODE_B:
  231. data = clk_mode_settings_b1;
  232. data2 = clk_mode_settings_b2;
  233. data3 = clk_mode_settings_b3;
  234. break;
  235. case CXD2880_TNRDMD_CLOCKMODE_C:
  236. data = clk_mode_settings_c1;
  237. data2 = clk_mode_settings_c2;
  238. data3 = clk_mode_settings_c3;
  239. break;
  240. default:
  241. return -EINVAL;
  242. }
  243. ret = tnr_dmd->io->write_reg(tnr_dmd->io,
  244. CXD2880_IO_TGT_DMD,
  245. 0x00, 0x04);
  246. if (ret)
  247. return ret;
  248. ret = tnr_dmd->io->write_regs(tnr_dmd->io,
  249. CXD2880_IO_TGT_DMD,
  250. 0x1d, &data[0], 3);
  251. if (ret)
  252. return ret;
  253. ret = tnr_dmd->io->write_reg(tnr_dmd->io,
  254. CXD2880_IO_TGT_DMD,
  255. 0x22, data[3]);
  256. if (ret)
  257. return ret;
  258. ret = tnr_dmd->io->write_reg(tnr_dmd->io,
  259. CXD2880_IO_TGT_DMD,
  260. 0x24, data[4]);
  261. if (ret)
  262. return ret;
  263. ret = tnr_dmd->io->write_reg(tnr_dmd->io,
  264. CXD2880_IO_TGT_DMD,
  265. 0x26, data[5]);
  266. if (ret)
  267. return ret;
  268. ret = tnr_dmd->io->write_regs(tnr_dmd->io,
  269. CXD2880_IO_TGT_DMD,
  270. 0x29, &data[6], 2);
  271. if (ret)
  272. return ret;
  273. ret = tnr_dmd->io->write_reg(tnr_dmd->io,
  274. CXD2880_IO_TGT_DMD,
  275. 0x2d, data[8]);
  276. if (ret)
  277. return ret;
  278. if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_SUB) {
  279. ret = tnr_dmd->io->write_regs(tnr_dmd->io,
  280. CXD2880_IO_TGT_DMD,
  281. 0x2e, &data2[0], 6);
  282. if (ret)
  283. return ret;
  284. ret = tnr_dmd->io->write_regs(tnr_dmd->io,
  285. CXD2880_IO_TGT_DMD,
  286. 0x35, &data2[6], 7);
  287. if (ret)
  288. return ret;
  289. }
  290. ret = tnr_dmd->io->write_regs(tnr_dmd->io,
  291. CXD2880_IO_TGT_DMD,
  292. 0x3c, &data3[0], 2);
  293. if (ret)
  294. return ret;
  295. ret = tnr_dmd->io->write_regs(tnr_dmd->io,
  296. CXD2880_IO_TGT_DMD,
  297. 0x56, &data3[2], 3);
  298. if (ret)
  299. return ret;
  300. switch (bandwidth) {
  301. case CXD2880_DTV_BW_8_MHZ:
  302. switch (clk_mode) {
  303. case CXD2880_TNRDMD_CLOCKMODE_A:
  304. case CXD2880_TNRDMD_CLOCKMODE_C:
  305. data = bw8_nomi_ac;
  306. break;
  307. case CXD2880_TNRDMD_CLOCKMODE_B:
  308. data = bw8_nomi_b;
  309. break;
  310. default:
  311. return -EINVAL;
  312. }
  313. ret = tnr_dmd->io->write_regs(tnr_dmd->io,
  314. CXD2880_IO_TGT_DMD,
  315. 0x10, data, 6);
  316. if (ret)
  317. return ret;
  318. ret = tnr_dmd->io->write_reg(tnr_dmd->io,
  319. CXD2880_IO_TGT_DMD,
  320. 0x4a, 0x00);
  321. if (ret)
  322. return ret;
  323. switch (clk_mode) {
  324. case CXD2880_TNRDMD_CLOCKMODE_A:
  325. data = bw8_gtdofst_a;
  326. break;
  327. case CXD2880_TNRDMD_CLOCKMODE_B:
  328. case CXD2880_TNRDMD_CLOCKMODE_C:
  329. data = gtdofst;
  330. break;
  331. default:
  332. return -EINVAL;
  333. }
  334. ret = tnr_dmd->io->write_regs(tnr_dmd->io,
  335. CXD2880_IO_TGT_DMD,
  336. 0x19, data, 2);
  337. if (ret)
  338. return ret;
  339. switch (clk_mode) {
  340. case CXD2880_TNRDMD_CLOCKMODE_A:
  341. data = bw8_sst_a;
  342. break;
  343. case CXD2880_TNRDMD_CLOCKMODE_B:
  344. data = bw8_sst_b;
  345. break;
  346. case CXD2880_TNRDMD_CLOCKMODE_C:
  347. data = bw8_sst_c;
  348. break;
  349. default:
  350. return -EINVAL;
  351. }
  352. ret = tnr_dmd->io->write_regs(tnr_dmd->io,
  353. CXD2880_IO_TGT_DMD,
  354. 0x1b, data, 2);
  355. if (ret)
  356. return ret;
  357. if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
  358. switch (clk_mode) {
  359. case CXD2880_TNRDMD_CLOCKMODE_A:
  360. data = bw8_mrc_a;
  361. break;
  362. case CXD2880_TNRDMD_CLOCKMODE_B:
  363. data = bw8_mrc_b;
  364. break;
  365. case CXD2880_TNRDMD_CLOCKMODE_C:
  366. data = bw8_mrc_c;
  367. break;
  368. default:
  369. return -EINVAL;
  370. }
  371. ret = tnr_dmd->io->write_regs(tnr_dmd->io,
  372. CXD2880_IO_TGT_DMD,
  373. 0x4b, data, 9);
  374. if (ret)
  375. return ret;
  376. }
  377. break;
  378. case CXD2880_DTV_BW_7_MHZ:
  379. switch (clk_mode) {
  380. case CXD2880_TNRDMD_CLOCKMODE_A:
  381. case CXD2880_TNRDMD_CLOCKMODE_C:
  382. data = bw7_nomi_ac;
  383. break;
  384. case CXD2880_TNRDMD_CLOCKMODE_B:
  385. data = bw7_nomi_b;
  386. break;
  387. default:
  388. return -EINVAL;
  389. }
  390. ret = tnr_dmd->io->write_regs(tnr_dmd->io,
  391. CXD2880_IO_TGT_DMD,
  392. 0x10, data, 6);
  393. if (ret)
  394. return ret;
  395. ret = tnr_dmd->io->write_reg(tnr_dmd->io,
  396. CXD2880_IO_TGT_DMD,
  397. 0x4a, 0x02);
  398. if (ret)
  399. return ret;
  400. ret = tnr_dmd->io->write_regs(tnr_dmd->io,
  401. CXD2880_IO_TGT_DMD,
  402. 0x19, gtdofst, 2);
  403. if (ret)
  404. return ret;
  405. switch (clk_mode) {
  406. case CXD2880_TNRDMD_CLOCKMODE_A:
  407. data = bw7_sst_a;
  408. break;
  409. case CXD2880_TNRDMD_CLOCKMODE_B:
  410. data = bw7_sst_b;
  411. break;
  412. case CXD2880_TNRDMD_CLOCKMODE_C:
  413. data = bw7_sst_c;
  414. break;
  415. default:
  416. return -EINVAL;
  417. }
  418. ret = tnr_dmd->io->write_regs(tnr_dmd->io,
  419. CXD2880_IO_TGT_DMD,
  420. 0x1b, data, 2);
  421. if (ret)
  422. return ret;
  423. if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
  424. switch (clk_mode) {
  425. case CXD2880_TNRDMD_CLOCKMODE_A:
  426. data = bw7_mrc_a;
  427. break;
  428. case CXD2880_TNRDMD_CLOCKMODE_B:
  429. data = bw7_mrc_b;
  430. break;
  431. case CXD2880_TNRDMD_CLOCKMODE_C:
  432. data = bw7_mrc_c;
  433. break;
  434. default:
  435. return -EINVAL;
  436. }
  437. ret = tnr_dmd->io->write_regs(tnr_dmd->io,
  438. CXD2880_IO_TGT_DMD,
  439. 0x4b, data, 9);
  440. if (ret)
  441. return ret;
  442. }
  443. break;
  444. case CXD2880_DTV_BW_6_MHZ:
  445. switch (clk_mode) {
  446. case CXD2880_TNRDMD_CLOCKMODE_A:
  447. case CXD2880_TNRDMD_CLOCKMODE_C:
  448. data = bw6_nomi_ac;
  449. break;
  450. case CXD2880_TNRDMD_CLOCKMODE_B:
  451. data = bw6_nomi_b;
  452. break;
  453. default:
  454. return -EINVAL;
  455. }
  456. ret = tnr_dmd->io->write_regs(tnr_dmd->io,
  457. CXD2880_IO_TGT_DMD,
  458. 0x10, data, 6);
  459. if (ret)
  460. return ret;
  461. ret = tnr_dmd->io->write_reg(tnr_dmd->io,
  462. CXD2880_IO_TGT_DMD,
  463. 0x4a, 0x04);
  464. if (ret)
  465. return ret;
  466. ret = tnr_dmd->io->write_regs(tnr_dmd->io,
  467. CXD2880_IO_TGT_DMD,
  468. 0x19, gtdofst, 2);
  469. if (ret)
  470. return ret;
  471. switch (clk_mode) {
  472. case CXD2880_TNRDMD_CLOCKMODE_A:
  473. data = bw6_sst_a;
  474. break;
  475. case CXD2880_TNRDMD_CLOCKMODE_B:
  476. data = bw6_sst_b;
  477. break;
  478. case CXD2880_TNRDMD_CLOCKMODE_C:
  479. data = bw6_sst_c;
  480. break;
  481. default:
  482. return -EINVAL;
  483. }
  484. ret = tnr_dmd->io->write_regs(tnr_dmd->io,
  485. CXD2880_IO_TGT_DMD,
  486. 0x1b, data, 2);
  487. if (ret)
  488. return ret;
  489. if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
  490. switch (clk_mode) {
  491. case CXD2880_TNRDMD_CLOCKMODE_A:
  492. data = bw6_mrc_a;
  493. break;
  494. case CXD2880_TNRDMD_CLOCKMODE_B:
  495. data = bw6_mrc_b;
  496. break;
  497. case CXD2880_TNRDMD_CLOCKMODE_C:
  498. data = bw6_mrc_c;
  499. break;
  500. default:
  501. return -EINVAL;
  502. }
  503. ret = tnr_dmd->io->write_regs(tnr_dmd->io,
  504. CXD2880_IO_TGT_DMD,
  505. 0x4b, data, 9);
  506. if (ret)
  507. return ret;
  508. }
  509. break;
  510. case CXD2880_DTV_BW_5_MHZ:
  511. switch (clk_mode) {
  512. case CXD2880_TNRDMD_CLOCKMODE_A:
  513. case CXD2880_TNRDMD_CLOCKMODE_C:
  514. data = bw5_nomi_ac;
  515. break;
  516. case CXD2880_TNRDMD_CLOCKMODE_B:
  517. data = bw5_nomi_b;
  518. break;
  519. default:
  520. return -EINVAL;
  521. }
  522. ret = tnr_dmd->io->write_regs(tnr_dmd->io,
  523. CXD2880_IO_TGT_DMD,
  524. 0x10, data, 6);
  525. if (ret)
  526. return ret;
  527. ret = tnr_dmd->io->write_reg(tnr_dmd->io,
  528. CXD2880_IO_TGT_DMD,
  529. 0x4a, 0x06);
  530. if (ret)
  531. return ret;
  532. ret = tnr_dmd->io->write_regs(tnr_dmd->io,
  533. CXD2880_IO_TGT_DMD,
  534. 0x19, gtdofst, 2);
  535. if (ret)
  536. return ret;
  537. switch (clk_mode) {
  538. case CXD2880_TNRDMD_CLOCKMODE_A:
  539. data = bw5_sst_a;
  540. break;
  541. case CXD2880_TNRDMD_CLOCKMODE_B:
  542. data = bw5_sst_b;
  543. break;
  544. case CXD2880_TNRDMD_CLOCKMODE_C:
  545. data = bw5_sst_c;
  546. break;
  547. default:
  548. return -EINVAL;
  549. }
  550. ret = tnr_dmd->io->write_regs(tnr_dmd->io,
  551. CXD2880_IO_TGT_DMD,
  552. 0x1b, data, 2);
  553. if (ret)
  554. return ret;
  555. if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
  556. switch (clk_mode) {
  557. case CXD2880_TNRDMD_CLOCKMODE_A:
  558. data = bw5_mrc_a;
  559. break;
  560. case CXD2880_TNRDMD_CLOCKMODE_B:
  561. data = bw5_mrc_b;
  562. break;
  563. case CXD2880_TNRDMD_CLOCKMODE_C:
  564. data = bw5_mrc_c;
  565. break;
  566. default:
  567. return -EINVAL;
  568. }
  569. ret = tnr_dmd->io->write_regs(tnr_dmd->io,
  570. CXD2880_IO_TGT_DMD,
  571. 0x4b, data, 9);
  572. if (ret)
  573. return ret;
  574. }
  575. break;
  576. case CXD2880_DTV_BW_1_7_MHZ:
  577. switch (clk_mode) {
  578. case CXD2880_TNRDMD_CLOCKMODE_A:
  579. data = bw1_7_nomi_a;
  580. break;
  581. case CXD2880_TNRDMD_CLOCKMODE_C:
  582. data = bw1_7_nomi_c;
  583. break;
  584. case CXD2880_TNRDMD_CLOCKMODE_B:
  585. data = bw1_7_nomi_b;
  586. break;
  587. default:
  588. return -EINVAL;
  589. }
  590. ret = tnr_dmd->io->write_regs(tnr_dmd->io,
  591. CXD2880_IO_TGT_DMD,
  592. 0x10, data, 6);
  593. if (ret)
  594. return ret;
  595. ret = tnr_dmd->io->write_reg(tnr_dmd->io,
  596. CXD2880_IO_TGT_DMD,
  597. 0x4a, 0x03);
  598. if (ret)
  599. return ret;
  600. ret = tnr_dmd->io->write_regs(tnr_dmd->io,
  601. CXD2880_IO_TGT_DMD,
  602. 0x19, gtdofst, 2);
  603. if (ret)
  604. return ret;
  605. switch (clk_mode) {
  606. case CXD2880_TNRDMD_CLOCKMODE_A:
  607. data = bw1_7_sst_a;
  608. break;
  609. case CXD2880_TNRDMD_CLOCKMODE_B:
  610. data = bw1_7_sst_b;
  611. break;
  612. case CXD2880_TNRDMD_CLOCKMODE_C:
  613. data = bw1_7_sst_c;
  614. break;
  615. default:
  616. return -EINVAL;
  617. }
  618. ret = tnr_dmd->io->write_regs(tnr_dmd->io,
  619. CXD2880_IO_TGT_DMD,
  620. 0x1b, data, 2);
  621. if (ret)
  622. return ret;
  623. if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
  624. switch (clk_mode) {
  625. case CXD2880_TNRDMD_CLOCKMODE_A:
  626. data = bw1_7_mrc_a;
  627. break;
  628. case CXD2880_TNRDMD_CLOCKMODE_B:
  629. data = bw1_7_mrc_b;
  630. break;
  631. case CXD2880_TNRDMD_CLOCKMODE_C:
  632. data = bw1_7_mrc_c;
  633. break;
  634. default:
  635. return -EINVAL;
  636. }
  637. ret = tnr_dmd->io->write_regs(tnr_dmd->io,
  638. CXD2880_IO_TGT_DMD,
  639. 0x4b, data, 9);
  640. if (ret)
  641. return ret;
  642. }
  643. break;
  644. default:
  645. return -EINVAL;
  646. }
  647. ret = tnr_dmd->io->write_reg(tnr_dmd->io,
  648. CXD2880_IO_TGT_DMD,
  649. 0x00, 0x00);
  650. if (ret)
  651. return ret;
  652. return tnr_dmd->io->write_reg(tnr_dmd->io,
  653. CXD2880_IO_TGT_DMD,
  654. 0xfd, 0x01);
  655. }
  656. static int x_sleep_dvbt2_demod_setting(struct cxd2880_tnrdmd
  657. *tnr_dmd)
  658. {
  659. static const u8 difint_clip[] = {
  660. 0, 1, 0, 2, 0, 4, 0, 8, 0, 16, 0, 32
  661. };
  662. int ret = 0;
  663. if (!tnr_dmd)
  664. return -EINVAL;
  665. if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
  666. ret = tnr_dmd->io->write_reg(tnr_dmd->io,
  667. CXD2880_IO_TGT_DMD,
  668. 0x00, 0x1d);
  669. if (ret)
  670. return ret;
  671. ret = tnr_dmd->io->write_regs(tnr_dmd->io,
  672. CXD2880_IO_TGT_DMD,
  673. 0x47, difint_clip, 12);
  674. }
  675. return ret;
  676. }
  677. static int dvbt2_set_profile(struct cxd2880_tnrdmd *tnr_dmd,
  678. enum cxd2880_dvbt2_profile profile)
  679. {
  680. u8 t2_mode_tune_mode = 0;
  681. u8 seq_not2_dtime = 0;
  682. u8 dtime1 = 0;
  683. u8 dtime2 = 0;
  684. int ret;
  685. if (!tnr_dmd)
  686. return -EINVAL;
  687. switch (tnr_dmd->clk_mode) {
  688. case CXD2880_TNRDMD_CLOCKMODE_A:
  689. dtime1 = 0x27;
  690. dtime2 = 0x0c;
  691. break;
  692. case CXD2880_TNRDMD_CLOCKMODE_B:
  693. dtime1 = 0x2c;
  694. dtime2 = 0x0d;
  695. break;
  696. case CXD2880_TNRDMD_CLOCKMODE_C:
  697. dtime1 = 0x2e;
  698. dtime2 = 0x0e;
  699. break;
  700. default:
  701. return -EINVAL;
  702. }
  703. switch (profile) {
  704. case CXD2880_DVBT2_PROFILE_BASE:
  705. t2_mode_tune_mode = 0x01;
  706. seq_not2_dtime = dtime2;
  707. break;
  708. case CXD2880_DVBT2_PROFILE_LITE:
  709. t2_mode_tune_mode = 0x05;
  710. seq_not2_dtime = dtime1;
  711. break;
  712. case CXD2880_DVBT2_PROFILE_ANY:
  713. t2_mode_tune_mode = 0x00;
  714. seq_not2_dtime = dtime1;
  715. break;
  716. default:
  717. return -EINVAL;
  718. }
  719. ret = tnr_dmd->io->write_reg(tnr_dmd->io,
  720. CXD2880_IO_TGT_DMD,
  721. 0x00, 0x2e);
  722. if (ret)
  723. return ret;
  724. ret = tnr_dmd->io->write_reg(tnr_dmd->io,
  725. CXD2880_IO_TGT_DMD,
  726. 0x10, t2_mode_tune_mode);
  727. if (ret)
  728. return ret;
  729. ret = tnr_dmd->io->write_reg(tnr_dmd->io,
  730. CXD2880_IO_TGT_DMD,
  731. 0x00, 0x04);
  732. if (ret)
  733. return ret;
  734. return tnr_dmd->io->write_reg(tnr_dmd->io,
  735. CXD2880_IO_TGT_DMD,
  736. 0x2c, seq_not2_dtime);
  737. }
  738. int cxd2880_tnrdmd_dvbt2_tune1(struct cxd2880_tnrdmd *tnr_dmd,
  739. struct cxd2880_dvbt2_tune_param
  740. *tune_param)
  741. {
  742. int ret;
  743. if (!tnr_dmd || !tune_param)
  744. return -EINVAL;
  745. if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
  746. return -EINVAL;
  747. if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP &&
  748. tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
  749. return -EINVAL;
  750. if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN &&
  751. tune_param->profile == CXD2880_DVBT2_PROFILE_ANY)
  752. return -ENOTTY;
  753. ret =
  754. cxd2880_tnrdmd_common_tune_setting1(tnr_dmd, CXD2880_DTV_SYS_DVBT2,
  755. tune_param->center_freq_khz,
  756. tune_param->bandwidth, 0, 0);
  757. if (ret)
  758. return ret;
  759. ret =
  760. x_tune_dvbt2_demod_setting(tnr_dmd, tune_param->bandwidth,
  761. tnr_dmd->clk_mode);
  762. if (ret)
  763. return ret;
  764. if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
  765. ret =
  766. x_tune_dvbt2_demod_setting(tnr_dmd->diver_sub,
  767. tune_param->bandwidth,
  768. tnr_dmd->diver_sub->clk_mode);
  769. if (ret)
  770. return ret;
  771. }
  772. ret = dvbt2_set_profile(tnr_dmd, tune_param->profile);
  773. if (ret)
  774. return ret;
  775. if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
  776. ret =
  777. dvbt2_set_profile(tnr_dmd->diver_sub, tune_param->profile);
  778. if (ret)
  779. return ret;
  780. }
  781. if (tune_param->data_plp_id == CXD2880_DVBT2_TUNE_PARAM_PLPID_AUTO)
  782. ret = cxd2880_tnrdmd_dvbt2_set_plp_cfg(tnr_dmd, 1, 0);
  783. else
  784. ret =
  785. cxd2880_tnrdmd_dvbt2_set_plp_cfg(tnr_dmd, 0,
  786. (u8)(tune_param->data_plp_id));
  787. return ret;
  788. }
  789. int cxd2880_tnrdmd_dvbt2_tune2(struct cxd2880_tnrdmd *tnr_dmd,
  790. struct cxd2880_dvbt2_tune_param
  791. *tune_param)
  792. {
  793. u8 en_fef_intmtnt_ctrl = 1;
  794. int ret;
  795. if (!tnr_dmd || !tune_param)
  796. return -EINVAL;
  797. if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
  798. return -EINVAL;
  799. if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP &&
  800. tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
  801. return -EINVAL;
  802. switch (tune_param->profile) {
  803. case CXD2880_DVBT2_PROFILE_BASE:
  804. en_fef_intmtnt_ctrl = tnr_dmd->en_fef_intmtnt_base;
  805. break;
  806. case CXD2880_DVBT2_PROFILE_LITE:
  807. en_fef_intmtnt_ctrl = tnr_dmd->en_fef_intmtnt_lite;
  808. break;
  809. case CXD2880_DVBT2_PROFILE_ANY:
  810. if (tnr_dmd->en_fef_intmtnt_base &&
  811. tnr_dmd->en_fef_intmtnt_lite)
  812. en_fef_intmtnt_ctrl = 1;
  813. else
  814. en_fef_intmtnt_ctrl = 0;
  815. break;
  816. default:
  817. return -EINVAL;
  818. }
  819. ret =
  820. cxd2880_tnrdmd_common_tune_setting2(tnr_dmd,
  821. CXD2880_DTV_SYS_DVBT2,
  822. en_fef_intmtnt_ctrl);
  823. if (ret)
  824. return ret;
  825. tnr_dmd->state = CXD2880_TNRDMD_STATE_ACTIVE;
  826. tnr_dmd->frequency_khz = tune_param->center_freq_khz;
  827. tnr_dmd->sys = CXD2880_DTV_SYS_DVBT2;
  828. tnr_dmd->bandwidth = tune_param->bandwidth;
  829. if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
  830. tnr_dmd->diver_sub->state = CXD2880_TNRDMD_STATE_ACTIVE;
  831. tnr_dmd->diver_sub->frequency_khz = tune_param->center_freq_khz;
  832. tnr_dmd->diver_sub->sys = CXD2880_DTV_SYS_DVBT2;
  833. tnr_dmd->diver_sub->bandwidth = tune_param->bandwidth;
  834. }
  835. return 0;
  836. }
  837. int cxd2880_tnrdmd_dvbt2_sleep_setting(struct cxd2880_tnrdmd
  838. *tnr_dmd)
  839. {
  840. int ret;
  841. if (!tnr_dmd)
  842. return -EINVAL;
  843. if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
  844. return -EINVAL;
  845. if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP &&
  846. tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
  847. return -EINVAL;
  848. ret = x_sleep_dvbt2_demod_setting(tnr_dmd);
  849. if (ret)
  850. return ret;
  851. if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN)
  852. ret = x_sleep_dvbt2_demod_setting(tnr_dmd->diver_sub);
  853. return ret;
  854. }
  855. int cxd2880_tnrdmd_dvbt2_check_demod_lock(struct cxd2880_tnrdmd
  856. *tnr_dmd,
  857. enum
  858. cxd2880_tnrdmd_lock_result
  859. *lock)
  860. {
  861. int ret;
  862. u8 sync_stat = 0;
  863. u8 ts_lock = 0;
  864. u8 unlock_detected = 0;
  865. u8 unlock_detected_sub = 0;
  866. if (!tnr_dmd || !lock)
  867. return -EINVAL;
  868. if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
  869. return -EINVAL;
  870. if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
  871. return -EINVAL;
  872. ret =
  873. cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd, &sync_stat, &ts_lock,
  874. &unlock_detected);
  875. if (ret)
  876. return ret;
  877. if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SINGLE) {
  878. if (sync_stat == 6)
  879. *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;
  880. else if (unlock_detected)
  881. *lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED;
  882. else
  883. *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
  884. return ret;
  885. }
  886. if (sync_stat == 6) {
  887. *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;
  888. return ret;
  889. }
  890. ret =
  891. cxd2880_tnrdmd_dvbt2_mon_sync_stat_sub(tnr_dmd, &sync_stat,
  892. &unlock_detected_sub);
  893. if (ret)
  894. return ret;
  895. if (sync_stat == 6)
  896. *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;
  897. else if (unlock_detected && unlock_detected_sub)
  898. *lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED;
  899. else
  900. *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
  901. return ret;
  902. }
  903. int cxd2880_tnrdmd_dvbt2_check_ts_lock(struct cxd2880_tnrdmd
  904. *tnr_dmd,
  905. enum
  906. cxd2880_tnrdmd_lock_result
  907. *lock)
  908. {
  909. int ret;
  910. u8 sync_stat = 0;
  911. u8 ts_lock = 0;
  912. u8 unlock_detected = 0;
  913. u8 unlock_detected_sub = 0;
  914. if (!tnr_dmd || !lock)
  915. return -EINVAL;
  916. if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
  917. return -EINVAL;
  918. if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
  919. return -EINVAL;
  920. ret =
  921. cxd2880_tnrdmd_dvbt2_mon_sync_stat(tnr_dmd, &sync_stat, &ts_lock,
  922. &unlock_detected);
  923. if (ret)
  924. return ret;
  925. if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SINGLE) {
  926. if (ts_lock)
  927. *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;
  928. else if (unlock_detected)
  929. *lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED;
  930. else
  931. *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
  932. return ret;
  933. }
  934. if (ts_lock) {
  935. *lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;
  936. return ret;
  937. } else if (!unlock_detected) {
  938. *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
  939. return ret;
  940. }
  941. ret =
  942. cxd2880_tnrdmd_dvbt2_mon_sync_stat_sub(tnr_dmd, &sync_stat,
  943. &unlock_detected_sub);
  944. if (ret)
  945. return ret;
  946. if (unlock_detected && unlock_detected_sub)
  947. *lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED;
  948. else
  949. *lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
  950. return ret;
  951. }
  952. int cxd2880_tnrdmd_dvbt2_set_plp_cfg(struct cxd2880_tnrdmd
  953. *tnr_dmd, u8 auto_plp,
  954. u8 plp_id)
  955. {
  956. int ret;
  957. if (!tnr_dmd)
  958. return -EINVAL;
  959. if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
  960. return -EINVAL;
  961. if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP &&
  962. tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
  963. return -EINVAL;
  964. ret = tnr_dmd->io->write_reg(tnr_dmd->io,
  965. CXD2880_IO_TGT_DMD,
  966. 0x00, 0x23);
  967. if (ret)
  968. return ret;
  969. if (!auto_plp) {
  970. ret = tnr_dmd->io->write_reg(tnr_dmd->io,
  971. CXD2880_IO_TGT_DMD,
  972. 0xaf, plp_id);
  973. if (ret)
  974. return ret;
  975. }
  976. return tnr_dmd->io->write_reg(tnr_dmd->io,
  977. CXD2880_IO_TGT_DMD,
  978. 0xad, auto_plp ? 0x00 : 0x01);
  979. }
  980. int cxd2880_tnrdmd_dvbt2_diver_fef_setting(struct cxd2880_tnrdmd
  981. *tnr_dmd)
  982. {
  983. struct cxd2880_dvbt2_ofdm ofdm;
  984. static const u8 data[] = { 0, 8, 0, 16, 0, 32, 0, 64, 0, 128, 1, 0};
  985. int ret;
  986. if (!tnr_dmd)
  987. return -EINVAL;
  988. if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
  989. return -EINVAL;
  990. if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
  991. return -EINVAL;
  992. if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SINGLE)
  993. return 0;
  994. ret = cxd2880_tnrdmd_dvbt2_mon_ofdm(tnr_dmd, &ofdm);
  995. if (ret)
  996. return ret;
  997. if (!ofdm.mixed)
  998. return 0;
  999. ret = tnr_dmd->io->write_reg(tnr_dmd->io,
  1000. CXD2880_IO_TGT_DMD,
  1001. 0x00, 0x1d);
  1002. if (ret)
  1003. return ret;
  1004. return tnr_dmd->io->write_regs(tnr_dmd->io,
  1005. CXD2880_IO_TGT_DMD,
  1006. 0x47, data, 12);
  1007. }
  1008. int cxd2880_tnrdmd_dvbt2_check_l1post_valid(struct cxd2880_tnrdmd
  1009. *tnr_dmd,
  1010. u8 *l1_post_valid)
  1011. {
  1012. int ret;
  1013. u8 data;
  1014. if (!tnr_dmd || !l1_post_valid)
  1015. return -EINVAL;
  1016. if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
  1017. return -EINVAL;
  1018. if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP &&
  1019. tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
  1020. return -EINVAL;
  1021. ret = tnr_dmd->io->write_reg(tnr_dmd->io,
  1022. CXD2880_IO_TGT_DMD,
  1023. 0x00, 0x0b);
  1024. if (ret)
  1025. return ret;
  1026. ret = tnr_dmd->io->read_regs(tnr_dmd->io,
  1027. CXD2880_IO_TGT_DMD,
  1028. 0x86, &data, 1);
  1029. if (ret)
  1030. return ret;
  1031. *l1_post_valid = data & 0x01;
  1032. return ret;
  1033. }