18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * helene.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Sony HELENE DVB-S/S2 DVB-T/T2 DVB-C/C2 ISDB-T/S tuner driver (CXD2858ER) 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright 2012 Sony Corporation 88c2ecf20Sopenharmony_ci * Copyright (C) 2014 NetUP Inc. 98c2ecf20Sopenharmony_ci * Copyright (C) 2014 Abylay Ospan <aospan@netup.ru> 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <linux/slab.h> 138c2ecf20Sopenharmony_ci#include <linux/module.h> 148c2ecf20Sopenharmony_ci#include <linux/dvb/frontend.h> 158c2ecf20Sopenharmony_ci#include <linux/types.h> 168c2ecf20Sopenharmony_ci#include "helene.h" 178c2ecf20Sopenharmony_ci#include <media/dvb_frontend.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#define MAX_WRITE_REGSIZE 20 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_cienum helene_state { 228c2ecf20Sopenharmony_ci STATE_UNKNOWN, 238c2ecf20Sopenharmony_ci STATE_SLEEP, 248c2ecf20Sopenharmony_ci STATE_ACTIVE 258c2ecf20Sopenharmony_ci}; 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_cistruct helene_priv { 288c2ecf20Sopenharmony_ci u32 frequency; 298c2ecf20Sopenharmony_ci u8 i2c_address; 308c2ecf20Sopenharmony_ci struct i2c_adapter *i2c; 318c2ecf20Sopenharmony_ci enum helene_state state; 328c2ecf20Sopenharmony_ci void *set_tuner_data; 338c2ecf20Sopenharmony_ci int (*set_tuner)(void *, int); 348c2ecf20Sopenharmony_ci enum helene_xtal xtal; 358c2ecf20Sopenharmony_ci}; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci#define TERR_INTERNAL_LOOPFILTER_AVAILABLE(tv_system) \ 388c2ecf20Sopenharmony_ci (((tv_system) != SONY_HELENE_DTV_DVBC_6) && \ 398c2ecf20Sopenharmony_ci ((tv_system) != SONY_HELENE_DTV_DVBC_8)\ 408c2ecf20Sopenharmony_ci && ((tv_system) != SONY_HELENE_DTV_DVBC2_6) && \ 418c2ecf20Sopenharmony_ci ((tv_system) != SONY_HELENE_DTV_DVBC2_8)) 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci#define HELENE_AUTO 0xff 448c2ecf20Sopenharmony_ci#define HELENE_OFFSET(ofs) ((u8)(ofs) & 0x1F) 458c2ecf20Sopenharmony_ci#define HELENE_BW_6 0x00 468c2ecf20Sopenharmony_ci#define HELENE_BW_7 0x01 478c2ecf20Sopenharmony_ci#define HELENE_BW_8 0x02 488c2ecf20Sopenharmony_ci#define HELENE_BW_1_7 0x03 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_cienum helene_tv_system_t { 518c2ecf20Sopenharmony_ci SONY_HELENE_TV_SYSTEM_UNKNOWN, 528c2ecf20Sopenharmony_ci /* Terrestrial Analog */ 538c2ecf20Sopenharmony_ci SONY_HELENE_ATV_MN_EIAJ, 548c2ecf20Sopenharmony_ci /**< System-M (Japan) (IF: Fp=5.75MHz in default) */ 558c2ecf20Sopenharmony_ci SONY_HELENE_ATV_MN_SAP, 568c2ecf20Sopenharmony_ci /**< System-M (US) (IF: Fp=5.75MHz in default) */ 578c2ecf20Sopenharmony_ci SONY_HELENE_ATV_MN_A2, 588c2ecf20Sopenharmony_ci /**< System-M (Korea) (IF: Fp=5.9MHz in default) */ 598c2ecf20Sopenharmony_ci SONY_HELENE_ATV_BG, 608c2ecf20Sopenharmony_ci /**< System-B/G (IF: Fp=7.3MHz in default) */ 618c2ecf20Sopenharmony_ci SONY_HELENE_ATV_I, 628c2ecf20Sopenharmony_ci /**< System-I (IF: Fp=7.85MHz in default) */ 638c2ecf20Sopenharmony_ci SONY_HELENE_ATV_DK, 648c2ecf20Sopenharmony_ci /**< System-D/K (IF: Fp=7.85MHz in default) */ 658c2ecf20Sopenharmony_ci SONY_HELENE_ATV_L, 668c2ecf20Sopenharmony_ci /**< System-L (IF: Fp=7.85MHz in default) */ 678c2ecf20Sopenharmony_ci SONY_HELENE_ATV_L_DASH, 688c2ecf20Sopenharmony_ci /**< System-L DASH (IF: Fp=2.2MHz in default) */ 698c2ecf20Sopenharmony_ci /* Terrestrial/Cable Digital */ 708c2ecf20Sopenharmony_ci SONY_HELENE_DTV_8VSB, 718c2ecf20Sopenharmony_ci /**< ATSC 8VSB (IF: Fc=3.7MHz in default) */ 728c2ecf20Sopenharmony_ci SONY_HELENE_DTV_QAM, 738c2ecf20Sopenharmony_ci /**< US QAM (IF: Fc=3.7MHz in default) */ 748c2ecf20Sopenharmony_ci SONY_HELENE_DTV_ISDBT_6, 758c2ecf20Sopenharmony_ci /**< ISDB-T 6MHzBW (IF: Fc=3.55MHz in default) */ 768c2ecf20Sopenharmony_ci SONY_HELENE_DTV_ISDBT_7, 778c2ecf20Sopenharmony_ci /**< ISDB-T 7MHzBW (IF: Fc=4.15MHz in default) */ 788c2ecf20Sopenharmony_ci SONY_HELENE_DTV_ISDBT_8, 798c2ecf20Sopenharmony_ci /**< ISDB-T 8MHzBW (IF: Fc=4.75MHz in default) */ 808c2ecf20Sopenharmony_ci SONY_HELENE_DTV_DVBT_5, 818c2ecf20Sopenharmony_ci /**< DVB-T 5MHzBW (IF: Fc=3.6MHz in default) */ 828c2ecf20Sopenharmony_ci SONY_HELENE_DTV_DVBT_6, 838c2ecf20Sopenharmony_ci /**< DVB-T 6MHzBW (IF: Fc=3.6MHz in default) */ 848c2ecf20Sopenharmony_ci SONY_HELENE_DTV_DVBT_7, 858c2ecf20Sopenharmony_ci /**< DVB-T 7MHzBW (IF: Fc=4.2MHz in default) */ 868c2ecf20Sopenharmony_ci SONY_HELENE_DTV_DVBT_8, 878c2ecf20Sopenharmony_ci /**< DVB-T 8MHzBW (IF: Fc=4.8MHz in default) */ 888c2ecf20Sopenharmony_ci SONY_HELENE_DTV_DVBT2_1_7, 898c2ecf20Sopenharmony_ci /**< DVB-T2 1.7MHzBW (IF: Fc=3.5MHz in default) */ 908c2ecf20Sopenharmony_ci SONY_HELENE_DTV_DVBT2_5, 918c2ecf20Sopenharmony_ci /**< DVB-T2 5MHzBW (IF: Fc=3.6MHz in default) */ 928c2ecf20Sopenharmony_ci SONY_HELENE_DTV_DVBT2_6, 938c2ecf20Sopenharmony_ci /**< DVB-T2 6MHzBW (IF: Fc=3.6MHz in default) */ 948c2ecf20Sopenharmony_ci SONY_HELENE_DTV_DVBT2_7, 958c2ecf20Sopenharmony_ci /**< DVB-T2 7MHzBW (IF: Fc=4.2MHz in default) */ 968c2ecf20Sopenharmony_ci SONY_HELENE_DTV_DVBT2_8, 978c2ecf20Sopenharmony_ci /**< DVB-T2 8MHzBW (IF: Fc=4.8MHz in default) */ 988c2ecf20Sopenharmony_ci SONY_HELENE_DTV_DVBC_6, 998c2ecf20Sopenharmony_ci /**< DVB-C 6MHzBW (IF: Fc=3.7MHz in default) */ 1008c2ecf20Sopenharmony_ci SONY_HELENE_DTV_DVBC_8, 1018c2ecf20Sopenharmony_ci /**< DVB-C 8MHzBW (IF: Fc=4.9MHz in default) */ 1028c2ecf20Sopenharmony_ci SONY_HELENE_DTV_DVBC2_6, 1038c2ecf20Sopenharmony_ci /**< DVB-C2 6MHzBW (IF: Fc=3.7MHz in default) */ 1048c2ecf20Sopenharmony_ci SONY_HELENE_DTV_DVBC2_8, 1058c2ecf20Sopenharmony_ci /**< DVB-C2 8MHzBW (IF: Fc=4.9MHz in default) */ 1068c2ecf20Sopenharmony_ci SONY_HELENE_DTV_DTMB, 1078c2ecf20Sopenharmony_ci /**< DTMB (IF: Fc=5.1MHz in default) */ 1088c2ecf20Sopenharmony_ci /* Satellite */ 1098c2ecf20Sopenharmony_ci SONY_HELENE_STV_ISDBS, 1108c2ecf20Sopenharmony_ci /**< ISDB-S */ 1118c2ecf20Sopenharmony_ci SONY_HELENE_STV_DVBS, 1128c2ecf20Sopenharmony_ci /**< DVB-S */ 1138c2ecf20Sopenharmony_ci SONY_HELENE_STV_DVBS2, 1148c2ecf20Sopenharmony_ci /**< DVB-S2 */ 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci SONY_HELENE_ATV_MIN = SONY_HELENE_ATV_MN_EIAJ, 1178c2ecf20Sopenharmony_ci /**< Minimum analog terrestrial system */ 1188c2ecf20Sopenharmony_ci SONY_HELENE_ATV_MAX = SONY_HELENE_ATV_L_DASH, 1198c2ecf20Sopenharmony_ci /**< Maximum analog terrestrial system */ 1208c2ecf20Sopenharmony_ci SONY_HELENE_DTV_MIN = SONY_HELENE_DTV_8VSB, 1218c2ecf20Sopenharmony_ci /**< Minimum digital terrestrial system */ 1228c2ecf20Sopenharmony_ci SONY_HELENE_DTV_MAX = SONY_HELENE_DTV_DTMB, 1238c2ecf20Sopenharmony_ci /**< Maximum digital terrestrial system */ 1248c2ecf20Sopenharmony_ci SONY_HELENE_TERR_TV_SYSTEM_NUM, 1258c2ecf20Sopenharmony_ci /**< Number of supported terrestrial broadcasting system */ 1268c2ecf20Sopenharmony_ci SONY_HELENE_STV_MIN = SONY_HELENE_STV_ISDBS, 1278c2ecf20Sopenharmony_ci /**< Minimum satellite system */ 1288c2ecf20Sopenharmony_ci SONY_HELENE_STV_MAX = SONY_HELENE_STV_DVBS2 1298c2ecf20Sopenharmony_ci /**< Maximum satellite system */ 1308c2ecf20Sopenharmony_ci}; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_cistruct helene_terr_adjust_param_t { 1338c2ecf20Sopenharmony_ci /* < Addr:0x69 Bit[6:4] : RFVGA gain. 1348c2ecf20Sopenharmony_ci * 0xFF means Auto. (RF_GAIN_SEL = 1) 1358c2ecf20Sopenharmony_ci */ 1368c2ecf20Sopenharmony_ci uint8_t RF_GAIN; 1378c2ecf20Sopenharmony_ci /* < Addr:0x69 Bit[3:0] : IF_BPF gain. 1388c2ecf20Sopenharmony_ci */ 1398c2ecf20Sopenharmony_ci uint8_t IF_BPF_GC; 1408c2ecf20Sopenharmony_ci /* < Addr:0x6B Bit[3:0] : RF overload 1418c2ecf20Sopenharmony_ci * RF input detect level. (FRF <= 172MHz) 1428c2ecf20Sopenharmony_ci */ 1438c2ecf20Sopenharmony_ci uint8_t RFOVLD_DET_LV1_VL; 1448c2ecf20Sopenharmony_ci /* < Addr:0x6B Bit[3:0] : RF overload 1458c2ecf20Sopenharmony_ci * RF input detect level. (172MHz < FRF <= 464MHz) 1468c2ecf20Sopenharmony_ci */ 1478c2ecf20Sopenharmony_ci uint8_t RFOVLD_DET_LV1_VH; 1488c2ecf20Sopenharmony_ci /* < Addr:0x6B Bit[3:0] : RF overload 1498c2ecf20Sopenharmony_ci * RF input detect level. (FRF > 464MHz) 1508c2ecf20Sopenharmony_ci */ 1518c2ecf20Sopenharmony_ci uint8_t RFOVLD_DET_LV1_U; 1528c2ecf20Sopenharmony_ci /* < Addr:0x6C Bit[2:0] : 1538c2ecf20Sopenharmony_ci * Internal RFAGC detect level. (FRF <= 172MHz) 1548c2ecf20Sopenharmony_ci */ 1558c2ecf20Sopenharmony_ci uint8_t IFOVLD_DET_LV_VL; 1568c2ecf20Sopenharmony_ci /* < Addr:0x6C Bit[2:0] : 1578c2ecf20Sopenharmony_ci * Internal RFAGC detect level. (172MHz < FRF <= 464MHz) 1588c2ecf20Sopenharmony_ci */ 1598c2ecf20Sopenharmony_ci uint8_t IFOVLD_DET_LV_VH; 1608c2ecf20Sopenharmony_ci /* < Addr:0x6C Bit[2:0] : 1618c2ecf20Sopenharmony_ci * Internal RFAGC detect level. (FRF > 464MHz) 1628c2ecf20Sopenharmony_ci */ 1638c2ecf20Sopenharmony_ci uint8_t IFOVLD_DET_LV_U; 1648c2ecf20Sopenharmony_ci /* < Addr:0x6D Bit[5:4] : 1658c2ecf20Sopenharmony_ci * IF filter center offset. 1668c2ecf20Sopenharmony_ci */ 1678c2ecf20Sopenharmony_ci uint8_t IF_BPF_F0; 1688c2ecf20Sopenharmony_ci /* < Addr:0x6D Bit[1:0] : 1698c2ecf20Sopenharmony_ci * 6MHzBW(0x00) or 7MHzBW(0x01) 1708c2ecf20Sopenharmony_ci * or 8MHzBW(0x02) or 1.7MHzBW(0x03) 1718c2ecf20Sopenharmony_ci */ 1728c2ecf20Sopenharmony_ci uint8_t BW; 1738c2ecf20Sopenharmony_ci /* < Addr:0x6E Bit[4:0] : 1748c2ecf20Sopenharmony_ci * 5bit signed. IF offset (kHz) = FIF_OFFSET x 50 1758c2ecf20Sopenharmony_ci */ 1768c2ecf20Sopenharmony_ci uint8_t FIF_OFFSET; 1778c2ecf20Sopenharmony_ci /* < Addr:0x6F Bit[4:0] : 1788c2ecf20Sopenharmony_ci * 5bit signed. BW offset (kHz) = 1798c2ecf20Sopenharmony_ci * BW_OFFSET x 50 (BW_OFFSET x 10 in 1.7MHzBW) 1808c2ecf20Sopenharmony_ci */ 1818c2ecf20Sopenharmony_ci uint8_t BW_OFFSET; 1828c2ecf20Sopenharmony_ci /* < Addr:0x9C Bit[0] : 1838c2ecf20Sopenharmony_ci * Local polarity. (0: Upper Local, 1: Lower Local) 1848c2ecf20Sopenharmony_ci */ 1858c2ecf20Sopenharmony_ci uint8_t IS_LOWERLOCAL; 1868c2ecf20Sopenharmony_ci}; 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_cistatic const struct helene_terr_adjust_param_t 1898c2ecf20Sopenharmony_citerr_params[SONY_HELENE_TERR_TV_SYSTEM_NUM] = { 1908c2ecf20Sopenharmony_ci /*< SONY_HELENE_TV_SYSTEM_UNKNOWN */ 1918c2ecf20Sopenharmony_ci {HELENE_AUTO, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1928c2ecf20Sopenharmony_ci HELENE_BW_6, HELENE_OFFSET(0), HELENE_OFFSET(0), 0x00}, 1938c2ecf20Sopenharmony_ci /* Analog */ 1948c2ecf20Sopenharmony_ci /**< SONY_HELENE_ATV_MN_EIAJ (System-M (Japan)) */ 1958c2ecf20Sopenharmony_ci {HELENE_AUTO, 0x05, 0x03, 0x06, 0x03, 0x01, 0x01, 0x01, 0x00, 1968c2ecf20Sopenharmony_ci HELENE_BW_6, HELENE_OFFSET(0), HELENE_OFFSET(1), 0x00}, 1978c2ecf20Sopenharmony_ci /**< SONY_HELENE_ATV_MN_SAP (System-M (US)) */ 1988c2ecf20Sopenharmony_ci {HELENE_AUTO, 0x05, 0x03, 0x06, 0x03, 0x01, 0x01, 0x01, 0x00, 1998c2ecf20Sopenharmony_ci HELENE_BW_6, HELENE_OFFSET(0), HELENE_OFFSET(1), 0x00}, 2008c2ecf20Sopenharmony_ci {HELENE_AUTO, 0x05, 0x03, 0x06, 0x03, 0x01, 0x01, 0x01, 0x00, 2018c2ecf20Sopenharmony_ci HELENE_BW_6, HELENE_OFFSET(3), HELENE_OFFSET(1), 0x00}, 2028c2ecf20Sopenharmony_ci /**< SONY_HELENE_ATV_MN_A2 (System-M (Korea)) */ 2038c2ecf20Sopenharmony_ci {HELENE_AUTO, 0x05, 0x03, 0x06, 0x03, 0x01, 0x01, 0x01, 0x00, 2048c2ecf20Sopenharmony_ci HELENE_BW_7, HELENE_OFFSET(11), HELENE_OFFSET(5), 0x00}, 2058c2ecf20Sopenharmony_ci /**< SONY_HELENE_ATV_BG (System-B/G) */ 2068c2ecf20Sopenharmony_ci {HELENE_AUTO, 0x05, 0x03, 0x06, 0x03, 0x01, 0x01, 0x01, 0x00, 2078c2ecf20Sopenharmony_ci HELENE_BW_8, HELENE_OFFSET(2), HELENE_OFFSET(-3), 0x00}, 2088c2ecf20Sopenharmony_ci /**< SONY_HELENE_ATV_I (System-I) */ 2098c2ecf20Sopenharmony_ci {HELENE_AUTO, 0x05, 0x03, 0x06, 0x03, 0x01, 0x01, 0x01, 0x00, 2108c2ecf20Sopenharmony_ci HELENE_BW_8, HELENE_OFFSET(2), HELENE_OFFSET(-3), 0x00}, 2118c2ecf20Sopenharmony_ci /**< SONY_HELENE_ATV_DK (System-D/K) */ 2128c2ecf20Sopenharmony_ci {HELENE_AUTO, 0x03, 0x04, 0x0A, 0x04, 0x04, 0x04, 0x04, 0x00, 2138c2ecf20Sopenharmony_ci HELENE_BW_8, HELENE_OFFSET(2), HELENE_OFFSET(-3), 0x00}, 2148c2ecf20Sopenharmony_ci /**< SONY_HELENE_ATV_L (System-L) */ 2158c2ecf20Sopenharmony_ci {HELENE_AUTO, 0x03, 0x04, 0x0A, 0x04, 0x04, 0x04, 0x04, 0x00, 2168c2ecf20Sopenharmony_ci HELENE_BW_8, HELENE_OFFSET(-1), HELENE_OFFSET(4), 0x00}, 2178c2ecf20Sopenharmony_ci /**< SONY_HELENE_ATV_L_DASH (System-L DASH) */ 2188c2ecf20Sopenharmony_ci /* Digital */ 2198c2ecf20Sopenharmony_ci {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x03, 0x03, 0x03, 0x00, 2208c2ecf20Sopenharmony_ci HELENE_BW_6, HELENE_OFFSET(-6), HELENE_OFFSET(-3), 0x00}, 2218c2ecf20Sopenharmony_ci /**< SONY_HELENE_DTV_8VSB (ATSC 8VSB) */ 2228c2ecf20Sopenharmony_ci {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00, 2238c2ecf20Sopenharmony_ci HELENE_BW_6, HELENE_OFFSET(-6), HELENE_OFFSET(-3), 0x00}, 2248c2ecf20Sopenharmony_ci /**< SONY_HELENE_DTV_QAM (US QAM) */ 2258c2ecf20Sopenharmony_ci {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00, 2268c2ecf20Sopenharmony_ci HELENE_BW_6, HELENE_OFFSET(-9), HELENE_OFFSET(-5), 0x00}, 2278c2ecf20Sopenharmony_ci /**< SONY_HELENE_DTV_ISDBT_6 (ISDB-T 6MHzBW) */ 2288c2ecf20Sopenharmony_ci {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00, 2298c2ecf20Sopenharmony_ci HELENE_BW_7, HELENE_OFFSET(-7), HELENE_OFFSET(-6), 0x00}, 2308c2ecf20Sopenharmony_ci /**< SONY_HELENE_DTV_ISDBT_7 (ISDB-T 7MHzBW) */ 2318c2ecf20Sopenharmony_ci {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00, 2328c2ecf20Sopenharmony_ci HELENE_BW_8, HELENE_OFFSET(-5), HELENE_OFFSET(-7), 0x00}, 2338c2ecf20Sopenharmony_ci /**< SONY_HELENE_DTV_ISDBT_8 (ISDB-T 8MHzBW) */ 2348c2ecf20Sopenharmony_ci {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00, 2358c2ecf20Sopenharmony_ci HELENE_BW_6, HELENE_OFFSET(-8), HELENE_OFFSET(-3), 0x00}, 2368c2ecf20Sopenharmony_ci /**< SONY_HELENE_DTV_DVBT_5 (DVB-T 5MHzBW) */ 2378c2ecf20Sopenharmony_ci {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00, 2388c2ecf20Sopenharmony_ci HELENE_BW_6, HELENE_OFFSET(-8), HELENE_OFFSET(-3), 0x00}, 2398c2ecf20Sopenharmony_ci /**< SONY_HELENE_DTV_DVBT_6 (DVB-T 6MHzBW) */ 2408c2ecf20Sopenharmony_ci {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00, 2418c2ecf20Sopenharmony_ci HELENE_BW_7, HELENE_OFFSET(-6), HELENE_OFFSET(-5), 0x00}, 2428c2ecf20Sopenharmony_ci /**< SONY_HELENE_DTV_DVBT_7 (DVB-T 7MHzBW) */ 2438c2ecf20Sopenharmony_ci {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00, 2448c2ecf20Sopenharmony_ci HELENE_BW_8, HELENE_OFFSET(-4), HELENE_OFFSET(-6), 0x00}, 2458c2ecf20Sopenharmony_ci /**< SONY_HELENE_DTV_DVBT_8 (DVB-T 8MHzBW) */ 2468c2ecf20Sopenharmony_ci {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00, 2478c2ecf20Sopenharmony_ci HELENE_BW_1_7, HELENE_OFFSET(-10), HELENE_OFFSET(-10), 0x00}, 2488c2ecf20Sopenharmony_ci /**< SONY_HELENE_DTV_DVBT2_1_7 (DVB-T2 1.7MHzBW) */ 2498c2ecf20Sopenharmony_ci {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00, 2508c2ecf20Sopenharmony_ci HELENE_BW_6, HELENE_OFFSET(-8), HELENE_OFFSET(-3), 0x00}, 2518c2ecf20Sopenharmony_ci /**< SONY_HELENE_DTV_DVBT2_5 (DVB-T2 5MHzBW) */ 2528c2ecf20Sopenharmony_ci {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00, 2538c2ecf20Sopenharmony_ci HELENE_BW_6, HELENE_OFFSET(-8), HELENE_OFFSET(-3), 0x00}, 2548c2ecf20Sopenharmony_ci /**< SONY_HELENE_DTV_DVBT2_6 (DVB-T2 6MHzBW) */ 2558c2ecf20Sopenharmony_ci {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00, 2568c2ecf20Sopenharmony_ci HELENE_BW_7, HELENE_OFFSET(-6), HELENE_OFFSET(-5), 0x00}, 2578c2ecf20Sopenharmony_ci /**< SONY_HELENE_DTV_DVBT2_7 (DVB-T2 7MHzBW) */ 2588c2ecf20Sopenharmony_ci {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00, 2598c2ecf20Sopenharmony_ci HELENE_BW_8, HELENE_OFFSET(-4), HELENE_OFFSET(-6), 0x00}, 2608c2ecf20Sopenharmony_ci /**< SONY_HELENE_DTV_DVBT2_8 (DVB-T2 8MHzBW) */ 2618c2ecf20Sopenharmony_ci {HELENE_AUTO, 0x05, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x00, 2628c2ecf20Sopenharmony_ci HELENE_BW_6, HELENE_OFFSET(-6), HELENE_OFFSET(-4), 0x00}, 2638c2ecf20Sopenharmony_ci /**< SONY_HELENE_DTV_DVBC_6 (DVB-C 6MHzBW) */ 2648c2ecf20Sopenharmony_ci {HELENE_AUTO, 0x05, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x00, 2658c2ecf20Sopenharmony_ci HELENE_BW_8, HELENE_OFFSET(-2), HELENE_OFFSET(-3), 0x00}, 2668c2ecf20Sopenharmony_ci /**< SONY_HELENE_DTV_DVBC_8 (DVB-C 8MHzBW) */ 2678c2ecf20Sopenharmony_ci {HELENE_AUTO, 0x03, 0x09, 0x09, 0x09, 0x02, 0x02, 0x02, 0x00, 2688c2ecf20Sopenharmony_ci HELENE_BW_6, HELENE_OFFSET(-6), HELENE_OFFSET(-2), 0x00}, 2698c2ecf20Sopenharmony_ci /**< SONY_HELENE_DTV_DVBC2_6 (DVB-C2 6MHzBW) */ 2708c2ecf20Sopenharmony_ci {HELENE_AUTO, 0x03, 0x09, 0x09, 0x09, 0x02, 0x02, 0x02, 0x00, 2718c2ecf20Sopenharmony_ci HELENE_BW_8, HELENE_OFFSET(-2), HELENE_OFFSET(0), 0x00}, 2728c2ecf20Sopenharmony_ci /**< SONY_HELENE_DTV_DVBC2_8 (DVB-C2 8MHzBW) */ 2738c2ecf20Sopenharmony_ci {HELENE_AUTO, 0x04, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00, 2748c2ecf20Sopenharmony_ci HELENE_BW_8, HELENE_OFFSET(2), HELENE_OFFSET(1), 0x00} 2758c2ecf20Sopenharmony_ci /**< SONY_HELENE_DTV_DTMB (DTMB) */ 2768c2ecf20Sopenharmony_ci}; 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_cistatic void helene_i2c_debug(struct helene_priv *priv, 2798c2ecf20Sopenharmony_ci u8 reg, u8 write, const u8 *data, u32 len) 2808c2ecf20Sopenharmony_ci{ 2818c2ecf20Sopenharmony_ci dev_dbg(&priv->i2c->dev, "helene: I2C %s reg 0x%02x size %d\n", 2828c2ecf20Sopenharmony_ci (write == 0 ? "read" : "write"), reg, len); 2838c2ecf20Sopenharmony_ci print_hex_dump_bytes("helene: I2C data: ", 2848c2ecf20Sopenharmony_ci DUMP_PREFIX_OFFSET, data, len); 2858c2ecf20Sopenharmony_ci} 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_cistatic int helene_write_regs(struct helene_priv *priv, 2888c2ecf20Sopenharmony_ci u8 reg, const u8 *data, u32 len) 2898c2ecf20Sopenharmony_ci{ 2908c2ecf20Sopenharmony_ci int ret; 2918c2ecf20Sopenharmony_ci u8 buf[MAX_WRITE_REGSIZE + 1]; 2928c2ecf20Sopenharmony_ci struct i2c_msg msg[1] = { 2938c2ecf20Sopenharmony_ci { 2948c2ecf20Sopenharmony_ci .addr = priv->i2c_address, 2958c2ecf20Sopenharmony_ci .flags = 0, 2968c2ecf20Sopenharmony_ci .len = len + 1, 2978c2ecf20Sopenharmony_ci .buf = buf, 2988c2ecf20Sopenharmony_ci } 2998c2ecf20Sopenharmony_ci }; 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci if (len + 1 > sizeof(buf)) { 3028c2ecf20Sopenharmony_ci dev_warn(&priv->i2c->dev, 3038c2ecf20Sopenharmony_ci "wr reg=%04x: len=%d vs %zu is too big!\n", 3048c2ecf20Sopenharmony_ci reg, len + 1, sizeof(buf)); 3058c2ecf20Sopenharmony_ci return -E2BIG; 3068c2ecf20Sopenharmony_ci } 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci helene_i2c_debug(priv, reg, 1, data, len); 3098c2ecf20Sopenharmony_ci buf[0] = reg; 3108c2ecf20Sopenharmony_ci memcpy(&buf[1], data, len); 3118c2ecf20Sopenharmony_ci ret = i2c_transfer(priv->i2c, msg, 1); 3128c2ecf20Sopenharmony_ci if (ret >= 0 && ret != 1) 3138c2ecf20Sopenharmony_ci ret = -EREMOTEIO; 3148c2ecf20Sopenharmony_ci if (ret < 0) { 3158c2ecf20Sopenharmony_ci dev_warn(&priv->i2c->dev, 3168c2ecf20Sopenharmony_ci "%s: i2c wr failed=%d reg=%02x len=%d\n", 3178c2ecf20Sopenharmony_ci KBUILD_MODNAME, ret, reg, len); 3188c2ecf20Sopenharmony_ci return ret; 3198c2ecf20Sopenharmony_ci } 3208c2ecf20Sopenharmony_ci return 0; 3218c2ecf20Sopenharmony_ci} 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_cistatic int helene_write_reg(struct helene_priv *priv, u8 reg, u8 val) 3248c2ecf20Sopenharmony_ci{ 3258c2ecf20Sopenharmony_ci u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */ 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci return helene_write_regs(priv, reg, &tmp, 1); 3288c2ecf20Sopenharmony_ci} 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_cistatic int helene_read_regs(struct helene_priv *priv, 3318c2ecf20Sopenharmony_ci u8 reg, u8 *val, u32 len) 3328c2ecf20Sopenharmony_ci{ 3338c2ecf20Sopenharmony_ci int ret; 3348c2ecf20Sopenharmony_ci struct i2c_msg msg[2] = { 3358c2ecf20Sopenharmony_ci { 3368c2ecf20Sopenharmony_ci .addr = priv->i2c_address, 3378c2ecf20Sopenharmony_ci .flags = 0, 3388c2ecf20Sopenharmony_ci .len = 1, 3398c2ecf20Sopenharmony_ci .buf = ®, 3408c2ecf20Sopenharmony_ci }, { 3418c2ecf20Sopenharmony_ci .addr = priv->i2c_address, 3428c2ecf20Sopenharmony_ci .flags = I2C_M_RD, 3438c2ecf20Sopenharmony_ci .len = len, 3448c2ecf20Sopenharmony_ci .buf = val, 3458c2ecf20Sopenharmony_ci } 3468c2ecf20Sopenharmony_ci }; 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci ret = i2c_transfer(priv->i2c, &msg[0], 1); 3498c2ecf20Sopenharmony_ci if (ret >= 0 && ret != 1) 3508c2ecf20Sopenharmony_ci ret = -EREMOTEIO; 3518c2ecf20Sopenharmony_ci if (ret < 0) { 3528c2ecf20Sopenharmony_ci dev_warn(&priv->i2c->dev, 3538c2ecf20Sopenharmony_ci "%s: I2C rw failed=%d addr=%02x reg=%02x\n", 3548c2ecf20Sopenharmony_ci KBUILD_MODNAME, ret, priv->i2c_address, reg); 3558c2ecf20Sopenharmony_ci return ret; 3568c2ecf20Sopenharmony_ci } 3578c2ecf20Sopenharmony_ci ret = i2c_transfer(priv->i2c, &msg[1], 1); 3588c2ecf20Sopenharmony_ci if (ret >= 0 && ret != 1) 3598c2ecf20Sopenharmony_ci ret = -EREMOTEIO; 3608c2ecf20Sopenharmony_ci if (ret < 0) { 3618c2ecf20Sopenharmony_ci dev_warn(&priv->i2c->dev, 3628c2ecf20Sopenharmony_ci "%s: i2c rd failed=%d addr=%02x reg=%02x\n", 3638c2ecf20Sopenharmony_ci KBUILD_MODNAME, ret, priv->i2c_address, reg); 3648c2ecf20Sopenharmony_ci return ret; 3658c2ecf20Sopenharmony_ci } 3668c2ecf20Sopenharmony_ci helene_i2c_debug(priv, reg, 0, val, len); 3678c2ecf20Sopenharmony_ci return 0; 3688c2ecf20Sopenharmony_ci} 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_cistatic int helene_read_reg(struct helene_priv *priv, u8 reg, u8 *val) 3718c2ecf20Sopenharmony_ci{ 3728c2ecf20Sopenharmony_ci return helene_read_regs(priv, reg, val, 1); 3738c2ecf20Sopenharmony_ci} 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_cistatic int helene_set_reg_bits(struct helene_priv *priv, 3768c2ecf20Sopenharmony_ci u8 reg, u8 data, u8 mask) 3778c2ecf20Sopenharmony_ci{ 3788c2ecf20Sopenharmony_ci int res; 3798c2ecf20Sopenharmony_ci u8 rdata; 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ci if (mask != 0xff) { 3828c2ecf20Sopenharmony_ci res = helene_read_reg(priv, reg, &rdata); 3838c2ecf20Sopenharmony_ci if (res != 0) 3848c2ecf20Sopenharmony_ci return res; 3858c2ecf20Sopenharmony_ci data = ((data & mask) | (rdata & (mask ^ 0xFF))); 3868c2ecf20Sopenharmony_ci } 3878c2ecf20Sopenharmony_ci return helene_write_reg(priv, reg, data); 3888c2ecf20Sopenharmony_ci} 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_cistatic int helene_enter_power_save(struct helene_priv *priv) 3918c2ecf20Sopenharmony_ci{ 3928c2ecf20Sopenharmony_ci dev_dbg(&priv->i2c->dev, "%s()\n", __func__); 3938c2ecf20Sopenharmony_ci if (priv->state == STATE_SLEEP) 3948c2ecf20Sopenharmony_ci return 0; 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci /* Standby setting for CPU */ 3978c2ecf20Sopenharmony_ci helene_write_reg(priv, 0x88, 0x0); 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ci /* Standby setting for internal logic block */ 4008c2ecf20Sopenharmony_ci helene_write_reg(priv, 0x87, 0xC0); 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci priv->state = STATE_SLEEP; 4038c2ecf20Sopenharmony_ci return 0; 4048c2ecf20Sopenharmony_ci} 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_cistatic int helene_leave_power_save(struct helene_priv *priv) 4078c2ecf20Sopenharmony_ci{ 4088c2ecf20Sopenharmony_ci dev_dbg(&priv->i2c->dev, "%s()\n", __func__); 4098c2ecf20Sopenharmony_ci if (priv->state == STATE_ACTIVE) 4108c2ecf20Sopenharmony_ci return 0; 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci /* Standby setting for internal logic block */ 4138c2ecf20Sopenharmony_ci helene_write_reg(priv, 0x87, 0xC4); 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci /* Standby setting for CPU */ 4168c2ecf20Sopenharmony_ci helene_write_reg(priv, 0x88, 0x40); 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci priv->state = STATE_ACTIVE; 4198c2ecf20Sopenharmony_ci return 0; 4208c2ecf20Sopenharmony_ci} 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_cistatic int helene_init(struct dvb_frontend *fe) 4238c2ecf20Sopenharmony_ci{ 4248c2ecf20Sopenharmony_ci struct helene_priv *priv = fe->tuner_priv; 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci dev_dbg(&priv->i2c->dev, "%s()\n", __func__); 4278c2ecf20Sopenharmony_ci return helene_leave_power_save(priv); 4288c2ecf20Sopenharmony_ci} 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_cistatic void helene_release(struct dvb_frontend *fe) 4318c2ecf20Sopenharmony_ci{ 4328c2ecf20Sopenharmony_ci struct helene_priv *priv = fe->tuner_priv; 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci dev_dbg(&priv->i2c->dev, "%s()\n", __func__); 4358c2ecf20Sopenharmony_ci kfree(fe->tuner_priv); 4368c2ecf20Sopenharmony_ci fe->tuner_priv = NULL; 4378c2ecf20Sopenharmony_ci} 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_cistatic int helene_sleep(struct dvb_frontend *fe) 4408c2ecf20Sopenharmony_ci{ 4418c2ecf20Sopenharmony_ci struct helene_priv *priv = fe->tuner_priv; 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ci dev_dbg(&priv->i2c->dev, "%s()\n", __func__); 4448c2ecf20Sopenharmony_ci helene_enter_power_save(priv); 4458c2ecf20Sopenharmony_ci return 0; 4468c2ecf20Sopenharmony_ci} 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_cistatic enum helene_tv_system_t helene_get_tv_system(struct dvb_frontend *fe) 4498c2ecf20Sopenharmony_ci{ 4508c2ecf20Sopenharmony_ci enum helene_tv_system_t system = SONY_HELENE_TV_SYSTEM_UNKNOWN; 4518c2ecf20Sopenharmony_ci struct dtv_frontend_properties *p = &fe->dtv_property_cache; 4528c2ecf20Sopenharmony_ci struct helene_priv *priv = fe->tuner_priv; 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ci if (p->delivery_system == SYS_DVBT) { 4558c2ecf20Sopenharmony_ci if (p->bandwidth_hz <= 5000000) 4568c2ecf20Sopenharmony_ci system = SONY_HELENE_DTV_DVBT_5; 4578c2ecf20Sopenharmony_ci else if (p->bandwidth_hz <= 6000000) 4588c2ecf20Sopenharmony_ci system = SONY_HELENE_DTV_DVBT_6; 4598c2ecf20Sopenharmony_ci else if (p->bandwidth_hz <= 7000000) 4608c2ecf20Sopenharmony_ci system = SONY_HELENE_DTV_DVBT_7; 4618c2ecf20Sopenharmony_ci else if (p->bandwidth_hz <= 8000000) 4628c2ecf20Sopenharmony_ci system = SONY_HELENE_DTV_DVBT_8; 4638c2ecf20Sopenharmony_ci else { 4648c2ecf20Sopenharmony_ci system = SONY_HELENE_DTV_DVBT_8; 4658c2ecf20Sopenharmony_ci p->bandwidth_hz = 8000000; 4668c2ecf20Sopenharmony_ci } 4678c2ecf20Sopenharmony_ci } else if (p->delivery_system == SYS_DVBT2) { 4688c2ecf20Sopenharmony_ci if (p->bandwidth_hz <= 5000000) 4698c2ecf20Sopenharmony_ci system = SONY_HELENE_DTV_DVBT2_5; 4708c2ecf20Sopenharmony_ci else if (p->bandwidth_hz <= 6000000) 4718c2ecf20Sopenharmony_ci system = SONY_HELENE_DTV_DVBT2_6; 4728c2ecf20Sopenharmony_ci else if (p->bandwidth_hz <= 7000000) 4738c2ecf20Sopenharmony_ci system = SONY_HELENE_DTV_DVBT2_7; 4748c2ecf20Sopenharmony_ci else if (p->bandwidth_hz <= 8000000) 4758c2ecf20Sopenharmony_ci system = SONY_HELENE_DTV_DVBT2_8; 4768c2ecf20Sopenharmony_ci else { 4778c2ecf20Sopenharmony_ci system = SONY_HELENE_DTV_DVBT2_8; 4788c2ecf20Sopenharmony_ci p->bandwidth_hz = 8000000; 4798c2ecf20Sopenharmony_ci } 4808c2ecf20Sopenharmony_ci } else if (p->delivery_system == SYS_DVBS) { 4818c2ecf20Sopenharmony_ci system = SONY_HELENE_STV_DVBS; 4828c2ecf20Sopenharmony_ci } else if (p->delivery_system == SYS_DVBS2) { 4838c2ecf20Sopenharmony_ci system = SONY_HELENE_STV_DVBS2; 4848c2ecf20Sopenharmony_ci } else if (p->delivery_system == SYS_ISDBS) { 4858c2ecf20Sopenharmony_ci system = SONY_HELENE_STV_ISDBS; 4868c2ecf20Sopenharmony_ci } else if (p->delivery_system == SYS_ISDBT) { 4878c2ecf20Sopenharmony_ci if (p->bandwidth_hz <= 6000000) 4888c2ecf20Sopenharmony_ci system = SONY_HELENE_DTV_ISDBT_6; 4898c2ecf20Sopenharmony_ci else if (p->bandwidth_hz <= 7000000) 4908c2ecf20Sopenharmony_ci system = SONY_HELENE_DTV_ISDBT_7; 4918c2ecf20Sopenharmony_ci else if (p->bandwidth_hz <= 8000000) 4928c2ecf20Sopenharmony_ci system = SONY_HELENE_DTV_ISDBT_8; 4938c2ecf20Sopenharmony_ci else { 4948c2ecf20Sopenharmony_ci system = SONY_HELENE_DTV_ISDBT_8; 4958c2ecf20Sopenharmony_ci p->bandwidth_hz = 8000000; 4968c2ecf20Sopenharmony_ci } 4978c2ecf20Sopenharmony_ci } else if (p->delivery_system == SYS_DVBC_ANNEX_A) { 4988c2ecf20Sopenharmony_ci if (p->bandwidth_hz <= 6000000) 4998c2ecf20Sopenharmony_ci system = SONY_HELENE_DTV_DVBC_6; 5008c2ecf20Sopenharmony_ci else if (p->bandwidth_hz <= 8000000) 5018c2ecf20Sopenharmony_ci system = SONY_HELENE_DTV_DVBC_8; 5028c2ecf20Sopenharmony_ci } 5038c2ecf20Sopenharmony_ci dev_dbg(&priv->i2c->dev, 5048c2ecf20Sopenharmony_ci "%s(): HELENE DTV system %d (delsys %d, bandwidth %d)\n", 5058c2ecf20Sopenharmony_ci __func__, (int)system, p->delivery_system, 5068c2ecf20Sopenharmony_ci p->bandwidth_hz); 5078c2ecf20Sopenharmony_ci return system; 5088c2ecf20Sopenharmony_ci} 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_cistatic int helene_set_params_s(struct dvb_frontend *fe) 5118c2ecf20Sopenharmony_ci{ 5128c2ecf20Sopenharmony_ci u8 data[MAX_WRITE_REGSIZE]; 5138c2ecf20Sopenharmony_ci u32 frequency; 5148c2ecf20Sopenharmony_ci enum helene_tv_system_t tv_system; 5158c2ecf20Sopenharmony_ci struct dtv_frontend_properties *p = &fe->dtv_property_cache; 5168c2ecf20Sopenharmony_ci struct helene_priv *priv = fe->tuner_priv; 5178c2ecf20Sopenharmony_ci int frequencykHz = p->frequency; 5188c2ecf20Sopenharmony_ci uint32_t frequency4kHz = 0; 5198c2ecf20Sopenharmony_ci u32 symbol_rate = p->symbol_rate/1000; 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_ci dev_dbg(&priv->i2c->dev, "%s(): tune frequency %dkHz sr=%uKsps\n", 5228c2ecf20Sopenharmony_ci __func__, frequencykHz, symbol_rate); 5238c2ecf20Sopenharmony_ci tv_system = helene_get_tv_system(fe); 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_ci if (tv_system == SONY_HELENE_TV_SYSTEM_UNKNOWN) { 5268c2ecf20Sopenharmony_ci dev_err(&priv->i2c->dev, "%s(): unknown DTV system\n", 5278c2ecf20Sopenharmony_ci __func__); 5288c2ecf20Sopenharmony_ci return -EINVAL; 5298c2ecf20Sopenharmony_ci } 5308c2ecf20Sopenharmony_ci /* RF switch turn to satellite */ 5318c2ecf20Sopenharmony_ci if (priv->set_tuner) 5328c2ecf20Sopenharmony_ci priv->set_tuner(priv->set_tuner_data, 0); 5338c2ecf20Sopenharmony_ci frequency = roundup(p->frequency / 1000, 1); 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci /* Disable IF signal output */ 5368c2ecf20Sopenharmony_ci helene_write_reg(priv, 0x15, 0x02); 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_ci /* RFIN matching in power save (Sat) reset */ 5398c2ecf20Sopenharmony_ci helene_write_reg(priv, 0x43, 0x06); 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci /* Analog block setting (0x6A, 0x6B) */ 5428c2ecf20Sopenharmony_ci data[0] = 0x00; 5438c2ecf20Sopenharmony_ci data[1] = 0x00; 5448c2ecf20Sopenharmony_ci helene_write_regs(priv, 0x6A, data, 2); 5458c2ecf20Sopenharmony_ci helene_write_reg(priv, 0x75, 0x99); 5468c2ecf20Sopenharmony_ci helene_write_reg(priv, 0x9D, 0x00); 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ci /* Tuning setting for CPU (0x61) */ 5498c2ecf20Sopenharmony_ci helene_write_reg(priv, 0x61, 0x07); 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_ci /* Satellite mode select (0x01) */ 5528c2ecf20Sopenharmony_ci helene_write_reg(priv, 0x01, 0x01); 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci /* Clock enable for internal logic block, CPU wake-up (0x04, 0x05) */ 5558c2ecf20Sopenharmony_ci data[0] = 0xC4; 5568c2ecf20Sopenharmony_ci data[1] = 0x40; 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci switch (priv->xtal) { 5598c2ecf20Sopenharmony_ci case SONY_HELENE_XTAL_16000: 5608c2ecf20Sopenharmony_ci data[2] = 0x02; 5618c2ecf20Sopenharmony_ci break; 5628c2ecf20Sopenharmony_ci case SONY_HELENE_XTAL_20500: 5638c2ecf20Sopenharmony_ci data[2] = 0x02; 5648c2ecf20Sopenharmony_ci break; 5658c2ecf20Sopenharmony_ci case SONY_HELENE_XTAL_24000: 5668c2ecf20Sopenharmony_ci data[2] = 0x03; 5678c2ecf20Sopenharmony_ci break; 5688c2ecf20Sopenharmony_ci case SONY_HELENE_XTAL_41000: 5698c2ecf20Sopenharmony_ci data[2] = 0x05; 5708c2ecf20Sopenharmony_ci break; 5718c2ecf20Sopenharmony_ci default: 5728c2ecf20Sopenharmony_ci dev_err(&priv->i2c->dev, "%s(): unknown xtal %d\n", 5738c2ecf20Sopenharmony_ci __func__, priv->xtal); 5748c2ecf20Sopenharmony_ci return -EINVAL; 5758c2ecf20Sopenharmony_ci } 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_ci /* Setting for analog block (0x07). LOOPFILTER INTERNAL */ 5788c2ecf20Sopenharmony_ci data[3] = 0x80; 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_ci /* Tuning setting for analog block 5818c2ecf20Sopenharmony_ci * (0x08, 0x09, 0x0A, 0x0B). LOOPFILTER INTERNAL 5828c2ecf20Sopenharmony_ci */ 5838c2ecf20Sopenharmony_ci if (priv->xtal == SONY_HELENE_XTAL_20500) 5848c2ecf20Sopenharmony_ci data[4] = 0x58; 5858c2ecf20Sopenharmony_ci else 5868c2ecf20Sopenharmony_ci data[4] = 0x70; 5878c2ecf20Sopenharmony_ci 5888c2ecf20Sopenharmony_ci data[5] = 0x1E; 5898c2ecf20Sopenharmony_ci data[6] = 0x02; 5908c2ecf20Sopenharmony_ci data[7] = 0x24; 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_ci /* Enable for analog block (0x0C, 0x0D, 0x0E). SAT LNA ON */ 5938c2ecf20Sopenharmony_ci data[8] = 0x0F; 5948c2ecf20Sopenharmony_ci data[8] |= 0xE0; /* POWERSAVE_TERR_RF_ACTIVE */ 5958c2ecf20Sopenharmony_ci data[9] = 0x02; 5968c2ecf20Sopenharmony_ci data[10] = 0x1E; 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_ci /* Setting for LPF cutoff frequency (0x0F) */ 5998c2ecf20Sopenharmony_ci switch (tv_system) { 6008c2ecf20Sopenharmony_ci case SONY_HELENE_STV_ISDBS: 6018c2ecf20Sopenharmony_ci data[11] = 0x22; /* 22MHz */ 6028c2ecf20Sopenharmony_ci break; 6038c2ecf20Sopenharmony_ci case SONY_HELENE_STV_DVBS: 6048c2ecf20Sopenharmony_ci if (symbol_rate <= 4000) 6058c2ecf20Sopenharmony_ci data[11] = 0x05; 6068c2ecf20Sopenharmony_ci else if (symbol_rate <= 10000) 6078c2ecf20Sopenharmony_ci data[11] = (uint8_t)((symbol_rate * 47 6088c2ecf20Sopenharmony_ci + (40000-1)) / 40000); 6098c2ecf20Sopenharmony_ci else 6108c2ecf20Sopenharmony_ci data[11] = (uint8_t)((symbol_rate * 27 6118c2ecf20Sopenharmony_ci + (40000-1)) / 40000 + 5); 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_ci if (data[11] > 36) 6148c2ecf20Sopenharmony_ci data[11] = 36; /* 5 <= lpf_cutoff <= 36 is valid */ 6158c2ecf20Sopenharmony_ci break; 6168c2ecf20Sopenharmony_ci case SONY_HELENE_STV_DVBS2: 6178c2ecf20Sopenharmony_ci if (symbol_rate <= 4000) 6188c2ecf20Sopenharmony_ci data[11] = 0x05; 6198c2ecf20Sopenharmony_ci else if (symbol_rate <= 10000) 6208c2ecf20Sopenharmony_ci data[11] = (uint8_t)((symbol_rate * 11 6218c2ecf20Sopenharmony_ci + (10000-1)) / 10000); 6228c2ecf20Sopenharmony_ci else 6238c2ecf20Sopenharmony_ci data[11] = (uint8_t)((symbol_rate * 3 6248c2ecf20Sopenharmony_ci + (5000-1)) / 5000 + 5); 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci if (data[11] > 36) 6278c2ecf20Sopenharmony_ci data[11] = 36; /* 5 <= lpf_cutoff <= 36 is valid */ 6288c2ecf20Sopenharmony_ci break; 6298c2ecf20Sopenharmony_ci default: 6308c2ecf20Sopenharmony_ci dev_err(&priv->i2c->dev, "%s(): unknown standard %d\n", 6318c2ecf20Sopenharmony_ci __func__, tv_system); 6328c2ecf20Sopenharmony_ci return -EINVAL; 6338c2ecf20Sopenharmony_ci } 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci /* RF tuning frequency setting (0x10, 0x11, 0x12) */ 6368c2ecf20Sopenharmony_ci frequency4kHz = (frequencykHz + 2) / 4; 6378c2ecf20Sopenharmony_ci data[12] = (uint8_t)(frequency4kHz & 0xFF); /* FRF_L */ 6388c2ecf20Sopenharmony_ci data[13] = (uint8_t)((frequency4kHz >> 8) & 0xFF); /* FRF_M */ 6398c2ecf20Sopenharmony_ci /* FRF_H (bit[3:0]) */ 6408c2ecf20Sopenharmony_ci data[14] = (uint8_t)((frequency4kHz >> 16) & 0x0F); 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_ci /* Tuning command (0x13) */ 6438c2ecf20Sopenharmony_ci data[15] = 0xFF; 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_ci /* Setting for IQOUT_LIMIT (0x14) 0.75Vpp */ 6468c2ecf20Sopenharmony_ci data[16] = 0x00; 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ci /* Enable IQ output (0x15) */ 6498c2ecf20Sopenharmony_ci data[17] = 0x01; 6508c2ecf20Sopenharmony_ci 6518c2ecf20Sopenharmony_ci helene_write_regs(priv, 0x04, data, 18); 6528c2ecf20Sopenharmony_ci 6538c2ecf20Sopenharmony_ci dev_dbg(&priv->i2c->dev, "%s(): tune done\n", 6548c2ecf20Sopenharmony_ci __func__); 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ci priv->frequency = frequency; 6578c2ecf20Sopenharmony_ci return 0; 6588c2ecf20Sopenharmony_ci} 6598c2ecf20Sopenharmony_ci 6608c2ecf20Sopenharmony_cistatic int helene_set_params_t(struct dvb_frontend *fe) 6618c2ecf20Sopenharmony_ci{ 6628c2ecf20Sopenharmony_ci u8 data[MAX_WRITE_REGSIZE]; 6638c2ecf20Sopenharmony_ci u32 frequency; 6648c2ecf20Sopenharmony_ci enum helene_tv_system_t tv_system; 6658c2ecf20Sopenharmony_ci struct dtv_frontend_properties *p = &fe->dtv_property_cache; 6668c2ecf20Sopenharmony_ci struct helene_priv *priv = fe->tuner_priv; 6678c2ecf20Sopenharmony_ci int frequencykHz = p->frequency / 1000; 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_ci dev_dbg(&priv->i2c->dev, "%s(): tune frequency %dkHz\n", 6708c2ecf20Sopenharmony_ci __func__, frequencykHz); 6718c2ecf20Sopenharmony_ci tv_system = helene_get_tv_system(fe); 6728c2ecf20Sopenharmony_ci 6738c2ecf20Sopenharmony_ci if (tv_system == SONY_HELENE_TV_SYSTEM_UNKNOWN) { 6748c2ecf20Sopenharmony_ci dev_dbg(&priv->i2c->dev, "%s(): unknown DTV system\n", 6758c2ecf20Sopenharmony_ci __func__); 6768c2ecf20Sopenharmony_ci return -EINVAL; 6778c2ecf20Sopenharmony_ci } 6788c2ecf20Sopenharmony_ci if (priv->set_tuner) 6798c2ecf20Sopenharmony_ci priv->set_tuner(priv->set_tuner_data, 1); 6808c2ecf20Sopenharmony_ci frequency = roundup(p->frequency / 1000, 25); 6818c2ecf20Sopenharmony_ci 6828c2ecf20Sopenharmony_ci /* mode select */ 6838c2ecf20Sopenharmony_ci helene_write_reg(priv, 0x01, 0x00); 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_ci /* Disable IF signal output */ 6868c2ecf20Sopenharmony_ci helene_write_reg(priv, 0x74, 0x02); 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_ci if (priv->state == STATE_SLEEP) 6898c2ecf20Sopenharmony_ci helene_leave_power_save(priv); 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_ci /* Initial setting for internal analog block (0x91, 0x92) */ 6928c2ecf20Sopenharmony_ci if ((tv_system == SONY_HELENE_DTV_DVBC_6) || 6938c2ecf20Sopenharmony_ci (tv_system == SONY_HELENE_DTV_DVBC_8)) { 6948c2ecf20Sopenharmony_ci data[0] = 0x16; 6958c2ecf20Sopenharmony_ci data[1] = 0x26; 6968c2ecf20Sopenharmony_ci } else { 6978c2ecf20Sopenharmony_ci data[0] = 0x10; 6988c2ecf20Sopenharmony_ci data[1] = 0x20; 6998c2ecf20Sopenharmony_ci } 7008c2ecf20Sopenharmony_ci helene_write_regs(priv, 0x91, data, 2); 7018c2ecf20Sopenharmony_ci 7028c2ecf20Sopenharmony_ci /* Setting for analog block */ 7038c2ecf20Sopenharmony_ci if (TERR_INTERNAL_LOOPFILTER_AVAILABLE(tv_system)) 7048c2ecf20Sopenharmony_ci data[0] = 0x90; 7058c2ecf20Sopenharmony_ci else 7068c2ecf20Sopenharmony_ci data[0] = 0x00; 7078c2ecf20Sopenharmony_ci 7088c2ecf20Sopenharmony_ci /* Setting for local polarity (0x9D) */ 7098c2ecf20Sopenharmony_ci data[1] = (uint8_t)(terr_params[tv_system].IS_LOWERLOCAL & 0x01); 7108c2ecf20Sopenharmony_ci helene_write_regs(priv, 0x9C, data, 2); 7118c2ecf20Sopenharmony_ci 7128c2ecf20Sopenharmony_ci /* Enable for analog block */ 7138c2ecf20Sopenharmony_ci data[0] = 0xEE; 7148c2ecf20Sopenharmony_ci data[1] = 0x02; 7158c2ecf20Sopenharmony_ci data[2] = 0x1E; 7168c2ecf20Sopenharmony_ci data[3] = 0x67; /* Tuning setting for CPU */ 7178c2ecf20Sopenharmony_ci 7188c2ecf20Sopenharmony_ci /* Setting for PLL reference divider for xtal=24MHz */ 7198c2ecf20Sopenharmony_ci if ((tv_system == SONY_HELENE_DTV_DVBC_6) || 7208c2ecf20Sopenharmony_ci (tv_system == SONY_HELENE_DTV_DVBC_8)) 7218c2ecf20Sopenharmony_ci data[4] = 0x18; 7228c2ecf20Sopenharmony_ci else 7238c2ecf20Sopenharmony_ci data[4] = 0x03; 7248c2ecf20Sopenharmony_ci 7258c2ecf20Sopenharmony_ci /* Tuning setting for analog block */ 7268c2ecf20Sopenharmony_ci if (TERR_INTERNAL_LOOPFILTER_AVAILABLE(tv_system)) { 7278c2ecf20Sopenharmony_ci data[5] = 0x38; 7288c2ecf20Sopenharmony_ci data[6] = 0x1E; 7298c2ecf20Sopenharmony_ci data[7] = 0x02; 7308c2ecf20Sopenharmony_ci data[8] = 0x24; 7318c2ecf20Sopenharmony_ci } else if ((tv_system == SONY_HELENE_DTV_DVBC_6) || 7328c2ecf20Sopenharmony_ci (tv_system == SONY_HELENE_DTV_DVBC_8)) { 7338c2ecf20Sopenharmony_ci data[5] = 0x1C; 7348c2ecf20Sopenharmony_ci data[6] = 0x78; 7358c2ecf20Sopenharmony_ci data[7] = 0x08; 7368c2ecf20Sopenharmony_ci data[8] = 0x1C; 7378c2ecf20Sopenharmony_ci } else { 7388c2ecf20Sopenharmony_ci data[5] = 0xB4; 7398c2ecf20Sopenharmony_ci data[6] = 0x78; 7408c2ecf20Sopenharmony_ci data[7] = 0x08; 7418c2ecf20Sopenharmony_ci data[8] = 0x30; 7428c2ecf20Sopenharmony_ci } 7438c2ecf20Sopenharmony_ci helene_write_regs(priv, 0x5E, data, 9); 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_ci /* LT_AMP_EN should be 0 */ 7468c2ecf20Sopenharmony_ci helene_set_reg_bits(priv, 0x67, 0x0, 0x02); 7478c2ecf20Sopenharmony_ci 7488c2ecf20Sopenharmony_ci /* Setting for IFOUT_LIMIT */ 7498c2ecf20Sopenharmony_ci data[0] = 0x00; /* 1.5Vpp */ 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_ci /* RF_GAIN setting */ 7528c2ecf20Sopenharmony_ci if (terr_params[tv_system].RF_GAIN == HELENE_AUTO) 7538c2ecf20Sopenharmony_ci data[1] = 0x80; /* RF_GAIN_SEL = 1 */ 7548c2ecf20Sopenharmony_ci else 7558c2ecf20Sopenharmony_ci data[1] = (uint8_t)((terr_params[tv_system].RF_GAIN 7568c2ecf20Sopenharmony_ci << 4) & 0x70); 7578c2ecf20Sopenharmony_ci 7588c2ecf20Sopenharmony_ci /* IF_BPF_GC setting */ 7598c2ecf20Sopenharmony_ci data[1] |= (uint8_t)(terr_params[tv_system].IF_BPF_GC & 0x0F); 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_ci /* Setting for internal RFAGC (0x6A, 0x6B, 0x6C) */ 7628c2ecf20Sopenharmony_ci data[2] = 0x00; 7638c2ecf20Sopenharmony_ci if (frequencykHz <= 172000) { 7648c2ecf20Sopenharmony_ci data[3] = (uint8_t)(terr_params[tv_system].RFOVLD_DET_LV1_VL 7658c2ecf20Sopenharmony_ci & 0x0F); 7668c2ecf20Sopenharmony_ci data[4] = (uint8_t)(terr_params[tv_system].IFOVLD_DET_LV_VL 7678c2ecf20Sopenharmony_ci & 0x07); 7688c2ecf20Sopenharmony_ci } else if (frequencykHz <= 464000) { 7698c2ecf20Sopenharmony_ci data[3] = (uint8_t)(terr_params[tv_system].RFOVLD_DET_LV1_VH 7708c2ecf20Sopenharmony_ci & 0x0F); 7718c2ecf20Sopenharmony_ci data[4] = (uint8_t)(terr_params[tv_system].IFOVLD_DET_LV_VH 7728c2ecf20Sopenharmony_ci & 0x07); 7738c2ecf20Sopenharmony_ci } else { 7748c2ecf20Sopenharmony_ci data[3] = (uint8_t)(terr_params[tv_system].RFOVLD_DET_LV1_U 7758c2ecf20Sopenharmony_ci & 0x0F); 7768c2ecf20Sopenharmony_ci data[4] = (uint8_t)(terr_params[tv_system].IFOVLD_DET_LV_U 7778c2ecf20Sopenharmony_ci & 0x07); 7788c2ecf20Sopenharmony_ci } 7798c2ecf20Sopenharmony_ci data[4] |= 0x20; 7808c2ecf20Sopenharmony_ci 7818c2ecf20Sopenharmony_ci /* Setting for IF frequency and bandwidth */ 7828c2ecf20Sopenharmony_ci 7838c2ecf20Sopenharmony_ci /* IF filter center frequency offset (IF_BPF_F0) (0x6D) */ 7848c2ecf20Sopenharmony_ci data[5] = (uint8_t)((terr_params[tv_system].IF_BPF_F0 << 4) & 0x30); 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_ci /* IF filter band width (BW) (0x6D) */ 7878c2ecf20Sopenharmony_ci data[5] |= (uint8_t)(terr_params[tv_system].BW & 0x03); 7888c2ecf20Sopenharmony_ci 7898c2ecf20Sopenharmony_ci /* IF frequency offset value (FIF_OFFSET) (0x6E) */ 7908c2ecf20Sopenharmony_ci data[6] = (uint8_t)(terr_params[tv_system].FIF_OFFSET & 0x1F); 7918c2ecf20Sopenharmony_ci 7928c2ecf20Sopenharmony_ci /* IF band width offset value (BW_OFFSET) (0x6F) */ 7938c2ecf20Sopenharmony_ci data[7] = (uint8_t)(terr_params[tv_system].BW_OFFSET & 0x1F); 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_ci /* RF tuning frequency setting (0x70, 0x71, 0x72) */ 7968c2ecf20Sopenharmony_ci data[8] = (uint8_t)(frequencykHz & 0xFF); /* FRF_L */ 7978c2ecf20Sopenharmony_ci data[9] = (uint8_t)((frequencykHz >> 8) & 0xFF); /* FRF_M */ 7988c2ecf20Sopenharmony_ci data[10] = (uint8_t)((frequencykHz >> 16) 7998c2ecf20Sopenharmony_ci & 0x0F); /* FRF_H (bit[3:0]) */ 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_ci /* Tuning command */ 8028c2ecf20Sopenharmony_ci data[11] = 0xFF; 8038c2ecf20Sopenharmony_ci 8048c2ecf20Sopenharmony_ci /* Enable IF output, AGC and IFOUT pin selection (0x74) */ 8058c2ecf20Sopenharmony_ci data[12] = 0x01; 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_ci if ((tv_system == SONY_HELENE_DTV_DVBC_6) || 8088c2ecf20Sopenharmony_ci (tv_system == SONY_HELENE_DTV_DVBC_8)) { 8098c2ecf20Sopenharmony_ci data[13] = 0xD9; 8108c2ecf20Sopenharmony_ci data[14] = 0x0F; 8118c2ecf20Sopenharmony_ci data[15] = 0x24; 8128c2ecf20Sopenharmony_ci data[16] = 0x87; 8138c2ecf20Sopenharmony_ci } else { 8148c2ecf20Sopenharmony_ci data[13] = 0x99; 8158c2ecf20Sopenharmony_ci data[14] = 0x00; 8168c2ecf20Sopenharmony_ci data[15] = 0x24; 8178c2ecf20Sopenharmony_ci data[16] = 0x87; 8188c2ecf20Sopenharmony_ci } 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_ci helene_write_regs(priv, 0x68, data, 17); 8218c2ecf20Sopenharmony_ci 8228c2ecf20Sopenharmony_ci dev_dbg(&priv->i2c->dev, "%s(): tune done\n", 8238c2ecf20Sopenharmony_ci __func__); 8248c2ecf20Sopenharmony_ci 8258c2ecf20Sopenharmony_ci priv->frequency = frequency; 8268c2ecf20Sopenharmony_ci return 0; 8278c2ecf20Sopenharmony_ci} 8288c2ecf20Sopenharmony_ci 8298c2ecf20Sopenharmony_cistatic int helene_set_params(struct dvb_frontend *fe) 8308c2ecf20Sopenharmony_ci{ 8318c2ecf20Sopenharmony_ci struct dtv_frontend_properties *p = &fe->dtv_property_cache; 8328c2ecf20Sopenharmony_ci 8338c2ecf20Sopenharmony_ci if (p->delivery_system == SYS_DVBT || 8348c2ecf20Sopenharmony_ci p->delivery_system == SYS_DVBT2 || 8358c2ecf20Sopenharmony_ci p->delivery_system == SYS_ISDBT || 8368c2ecf20Sopenharmony_ci p->delivery_system == SYS_DVBC_ANNEX_A) 8378c2ecf20Sopenharmony_ci return helene_set_params_t(fe); 8388c2ecf20Sopenharmony_ci 8398c2ecf20Sopenharmony_ci return helene_set_params_s(fe); 8408c2ecf20Sopenharmony_ci} 8418c2ecf20Sopenharmony_ci 8428c2ecf20Sopenharmony_cistatic int helene_get_frequency(struct dvb_frontend *fe, u32 *frequency) 8438c2ecf20Sopenharmony_ci{ 8448c2ecf20Sopenharmony_ci struct helene_priv *priv = fe->tuner_priv; 8458c2ecf20Sopenharmony_ci 8468c2ecf20Sopenharmony_ci *frequency = priv->frequency * 1000; 8478c2ecf20Sopenharmony_ci return 0; 8488c2ecf20Sopenharmony_ci} 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_cistatic const struct dvb_tuner_ops helene_tuner_ops_t = { 8518c2ecf20Sopenharmony_ci .info = { 8528c2ecf20Sopenharmony_ci .name = "Sony HELENE Ter tuner", 8538c2ecf20Sopenharmony_ci .frequency_min_hz = 1 * MHz, 8548c2ecf20Sopenharmony_ci .frequency_max_hz = 1200 * MHz, 8558c2ecf20Sopenharmony_ci .frequency_step_hz = 25 * kHz, 8568c2ecf20Sopenharmony_ci }, 8578c2ecf20Sopenharmony_ci .init = helene_init, 8588c2ecf20Sopenharmony_ci .release = helene_release, 8598c2ecf20Sopenharmony_ci .sleep = helene_sleep, 8608c2ecf20Sopenharmony_ci .set_params = helene_set_params_t, 8618c2ecf20Sopenharmony_ci .get_frequency = helene_get_frequency, 8628c2ecf20Sopenharmony_ci}; 8638c2ecf20Sopenharmony_ci 8648c2ecf20Sopenharmony_cistatic const struct dvb_tuner_ops helene_tuner_ops_s = { 8658c2ecf20Sopenharmony_ci .info = { 8668c2ecf20Sopenharmony_ci .name = "Sony HELENE Sat tuner", 8678c2ecf20Sopenharmony_ci .frequency_min_hz = 500 * MHz, 8688c2ecf20Sopenharmony_ci .frequency_max_hz = 2500 * MHz, 8698c2ecf20Sopenharmony_ci .frequency_step_hz = 1 * MHz, 8708c2ecf20Sopenharmony_ci }, 8718c2ecf20Sopenharmony_ci .init = helene_init, 8728c2ecf20Sopenharmony_ci .release = helene_release, 8738c2ecf20Sopenharmony_ci .sleep = helene_sleep, 8748c2ecf20Sopenharmony_ci .set_params = helene_set_params_s, 8758c2ecf20Sopenharmony_ci .get_frequency = helene_get_frequency, 8768c2ecf20Sopenharmony_ci}; 8778c2ecf20Sopenharmony_ci 8788c2ecf20Sopenharmony_cistatic const struct dvb_tuner_ops helene_tuner_ops = { 8798c2ecf20Sopenharmony_ci .info = { 8808c2ecf20Sopenharmony_ci .name = "Sony HELENE Sat/Ter tuner", 8818c2ecf20Sopenharmony_ci .frequency_min_hz = 1 * MHz, 8828c2ecf20Sopenharmony_ci .frequency_max_hz = 2500 * MHz, 8838c2ecf20Sopenharmony_ci .frequency_step_hz = 25 * kHz, 8848c2ecf20Sopenharmony_ci }, 8858c2ecf20Sopenharmony_ci .init = helene_init, 8868c2ecf20Sopenharmony_ci .release = helene_release, 8878c2ecf20Sopenharmony_ci .sleep = helene_sleep, 8888c2ecf20Sopenharmony_ci .set_params = helene_set_params, 8898c2ecf20Sopenharmony_ci .get_frequency = helene_get_frequency, 8908c2ecf20Sopenharmony_ci}; 8918c2ecf20Sopenharmony_ci 8928c2ecf20Sopenharmony_ci/* power-on tuner 8938c2ecf20Sopenharmony_ci * call once after reset 8948c2ecf20Sopenharmony_ci */ 8958c2ecf20Sopenharmony_cistatic int helene_x_pon(struct helene_priv *priv) 8968c2ecf20Sopenharmony_ci{ 8978c2ecf20Sopenharmony_ci /* RFIN matching in power save (terrestrial) = ACTIVE */ 8988c2ecf20Sopenharmony_ci /* RFIN matching in power save (satellite) = ACTIVE */ 8998c2ecf20Sopenharmony_ci u8 dataT[] = { 0x06, 0x00, 0x02, 0x00 }; 9008c2ecf20Sopenharmony_ci /* SAT_RF_ACTIVE = true, lnaOff = false, terrRfActive = true */ 9018c2ecf20Sopenharmony_ci u8 dataS[] = { 0x05, 0x06 }; 9028c2ecf20Sopenharmony_ci u8 cdata[] = {0x7A, 0x01}; 9038c2ecf20Sopenharmony_ci u8 data[20]; 9048c2ecf20Sopenharmony_ci u8 rdata[2]; 9058c2ecf20Sopenharmony_ci 9068c2ecf20Sopenharmony_ci /* mode select */ 9078c2ecf20Sopenharmony_ci helene_write_reg(priv, 0x01, 0x00); 9088c2ecf20Sopenharmony_ci 9098c2ecf20Sopenharmony_ci helene_write_reg(priv, 0x67, dataT[3]); 9108c2ecf20Sopenharmony_ci helene_write_reg(priv, 0x43, dataS[1]); 9118c2ecf20Sopenharmony_ci helene_write_regs(priv, 0x5E, dataT, 3); 9128c2ecf20Sopenharmony_ci helene_write_reg(priv, 0x0C, dataS[0]); 9138c2ecf20Sopenharmony_ci 9148c2ecf20Sopenharmony_ci /* Initial setting for internal logic block */ 9158c2ecf20Sopenharmony_ci helene_write_regs(priv, 0x99, cdata, sizeof(cdata)); 9168c2ecf20Sopenharmony_ci 9178c2ecf20Sopenharmony_ci /* 0x81 - 0x94 */ 9188c2ecf20Sopenharmony_ci if (priv->xtal == SONY_HELENE_XTAL_16000) 9198c2ecf20Sopenharmony_ci data[0] = 0x10; /* xtal 16 MHz */ 9208c2ecf20Sopenharmony_ci else 9218c2ecf20Sopenharmony_ci data[0] = 0x18; /* xtal 24 MHz */ 9228c2ecf20Sopenharmony_ci data[1] = (uint8_t)(0x80 | (0x04 & 0x1F)); /* 4 x 25 = 100uA */ 9238c2ecf20Sopenharmony_ci data[2] = (uint8_t)(0x80 | (0x26 & 0x7F)); /* 38 x 0.25 = 9.5pF */ 9248c2ecf20Sopenharmony_ci data[3] = 0x80; /* REFOUT signal output 500mVpp */ 9258c2ecf20Sopenharmony_ci data[4] = 0x00; /* GPIO settings */ 9268c2ecf20Sopenharmony_ci data[5] = 0x00; /* GPIO settings */ 9278c2ecf20Sopenharmony_ci data[6] = 0xC4; /* Clock enable for internal logic block */ 9288c2ecf20Sopenharmony_ci data[7] = 0x40; /* Start CPU boot-up */ 9298c2ecf20Sopenharmony_ci data[8] = 0x10; /* For burst-write */ 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_ci /* Setting for internal RFAGC */ 9328c2ecf20Sopenharmony_ci data[9] = 0x00; 9338c2ecf20Sopenharmony_ci data[10] = 0x45; 9348c2ecf20Sopenharmony_ci data[11] = 0x75; 9358c2ecf20Sopenharmony_ci 9368c2ecf20Sopenharmony_ci data[12] = 0x07; /* Setting for analog block */ 9378c2ecf20Sopenharmony_ci 9388c2ecf20Sopenharmony_ci /* Initial setting for internal analog block */ 9398c2ecf20Sopenharmony_ci data[13] = 0x1C; 9408c2ecf20Sopenharmony_ci data[14] = 0x3F; 9418c2ecf20Sopenharmony_ci data[15] = 0x02; 9428c2ecf20Sopenharmony_ci data[16] = 0x10; 9438c2ecf20Sopenharmony_ci data[17] = 0x20; 9448c2ecf20Sopenharmony_ci data[18] = 0x0A; 9458c2ecf20Sopenharmony_ci data[19] = 0x00; 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_ci helene_write_regs(priv, 0x81, data, sizeof(data)); 9488c2ecf20Sopenharmony_ci 9498c2ecf20Sopenharmony_ci /* Setting for internal RFAGC */ 9508c2ecf20Sopenharmony_ci helene_write_reg(priv, 0x9B, 0x00); 9518c2ecf20Sopenharmony_ci 9528c2ecf20Sopenharmony_ci msleep(20); 9538c2ecf20Sopenharmony_ci 9548c2ecf20Sopenharmony_ci /* Check CPU_STT/CPU_ERR */ 9558c2ecf20Sopenharmony_ci helene_read_regs(priv, 0x1A, rdata, sizeof(rdata)); 9568c2ecf20Sopenharmony_ci 9578c2ecf20Sopenharmony_ci if (rdata[0] != 0x00) { 9588c2ecf20Sopenharmony_ci dev_err(&priv->i2c->dev, 9598c2ecf20Sopenharmony_ci "HELENE tuner CPU error 0x%x\n", rdata[0]); 9608c2ecf20Sopenharmony_ci return -EIO; 9618c2ecf20Sopenharmony_ci } 9628c2ecf20Sopenharmony_ci 9638c2ecf20Sopenharmony_ci /* VCO current setting */ 9648c2ecf20Sopenharmony_ci cdata[0] = 0x90; 9658c2ecf20Sopenharmony_ci cdata[1] = 0x06; 9668c2ecf20Sopenharmony_ci helene_write_regs(priv, 0x17, cdata, sizeof(cdata)); 9678c2ecf20Sopenharmony_ci msleep(20); 9688c2ecf20Sopenharmony_ci helene_read_reg(priv, 0x19, data); 9698c2ecf20Sopenharmony_ci helene_write_reg(priv, 0x95, (uint8_t)((data[0] >> 4) & 0x0F)); 9708c2ecf20Sopenharmony_ci 9718c2ecf20Sopenharmony_ci /* Disable IF signal output */ 9728c2ecf20Sopenharmony_ci helene_write_reg(priv, 0x74, 0x02); 9738c2ecf20Sopenharmony_ci 9748c2ecf20Sopenharmony_ci /* Standby setting for CPU */ 9758c2ecf20Sopenharmony_ci helene_write_reg(priv, 0x88, 0x00); 9768c2ecf20Sopenharmony_ci 9778c2ecf20Sopenharmony_ci /* Standby setting for internal logic block */ 9788c2ecf20Sopenharmony_ci helene_write_reg(priv, 0x87, 0xC0); 9798c2ecf20Sopenharmony_ci 9808c2ecf20Sopenharmony_ci /* Load capacitance control setting for crystal oscillator */ 9818c2ecf20Sopenharmony_ci helene_write_reg(priv, 0x80, 0x01); 9828c2ecf20Sopenharmony_ci 9838c2ecf20Sopenharmony_ci /* Satellite initial setting */ 9848c2ecf20Sopenharmony_ci cdata[0] = 0x07; 9858c2ecf20Sopenharmony_ci cdata[1] = 0x00; 9868c2ecf20Sopenharmony_ci helene_write_regs(priv, 0x41, cdata, sizeof(cdata)); 9878c2ecf20Sopenharmony_ci 9888c2ecf20Sopenharmony_ci dev_info(&priv->i2c->dev, 9898c2ecf20Sopenharmony_ci "HELENE tuner x_pon done\n"); 9908c2ecf20Sopenharmony_ci 9918c2ecf20Sopenharmony_ci return 0; 9928c2ecf20Sopenharmony_ci} 9938c2ecf20Sopenharmony_ci 9948c2ecf20Sopenharmony_cistruct dvb_frontend *helene_attach_s(struct dvb_frontend *fe, 9958c2ecf20Sopenharmony_ci const struct helene_config *config, 9968c2ecf20Sopenharmony_ci struct i2c_adapter *i2c) 9978c2ecf20Sopenharmony_ci{ 9988c2ecf20Sopenharmony_ci struct helene_priv *priv = NULL; 9998c2ecf20Sopenharmony_ci 10008c2ecf20Sopenharmony_ci priv = kzalloc(sizeof(struct helene_priv), GFP_KERNEL); 10018c2ecf20Sopenharmony_ci if (priv == NULL) 10028c2ecf20Sopenharmony_ci return NULL; 10038c2ecf20Sopenharmony_ci priv->i2c_address = (config->i2c_address >> 1); 10048c2ecf20Sopenharmony_ci priv->i2c = i2c; 10058c2ecf20Sopenharmony_ci priv->set_tuner_data = config->set_tuner_priv; 10068c2ecf20Sopenharmony_ci priv->set_tuner = config->set_tuner_callback; 10078c2ecf20Sopenharmony_ci priv->xtal = config->xtal; 10088c2ecf20Sopenharmony_ci 10098c2ecf20Sopenharmony_ci if (fe->ops.i2c_gate_ctrl) 10108c2ecf20Sopenharmony_ci fe->ops.i2c_gate_ctrl(fe, 1); 10118c2ecf20Sopenharmony_ci 10128c2ecf20Sopenharmony_ci if (helene_x_pon(priv) != 0) { 10138c2ecf20Sopenharmony_ci kfree(priv); 10148c2ecf20Sopenharmony_ci return NULL; 10158c2ecf20Sopenharmony_ci } 10168c2ecf20Sopenharmony_ci 10178c2ecf20Sopenharmony_ci if (fe->ops.i2c_gate_ctrl) 10188c2ecf20Sopenharmony_ci fe->ops.i2c_gate_ctrl(fe, 0); 10198c2ecf20Sopenharmony_ci 10208c2ecf20Sopenharmony_ci memcpy(&fe->ops.tuner_ops, &helene_tuner_ops_s, 10218c2ecf20Sopenharmony_ci sizeof(struct dvb_tuner_ops)); 10228c2ecf20Sopenharmony_ci fe->tuner_priv = priv; 10238c2ecf20Sopenharmony_ci dev_info(&priv->i2c->dev, 10248c2ecf20Sopenharmony_ci "Sony HELENE Sat attached on addr=%x at I2C adapter %p\n", 10258c2ecf20Sopenharmony_ci priv->i2c_address, priv->i2c); 10268c2ecf20Sopenharmony_ci return fe; 10278c2ecf20Sopenharmony_ci} 10288c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(helene_attach_s); 10298c2ecf20Sopenharmony_ci 10308c2ecf20Sopenharmony_cistruct dvb_frontend *helene_attach(struct dvb_frontend *fe, 10318c2ecf20Sopenharmony_ci const struct helene_config *config, 10328c2ecf20Sopenharmony_ci struct i2c_adapter *i2c) 10338c2ecf20Sopenharmony_ci{ 10348c2ecf20Sopenharmony_ci struct helene_priv *priv = NULL; 10358c2ecf20Sopenharmony_ci 10368c2ecf20Sopenharmony_ci priv = kzalloc(sizeof(struct helene_priv), GFP_KERNEL); 10378c2ecf20Sopenharmony_ci if (priv == NULL) 10388c2ecf20Sopenharmony_ci return NULL; 10398c2ecf20Sopenharmony_ci priv->i2c_address = (config->i2c_address >> 1); 10408c2ecf20Sopenharmony_ci priv->i2c = i2c; 10418c2ecf20Sopenharmony_ci priv->set_tuner_data = config->set_tuner_priv; 10428c2ecf20Sopenharmony_ci priv->set_tuner = config->set_tuner_callback; 10438c2ecf20Sopenharmony_ci priv->xtal = config->xtal; 10448c2ecf20Sopenharmony_ci 10458c2ecf20Sopenharmony_ci if (fe->ops.i2c_gate_ctrl) 10468c2ecf20Sopenharmony_ci fe->ops.i2c_gate_ctrl(fe, 1); 10478c2ecf20Sopenharmony_ci 10488c2ecf20Sopenharmony_ci if (helene_x_pon(priv) != 0) { 10498c2ecf20Sopenharmony_ci kfree(priv); 10508c2ecf20Sopenharmony_ci return NULL; 10518c2ecf20Sopenharmony_ci } 10528c2ecf20Sopenharmony_ci 10538c2ecf20Sopenharmony_ci if (fe->ops.i2c_gate_ctrl) 10548c2ecf20Sopenharmony_ci fe->ops.i2c_gate_ctrl(fe, 0); 10558c2ecf20Sopenharmony_ci 10568c2ecf20Sopenharmony_ci memcpy(&fe->ops.tuner_ops, &helene_tuner_ops_t, 10578c2ecf20Sopenharmony_ci sizeof(struct dvb_tuner_ops)); 10588c2ecf20Sopenharmony_ci fe->tuner_priv = priv; 10598c2ecf20Sopenharmony_ci dev_info(&priv->i2c->dev, 10608c2ecf20Sopenharmony_ci "Sony HELENE Ter attached on addr=%x at I2C adapter %p\n", 10618c2ecf20Sopenharmony_ci priv->i2c_address, priv->i2c); 10628c2ecf20Sopenharmony_ci return fe; 10638c2ecf20Sopenharmony_ci} 10648c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(helene_attach); 10658c2ecf20Sopenharmony_ci 10668c2ecf20Sopenharmony_cistatic int helene_probe(struct i2c_client *client, 10678c2ecf20Sopenharmony_ci const struct i2c_device_id *id) 10688c2ecf20Sopenharmony_ci{ 10698c2ecf20Sopenharmony_ci struct helene_config *config = client->dev.platform_data; 10708c2ecf20Sopenharmony_ci struct dvb_frontend *fe = config->fe; 10718c2ecf20Sopenharmony_ci struct device *dev = &client->dev; 10728c2ecf20Sopenharmony_ci struct helene_priv *priv; 10738c2ecf20Sopenharmony_ci 10748c2ecf20Sopenharmony_ci priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 10758c2ecf20Sopenharmony_ci if (!priv) 10768c2ecf20Sopenharmony_ci return -ENOMEM; 10778c2ecf20Sopenharmony_ci 10788c2ecf20Sopenharmony_ci priv->i2c_address = client->addr; 10798c2ecf20Sopenharmony_ci priv->i2c = client->adapter; 10808c2ecf20Sopenharmony_ci priv->set_tuner_data = config->set_tuner_priv; 10818c2ecf20Sopenharmony_ci priv->set_tuner = config->set_tuner_callback; 10828c2ecf20Sopenharmony_ci priv->xtal = config->xtal; 10838c2ecf20Sopenharmony_ci 10848c2ecf20Sopenharmony_ci if (fe->ops.i2c_gate_ctrl) 10858c2ecf20Sopenharmony_ci fe->ops.i2c_gate_ctrl(fe, 1); 10868c2ecf20Sopenharmony_ci 10878c2ecf20Sopenharmony_ci if (helene_x_pon(priv) != 0) 10888c2ecf20Sopenharmony_ci return -EINVAL; 10898c2ecf20Sopenharmony_ci 10908c2ecf20Sopenharmony_ci if (fe->ops.i2c_gate_ctrl) 10918c2ecf20Sopenharmony_ci fe->ops.i2c_gate_ctrl(fe, 0); 10928c2ecf20Sopenharmony_ci 10938c2ecf20Sopenharmony_ci memcpy(&fe->ops.tuner_ops, &helene_tuner_ops, 10948c2ecf20Sopenharmony_ci sizeof(struct dvb_tuner_ops)); 10958c2ecf20Sopenharmony_ci fe->tuner_priv = priv; 10968c2ecf20Sopenharmony_ci i2c_set_clientdata(client, priv); 10978c2ecf20Sopenharmony_ci 10988c2ecf20Sopenharmony_ci dev_info(dev, "Sony HELENE attached on addr=%x at I2C adapter %p\n", 10998c2ecf20Sopenharmony_ci priv->i2c_address, priv->i2c); 11008c2ecf20Sopenharmony_ci 11018c2ecf20Sopenharmony_ci return 0; 11028c2ecf20Sopenharmony_ci} 11038c2ecf20Sopenharmony_ci 11048c2ecf20Sopenharmony_cistatic const struct i2c_device_id helene_id[] = { 11058c2ecf20Sopenharmony_ci { "helene", }, 11068c2ecf20Sopenharmony_ci {} 11078c2ecf20Sopenharmony_ci}; 11088c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, helene_id); 11098c2ecf20Sopenharmony_ci 11108c2ecf20Sopenharmony_cistatic struct i2c_driver helene_driver = { 11118c2ecf20Sopenharmony_ci .driver = { 11128c2ecf20Sopenharmony_ci .name = "helene", 11138c2ecf20Sopenharmony_ci }, 11148c2ecf20Sopenharmony_ci .probe = helene_probe, 11158c2ecf20Sopenharmony_ci .id_table = helene_id, 11168c2ecf20Sopenharmony_ci}; 11178c2ecf20Sopenharmony_cimodule_i2c_driver(helene_driver); 11188c2ecf20Sopenharmony_ci 11198c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Sony HELENE Sat/Ter tuner driver"); 11208c2ecf20Sopenharmony_ciMODULE_AUTHOR("Abylay Ospan <aospan@netup.ru>"); 11218c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 1122