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