Thomas Gleixner | c942fdd | 2019-05-27 08:55:06 +0200 | [diff] [blame^] | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
Abylay Ospan | 2dc1ed4 | 2016-03-21 22:19:12 -0300 | [diff] [blame] | 2 | /* |
| 3 | * helene.c |
| 4 | * |
| 5 | * Sony HELENE DVB-S/S2 DVB-T/T2 DVB-C/C2 ISDB-T/S tuner driver (CXD2858ER) |
| 6 | * |
| 7 | * Copyright 2012 Sony Corporation |
| 8 | * Copyright (C) 2014 NetUP Inc. |
| 9 | * Copyright (C) 2014 Abylay Ospan <aospan@netup.ru> |
Abylay Ospan | 2dc1ed4 | 2016-03-21 22:19:12 -0300 | [diff] [blame] | 10 | */ |
| 11 | |
| 12 | #include <linux/slab.h> |
| 13 | #include <linux/module.h> |
| 14 | #include <linux/dvb/frontend.h> |
| 15 | #include <linux/types.h> |
| 16 | #include "helene.h" |
Mauro Carvalho Chehab | fada193 | 2017-12-28 13:03:51 -0500 | [diff] [blame] | 17 | #include <media/dvb_frontend.h> |
Abylay Ospan | 2dc1ed4 | 2016-03-21 22:19:12 -0300 | [diff] [blame] | 18 | |
| 19 | #define MAX_WRITE_REGSIZE 20 |
| 20 | |
| 21 | enum helene_state { |
| 22 | STATE_UNKNOWN, |
| 23 | STATE_SLEEP, |
| 24 | STATE_ACTIVE |
| 25 | }; |
| 26 | |
| 27 | struct helene_priv { |
| 28 | u32 frequency; |
| 29 | u8 i2c_address; |
| 30 | struct i2c_adapter *i2c; |
| 31 | enum helene_state state; |
| 32 | void *set_tuner_data; |
| 33 | int (*set_tuner)(void *, int); |
| 34 | enum helene_xtal xtal; |
| 35 | }; |
| 36 | |
| 37 | #define TERR_INTERNAL_LOOPFILTER_AVAILABLE(tv_system) \ |
| 38 | (((tv_system) != SONY_HELENE_DTV_DVBC_6) && \ |
| 39 | ((tv_system) != SONY_HELENE_DTV_DVBC_8)\ |
| 40 | && ((tv_system) != SONY_HELENE_DTV_DVBC2_6) && \ |
| 41 | ((tv_system) != SONY_HELENE_DTV_DVBC2_8)) |
| 42 | |
| 43 | #define HELENE_AUTO 0xff |
| 44 | #define HELENE_OFFSET(ofs) ((u8)(ofs) & 0x1F) |
| 45 | #define HELENE_BW_6 0x00 |
| 46 | #define HELENE_BW_7 0x01 |
| 47 | #define HELENE_BW_8 0x02 |
| 48 | #define HELENE_BW_1_7 0x03 |
| 49 | |
| 50 | enum helene_tv_system_t { |
| 51 | SONY_HELENE_TV_SYSTEM_UNKNOWN, |
| 52 | /* Terrestrial Analog */ |
| 53 | SONY_HELENE_ATV_MN_EIAJ, |
| 54 | /**< System-M (Japan) (IF: Fp=5.75MHz in default) */ |
| 55 | SONY_HELENE_ATV_MN_SAP, |
| 56 | /**< System-M (US) (IF: Fp=5.75MHz in default) */ |
| 57 | SONY_HELENE_ATV_MN_A2, |
| 58 | /**< System-M (Korea) (IF: Fp=5.9MHz in default) */ |
| 59 | SONY_HELENE_ATV_BG, |
| 60 | /**< System-B/G (IF: Fp=7.3MHz in default) */ |
| 61 | SONY_HELENE_ATV_I, |
| 62 | /**< System-I (IF: Fp=7.85MHz in default) */ |
| 63 | SONY_HELENE_ATV_DK, |
| 64 | /**< System-D/K (IF: Fp=7.85MHz in default) */ |
| 65 | SONY_HELENE_ATV_L, |
| 66 | /**< System-L (IF: Fp=7.85MHz in default) */ |
| 67 | SONY_HELENE_ATV_L_DASH, |
| 68 | /**< System-L DASH (IF: Fp=2.2MHz in default) */ |
| 69 | /* Terrestrial/Cable Digital */ |
| 70 | SONY_HELENE_DTV_8VSB, |
| 71 | /**< ATSC 8VSB (IF: Fc=3.7MHz in default) */ |
| 72 | SONY_HELENE_DTV_QAM, |
| 73 | /**< US QAM (IF: Fc=3.7MHz in default) */ |
| 74 | SONY_HELENE_DTV_ISDBT_6, |
| 75 | /**< ISDB-T 6MHzBW (IF: Fc=3.55MHz in default) */ |
| 76 | SONY_HELENE_DTV_ISDBT_7, |
| 77 | /**< ISDB-T 7MHzBW (IF: Fc=4.15MHz in default) */ |
| 78 | SONY_HELENE_DTV_ISDBT_8, |
| 79 | /**< ISDB-T 8MHzBW (IF: Fc=4.75MHz in default) */ |
| 80 | SONY_HELENE_DTV_DVBT_5, |
| 81 | /**< DVB-T 5MHzBW (IF: Fc=3.6MHz in default) */ |
| 82 | SONY_HELENE_DTV_DVBT_6, |
| 83 | /**< DVB-T 6MHzBW (IF: Fc=3.6MHz in default) */ |
| 84 | SONY_HELENE_DTV_DVBT_7, |
| 85 | /**< DVB-T 7MHzBW (IF: Fc=4.2MHz in default) */ |
| 86 | SONY_HELENE_DTV_DVBT_8, |
| 87 | /**< DVB-T 8MHzBW (IF: Fc=4.8MHz in default) */ |
| 88 | SONY_HELENE_DTV_DVBT2_1_7, |
| 89 | /**< DVB-T2 1.7MHzBW (IF: Fc=3.5MHz in default) */ |
| 90 | SONY_HELENE_DTV_DVBT2_5, |
| 91 | /**< DVB-T2 5MHzBW (IF: Fc=3.6MHz in default) */ |
| 92 | SONY_HELENE_DTV_DVBT2_6, |
| 93 | /**< DVB-T2 6MHzBW (IF: Fc=3.6MHz in default) */ |
| 94 | SONY_HELENE_DTV_DVBT2_7, |
| 95 | /**< DVB-T2 7MHzBW (IF: Fc=4.2MHz in default) */ |
| 96 | SONY_HELENE_DTV_DVBT2_8, |
| 97 | /**< DVB-T2 8MHzBW (IF: Fc=4.8MHz in default) */ |
| 98 | SONY_HELENE_DTV_DVBC_6, |
| 99 | /**< DVB-C 6MHzBW (IF: Fc=3.7MHz in default) */ |
| 100 | SONY_HELENE_DTV_DVBC_8, |
| 101 | /**< DVB-C 8MHzBW (IF: Fc=4.9MHz in default) */ |
| 102 | SONY_HELENE_DTV_DVBC2_6, |
| 103 | /**< DVB-C2 6MHzBW (IF: Fc=3.7MHz in default) */ |
| 104 | SONY_HELENE_DTV_DVBC2_8, |
| 105 | /**< DVB-C2 8MHzBW (IF: Fc=4.9MHz in default) */ |
| 106 | SONY_HELENE_DTV_DTMB, |
| 107 | /**< DTMB (IF: Fc=5.1MHz in default) */ |
| 108 | /* Satellite */ |
| 109 | SONY_HELENE_STV_ISDBS, |
| 110 | /**< ISDB-S */ |
| 111 | SONY_HELENE_STV_DVBS, |
| 112 | /**< DVB-S */ |
| 113 | SONY_HELENE_STV_DVBS2, |
| 114 | /**< DVB-S2 */ |
| 115 | |
| 116 | SONY_HELENE_ATV_MIN = SONY_HELENE_ATV_MN_EIAJ, |
| 117 | /**< Minimum analog terrestrial system */ |
| 118 | SONY_HELENE_ATV_MAX = SONY_HELENE_ATV_L_DASH, |
| 119 | /**< Maximum analog terrestrial system */ |
| 120 | SONY_HELENE_DTV_MIN = SONY_HELENE_DTV_8VSB, |
| 121 | /**< Minimum digital terrestrial system */ |
| 122 | SONY_HELENE_DTV_MAX = SONY_HELENE_DTV_DTMB, |
| 123 | /**< Maximum digital terrestrial system */ |
| 124 | SONY_HELENE_TERR_TV_SYSTEM_NUM, |
| 125 | /**< Number of supported terrestrial broadcasting system */ |
| 126 | SONY_HELENE_STV_MIN = SONY_HELENE_STV_ISDBS, |
| 127 | /**< Minimum satellite system */ |
| 128 | SONY_HELENE_STV_MAX = SONY_HELENE_STV_DVBS2 |
| 129 | /**< Maximum satellite system */ |
| 130 | }; |
| 131 | |
| 132 | struct helene_terr_adjust_param_t { |
| 133 | /* < Addr:0x69 Bit[6:4] : RFVGA gain. |
| 134 | * 0xFF means Auto. (RF_GAIN_SEL = 1) |
| 135 | */ |
| 136 | uint8_t RF_GAIN; |
| 137 | /* < Addr:0x69 Bit[3:0] : IF_BPF gain. |
| 138 | */ |
| 139 | uint8_t IF_BPF_GC; |
| 140 | /* < Addr:0x6B Bit[3:0] : RF overload |
| 141 | * RF input detect level. (FRF <= 172MHz) |
| 142 | */ |
| 143 | uint8_t RFOVLD_DET_LV1_VL; |
| 144 | /* < Addr:0x6B Bit[3:0] : RF overload |
| 145 | * RF input detect level. (172MHz < FRF <= 464MHz) |
| 146 | */ |
| 147 | uint8_t RFOVLD_DET_LV1_VH; |
| 148 | /* < Addr:0x6B Bit[3:0] : RF overload |
| 149 | * RF input detect level. (FRF > 464MHz) |
| 150 | */ |
| 151 | uint8_t RFOVLD_DET_LV1_U; |
| 152 | /* < Addr:0x6C Bit[2:0] : |
| 153 | * Internal RFAGC detect level. (FRF <= 172MHz) |
| 154 | */ |
| 155 | uint8_t IFOVLD_DET_LV_VL; |
| 156 | /* < Addr:0x6C Bit[2:0] : |
| 157 | * Internal RFAGC detect level. (172MHz < FRF <= 464MHz) |
| 158 | */ |
| 159 | uint8_t IFOVLD_DET_LV_VH; |
| 160 | /* < Addr:0x6C Bit[2:0] : |
| 161 | * Internal RFAGC detect level. (FRF > 464MHz) |
| 162 | */ |
| 163 | uint8_t IFOVLD_DET_LV_U; |
| 164 | /* < Addr:0x6D Bit[5:4] : |
| 165 | * IF filter center offset. |
| 166 | */ |
| 167 | uint8_t IF_BPF_F0; |
| 168 | /* < Addr:0x6D Bit[1:0] : |
| 169 | * 6MHzBW(0x00) or 7MHzBW(0x01) |
| 170 | * or 8MHzBW(0x02) or 1.7MHzBW(0x03) |
| 171 | */ |
| 172 | uint8_t BW; |
| 173 | /* < Addr:0x6E Bit[4:0] : |
| 174 | * 5bit signed. IF offset (kHz) = FIF_OFFSET x 50 |
| 175 | */ |
| 176 | uint8_t FIF_OFFSET; |
| 177 | /* < Addr:0x6F Bit[4:0] : |
| 178 | * 5bit signed. BW offset (kHz) = |
| 179 | * BW_OFFSET x 50 (BW_OFFSET x 10 in 1.7MHzBW) |
| 180 | */ |
| 181 | uint8_t BW_OFFSET; |
| 182 | /* < Addr:0x9C Bit[0] : |
| 183 | * Local polarity. (0: Upper Local, 1: Lower Local) |
| 184 | */ |
| 185 | uint8_t IS_LOWERLOCAL; |
| 186 | }; |
| 187 | |
| 188 | static const struct helene_terr_adjust_param_t |
| 189 | terr_params[SONY_HELENE_TERR_TV_SYSTEM_NUM] = { |
| 190 | /*< SONY_HELENE_TV_SYSTEM_UNKNOWN */ |
| 191 | {HELENE_AUTO, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 192 | HELENE_BW_6, HELENE_OFFSET(0), HELENE_OFFSET(0), 0x00}, |
| 193 | /* Analog */ |
| 194 | /**< SONY_HELENE_ATV_MN_EIAJ (System-M (Japan)) */ |
| 195 | {HELENE_AUTO, 0x05, 0x03, 0x06, 0x03, 0x01, 0x01, 0x01, 0x00, |
| 196 | HELENE_BW_6, HELENE_OFFSET(0), HELENE_OFFSET(1), 0x00}, |
| 197 | /**< SONY_HELENE_ATV_MN_SAP (System-M (US)) */ |
| 198 | {HELENE_AUTO, 0x05, 0x03, 0x06, 0x03, 0x01, 0x01, 0x01, 0x00, |
| 199 | HELENE_BW_6, HELENE_OFFSET(0), HELENE_OFFSET(1), 0x00}, |
| 200 | {HELENE_AUTO, 0x05, 0x03, 0x06, 0x03, 0x01, 0x01, 0x01, 0x00, |
| 201 | HELENE_BW_6, HELENE_OFFSET(3), HELENE_OFFSET(1), 0x00}, |
| 202 | /**< SONY_HELENE_ATV_MN_A2 (System-M (Korea)) */ |
| 203 | {HELENE_AUTO, 0x05, 0x03, 0x06, 0x03, 0x01, 0x01, 0x01, 0x00, |
| 204 | HELENE_BW_7, HELENE_OFFSET(11), HELENE_OFFSET(5), 0x00}, |
| 205 | /**< SONY_HELENE_ATV_BG (System-B/G) */ |
| 206 | {HELENE_AUTO, 0x05, 0x03, 0x06, 0x03, 0x01, 0x01, 0x01, 0x00, |
| 207 | HELENE_BW_8, HELENE_OFFSET(2), HELENE_OFFSET(-3), 0x00}, |
| 208 | /**< SONY_HELENE_ATV_I (System-I) */ |
| 209 | {HELENE_AUTO, 0x05, 0x03, 0x06, 0x03, 0x01, 0x01, 0x01, 0x00, |
| 210 | HELENE_BW_8, HELENE_OFFSET(2), HELENE_OFFSET(-3), 0x00}, |
| 211 | /**< SONY_HELENE_ATV_DK (System-D/K) */ |
| 212 | {HELENE_AUTO, 0x03, 0x04, 0x0A, 0x04, 0x04, 0x04, 0x04, 0x00, |
| 213 | HELENE_BW_8, HELENE_OFFSET(2), HELENE_OFFSET(-3), 0x00}, |
| 214 | /**< SONY_HELENE_ATV_L (System-L) */ |
| 215 | {HELENE_AUTO, 0x03, 0x04, 0x0A, 0x04, 0x04, 0x04, 0x04, 0x00, |
| 216 | HELENE_BW_8, HELENE_OFFSET(-1), HELENE_OFFSET(4), 0x00}, |
| 217 | /**< SONY_HELENE_ATV_L_DASH (System-L DASH) */ |
| 218 | /* Digital */ |
| 219 | {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x03, 0x03, 0x03, 0x00, |
| 220 | HELENE_BW_6, HELENE_OFFSET(-6), HELENE_OFFSET(-3), 0x00}, |
| 221 | /**< SONY_HELENE_DTV_8VSB (ATSC 8VSB) */ |
| 222 | {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00, |
| 223 | HELENE_BW_6, HELENE_OFFSET(-6), HELENE_OFFSET(-3), 0x00}, |
| 224 | /**< SONY_HELENE_DTV_QAM (US QAM) */ |
| 225 | {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00, |
| 226 | HELENE_BW_6, HELENE_OFFSET(-9), HELENE_OFFSET(-5), 0x00}, |
| 227 | /**< SONY_HELENE_DTV_ISDBT_6 (ISDB-T 6MHzBW) */ |
| 228 | {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00, |
| 229 | HELENE_BW_7, HELENE_OFFSET(-7), HELENE_OFFSET(-6), 0x00}, |
| 230 | /**< SONY_HELENE_DTV_ISDBT_7 (ISDB-T 7MHzBW) */ |
| 231 | {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00, |
| 232 | HELENE_BW_8, HELENE_OFFSET(-5), HELENE_OFFSET(-7), 0x00}, |
| 233 | /**< SONY_HELENE_DTV_ISDBT_8 (ISDB-T 8MHzBW) */ |
| 234 | {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00, |
| 235 | HELENE_BW_6, HELENE_OFFSET(-8), HELENE_OFFSET(-3), 0x00}, |
| 236 | /**< SONY_HELENE_DTV_DVBT_5 (DVB-T 5MHzBW) */ |
| 237 | {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00, |
| 238 | HELENE_BW_6, HELENE_OFFSET(-8), HELENE_OFFSET(-3), 0x00}, |
| 239 | /**< SONY_HELENE_DTV_DVBT_6 (DVB-T 6MHzBW) */ |
| 240 | {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00, |
| 241 | HELENE_BW_7, HELENE_OFFSET(-6), HELENE_OFFSET(-5), 0x00}, |
| 242 | /**< SONY_HELENE_DTV_DVBT_7 (DVB-T 7MHzBW) */ |
| 243 | {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00, |
| 244 | HELENE_BW_8, HELENE_OFFSET(-4), HELENE_OFFSET(-6), 0x00}, |
| 245 | /**< SONY_HELENE_DTV_DVBT_8 (DVB-T 8MHzBW) */ |
| 246 | {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00, |
| 247 | HELENE_BW_1_7, HELENE_OFFSET(-10), HELENE_OFFSET(-10), 0x00}, |
| 248 | /**< SONY_HELENE_DTV_DVBT2_1_7 (DVB-T2 1.7MHzBW) */ |
| 249 | {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00, |
| 250 | HELENE_BW_6, HELENE_OFFSET(-8), HELENE_OFFSET(-3), 0x00}, |
| 251 | /**< SONY_HELENE_DTV_DVBT2_5 (DVB-T2 5MHzBW) */ |
| 252 | {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00, |
| 253 | HELENE_BW_6, HELENE_OFFSET(-8), HELENE_OFFSET(-3), 0x00}, |
| 254 | /**< SONY_HELENE_DTV_DVBT2_6 (DVB-T2 6MHzBW) */ |
| 255 | {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00, |
| 256 | HELENE_BW_7, HELENE_OFFSET(-6), HELENE_OFFSET(-5), 0x00}, |
| 257 | /**< SONY_HELENE_DTV_DVBT2_7 (DVB-T2 7MHzBW) */ |
| 258 | {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00, |
| 259 | HELENE_BW_8, HELENE_OFFSET(-4), HELENE_OFFSET(-6), 0x00}, |
| 260 | /**< SONY_HELENE_DTV_DVBT2_8 (DVB-T2 8MHzBW) */ |
| 261 | {HELENE_AUTO, 0x05, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x00, |
| 262 | HELENE_BW_6, HELENE_OFFSET(-6), HELENE_OFFSET(-4), 0x00}, |
| 263 | /**< SONY_HELENE_DTV_DVBC_6 (DVB-C 6MHzBW) */ |
| 264 | {HELENE_AUTO, 0x05, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x00, |
| 265 | HELENE_BW_8, HELENE_OFFSET(-2), HELENE_OFFSET(-3), 0x00}, |
| 266 | /**< SONY_HELENE_DTV_DVBC_8 (DVB-C 8MHzBW) */ |
| 267 | {HELENE_AUTO, 0x03, 0x09, 0x09, 0x09, 0x02, 0x02, 0x02, 0x00, |
| 268 | HELENE_BW_6, HELENE_OFFSET(-6), HELENE_OFFSET(-2), 0x00}, |
| 269 | /**< SONY_HELENE_DTV_DVBC2_6 (DVB-C2 6MHzBW) */ |
| 270 | {HELENE_AUTO, 0x03, 0x09, 0x09, 0x09, 0x02, 0x02, 0x02, 0x00, |
| 271 | HELENE_BW_8, HELENE_OFFSET(-2), HELENE_OFFSET(0), 0x00}, |
| 272 | /**< SONY_HELENE_DTV_DVBC2_8 (DVB-C2 8MHzBW) */ |
| 273 | {HELENE_AUTO, 0x04, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00, |
| 274 | HELENE_BW_8, HELENE_OFFSET(2), HELENE_OFFSET(1), 0x00} |
| 275 | /**< SONY_HELENE_DTV_DTMB (DTMB) */ |
| 276 | }; |
| 277 | |
| 278 | static void helene_i2c_debug(struct helene_priv *priv, |
| 279 | u8 reg, u8 write, const u8 *data, u32 len) |
| 280 | { |
| 281 | dev_dbg(&priv->i2c->dev, "helene: I2C %s reg 0x%02x size %d\n", |
| 282 | (write == 0 ? "read" : "write"), reg, len); |
| 283 | print_hex_dump_bytes("helene: I2C data: ", |
| 284 | DUMP_PREFIX_OFFSET, data, len); |
| 285 | } |
| 286 | |
| 287 | static int helene_write_regs(struct helene_priv *priv, |
| 288 | u8 reg, const u8 *data, u32 len) |
| 289 | { |
| 290 | int ret; |
| 291 | u8 buf[MAX_WRITE_REGSIZE + 1]; |
| 292 | struct i2c_msg msg[1] = { |
| 293 | { |
| 294 | .addr = priv->i2c_address, |
| 295 | .flags = 0, |
| 296 | .len = len + 1, |
| 297 | .buf = buf, |
| 298 | } |
| 299 | }; |
| 300 | |
| 301 | if (len + 1 > sizeof(buf)) { |
| 302 | dev_warn(&priv->i2c->dev, |
Alexey Dobriyan | 5b5e092 | 2017-02-27 14:30:02 -0800 | [diff] [blame] | 303 | "wr reg=%04x: len=%d vs %zu is too big!\n", |
Abylay Ospan | 2dc1ed4 | 2016-03-21 22:19:12 -0300 | [diff] [blame] | 304 | reg, len + 1, sizeof(buf)); |
| 305 | return -E2BIG; |
| 306 | } |
| 307 | |
| 308 | helene_i2c_debug(priv, reg, 1, data, len); |
| 309 | buf[0] = reg; |
| 310 | memcpy(&buf[1], data, len); |
| 311 | ret = i2c_transfer(priv->i2c, msg, 1); |
| 312 | if (ret >= 0 && ret != 1) |
| 313 | ret = -EREMOTEIO; |
| 314 | if (ret < 0) { |
| 315 | dev_warn(&priv->i2c->dev, |
| 316 | "%s: i2c wr failed=%d reg=%02x len=%d\n", |
| 317 | KBUILD_MODNAME, ret, reg, len); |
| 318 | return ret; |
| 319 | } |
| 320 | return 0; |
| 321 | } |
| 322 | |
| 323 | static int helene_write_reg(struct helene_priv *priv, u8 reg, u8 val) |
| 324 | { |
Arnd Bergmann | 3cd890d | 2017-11-30 11:55:46 -0500 | [diff] [blame] | 325 | u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */ |
| 326 | |
| 327 | return helene_write_regs(priv, reg, &tmp, 1); |
Abylay Ospan | 2dc1ed4 | 2016-03-21 22:19:12 -0300 | [diff] [blame] | 328 | } |
| 329 | |
| 330 | static int helene_read_regs(struct helene_priv *priv, |
| 331 | u8 reg, u8 *val, u32 len) |
| 332 | { |
| 333 | int ret; |
| 334 | struct i2c_msg msg[2] = { |
| 335 | { |
| 336 | .addr = priv->i2c_address, |
| 337 | .flags = 0, |
| 338 | .len = 1, |
| 339 | .buf = ®, |
| 340 | }, { |
| 341 | .addr = priv->i2c_address, |
| 342 | .flags = I2C_M_RD, |
| 343 | .len = len, |
| 344 | .buf = val, |
| 345 | } |
| 346 | }; |
| 347 | |
| 348 | ret = i2c_transfer(priv->i2c, &msg[0], 1); |
| 349 | if (ret >= 0 && ret != 1) |
| 350 | ret = -EREMOTEIO; |
| 351 | if (ret < 0) { |
| 352 | dev_warn(&priv->i2c->dev, |
| 353 | "%s: I2C rw failed=%d addr=%02x reg=%02x\n", |
| 354 | KBUILD_MODNAME, ret, priv->i2c_address, reg); |
| 355 | return ret; |
| 356 | } |
| 357 | ret = i2c_transfer(priv->i2c, &msg[1], 1); |
| 358 | if (ret >= 0 && ret != 1) |
| 359 | ret = -EREMOTEIO; |
| 360 | if (ret < 0) { |
| 361 | dev_warn(&priv->i2c->dev, |
| 362 | "%s: i2c rd failed=%d addr=%02x reg=%02x\n", |
| 363 | KBUILD_MODNAME, ret, priv->i2c_address, reg); |
| 364 | return ret; |
| 365 | } |
| 366 | helene_i2c_debug(priv, reg, 0, val, len); |
| 367 | return 0; |
| 368 | } |
| 369 | |
| 370 | static int helene_read_reg(struct helene_priv *priv, u8 reg, u8 *val) |
| 371 | { |
| 372 | return helene_read_regs(priv, reg, val, 1); |
| 373 | } |
| 374 | |
| 375 | static int helene_set_reg_bits(struct helene_priv *priv, |
| 376 | u8 reg, u8 data, u8 mask) |
| 377 | { |
| 378 | int res; |
| 379 | u8 rdata; |
| 380 | |
| 381 | if (mask != 0xff) { |
| 382 | res = helene_read_reg(priv, reg, &rdata); |
| 383 | if (res != 0) |
| 384 | return res; |
| 385 | data = ((data & mask) | (rdata & (mask ^ 0xFF))); |
| 386 | } |
| 387 | return helene_write_reg(priv, reg, data); |
| 388 | } |
| 389 | |
| 390 | static int helene_enter_power_save(struct helene_priv *priv) |
| 391 | { |
| 392 | dev_dbg(&priv->i2c->dev, "%s()\n", __func__); |
| 393 | if (priv->state == STATE_SLEEP) |
| 394 | return 0; |
| 395 | |
| 396 | /* Standby setting for CPU */ |
| 397 | helene_write_reg(priv, 0x88, 0x0); |
| 398 | |
| 399 | /* Standby setting for internal logic block */ |
| 400 | helene_write_reg(priv, 0x87, 0xC0); |
| 401 | |
| 402 | priv->state = STATE_SLEEP; |
| 403 | return 0; |
| 404 | } |
| 405 | |
| 406 | static int helene_leave_power_save(struct helene_priv *priv) |
| 407 | { |
| 408 | dev_dbg(&priv->i2c->dev, "%s()\n", __func__); |
| 409 | if (priv->state == STATE_ACTIVE) |
| 410 | return 0; |
| 411 | |
| 412 | /* Standby setting for internal logic block */ |
| 413 | helene_write_reg(priv, 0x87, 0xC4); |
| 414 | |
| 415 | /* Standby setting for CPU */ |
| 416 | helene_write_reg(priv, 0x88, 0x40); |
| 417 | |
| 418 | priv->state = STATE_ACTIVE; |
| 419 | return 0; |
| 420 | } |
| 421 | |
| 422 | static int helene_init(struct dvb_frontend *fe) |
| 423 | { |
| 424 | struct helene_priv *priv = fe->tuner_priv; |
| 425 | |
| 426 | dev_dbg(&priv->i2c->dev, "%s()\n", __func__); |
| 427 | return helene_leave_power_save(priv); |
| 428 | } |
| 429 | |
Max Kellermann | 194ced7 | 2016-08-09 18:32:31 -0300 | [diff] [blame] | 430 | static void helene_release(struct dvb_frontend *fe) |
Abylay Ospan | 2dc1ed4 | 2016-03-21 22:19:12 -0300 | [diff] [blame] | 431 | { |
| 432 | struct helene_priv *priv = fe->tuner_priv; |
| 433 | |
| 434 | dev_dbg(&priv->i2c->dev, "%s()\n", __func__); |
| 435 | kfree(fe->tuner_priv); |
| 436 | fe->tuner_priv = NULL; |
Abylay Ospan | 2dc1ed4 | 2016-03-21 22:19:12 -0300 | [diff] [blame] | 437 | } |
| 438 | |
| 439 | static int helene_sleep(struct dvb_frontend *fe) |
| 440 | { |
| 441 | struct helene_priv *priv = fe->tuner_priv; |
| 442 | |
| 443 | dev_dbg(&priv->i2c->dev, "%s()\n", __func__); |
| 444 | helene_enter_power_save(priv); |
| 445 | return 0; |
| 446 | } |
| 447 | |
| 448 | static enum helene_tv_system_t helene_get_tv_system(struct dvb_frontend *fe) |
| 449 | { |
| 450 | enum helene_tv_system_t system = SONY_HELENE_TV_SYSTEM_UNKNOWN; |
| 451 | struct dtv_frontend_properties *p = &fe->dtv_property_cache; |
| 452 | struct helene_priv *priv = fe->tuner_priv; |
| 453 | |
| 454 | if (p->delivery_system == SYS_DVBT) { |
| 455 | if (p->bandwidth_hz <= 5000000) |
| 456 | system = SONY_HELENE_DTV_DVBT_5; |
| 457 | else if (p->bandwidth_hz <= 6000000) |
| 458 | system = SONY_HELENE_DTV_DVBT_6; |
| 459 | else if (p->bandwidth_hz <= 7000000) |
| 460 | system = SONY_HELENE_DTV_DVBT_7; |
| 461 | else if (p->bandwidth_hz <= 8000000) |
| 462 | system = SONY_HELENE_DTV_DVBT_8; |
| 463 | else { |
| 464 | system = SONY_HELENE_DTV_DVBT_8; |
| 465 | p->bandwidth_hz = 8000000; |
| 466 | } |
| 467 | } else if (p->delivery_system == SYS_DVBT2) { |
| 468 | if (p->bandwidth_hz <= 5000000) |
| 469 | system = SONY_HELENE_DTV_DVBT2_5; |
| 470 | else if (p->bandwidth_hz <= 6000000) |
| 471 | system = SONY_HELENE_DTV_DVBT2_6; |
| 472 | else if (p->bandwidth_hz <= 7000000) |
| 473 | system = SONY_HELENE_DTV_DVBT2_7; |
| 474 | else if (p->bandwidth_hz <= 8000000) |
| 475 | system = SONY_HELENE_DTV_DVBT2_8; |
| 476 | else { |
| 477 | system = SONY_HELENE_DTV_DVBT2_8; |
| 478 | p->bandwidth_hz = 8000000; |
| 479 | } |
| 480 | } else if (p->delivery_system == SYS_DVBS) { |
| 481 | system = SONY_HELENE_STV_DVBS; |
| 482 | } else if (p->delivery_system == SYS_DVBS2) { |
| 483 | system = SONY_HELENE_STV_DVBS2; |
| 484 | } else if (p->delivery_system == SYS_ISDBS) { |
| 485 | system = SONY_HELENE_STV_ISDBS; |
| 486 | } else if (p->delivery_system == SYS_ISDBT) { |
| 487 | if (p->bandwidth_hz <= 6000000) |
| 488 | system = SONY_HELENE_DTV_ISDBT_6; |
| 489 | else if (p->bandwidth_hz <= 7000000) |
| 490 | system = SONY_HELENE_DTV_ISDBT_7; |
| 491 | else if (p->bandwidth_hz <= 8000000) |
| 492 | system = SONY_HELENE_DTV_ISDBT_8; |
| 493 | else { |
| 494 | system = SONY_HELENE_DTV_ISDBT_8; |
| 495 | p->bandwidth_hz = 8000000; |
| 496 | } |
| 497 | } else if (p->delivery_system == SYS_DVBC_ANNEX_A) { |
| 498 | if (p->bandwidth_hz <= 6000000) |
| 499 | system = SONY_HELENE_DTV_DVBC_6; |
| 500 | else if (p->bandwidth_hz <= 8000000) |
| 501 | system = SONY_HELENE_DTV_DVBC_8; |
| 502 | } |
| 503 | dev_dbg(&priv->i2c->dev, |
| 504 | "%s(): HELENE DTV system %d (delsys %d, bandwidth %d)\n", |
| 505 | __func__, (int)system, p->delivery_system, |
| 506 | p->bandwidth_hz); |
| 507 | return system; |
| 508 | } |
| 509 | |
| 510 | static int helene_set_params_s(struct dvb_frontend *fe) |
| 511 | { |
| 512 | u8 data[MAX_WRITE_REGSIZE]; |
| 513 | u32 frequency; |
| 514 | enum helene_tv_system_t tv_system; |
| 515 | struct dtv_frontend_properties *p = &fe->dtv_property_cache; |
| 516 | struct helene_priv *priv = fe->tuner_priv; |
Abylay Ospan | 1cdc4f0 | 2016-05-12 00:02:04 -0300 | [diff] [blame] | 517 | int frequencykHz = p->frequency; |
Abylay Ospan | 2dc1ed4 | 2016-03-21 22:19:12 -0300 | [diff] [blame] | 518 | uint32_t frequency4kHz = 0; |
| 519 | u32 symbol_rate = p->symbol_rate/1000; |
| 520 | |
| 521 | dev_dbg(&priv->i2c->dev, "%s(): tune frequency %dkHz sr=%uKsps\n", |
| 522 | __func__, frequencykHz, symbol_rate); |
| 523 | tv_system = helene_get_tv_system(fe); |
| 524 | |
| 525 | if (tv_system == SONY_HELENE_TV_SYSTEM_UNKNOWN) { |
| 526 | dev_err(&priv->i2c->dev, "%s(): unknown DTV system\n", |
| 527 | __func__); |
| 528 | return -EINVAL; |
| 529 | } |
| 530 | /* RF switch turn to satellite */ |
| 531 | if (priv->set_tuner) |
| 532 | priv->set_tuner(priv->set_tuner_data, 0); |
| 533 | frequency = roundup(p->frequency / 1000, 1); |
| 534 | |
| 535 | /* Disable IF signal output */ |
| 536 | helene_write_reg(priv, 0x15, 0x02); |
| 537 | |
| 538 | /* RFIN matching in power save (Sat) reset */ |
| 539 | helene_write_reg(priv, 0x43, 0x06); |
| 540 | |
| 541 | /* Analog block setting (0x6A, 0x6B) */ |
| 542 | data[0] = 0x00; |
| 543 | data[1] = 0x00; |
| 544 | helene_write_regs(priv, 0x6A, data, 2); |
| 545 | helene_write_reg(priv, 0x75, 0x99); |
| 546 | helene_write_reg(priv, 0x9D, 0x00); |
| 547 | |
| 548 | /* Tuning setting for CPU (0x61) */ |
| 549 | helene_write_reg(priv, 0x61, 0x07); |
| 550 | |
| 551 | /* Satellite mode select (0x01) */ |
| 552 | helene_write_reg(priv, 0x01, 0x01); |
| 553 | |
| 554 | /* Clock enable for internal logic block, CPU wake-up (0x04, 0x05) */ |
| 555 | data[0] = 0xC4; |
| 556 | data[1] = 0x40; |
| 557 | |
| 558 | switch (priv->xtal) { |
| 559 | case SONY_HELENE_XTAL_16000: |
| 560 | data[2] = 0x02; |
| 561 | break; |
| 562 | case SONY_HELENE_XTAL_20500: |
| 563 | data[2] = 0x02; |
| 564 | break; |
| 565 | case SONY_HELENE_XTAL_24000: |
| 566 | data[2] = 0x03; |
| 567 | break; |
| 568 | case SONY_HELENE_XTAL_41000: |
| 569 | data[2] = 0x05; |
| 570 | break; |
| 571 | default: |
| 572 | dev_err(&priv->i2c->dev, "%s(): unknown xtal %d\n", |
| 573 | __func__, priv->xtal); |
| 574 | return -EINVAL; |
| 575 | } |
| 576 | |
| 577 | /* Setting for analog block (0x07). LOOPFILTER INTERNAL */ |
| 578 | data[3] = 0x80; |
| 579 | |
| 580 | /* Tuning setting for analog block |
| 581 | * (0x08, 0x09, 0x0A, 0x0B). LOOPFILTER INTERNAL |
| 582 | */ |
| 583 | if (priv->xtal == SONY_HELENE_XTAL_20500) |
| 584 | data[4] = 0x58; |
| 585 | else |
| 586 | data[4] = 0x70; |
| 587 | |
| 588 | data[5] = 0x1E; |
| 589 | data[6] = 0x02; |
| 590 | data[7] = 0x24; |
| 591 | |
| 592 | /* Enable for analog block (0x0C, 0x0D, 0x0E). SAT LNA ON */ |
| 593 | data[8] = 0x0F; |
| 594 | data[8] |= 0xE0; /* POWERSAVE_TERR_RF_ACTIVE */ |
| 595 | data[9] = 0x02; |
| 596 | data[10] = 0x1E; |
| 597 | |
| 598 | /* Setting for LPF cutoff frequency (0x0F) */ |
| 599 | switch (tv_system) { |
| 600 | case SONY_HELENE_STV_ISDBS: |
| 601 | data[11] = 0x22; /* 22MHz */ |
| 602 | break; |
| 603 | case SONY_HELENE_STV_DVBS: |
| 604 | if (symbol_rate <= 4000) |
| 605 | data[11] = 0x05; |
| 606 | else if (symbol_rate <= 10000) |
| 607 | data[11] = (uint8_t)((symbol_rate * 47 |
| 608 | + (40000-1)) / 40000); |
| 609 | else |
| 610 | data[11] = (uint8_t)((symbol_rate * 27 |
| 611 | + (40000-1)) / 40000 + 5); |
| 612 | |
| 613 | if (data[11] > 36) |
| 614 | data[11] = 36; /* 5 <= lpf_cutoff <= 36 is valid */ |
| 615 | break; |
| 616 | case SONY_HELENE_STV_DVBS2: |
| 617 | if (symbol_rate <= 4000) |
| 618 | data[11] = 0x05; |
| 619 | else if (symbol_rate <= 10000) |
| 620 | data[11] = (uint8_t)((symbol_rate * 11 |
| 621 | + (10000-1)) / 10000); |
| 622 | else |
| 623 | data[11] = (uint8_t)((symbol_rate * 3 |
| 624 | + (5000-1)) / 5000 + 5); |
| 625 | |
| 626 | if (data[11] > 36) |
| 627 | data[11] = 36; /* 5 <= lpf_cutoff <= 36 is valid */ |
| 628 | break; |
| 629 | default: |
| 630 | dev_err(&priv->i2c->dev, "%s(): unknown standard %d\n", |
| 631 | __func__, tv_system); |
| 632 | return -EINVAL; |
| 633 | } |
| 634 | |
| 635 | /* RF tuning frequency setting (0x10, 0x11, 0x12) */ |
| 636 | frequency4kHz = (frequencykHz + 2) / 4; |
| 637 | data[12] = (uint8_t)(frequency4kHz & 0xFF); /* FRF_L */ |
| 638 | data[13] = (uint8_t)((frequency4kHz >> 8) & 0xFF); /* FRF_M */ |
| 639 | /* FRF_H (bit[3:0]) */ |
| 640 | data[14] = (uint8_t)((frequency4kHz >> 16) & 0x0F); |
| 641 | |
| 642 | /* Tuning command (0x13) */ |
| 643 | data[15] = 0xFF; |
| 644 | |
| 645 | /* Setting for IQOUT_LIMIT (0x14) 0.75Vpp */ |
| 646 | data[16] = 0x00; |
| 647 | |
| 648 | /* Enable IQ output (0x15) */ |
| 649 | data[17] = 0x01; |
| 650 | |
| 651 | helene_write_regs(priv, 0x04, data, 18); |
| 652 | |
| 653 | dev_dbg(&priv->i2c->dev, "%s(): tune done\n", |
| 654 | __func__); |
| 655 | |
| 656 | priv->frequency = frequency; |
| 657 | return 0; |
| 658 | } |
| 659 | |
Katsuhiro Suzuki | 817dc4b | 2018-07-17 21:06:42 -0400 | [diff] [blame] | 660 | static int helene_set_params_t(struct dvb_frontend *fe) |
Abylay Ospan | 2dc1ed4 | 2016-03-21 22:19:12 -0300 | [diff] [blame] | 661 | { |
| 662 | u8 data[MAX_WRITE_REGSIZE]; |
| 663 | u32 frequency; |
| 664 | enum helene_tv_system_t tv_system; |
| 665 | struct dtv_frontend_properties *p = &fe->dtv_property_cache; |
| 666 | struct helene_priv *priv = fe->tuner_priv; |
| 667 | int frequencykHz = p->frequency / 1000; |
| 668 | |
| 669 | dev_dbg(&priv->i2c->dev, "%s(): tune frequency %dkHz\n", |
| 670 | __func__, frequencykHz); |
| 671 | tv_system = helene_get_tv_system(fe); |
| 672 | |
| 673 | if (tv_system == SONY_HELENE_TV_SYSTEM_UNKNOWN) { |
| 674 | dev_dbg(&priv->i2c->dev, "%s(): unknown DTV system\n", |
| 675 | __func__); |
| 676 | return -EINVAL; |
| 677 | } |
| 678 | if (priv->set_tuner) |
| 679 | priv->set_tuner(priv->set_tuner_data, 1); |
| 680 | frequency = roundup(p->frequency / 1000, 25); |
| 681 | |
| 682 | /* mode select */ |
| 683 | helene_write_reg(priv, 0x01, 0x00); |
| 684 | |
| 685 | /* Disable IF signal output */ |
| 686 | helene_write_reg(priv, 0x74, 0x02); |
| 687 | |
| 688 | if (priv->state == STATE_SLEEP) |
| 689 | helene_leave_power_save(priv); |
| 690 | |
| 691 | /* Initial setting for internal analog block (0x91, 0x92) */ |
| 692 | if ((tv_system == SONY_HELENE_DTV_DVBC_6) || |
| 693 | (tv_system == SONY_HELENE_DTV_DVBC_8)) { |
| 694 | data[0] = 0x16; |
| 695 | data[1] = 0x26; |
| 696 | } else { |
| 697 | data[0] = 0x10; |
| 698 | data[1] = 0x20; |
| 699 | } |
| 700 | helene_write_regs(priv, 0x91, data, 2); |
| 701 | |
| 702 | /* Setting for analog block */ |
| 703 | if (TERR_INTERNAL_LOOPFILTER_AVAILABLE(tv_system)) |
| 704 | data[0] = 0x90; |
| 705 | else |
| 706 | data[0] = 0x00; |
| 707 | |
| 708 | /* Setting for local polarity (0x9D) */ |
| 709 | data[1] = (uint8_t)(terr_params[tv_system].IS_LOWERLOCAL & 0x01); |
| 710 | helene_write_regs(priv, 0x9C, data, 2); |
| 711 | |
| 712 | /* Enable for analog block */ |
| 713 | data[0] = 0xEE; |
| 714 | data[1] = 0x02; |
| 715 | data[2] = 0x1E; |
| 716 | data[3] = 0x67; /* Tuning setting for CPU */ |
| 717 | |
| 718 | /* Setting for PLL reference divider for xtal=24MHz */ |
| 719 | if ((tv_system == SONY_HELENE_DTV_DVBC_6) || |
| 720 | (tv_system == SONY_HELENE_DTV_DVBC_8)) |
| 721 | data[4] = 0x18; |
| 722 | else |
| 723 | data[4] = 0x03; |
| 724 | |
| 725 | /* Tuning setting for analog block */ |
| 726 | if (TERR_INTERNAL_LOOPFILTER_AVAILABLE(tv_system)) { |
| 727 | data[5] = 0x38; |
| 728 | data[6] = 0x1E; |
| 729 | data[7] = 0x02; |
| 730 | data[8] = 0x24; |
| 731 | } else if ((tv_system == SONY_HELENE_DTV_DVBC_6) || |
| 732 | (tv_system == SONY_HELENE_DTV_DVBC_8)) { |
| 733 | data[5] = 0x1C; |
| 734 | data[6] = 0x78; |
| 735 | data[7] = 0x08; |
| 736 | data[8] = 0x1C; |
| 737 | } else { |
| 738 | data[5] = 0xB4; |
| 739 | data[6] = 0x78; |
| 740 | data[7] = 0x08; |
| 741 | data[8] = 0x30; |
Fengguang Wu | 155af08 | 2016-06-07 12:26:01 -0300 | [diff] [blame] | 742 | } |
Abylay Ospan | 2dc1ed4 | 2016-03-21 22:19:12 -0300 | [diff] [blame] | 743 | helene_write_regs(priv, 0x5E, data, 9); |
| 744 | |
| 745 | /* LT_AMP_EN should be 0 */ |
| 746 | helene_set_reg_bits(priv, 0x67, 0x0, 0x02); |
| 747 | |
| 748 | /* Setting for IFOUT_LIMIT */ |
| 749 | data[0] = 0x00; /* 1.5Vpp */ |
| 750 | |
| 751 | /* RF_GAIN setting */ |
| 752 | if (terr_params[tv_system].RF_GAIN == HELENE_AUTO) |
| 753 | data[1] = 0x80; /* RF_GAIN_SEL = 1 */ |
| 754 | else |
| 755 | data[1] = (uint8_t)((terr_params[tv_system].RF_GAIN |
| 756 | << 4) & 0x70); |
| 757 | |
| 758 | /* IF_BPF_GC setting */ |
| 759 | data[1] |= (uint8_t)(terr_params[tv_system].IF_BPF_GC & 0x0F); |
| 760 | |
| 761 | /* Setting for internal RFAGC (0x6A, 0x6B, 0x6C) */ |
| 762 | data[2] = 0x00; |
| 763 | if (frequencykHz <= 172000) { |
| 764 | data[3] = (uint8_t)(terr_params[tv_system].RFOVLD_DET_LV1_VL |
| 765 | & 0x0F); |
| 766 | data[4] = (uint8_t)(terr_params[tv_system].IFOVLD_DET_LV_VL |
| 767 | & 0x07); |
| 768 | } else if (frequencykHz <= 464000) { |
| 769 | data[3] = (uint8_t)(terr_params[tv_system].RFOVLD_DET_LV1_VH |
| 770 | & 0x0F); |
| 771 | data[4] = (uint8_t)(terr_params[tv_system].IFOVLD_DET_LV_VH |
| 772 | & 0x07); |
| 773 | } else { |
| 774 | data[3] = (uint8_t)(terr_params[tv_system].RFOVLD_DET_LV1_U |
| 775 | & 0x0F); |
| 776 | data[4] = (uint8_t)(terr_params[tv_system].IFOVLD_DET_LV_U |
| 777 | & 0x07); |
| 778 | } |
| 779 | data[4] |= 0x20; |
| 780 | |
| 781 | /* Setting for IF frequency and bandwidth */ |
| 782 | |
| 783 | /* IF filter center frequency offset (IF_BPF_F0) (0x6D) */ |
| 784 | data[5] = (uint8_t)((terr_params[tv_system].IF_BPF_F0 << 4) & 0x30); |
| 785 | |
| 786 | /* IF filter band width (BW) (0x6D) */ |
| 787 | data[5] |= (uint8_t)(terr_params[tv_system].BW & 0x03); |
| 788 | |
| 789 | /* IF frequency offset value (FIF_OFFSET) (0x6E) */ |
| 790 | data[6] = (uint8_t)(terr_params[tv_system].FIF_OFFSET & 0x1F); |
| 791 | |
| 792 | /* IF band width offset value (BW_OFFSET) (0x6F) */ |
| 793 | data[7] = (uint8_t)(terr_params[tv_system].BW_OFFSET & 0x1F); |
| 794 | |
| 795 | /* RF tuning frequency setting (0x70, 0x71, 0x72) */ |
| 796 | data[8] = (uint8_t)(frequencykHz & 0xFF); /* FRF_L */ |
| 797 | data[9] = (uint8_t)((frequencykHz >> 8) & 0xFF); /* FRF_M */ |
| 798 | data[10] = (uint8_t)((frequencykHz >> 16) |
| 799 | & 0x0F); /* FRF_H (bit[3:0]) */ |
| 800 | |
| 801 | /* Tuning command */ |
| 802 | data[11] = 0xFF; |
| 803 | |
| 804 | /* Enable IF output, AGC and IFOUT pin selection (0x74) */ |
| 805 | data[12] = 0x01; |
| 806 | |
| 807 | if ((tv_system == SONY_HELENE_DTV_DVBC_6) || |
| 808 | (tv_system == SONY_HELENE_DTV_DVBC_8)) { |
| 809 | data[13] = 0xD9; |
| 810 | data[14] = 0x0F; |
| 811 | data[15] = 0x24; |
| 812 | data[16] = 0x87; |
| 813 | } else { |
| 814 | data[13] = 0x99; |
| 815 | data[14] = 0x00; |
| 816 | data[15] = 0x24; |
| 817 | data[16] = 0x87; |
| 818 | } |
| 819 | |
| 820 | helene_write_regs(priv, 0x68, data, 17); |
| 821 | |
| 822 | dev_dbg(&priv->i2c->dev, "%s(): tune done\n", |
| 823 | __func__); |
| 824 | |
| 825 | priv->frequency = frequency; |
| 826 | return 0; |
| 827 | } |
| 828 | |
Katsuhiro Suzuki | 817dc4b | 2018-07-17 21:06:42 -0400 | [diff] [blame] | 829 | static int helene_set_params(struct dvb_frontend *fe) |
| 830 | { |
| 831 | struct dtv_frontend_properties *p = &fe->dtv_property_cache; |
| 832 | |
| 833 | if (p->delivery_system == SYS_DVBT || |
| 834 | p->delivery_system == SYS_DVBT2 || |
| 835 | p->delivery_system == SYS_ISDBT || |
| 836 | p->delivery_system == SYS_DVBC_ANNEX_A) |
| 837 | return helene_set_params_t(fe); |
| 838 | |
| 839 | return helene_set_params_s(fe); |
| 840 | } |
| 841 | |
Abylay Ospan | 2dc1ed4 | 2016-03-21 22:19:12 -0300 | [diff] [blame] | 842 | static int helene_get_frequency(struct dvb_frontend *fe, u32 *frequency) |
| 843 | { |
| 844 | struct helene_priv *priv = fe->tuner_priv; |
| 845 | |
| 846 | *frequency = priv->frequency * 1000; |
| 847 | return 0; |
| 848 | } |
| 849 | |
Katsuhiro Suzuki | 817dc4b | 2018-07-17 21:06:42 -0400 | [diff] [blame] | 850 | static const struct dvb_tuner_ops helene_tuner_ops_t = { |
Abylay Ospan | 2dc1ed4 | 2016-03-21 22:19:12 -0300 | [diff] [blame] | 851 | .info = { |
| 852 | .name = "Sony HELENE Ter tuner", |
Mauro Carvalho Chehab | a3f90c7 | 2018-07-05 18:59:35 -0400 | [diff] [blame] | 853 | .frequency_min_hz = 1 * MHz, |
| 854 | .frequency_max_hz = 1200 * MHz, |
| 855 | .frequency_step_hz = 25 * kHz, |
Abylay Ospan | 2dc1ed4 | 2016-03-21 22:19:12 -0300 | [diff] [blame] | 856 | }, |
| 857 | .init = helene_init, |
| 858 | .release = helene_release, |
| 859 | .sleep = helene_sleep, |
Katsuhiro Suzuki | 817dc4b | 2018-07-17 21:06:42 -0400 | [diff] [blame] | 860 | .set_params = helene_set_params_t, |
Abylay Ospan | 2dc1ed4 | 2016-03-21 22:19:12 -0300 | [diff] [blame] | 861 | .get_frequency = helene_get_frequency, |
| 862 | }; |
| 863 | |
Julia Lawall | 14c4bf3 | 2016-09-11 11:44:12 -0300 | [diff] [blame] | 864 | static const struct dvb_tuner_ops helene_tuner_ops_s = { |
Abylay Ospan | 2dc1ed4 | 2016-03-21 22:19:12 -0300 | [diff] [blame] | 865 | .info = { |
| 866 | .name = "Sony HELENE Sat tuner", |
Mauro Carvalho Chehab | a3f90c7 | 2018-07-05 18:59:35 -0400 | [diff] [blame] | 867 | .frequency_min_hz = 500 * MHz, |
| 868 | .frequency_max_hz = 2500 * MHz, |
| 869 | .frequency_step_hz = 1 * MHz, |
Abylay Ospan | 2dc1ed4 | 2016-03-21 22:19:12 -0300 | [diff] [blame] | 870 | }, |
| 871 | .init = helene_init, |
| 872 | .release = helene_release, |
| 873 | .sleep = helene_sleep, |
| 874 | .set_params = helene_set_params_s, |
| 875 | .get_frequency = helene_get_frequency, |
| 876 | }; |
| 877 | |
Katsuhiro Suzuki | 817dc4b | 2018-07-17 21:06:42 -0400 | [diff] [blame] | 878 | static const struct dvb_tuner_ops helene_tuner_ops = { |
| 879 | .info = { |
| 880 | .name = "Sony HELENE Sat/Ter tuner", |
| 881 | .frequency_min_hz = 1 * MHz, |
| 882 | .frequency_max_hz = 2500 * MHz, |
| 883 | .frequency_step_hz = 25 * kHz, |
| 884 | }, |
| 885 | .init = helene_init, |
| 886 | .release = helene_release, |
| 887 | .sleep = helene_sleep, |
| 888 | .set_params = helene_set_params, |
| 889 | .get_frequency = helene_get_frequency, |
| 890 | }; |
| 891 | |
Abylay Ospan | 2dc1ed4 | 2016-03-21 22:19:12 -0300 | [diff] [blame] | 892 | /* power-on tuner |
| 893 | * call once after reset |
| 894 | */ |
| 895 | static int helene_x_pon(struct helene_priv *priv) |
| 896 | { |
| 897 | /* RFIN matching in power save (terrestrial) = ACTIVE */ |
| 898 | /* RFIN matching in power save (satellite) = ACTIVE */ |
| 899 | u8 dataT[] = { 0x06, 0x00, 0x02, 0x00 }; |
| 900 | /* SAT_RF_ACTIVE = true, lnaOff = false, terrRfActive = true */ |
| 901 | u8 dataS[] = { 0x05, 0x06 }; |
| 902 | u8 cdata[] = {0x7A, 0x01}; |
| 903 | u8 data[20]; |
| 904 | u8 rdata[2]; |
| 905 | |
| 906 | /* mode select */ |
| 907 | helene_write_reg(priv, 0x01, 0x00); |
| 908 | |
| 909 | helene_write_reg(priv, 0x67, dataT[3]); |
| 910 | helene_write_reg(priv, 0x43, dataS[1]); |
| 911 | helene_write_regs(priv, 0x5E, dataT, 3); |
| 912 | helene_write_reg(priv, 0x0C, dataS[0]); |
| 913 | |
| 914 | /* Initial setting for internal logic block */ |
| 915 | helene_write_regs(priv, 0x99, cdata, sizeof(cdata)); |
| 916 | |
| 917 | /* 0x81 - 0x94 */ |
Katsuhiro Suzuki | a00e5f0 | 2018-05-28 21:09:20 -0400 | [diff] [blame] | 918 | if (priv->xtal == SONY_HELENE_XTAL_16000) |
| 919 | data[0] = 0x10; /* xtal 16 MHz */ |
| 920 | else |
| 921 | data[0] = 0x18; /* xtal 24 MHz */ |
Abylay Ospan | 2dc1ed4 | 2016-03-21 22:19:12 -0300 | [diff] [blame] | 922 | data[1] = (uint8_t)(0x80 | (0x04 & 0x1F)); /* 4 x 25 = 100uA */ |
| 923 | data[2] = (uint8_t)(0x80 | (0x26 & 0x7F)); /* 38 x 0.25 = 9.5pF */ |
| 924 | data[3] = 0x80; /* REFOUT signal output 500mVpp */ |
| 925 | data[4] = 0x00; /* GPIO settings */ |
| 926 | data[5] = 0x00; /* GPIO settings */ |
| 927 | data[6] = 0xC4; /* Clock enable for internal logic block */ |
| 928 | data[7] = 0x40; /* Start CPU boot-up */ |
| 929 | data[8] = 0x10; /* For burst-write */ |
| 930 | |
| 931 | /* Setting for internal RFAGC */ |
| 932 | data[9] = 0x00; |
| 933 | data[10] = 0x45; |
| 934 | data[11] = 0x75; |
| 935 | |
| 936 | data[12] = 0x07; /* Setting for analog block */ |
| 937 | |
| 938 | /* Initial setting for internal analog block */ |
| 939 | data[13] = 0x1C; |
| 940 | data[14] = 0x3F; |
| 941 | data[15] = 0x02; |
| 942 | data[16] = 0x10; |
| 943 | data[17] = 0x20; |
| 944 | data[18] = 0x0A; |
| 945 | data[19] = 0x00; |
| 946 | |
| 947 | helene_write_regs(priv, 0x81, data, sizeof(data)); |
| 948 | |
| 949 | /* Setting for internal RFAGC */ |
| 950 | helene_write_reg(priv, 0x9B, 0x00); |
| 951 | |
| 952 | msleep(20); |
| 953 | |
| 954 | /* Check CPU_STT/CPU_ERR */ |
| 955 | helene_read_regs(priv, 0x1A, rdata, sizeof(rdata)); |
| 956 | |
| 957 | if (rdata[0] != 0x00) { |
| 958 | dev_err(&priv->i2c->dev, |
| 959 | "HELENE tuner CPU error 0x%x\n", rdata[0]); |
| 960 | return -EIO; |
| 961 | } |
| 962 | |
| 963 | /* VCO current setting */ |
| 964 | cdata[0] = 0x90; |
| 965 | cdata[1] = 0x06; |
| 966 | helene_write_regs(priv, 0x17, cdata, sizeof(cdata)); |
| 967 | msleep(20); |
| 968 | helene_read_reg(priv, 0x19, data); |
| 969 | helene_write_reg(priv, 0x95, (uint8_t)((data[0] >> 4) & 0x0F)); |
| 970 | |
| 971 | /* Disable IF signal output */ |
| 972 | helene_write_reg(priv, 0x74, 0x02); |
| 973 | |
| 974 | /* Standby setting for CPU */ |
| 975 | helene_write_reg(priv, 0x88, 0x00); |
| 976 | |
| 977 | /* Standby setting for internal logic block */ |
| 978 | helene_write_reg(priv, 0x87, 0xC0); |
| 979 | |
| 980 | /* Load capacitance control setting for crystal oscillator */ |
| 981 | helene_write_reg(priv, 0x80, 0x01); |
| 982 | |
| 983 | /* Satellite initial setting */ |
| 984 | cdata[0] = 0x07; |
| 985 | cdata[1] = 0x00; |
| 986 | helene_write_regs(priv, 0x41, cdata, sizeof(cdata)); |
| 987 | |
| 988 | dev_info(&priv->i2c->dev, |
| 989 | "HELENE tuner x_pon done\n"); |
| 990 | |
| 991 | return 0; |
| 992 | } |
| 993 | |
| 994 | struct dvb_frontend *helene_attach_s(struct dvb_frontend *fe, |
| 995 | const struct helene_config *config, |
| 996 | struct i2c_adapter *i2c) |
| 997 | { |
| 998 | struct helene_priv *priv = NULL; |
| 999 | |
| 1000 | priv = kzalloc(sizeof(struct helene_priv), GFP_KERNEL); |
| 1001 | if (priv == NULL) |
| 1002 | return NULL; |
| 1003 | priv->i2c_address = (config->i2c_address >> 1); |
| 1004 | priv->i2c = i2c; |
| 1005 | priv->set_tuner_data = config->set_tuner_priv; |
| 1006 | priv->set_tuner = config->set_tuner_callback; |
| 1007 | priv->xtal = config->xtal; |
| 1008 | |
| 1009 | if (fe->ops.i2c_gate_ctrl) |
| 1010 | fe->ops.i2c_gate_ctrl(fe, 1); |
| 1011 | |
Colin Ian King | fd32239 | 2016-08-13 15:16:54 -0300 | [diff] [blame] | 1012 | if (helene_x_pon(priv) != 0) { |
| 1013 | kfree(priv); |
Abylay Ospan | 2dc1ed4 | 2016-03-21 22:19:12 -0300 | [diff] [blame] | 1014 | return NULL; |
Colin Ian King | fd32239 | 2016-08-13 15:16:54 -0300 | [diff] [blame] | 1015 | } |
Abylay Ospan | 2dc1ed4 | 2016-03-21 22:19:12 -0300 | [diff] [blame] | 1016 | |
| 1017 | if (fe->ops.i2c_gate_ctrl) |
| 1018 | fe->ops.i2c_gate_ctrl(fe, 0); |
| 1019 | |
| 1020 | memcpy(&fe->ops.tuner_ops, &helene_tuner_ops_s, |
| 1021 | sizeof(struct dvb_tuner_ops)); |
| 1022 | fe->tuner_priv = priv; |
| 1023 | dev_info(&priv->i2c->dev, |
| 1024 | "Sony HELENE Sat attached on addr=%x at I2C adapter %p\n", |
| 1025 | priv->i2c_address, priv->i2c); |
| 1026 | return fe; |
| 1027 | } |
| 1028 | EXPORT_SYMBOL(helene_attach_s); |
| 1029 | |
| 1030 | struct dvb_frontend *helene_attach(struct dvb_frontend *fe, |
| 1031 | const struct helene_config *config, |
| 1032 | struct i2c_adapter *i2c) |
| 1033 | { |
| 1034 | struct helene_priv *priv = NULL; |
| 1035 | |
| 1036 | priv = kzalloc(sizeof(struct helene_priv), GFP_KERNEL); |
| 1037 | if (priv == NULL) |
| 1038 | return NULL; |
| 1039 | priv->i2c_address = (config->i2c_address >> 1); |
| 1040 | priv->i2c = i2c; |
| 1041 | priv->set_tuner_data = config->set_tuner_priv; |
| 1042 | priv->set_tuner = config->set_tuner_callback; |
| 1043 | priv->xtal = config->xtal; |
| 1044 | |
| 1045 | if (fe->ops.i2c_gate_ctrl) |
| 1046 | fe->ops.i2c_gate_ctrl(fe, 1); |
| 1047 | |
Colin Ian King | fd32239 | 2016-08-13 15:16:54 -0300 | [diff] [blame] | 1048 | if (helene_x_pon(priv) != 0) { |
| 1049 | kfree(priv); |
Abylay Ospan | 2dc1ed4 | 2016-03-21 22:19:12 -0300 | [diff] [blame] | 1050 | return NULL; |
Colin Ian King | fd32239 | 2016-08-13 15:16:54 -0300 | [diff] [blame] | 1051 | } |
Abylay Ospan | 2dc1ed4 | 2016-03-21 22:19:12 -0300 | [diff] [blame] | 1052 | |
| 1053 | if (fe->ops.i2c_gate_ctrl) |
| 1054 | fe->ops.i2c_gate_ctrl(fe, 0); |
| 1055 | |
Katsuhiro Suzuki | 817dc4b | 2018-07-17 21:06:42 -0400 | [diff] [blame] | 1056 | memcpy(&fe->ops.tuner_ops, &helene_tuner_ops_t, |
Abylay Ospan | 2dc1ed4 | 2016-03-21 22:19:12 -0300 | [diff] [blame] | 1057 | sizeof(struct dvb_tuner_ops)); |
| 1058 | fe->tuner_priv = priv; |
| 1059 | dev_info(&priv->i2c->dev, |
| 1060 | "Sony HELENE Ter attached on addr=%x at I2C adapter %p\n", |
| 1061 | priv->i2c_address, priv->i2c); |
| 1062 | return fe; |
| 1063 | } |
| 1064 | EXPORT_SYMBOL(helene_attach); |
| 1065 | |
Katsuhiro Suzuki | 817dc4b | 2018-07-17 21:06:42 -0400 | [diff] [blame] | 1066 | static int helene_probe(struct i2c_client *client, |
| 1067 | const struct i2c_device_id *id) |
| 1068 | { |
| 1069 | struct helene_config *config = client->dev.platform_data; |
| 1070 | struct dvb_frontend *fe = config->fe; |
| 1071 | struct device *dev = &client->dev; |
| 1072 | struct helene_priv *priv; |
| 1073 | |
| 1074 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); |
| 1075 | if (!priv) |
| 1076 | return -ENOMEM; |
| 1077 | |
| 1078 | priv->i2c_address = client->addr; |
| 1079 | priv->i2c = client->adapter; |
| 1080 | priv->set_tuner_data = config->set_tuner_priv; |
| 1081 | priv->set_tuner = config->set_tuner_callback; |
| 1082 | priv->xtal = config->xtal; |
| 1083 | |
| 1084 | if (fe->ops.i2c_gate_ctrl) |
| 1085 | fe->ops.i2c_gate_ctrl(fe, 1); |
| 1086 | |
| 1087 | if (helene_x_pon(priv) != 0) |
| 1088 | return -EINVAL; |
| 1089 | |
| 1090 | if (fe->ops.i2c_gate_ctrl) |
| 1091 | fe->ops.i2c_gate_ctrl(fe, 0); |
| 1092 | |
| 1093 | memcpy(&fe->ops.tuner_ops, &helene_tuner_ops, |
| 1094 | sizeof(struct dvb_tuner_ops)); |
| 1095 | fe->tuner_priv = priv; |
| 1096 | i2c_set_clientdata(client, priv); |
| 1097 | |
| 1098 | dev_info(dev, "Sony HELENE attached on addr=%x at I2C adapter %p\n", |
| 1099 | priv->i2c_address, priv->i2c); |
| 1100 | |
| 1101 | return 0; |
| 1102 | } |
| 1103 | |
| 1104 | static const struct i2c_device_id helene_id[] = { |
| 1105 | { "helene", }, |
| 1106 | {} |
| 1107 | }; |
| 1108 | MODULE_DEVICE_TABLE(i2c, helene_id); |
| 1109 | |
| 1110 | static struct i2c_driver helene_driver = { |
| 1111 | .driver = { |
| 1112 | .name = "helene", |
| 1113 | }, |
| 1114 | .probe = helene_probe, |
| 1115 | .id_table = helene_id, |
| 1116 | }; |
| 1117 | module_i2c_driver(helene_driver); |
| 1118 | |
Abylay Ospan | 2dc1ed4 | 2016-03-21 22:19:12 -0300 | [diff] [blame] | 1119 | MODULE_DESCRIPTION("Sony HELENE Sat/Ter tuner driver"); |
| 1120 | MODULE_AUTHOR("Abylay Ospan <aospan@netup.ru>"); |
| 1121 | MODULE_LICENSE("GPL"); |