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 } 151