GNU Linux-libre 4.19.264-gnu1
[releases.git] / drivers / media / dvb-frontends / cxd2880 / cxd2880_tnrdmd_mon.c
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(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
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
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->diver_sub,
149                                                       status);
150 }