1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * cxd2880_tnrdmd_mon.c |
4 | * Sony CXD2880 DVB-T2/T tuner + demodulator driver |
5 | * common monitor functions |
6 | * |
7 | * Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation |
8 | */ |
9 | |
10 | #include "cxd2880_common.h" |
11 | #include "cxd2880_tnrdmd_mon.h" |
12 | |
13 | static const u8 rf_lvl_seq[2] = { |
14 | 0x80, 0x00, |
15 | }; |
16 | |
17 | int cxd2880_tnrdmd_mon_rf_lvl(struct cxd2880_tnrdmd *tnr_dmd, |
18 | int *rf_lvl_db) |
19 | { |
20 | u8 rdata[2]; |
21 | int ret; |
22 | |
23 | if (!tnr_dmd || !rf_lvl_db) |
24 | return -EINVAL; |
25 | |
26 | if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE) |
27 | return -EINVAL; |
28 | |
29 | ret = tnr_dmd->io->write_reg(tnr_dmd->io, |
30 | CXD2880_IO_TGT_DMD, |
31 | 0x00, 0x00); |
32 | if (ret) |
33 | return ret; |
34 | |
35 | ret = tnr_dmd->io->write_reg(tnr_dmd->io, |
36 | CXD2880_IO_TGT_DMD, |
37 | 0x10, 0x01); |
38 | if (ret) |
39 | return ret; |
40 | |
41 | ret = tnr_dmd->io->write_reg(tnr_dmd->io, |
42 | CXD2880_IO_TGT_SYS, |
43 | 0x00, 0x10); |
44 | if (ret) |
45 | return ret; |
46 | |
47 | ret = tnr_dmd->io->write_regs(tnr_dmd->io, |
48 | CXD2880_IO_TGT_SYS, |
49 | 0x5b, rf_lvl_seq, 2); |
50 | if (ret) |
51 | return ret; |
52 | |
53 | usleep_range(min: 2000, max: 3000); |
54 | |
55 | ret = tnr_dmd->io->write_reg(tnr_dmd->io, |
56 | CXD2880_IO_TGT_SYS, |
57 | 0x00, 0x1a); |
58 | if (ret) |
59 | return ret; |
60 | |
61 | ret = tnr_dmd->io->read_regs(tnr_dmd->io, |
62 | CXD2880_IO_TGT_SYS, |
63 | 0x15, rdata, 2); |
64 | if (ret) |
65 | return ret; |
66 | |
67 | if (rdata[0] || rdata[1]) |
68 | return -EINVAL; |
69 | |
70 | ret = tnr_dmd->io->read_regs(tnr_dmd->io, |
71 | CXD2880_IO_TGT_SYS, |
72 | 0x11, rdata, 2); |
73 | if (ret) |
74 | return ret; |
75 | |
76 | *rf_lvl_db = |
77 | cxd2880_convert2s_complement(value: (rdata[0] << 3) | |
78 | ((rdata[1] & 0xe0) >> 5), bitlen: 11); |
79 | |
80 | *rf_lvl_db *= 125; |
81 | |
82 | ret = tnr_dmd->io->write_reg(tnr_dmd->io, |
83 | CXD2880_IO_TGT_DMD, |
84 | 0x00, 0x00); |
85 | if (ret) |
86 | return ret; |
87 | |
88 | ret = tnr_dmd->io->write_reg(tnr_dmd->io, |
89 | CXD2880_IO_TGT_DMD, |
90 | 0x10, 0x00); |
91 | if (ret) |
92 | return ret; |
93 | |
94 | if (tnr_dmd->rf_lvl_cmpstn) |
95 | ret = tnr_dmd->rf_lvl_cmpstn(tnr_dmd, rf_lvl_db); |
96 | |
97 | return ret; |
98 | } |
99 | |
100 | int cxd2880_tnrdmd_mon_rf_lvl_sub(struct cxd2880_tnrdmd *tnr_dmd, |
101 | int *rf_lvl_db) |
102 | { |
103 | if (!tnr_dmd || !rf_lvl_db) |
104 | return -EINVAL; |
105 | |
106 | if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN) |
107 | return -EINVAL; |
108 | |
109 | return cxd2880_tnrdmd_mon_rf_lvl(tnr_dmd: tnr_dmd->diver_sub, rf_lvl_db); |
110 | } |
111 | |
112 | int cxd2880_tnrdmd_mon_internal_cpu_status(struct cxd2880_tnrdmd |
113 | *tnr_dmd, u16 *status) |
114 | { |
115 | u8 data[2] = { 0 }; |
116 | int ret; |
117 | |
118 | if (!tnr_dmd || !status) |
119 | return -EINVAL; |
120 | |
121 | ret = tnr_dmd->io->write_reg(tnr_dmd->io, |
122 | CXD2880_IO_TGT_SYS, |
123 | 0x00, 0x1a); |
124 | if (ret) |
125 | return ret; |
126 | ret = tnr_dmd->io->read_regs(tnr_dmd->io, |
127 | CXD2880_IO_TGT_SYS, |
128 | 0x15, data, 2); |
129 | if (ret) |
130 | return ret; |
131 | |
132 | *status = (data[0] << 8) | data[1]; |
133 | |
134 | return 0; |
135 | } |
136 | |
137 | int cxd2880_tnrdmd_mon_internal_cpu_status_sub(struct |
138 | cxd2880_tnrdmd |
139 | *tnr_dmd, |
140 | u16 *status) |
141 | { |
142 | if (!tnr_dmd || !status) |
143 | return -EINVAL; |
144 | |
145 | if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN) |
146 | return -EINVAL; |
147 | |
148 | return cxd2880_tnrdmd_mon_internal_cpu_status(tnr_dmd: tnr_dmd->diver_sub, |
149 | status); |
150 | } |
151 | |