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
cxd2880_tnrdmd_mon_rf_lvl(struct cxd2880_tnrdmd * tnr_dmd,int * rf_lvl_db)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(2000, 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((rdata[0] << 3) |
78 ((rdata[1] & 0xe0) >> 5), 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
cxd2880_tnrdmd_mon_rf_lvl_sub(struct cxd2880_tnrdmd * tnr_dmd,int * rf_lvl_db)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->diver_sub, rf_lvl_db);
110 }
111
cxd2880_tnrdmd_mon_internal_cpu_status(struct cxd2880_tnrdmd * tnr_dmd,u16 * status)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
cxd2880_tnrdmd_mon_internal_cpu_status_sub(struct cxd2880_tnrdmd * tnr_dmd,u16 * status)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->diver_sub,
149 status);
150 }
151