10f408ce8SKatsuhiro Suzuki // SPDX-License-Identifier: GPL-2.0 20f408ce8SKatsuhiro Suzuki // 30f408ce8SKatsuhiro Suzuki // Socionext MN88443x series demodulator driver for ISDB-S/ISDB-T. 40f408ce8SKatsuhiro Suzuki // 50f408ce8SKatsuhiro Suzuki // Copyright (c) 2018 Socionext Inc. 60f408ce8SKatsuhiro Suzuki 70f408ce8SKatsuhiro Suzuki #include <linux/bitfield.h> 80f408ce8SKatsuhiro Suzuki #include <linux/clk.h> 90f408ce8SKatsuhiro Suzuki #include <linux/delay.h> 100f408ce8SKatsuhiro Suzuki #include <linux/gpio/consumer.h> 110f408ce8SKatsuhiro Suzuki #include <linux/of_device.h> 120f408ce8SKatsuhiro Suzuki #include <linux/regmap.h> 130f408ce8SKatsuhiro Suzuki #include <media/dvb_math.h> 140f408ce8SKatsuhiro Suzuki 150f408ce8SKatsuhiro Suzuki #include "mn88443x.h" 160f408ce8SKatsuhiro Suzuki 170f408ce8SKatsuhiro Suzuki /* ISDB-S registers */ 180f408ce8SKatsuhiro Suzuki #define ATSIDU_S 0x2f 190f408ce8SKatsuhiro Suzuki #define ATSIDL_S 0x30 200f408ce8SKatsuhiro Suzuki #define TSSET_S 0x31 210f408ce8SKatsuhiro Suzuki #define AGCREAD_S 0x5a 220f408ce8SKatsuhiro Suzuki #define CPMON1_S 0x5e 230f408ce8SKatsuhiro Suzuki #define CPMON1_S_FSYNC BIT(5) 240f408ce8SKatsuhiro Suzuki #define CPMON1_S_ERRMON BIT(4) 250f408ce8SKatsuhiro Suzuki #define CPMON1_S_SIGOFF BIT(3) 260f408ce8SKatsuhiro Suzuki #define CPMON1_S_W2LOCK BIT(2) 270f408ce8SKatsuhiro Suzuki #define CPMON1_S_W1LOCK BIT(1) 280f408ce8SKatsuhiro Suzuki #define CPMON1_S_DW1LOCK BIT(0) 290f408ce8SKatsuhiro Suzuki #define TRMON_S 0x60 300f408ce8SKatsuhiro Suzuki #define BERCNFLG_S 0x68 310f408ce8SKatsuhiro Suzuki #define BERCNFLG_S_BERVRDY BIT(5) 320f408ce8SKatsuhiro Suzuki #define BERCNFLG_S_BERVCHK BIT(4) 330f408ce8SKatsuhiro Suzuki #define BERCNFLG_S_BERDRDY BIT(3) 340f408ce8SKatsuhiro Suzuki #define BERCNFLG_S_BERDCHK BIT(2) 350f408ce8SKatsuhiro Suzuki #define CNRDXU_S 0x69 360f408ce8SKatsuhiro Suzuki #define CNRDXL_S 0x6a 370f408ce8SKatsuhiro Suzuki #define CNRDYU_S 0x6b 380f408ce8SKatsuhiro Suzuki #define CNRDYL_S 0x6c 390f408ce8SKatsuhiro Suzuki #define BERVRDU_S 0x71 400f408ce8SKatsuhiro Suzuki #define BERVRDL_S 0x72 410f408ce8SKatsuhiro Suzuki #define DOSET1_S 0x73 420f408ce8SKatsuhiro Suzuki 430f408ce8SKatsuhiro Suzuki /* Primary ISDB-T */ 440f408ce8SKatsuhiro Suzuki #define PLLASET1 0x00 450f408ce8SKatsuhiro Suzuki #define PLLASET2 0x01 460f408ce8SKatsuhiro Suzuki #define PLLBSET1 0x02 470f408ce8SKatsuhiro Suzuki #define PLLBSET2 0x03 480f408ce8SKatsuhiro Suzuki #define PLLSET 0x04 490f408ce8SKatsuhiro Suzuki #define OUTCSET 0x08 500f408ce8SKatsuhiro Suzuki #define OUTCSET_CHDRV_8MA 0xff 510f408ce8SKatsuhiro Suzuki #define OUTCSET_CHDRV_4MA 0x00 520f408ce8SKatsuhiro Suzuki #define PLDWSET 0x09 530f408ce8SKatsuhiro Suzuki #define PLDWSET_NORMAL 0x00 540f408ce8SKatsuhiro Suzuki #define PLDWSET_PULLDOWN 0xff 550f408ce8SKatsuhiro Suzuki #define HIZSET1 0x0a 560f408ce8SKatsuhiro Suzuki #define HIZSET2 0x0b 570f408ce8SKatsuhiro Suzuki 580f408ce8SKatsuhiro Suzuki /* Secondary ISDB-T (for MN884434 only) */ 590f408ce8SKatsuhiro Suzuki #define RCVSET 0x00 600f408ce8SKatsuhiro Suzuki #define TSSET1_M 0x01 610f408ce8SKatsuhiro Suzuki #define TSSET2_M 0x02 620f408ce8SKatsuhiro Suzuki #define TSSET3_M 0x03 630f408ce8SKatsuhiro Suzuki #define INTACSET 0x08 640f408ce8SKatsuhiro Suzuki #define HIZSET3 0x0b 650f408ce8SKatsuhiro Suzuki 660f408ce8SKatsuhiro Suzuki /* ISDB-T registers */ 670f408ce8SKatsuhiro Suzuki #define TSSET1 0x05 680f408ce8SKatsuhiro Suzuki #define TSSET1_TSASEL_MASK GENMASK(4, 3) 690f408ce8SKatsuhiro Suzuki #define TSSET1_TSASEL_ISDBT (0x0 << 3) 700f408ce8SKatsuhiro Suzuki #define TSSET1_TSASEL_ISDBS (0x1 << 3) 710f408ce8SKatsuhiro Suzuki #define TSSET1_TSASEL_NONE (0x2 << 3) 720f408ce8SKatsuhiro Suzuki #define TSSET1_TSBSEL_MASK GENMASK(2, 1) 730f408ce8SKatsuhiro Suzuki #define TSSET1_TSBSEL_ISDBS (0x0 << 1) 740f408ce8SKatsuhiro Suzuki #define TSSET1_TSBSEL_ISDBT (0x1 << 1) 750f408ce8SKatsuhiro Suzuki #define TSSET1_TSBSEL_NONE (0x2 << 1) 760f408ce8SKatsuhiro Suzuki #define TSSET2 0x06 770f408ce8SKatsuhiro Suzuki #define TSSET3 0x07 780f408ce8SKatsuhiro Suzuki #define TSSET3_INTASEL_MASK GENMASK(7, 6) 790f408ce8SKatsuhiro Suzuki #define TSSET3_INTASEL_T (0x0 << 6) 800f408ce8SKatsuhiro Suzuki #define TSSET3_INTASEL_S (0x1 << 6) 810f408ce8SKatsuhiro Suzuki #define TSSET3_INTASEL_NONE (0x2 << 6) 820f408ce8SKatsuhiro Suzuki #define TSSET3_INTBSEL_MASK GENMASK(5, 4) 830f408ce8SKatsuhiro Suzuki #define TSSET3_INTBSEL_S (0x0 << 4) 840f408ce8SKatsuhiro Suzuki #define TSSET3_INTBSEL_T (0x1 << 4) 850f408ce8SKatsuhiro Suzuki #define TSSET3_INTBSEL_NONE (0x2 << 4) 860f408ce8SKatsuhiro Suzuki #define OUTSET2 0x0d 870f408ce8SKatsuhiro Suzuki #define PWDSET 0x0f 880f408ce8SKatsuhiro Suzuki #define PWDSET_OFDMPD_MASK GENMASK(3, 2) 890f408ce8SKatsuhiro Suzuki #define PWDSET_OFDMPD_DOWN BIT(3) 900f408ce8SKatsuhiro Suzuki #define PWDSET_PSKPD_MASK GENMASK(1, 0) 910f408ce8SKatsuhiro Suzuki #define PWDSET_PSKPD_DOWN BIT(1) 920f408ce8SKatsuhiro Suzuki #define CLKSET1_T 0x11 930f408ce8SKatsuhiro Suzuki #define MDSET_T 0x13 940f408ce8SKatsuhiro Suzuki #define MDSET_T_MDAUTO_MASK GENMASK(7, 4) 950f408ce8SKatsuhiro Suzuki #define MDSET_T_MDAUTO_AUTO (0xf << 4) 960f408ce8SKatsuhiro Suzuki #define MDSET_T_MDAUTO_MANUAL (0x0 << 4) 970f408ce8SKatsuhiro Suzuki #define MDSET_T_FFTS_MASK GENMASK(3, 2) 980f408ce8SKatsuhiro Suzuki #define MDSET_T_FFTS_MODE1 (0x0 << 2) 990f408ce8SKatsuhiro Suzuki #define MDSET_T_FFTS_MODE2 (0x1 << 2) 1000f408ce8SKatsuhiro Suzuki #define MDSET_T_FFTS_MODE3 (0x2 << 2) 1010f408ce8SKatsuhiro Suzuki #define MDSET_T_GI_MASK GENMASK(1, 0) 1020f408ce8SKatsuhiro Suzuki #define MDSET_T_GI_1_32 (0x0 << 0) 1030f408ce8SKatsuhiro Suzuki #define MDSET_T_GI_1_16 (0x1 << 0) 1040f408ce8SKatsuhiro Suzuki #define MDSET_T_GI_1_8 (0x2 << 0) 1050f408ce8SKatsuhiro Suzuki #define MDSET_T_GI_1_4 (0x3 << 0) 1060f408ce8SKatsuhiro Suzuki #define MDASET_T 0x14 1070f408ce8SKatsuhiro Suzuki #define ADCSET1_T 0x20 1080f408ce8SKatsuhiro Suzuki #define ADCSET1_T_REFSEL_MASK GENMASK(1, 0) 1090f408ce8SKatsuhiro Suzuki #define ADCSET1_T_REFSEL_2V (0x3 << 0) 1100f408ce8SKatsuhiro Suzuki #define ADCSET1_T_REFSEL_1_5V (0x2 << 0) 1110f408ce8SKatsuhiro Suzuki #define ADCSET1_T_REFSEL_1V (0x1 << 0) 1120f408ce8SKatsuhiro Suzuki #define NCOFREQU_T 0x24 1130f408ce8SKatsuhiro Suzuki #define NCOFREQM_T 0x25 1140f408ce8SKatsuhiro Suzuki #define NCOFREQL_T 0x26 1150f408ce8SKatsuhiro Suzuki #define FADU_T 0x27 1160f408ce8SKatsuhiro Suzuki #define FADM_T 0x28 1170f408ce8SKatsuhiro Suzuki #define FADL_T 0x29 1180f408ce8SKatsuhiro Suzuki #define AGCSET2_T 0x2c 1190f408ce8SKatsuhiro Suzuki #define AGCSET2_T_IFPOLINV_INC BIT(0) 1200f408ce8SKatsuhiro Suzuki #define AGCSET2_T_RFPOLINV_INC BIT(1) 1210f408ce8SKatsuhiro Suzuki #define AGCV3_T 0x3e 1220f408ce8SKatsuhiro Suzuki #define MDRD_T 0xa2 1230f408ce8SKatsuhiro Suzuki #define MDRD_T_SEGID_MASK GENMASK(5, 4) 1240f408ce8SKatsuhiro Suzuki #define MDRD_T_SEGID_13 (0x0 << 4) 1250f408ce8SKatsuhiro Suzuki #define MDRD_T_SEGID_1 (0x1 << 4) 1260f408ce8SKatsuhiro Suzuki #define MDRD_T_SEGID_3 (0x2 << 4) 1270f408ce8SKatsuhiro Suzuki #define MDRD_T_FFTS_MASK GENMASK(3, 2) 1280f408ce8SKatsuhiro Suzuki #define MDRD_T_FFTS_MODE1 (0x0 << 2) 1290f408ce8SKatsuhiro Suzuki #define MDRD_T_FFTS_MODE2 (0x1 << 2) 1300f408ce8SKatsuhiro Suzuki #define MDRD_T_FFTS_MODE3 (0x2 << 2) 1310f408ce8SKatsuhiro Suzuki #define MDRD_T_GI_MASK GENMASK(1, 0) 1320f408ce8SKatsuhiro Suzuki #define MDRD_T_GI_1_32 (0x0 << 0) 1330f408ce8SKatsuhiro Suzuki #define MDRD_T_GI_1_16 (0x1 << 0) 1340f408ce8SKatsuhiro Suzuki #define MDRD_T_GI_1_8 (0x2 << 0) 1350f408ce8SKatsuhiro Suzuki #define MDRD_T_GI_1_4 (0x3 << 0) 1360f408ce8SKatsuhiro Suzuki #define SSEQRD_T 0xa3 1370f408ce8SKatsuhiro Suzuki #define SSEQRD_T_SSEQSTRD_MASK GENMASK(3, 0) 1380f408ce8SKatsuhiro Suzuki #define SSEQRD_T_SSEQSTRD_RESET (0x0 << 0) 1390f408ce8SKatsuhiro Suzuki #define SSEQRD_T_SSEQSTRD_TUNING (0x1 << 0) 1400f408ce8SKatsuhiro Suzuki #define SSEQRD_T_SSEQSTRD_AGC (0x2 << 0) 1410f408ce8SKatsuhiro Suzuki #define SSEQRD_T_SSEQSTRD_SEARCH (0x3 << 0) 1420f408ce8SKatsuhiro Suzuki #define SSEQRD_T_SSEQSTRD_CLOCK_SYNC (0x4 << 0) 1430f408ce8SKatsuhiro Suzuki #define SSEQRD_T_SSEQSTRD_FREQ_SYNC (0x8 << 0) 1440f408ce8SKatsuhiro Suzuki #define SSEQRD_T_SSEQSTRD_FRAME_SYNC (0x9 << 0) 1450f408ce8SKatsuhiro Suzuki #define SSEQRD_T_SSEQSTRD_SYNC (0xa << 0) 1460f408ce8SKatsuhiro Suzuki #define SSEQRD_T_SSEQSTRD_LOCK (0xb << 0) 1470f408ce8SKatsuhiro Suzuki #define AGCRDU_T 0xa8 1480f408ce8SKatsuhiro Suzuki #define AGCRDL_T 0xa9 1490f408ce8SKatsuhiro Suzuki #define CNRDU_T 0xbe 1500f408ce8SKatsuhiro Suzuki #define CNRDL_T 0xbf 1510f408ce8SKatsuhiro Suzuki #define BERFLG_T 0xc0 1520f408ce8SKatsuhiro Suzuki #define BERFLG_T_BERDRDY BIT(7) 1530f408ce8SKatsuhiro Suzuki #define BERFLG_T_BERDCHK BIT(6) 1540f408ce8SKatsuhiro Suzuki #define BERFLG_T_BERVRDYA BIT(5) 1550f408ce8SKatsuhiro Suzuki #define BERFLG_T_BERVCHKA BIT(4) 1560f408ce8SKatsuhiro Suzuki #define BERFLG_T_BERVRDYB BIT(3) 1570f408ce8SKatsuhiro Suzuki #define BERFLG_T_BERVCHKB BIT(2) 1580f408ce8SKatsuhiro Suzuki #define BERFLG_T_BERVRDYC BIT(1) 1590f408ce8SKatsuhiro Suzuki #define BERFLG_T_BERVCHKC BIT(0) 1600f408ce8SKatsuhiro Suzuki #define BERRDU_T 0xc1 1610f408ce8SKatsuhiro Suzuki #define BERRDM_T 0xc2 1620f408ce8SKatsuhiro Suzuki #define BERRDL_T 0xc3 1630f408ce8SKatsuhiro Suzuki #define BERLENRDU_T 0xc4 1640f408ce8SKatsuhiro Suzuki #define BERLENRDL_T 0xc5 1650f408ce8SKatsuhiro Suzuki #define ERRFLG_T 0xc6 1660f408ce8SKatsuhiro Suzuki #define ERRFLG_T_BERDOVF BIT(7) 1670f408ce8SKatsuhiro Suzuki #define ERRFLG_T_BERVOVFA BIT(6) 1680f408ce8SKatsuhiro Suzuki #define ERRFLG_T_BERVOVFB BIT(5) 1690f408ce8SKatsuhiro Suzuki #define ERRFLG_T_BERVOVFC BIT(4) 1700f408ce8SKatsuhiro Suzuki #define ERRFLG_T_NERRFA BIT(3) 1710f408ce8SKatsuhiro Suzuki #define ERRFLG_T_NERRFB BIT(2) 1720f408ce8SKatsuhiro Suzuki #define ERRFLG_T_NERRFC BIT(1) 1730f408ce8SKatsuhiro Suzuki #define ERRFLG_T_NERRF BIT(0) 1740f408ce8SKatsuhiro Suzuki #define DOSET1_T 0xcf 1750f408ce8SKatsuhiro Suzuki 1760f408ce8SKatsuhiro Suzuki #define CLK_LOW 4000000 1770f408ce8SKatsuhiro Suzuki #define CLK_DIRECT 20200000 1780f408ce8SKatsuhiro Suzuki #define CLK_MAX 25410000 1790f408ce8SKatsuhiro Suzuki 1800f408ce8SKatsuhiro Suzuki #define S_T_FREQ 8126984 /* 512 / 63 MHz */ 1810f408ce8SKatsuhiro Suzuki 1820f408ce8SKatsuhiro Suzuki struct mn88443x_spec { 1830f408ce8SKatsuhiro Suzuki bool primary; 1840f408ce8SKatsuhiro Suzuki }; 1850f408ce8SKatsuhiro Suzuki 1860f408ce8SKatsuhiro Suzuki struct mn88443x_priv { 1870f408ce8SKatsuhiro Suzuki const struct mn88443x_spec *spec; 1880f408ce8SKatsuhiro Suzuki 1890f408ce8SKatsuhiro Suzuki struct dvb_frontend fe; 1900f408ce8SKatsuhiro Suzuki struct clk *mclk; 1910f408ce8SKatsuhiro Suzuki struct gpio_desc *reset_gpio; 1920f408ce8SKatsuhiro Suzuki u32 clk_freq; 1930f408ce8SKatsuhiro Suzuki u32 if_freq; 1940f408ce8SKatsuhiro Suzuki 1950f408ce8SKatsuhiro Suzuki /* Common */ 1960f408ce8SKatsuhiro Suzuki bool use_clkbuf; 1970f408ce8SKatsuhiro Suzuki 1980f408ce8SKatsuhiro Suzuki /* ISDB-S */ 1990f408ce8SKatsuhiro Suzuki struct i2c_client *client_s; 2000f408ce8SKatsuhiro Suzuki struct regmap *regmap_s; 2010f408ce8SKatsuhiro Suzuki 2020f408ce8SKatsuhiro Suzuki /* ISDB-T */ 2030f408ce8SKatsuhiro Suzuki struct i2c_client *client_t; 2040f408ce8SKatsuhiro Suzuki struct regmap *regmap_t; 2050f408ce8SKatsuhiro Suzuki }; 2060f408ce8SKatsuhiro Suzuki 2070f408ce8SKatsuhiro Suzuki static void mn88443x_cmn_power_on(struct mn88443x_priv *chip) 2080f408ce8SKatsuhiro Suzuki { 2090f408ce8SKatsuhiro Suzuki struct regmap *r_t = chip->regmap_t; 2100f408ce8SKatsuhiro Suzuki 2110f408ce8SKatsuhiro Suzuki clk_prepare_enable(chip->mclk); 2120f408ce8SKatsuhiro Suzuki 2130f408ce8SKatsuhiro Suzuki gpiod_set_value_cansleep(chip->reset_gpio, 1); 2140f408ce8SKatsuhiro Suzuki usleep_range(100, 1000); 2150f408ce8SKatsuhiro Suzuki gpiod_set_value_cansleep(chip->reset_gpio, 0); 2160f408ce8SKatsuhiro Suzuki 2170f408ce8SKatsuhiro Suzuki if (chip->spec->primary) { 2180f408ce8SKatsuhiro Suzuki regmap_write(r_t, OUTCSET, OUTCSET_CHDRV_8MA); 2190f408ce8SKatsuhiro Suzuki regmap_write(r_t, PLDWSET, PLDWSET_NORMAL); 2200f408ce8SKatsuhiro Suzuki regmap_write(r_t, HIZSET1, 0x80); 2210f408ce8SKatsuhiro Suzuki regmap_write(r_t, HIZSET2, 0xe0); 2220f408ce8SKatsuhiro Suzuki } else { 2230f408ce8SKatsuhiro Suzuki regmap_write(r_t, HIZSET3, 0x8f); 2240f408ce8SKatsuhiro Suzuki } 2250f408ce8SKatsuhiro Suzuki } 2260f408ce8SKatsuhiro Suzuki 2270f408ce8SKatsuhiro Suzuki static void mn88443x_cmn_power_off(struct mn88443x_priv *chip) 2280f408ce8SKatsuhiro Suzuki { 2290f408ce8SKatsuhiro Suzuki gpiod_set_value_cansleep(chip->reset_gpio, 1); 2300f408ce8SKatsuhiro Suzuki 2310f408ce8SKatsuhiro Suzuki clk_disable_unprepare(chip->mclk); 2320f408ce8SKatsuhiro Suzuki } 2330f408ce8SKatsuhiro Suzuki 2340f408ce8SKatsuhiro Suzuki static void mn88443x_s_sleep(struct mn88443x_priv *chip) 2350f408ce8SKatsuhiro Suzuki { 2360f408ce8SKatsuhiro Suzuki struct regmap *r_t = chip->regmap_t; 2370f408ce8SKatsuhiro Suzuki 2380f408ce8SKatsuhiro Suzuki regmap_update_bits(r_t, PWDSET, PWDSET_PSKPD_MASK, 2390f408ce8SKatsuhiro Suzuki PWDSET_PSKPD_DOWN); 2400f408ce8SKatsuhiro Suzuki } 2410f408ce8SKatsuhiro Suzuki 2420f408ce8SKatsuhiro Suzuki static void mn88443x_s_wake(struct mn88443x_priv *chip) 2430f408ce8SKatsuhiro Suzuki { 2440f408ce8SKatsuhiro Suzuki struct regmap *r_t = chip->regmap_t; 2450f408ce8SKatsuhiro Suzuki 2460f408ce8SKatsuhiro Suzuki regmap_update_bits(r_t, PWDSET, PWDSET_PSKPD_MASK, 0); 2470f408ce8SKatsuhiro Suzuki } 2480f408ce8SKatsuhiro Suzuki 2490f408ce8SKatsuhiro Suzuki static void mn88443x_s_tune(struct mn88443x_priv *chip, 2500f408ce8SKatsuhiro Suzuki struct dtv_frontend_properties *c) 2510f408ce8SKatsuhiro Suzuki { 2520f408ce8SKatsuhiro Suzuki struct regmap *r_s = chip->regmap_s; 2530f408ce8SKatsuhiro Suzuki 2540f408ce8SKatsuhiro Suzuki regmap_write(r_s, ATSIDU_S, c->stream_id >> 8); 2550f408ce8SKatsuhiro Suzuki regmap_write(r_s, ATSIDL_S, c->stream_id); 2560f408ce8SKatsuhiro Suzuki regmap_write(r_s, TSSET_S, 0); 2570f408ce8SKatsuhiro Suzuki } 2580f408ce8SKatsuhiro Suzuki 2590f408ce8SKatsuhiro Suzuki static int mn88443x_s_read_status(struct mn88443x_priv *chip, 2600f408ce8SKatsuhiro Suzuki struct dtv_frontend_properties *c, 2610f408ce8SKatsuhiro Suzuki enum fe_status *status) 2620f408ce8SKatsuhiro Suzuki { 2630f408ce8SKatsuhiro Suzuki struct regmap *r_s = chip->regmap_s; 2640f408ce8SKatsuhiro Suzuki u32 cpmon, tmpu, tmpl, flg; 2650f408ce8SKatsuhiro Suzuki u64 tmp; 2660f408ce8SKatsuhiro Suzuki 2670f408ce8SKatsuhiro Suzuki /* Sync detection */ 2680f408ce8SKatsuhiro Suzuki regmap_read(r_s, CPMON1_S, &cpmon); 2690f408ce8SKatsuhiro Suzuki 2700f408ce8SKatsuhiro Suzuki *status = 0; 2710f408ce8SKatsuhiro Suzuki if (cpmon & CPMON1_S_FSYNC) 2720f408ce8SKatsuhiro Suzuki *status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; 2730f408ce8SKatsuhiro Suzuki if (cpmon & CPMON1_S_W2LOCK) 2740f408ce8SKatsuhiro Suzuki *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER; 2750f408ce8SKatsuhiro Suzuki 2760f408ce8SKatsuhiro Suzuki /* Signal strength */ 2770f408ce8SKatsuhiro Suzuki c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 2780f408ce8SKatsuhiro Suzuki 2790f408ce8SKatsuhiro Suzuki if (*status & FE_HAS_SIGNAL) { 2800f408ce8SKatsuhiro Suzuki u32 agc; 2810f408ce8SKatsuhiro Suzuki 2820f408ce8SKatsuhiro Suzuki regmap_read(r_s, AGCREAD_S, &tmpu); 2830f408ce8SKatsuhiro Suzuki agc = tmpu << 8; 2840f408ce8SKatsuhiro Suzuki 2850f408ce8SKatsuhiro Suzuki c->strength.len = 1; 2860f408ce8SKatsuhiro Suzuki c->strength.stat[0].scale = FE_SCALE_RELATIVE; 2870f408ce8SKatsuhiro Suzuki c->strength.stat[0].uvalue = agc; 2880f408ce8SKatsuhiro Suzuki } 2890f408ce8SKatsuhiro Suzuki 2900f408ce8SKatsuhiro Suzuki /* C/N rate */ 2910f408ce8SKatsuhiro Suzuki c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 2920f408ce8SKatsuhiro Suzuki 2930f408ce8SKatsuhiro Suzuki if (*status & FE_HAS_VITERBI) { 2940f408ce8SKatsuhiro Suzuki u32 cnr = 0, x, y, d; 2950f408ce8SKatsuhiro Suzuki u64 d_3 = 0; 2960f408ce8SKatsuhiro Suzuki 2970f408ce8SKatsuhiro Suzuki regmap_read(r_s, CNRDXU_S, &tmpu); 2980f408ce8SKatsuhiro Suzuki regmap_read(r_s, CNRDXL_S, &tmpl); 2990f408ce8SKatsuhiro Suzuki x = (tmpu << 8) | tmpl; 3000f408ce8SKatsuhiro Suzuki regmap_read(r_s, CNRDYU_S, &tmpu); 3010f408ce8SKatsuhiro Suzuki regmap_read(r_s, CNRDYL_S, &tmpl); 3020f408ce8SKatsuhiro Suzuki y = (tmpu << 8) | tmpl; 3030f408ce8SKatsuhiro Suzuki 3040f408ce8SKatsuhiro Suzuki /* CNR[dB]: 10 * log10(D) - 30.74 / D^3 - 3 */ 3050f408ce8SKatsuhiro Suzuki /* D = x^2 / (2^15 * y - x^2) */ 3060f408ce8SKatsuhiro Suzuki d = (y << 15) - x * x; 3070f408ce8SKatsuhiro Suzuki if (d > 0) { 3080f408ce8SKatsuhiro Suzuki /* (2^4 * D)^3 = 2^12 * D^3 */ 3090f408ce8SKatsuhiro Suzuki /* 3.074 * 2^(12 + 24) = 211243671486 */ 3100f408ce8SKatsuhiro Suzuki d_3 = div_u64(16 * x * x, d); 3110f408ce8SKatsuhiro Suzuki d_3 = d_3 * d_3 * d_3; 3120f408ce8SKatsuhiro Suzuki if (d_3) 3130f408ce8SKatsuhiro Suzuki d_3 = div_u64(211243671486ULL, d_3); 3140f408ce8SKatsuhiro Suzuki } 3150f408ce8SKatsuhiro Suzuki 3160f408ce8SKatsuhiro Suzuki if (d_3) { 3170f408ce8SKatsuhiro Suzuki /* 0.3 * 2^24 = 5033164 */ 3180f408ce8SKatsuhiro Suzuki tmp = (s64)2 * intlog10(x) - intlog10(abs(d)) - d_3 3190f408ce8SKatsuhiro Suzuki - 5033164; 3200f408ce8SKatsuhiro Suzuki cnr = div_u64(tmp * 10000, 1 << 24); 3210f408ce8SKatsuhiro Suzuki } 3220f408ce8SKatsuhiro Suzuki 3230f408ce8SKatsuhiro Suzuki if (cnr) { 3240f408ce8SKatsuhiro Suzuki c->cnr.len = 1; 3250f408ce8SKatsuhiro Suzuki c->cnr.stat[0].scale = FE_SCALE_DECIBEL; 3260f408ce8SKatsuhiro Suzuki c->cnr.stat[0].uvalue = cnr; 3270f408ce8SKatsuhiro Suzuki } 3280f408ce8SKatsuhiro Suzuki } 3290f408ce8SKatsuhiro Suzuki 3300f408ce8SKatsuhiro Suzuki /* BER */ 3310f408ce8SKatsuhiro Suzuki c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 3320f408ce8SKatsuhiro Suzuki c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 3330f408ce8SKatsuhiro Suzuki 3340f408ce8SKatsuhiro Suzuki regmap_read(r_s, BERCNFLG_S, &flg); 3350f408ce8SKatsuhiro Suzuki 3360f408ce8SKatsuhiro Suzuki if ((*status & FE_HAS_VITERBI) && (flg & BERCNFLG_S_BERVRDY)) { 3370f408ce8SKatsuhiro Suzuki u32 bit_err, bit_cnt; 3380f408ce8SKatsuhiro Suzuki 3390f408ce8SKatsuhiro Suzuki regmap_read(r_s, BERVRDU_S, &tmpu); 3400f408ce8SKatsuhiro Suzuki regmap_read(r_s, BERVRDL_S, &tmpl); 3410f408ce8SKatsuhiro Suzuki bit_err = (tmpu << 8) | tmpl; 3420f408ce8SKatsuhiro Suzuki bit_cnt = (1 << 13) * 204; 3430f408ce8SKatsuhiro Suzuki 3440f408ce8SKatsuhiro Suzuki if (bit_cnt) { 3450f408ce8SKatsuhiro Suzuki c->post_bit_error.len = 1; 3460f408ce8SKatsuhiro Suzuki c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; 3470f408ce8SKatsuhiro Suzuki c->post_bit_error.stat[0].uvalue = bit_err; 3480f408ce8SKatsuhiro Suzuki c->post_bit_count.len = 1; 3490f408ce8SKatsuhiro Suzuki c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; 3500f408ce8SKatsuhiro Suzuki c->post_bit_count.stat[0].uvalue = bit_cnt; 3510f408ce8SKatsuhiro Suzuki } 3520f408ce8SKatsuhiro Suzuki } 3530f408ce8SKatsuhiro Suzuki 3540f408ce8SKatsuhiro Suzuki return 0; 3550f408ce8SKatsuhiro Suzuki } 3560f408ce8SKatsuhiro Suzuki 3570f408ce8SKatsuhiro Suzuki static void mn88443x_t_sleep(struct mn88443x_priv *chip) 3580f408ce8SKatsuhiro Suzuki { 3590f408ce8SKatsuhiro Suzuki struct regmap *r_t = chip->regmap_t; 3600f408ce8SKatsuhiro Suzuki 3610f408ce8SKatsuhiro Suzuki regmap_update_bits(r_t, PWDSET, PWDSET_OFDMPD_MASK, 3620f408ce8SKatsuhiro Suzuki PWDSET_OFDMPD_DOWN); 3630f408ce8SKatsuhiro Suzuki } 3640f408ce8SKatsuhiro Suzuki 3650f408ce8SKatsuhiro Suzuki static void mn88443x_t_wake(struct mn88443x_priv *chip) 3660f408ce8SKatsuhiro Suzuki { 3670f408ce8SKatsuhiro Suzuki struct regmap *r_t = chip->regmap_t; 3680f408ce8SKatsuhiro Suzuki 3690f408ce8SKatsuhiro Suzuki regmap_update_bits(r_t, PWDSET, PWDSET_OFDMPD_MASK, 0); 3700f408ce8SKatsuhiro Suzuki } 3710f408ce8SKatsuhiro Suzuki 3720f408ce8SKatsuhiro Suzuki static bool mn88443x_t_is_valid_clk(u32 adckt, u32 if_freq) 3730f408ce8SKatsuhiro Suzuki { 3740f408ce8SKatsuhiro Suzuki if (if_freq == DIRECT_IF_57MHZ) { 3750f408ce8SKatsuhiro Suzuki if (adckt >= CLK_DIRECT && adckt <= 21000000) 3760f408ce8SKatsuhiro Suzuki return true; 3770f408ce8SKatsuhiro Suzuki if (adckt >= 25300000 && adckt <= CLK_MAX) 3780f408ce8SKatsuhiro Suzuki return true; 3790f408ce8SKatsuhiro Suzuki } else if (if_freq == DIRECT_IF_44MHZ) { 3800f408ce8SKatsuhiro Suzuki if (adckt >= 25000000 && adckt <= CLK_MAX) 3810f408ce8SKatsuhiro Suzuki return true; 3820f408ce8SKatsuhiro Suzuki } else if (if_freq >= LOW_IF_4MHZ && if_freq < DIRECT_IF_44MHZ) { 3830f408ce8SKatsuhiro Suzuki if (adckt >= CLK_DIRECT && adckt <= CLK_MAX) 3840f408ce8SKatsuhiro Suzuki return true; 3850f408ce8SKatsuhiro Suzuki } 3860f408ce8SKatsuhiro Suzuki 3870f408ce8SKatsuhiro Suzuki return false; 3880f408ce8SKatsuhiro Suzuki } 3890f408ce8SKatsuhiro Suzuki 3900f408ce8SKatsuhiro Suzuki static int mn88443x_t_set_freq(struct mn88443x_priv *chip) 3910f408ce8SKatsuhiro Suzuki { 3920f408ce8SKatsuhiro Suzuki struct device *dev = &chip->client_s->dev; 3930f408ce8SKatsuhiro Suzuki struct regmap *r_t = chip->regmap_t; 3940f408ce8SKatsuhiro Suzuki s64 adckt, nco, ad_t; 3950f408ce8SKatsuhiro Suzuki u32 m, v; 3960f408ce8SKatsuhiro Suzuki 3970f408ce8SKatsuhiro Suzuki /* Clock buffer (but not supported) or XTAL */ 3980f408ce8SKatsuhiro Suzuki if (chip->clk_freq >= CLK_LOW && chip->clk_freq < CLK_DIRECT) { 3990f408ce8SKatsuhiro Suzuki chip->use_clkbuf = true; 4000f408ce8SKatsuhiro Suzuki regmap_write(r_t, CLKSET1_T, 0x07); 4010f408ce8SKatsuhiro Suzuki 4020f408ce8SKatsuhiro Suzuki adckt = 0; 4030f408ce8SKatsuhiro Suzuki } else { 4040f408ce8SKatsuhiro Suzuki chip->use_clkbuf = false; 4050f408ce8SKatsuhiro Suzuki regmap_write(r_t, CLKSET1_T, 0x00); 4060f408ce8SKatsuhiro Suzuki 4070f408ce8SKatsuhiro Suzuki adckt = chip->clk_freq; 4080f408ce8SKatsuhiro Suzuki } 4090f408ce8SKatsuhiro Suzuki if (!mn88443x_t_is_valid_clk(adckt, chip->if_freq)) { 4100f408ce8SKatsuhiro Suzuki dev_err(dev, "Invalid clock, CLK:%d, ADCKT:%lld, IF:%d\n", 4110f408ce8SKatsuhiro Suzuki chip->clk_freq, adckt, chip->if_freq); 4120f408ce8SKatsuhiro Suzuki return -EINVAL; 4130f408ce8SKatsuhiro Suzuki } 4140f408ce8SKatsuhiro Suzuki 4150f408ce8SKatsuhiro Suzuki /* Direct IF or Low IF */ 4160f408ce8SKatsuhiro Suzuki if (chip->if_freq == DIRECT_IF_57MHZ || 4170f408ce8SKatsuhiro Suzuki chip->if_freq == DIRECT_IF_44MHZ) 4180f408ce8SKatsuhiro Suzuki nco = adckt * 2 - chip->if_freq; 4190f408ce8SKatsuhiro Suzuki else 4200f408ce8SKatsuhiro Suzuki nco = -((s64)chip->if_freq); 4210f408ce8SKatsuhiro Suzuki nco = div_s64(nco << 24, adckt); 4220f408ce8SKatsuhiro Suzuki ad_t = div_s64(adckt << 22, S_T_FREQ); 4230f408ce8SKatsuhiro Suzuki 4240f408ce8SKatsuhiro Suzuki regmap_write(r_t, NCOFREQU_T, nco >> 16); 4250f408ce8SKatsuhiro Suzuki regmap_write(r_t, NCOFREQM_T, nco >> 8); 4260f408ce8SKatsuhiro Suzuki regmap_write(r_t, NCOFREQL_T, nco); 4270f408ce8SKatsuhiro Suzuki regmap_write(r_t, FADU_T, ad_t >> 16); 4280f408ce8SKatsuhiro Suzuki regmap_write(r_t, FADM_T, ad_t >> 8); 4290f408ce8SKatsuhiro Suzuki regmap_write(r_t, FADL_T, ad_t); 4300f408ce8SKatsuhiro Suzuki 4310f408ce8SKatsuhiro Suzuki /* Level of IF */ 4320f408ce8SKatsuhiro Suzuki m = ADCSET1_T_REFSEL_MASK; 4330f408ce8SKatsuhiro Suzuki v = ADCSET1_T_REFSEL_1_5V; 4340f408ce8SKatsuhiro Suzuki regmap_update_bits(r_t, ADCSET1_T, m, v); 4350f408ce8SKatsuhiro Suzuki 4360f408ce8SKatsuhiro Suzuki /* Polarity of AGC */ 4370f408ce8SKatsuhiro Suzuki v = AGCSET2_T_IFPOLINV_INC | AGCSET2_T_RFPOLINV_INC; 4380f408ce8SKatsuhiro Suzuki regmap_update_bits(r_t, AGCSET2_T, v, v); 4390f408ce8SKatsuhiro Suzuki 4400f408ce8SKatsuhiro Suzuki /* Lower output level of AGC */ 4410f408ce8SKatsuhiro Suzuki regmap_write(r_t, AGCV3_T, 0x00); 4420f408ce8SKatsuhiro Suzuki 4430f408ce8SKatsuhiro Suzuki regmap_write(r_t, MDSET_T, 0xfa); 4440f408ce8SKatsuhiro Suzuki 4450f408ce8SKatsuhiro Suzuki return 0; 4460f408ce8SKatsuhiro Suzuki } 4470f408ce8SKatsuhiro Suzuki 4480f408ce8SKatsuhiro Suzuki static void mn88443x_t_tune(struct mn88443x_priv *chip, 4490f408ce8SKatsuhiro Suzuki struct dtv_frontend_properties *c) 4500f408ce8SKatsuhiro Suzuki { 4510f408ce8SKatsuhiro Suzuki struct regmap *r_t = chip->regmap_t; 4520f408ce8SKatsuhiro Suzuki u32 m, v; 4530f408ce8SKatsuhiro Suzuki 4540f408ce8SKatsuhiro Suzuki m = MDSET_T_MDAUTO_MASK | MDSET_T_FFTS_MASK | MDSET_T_GI_MASK; 4550f408ce8SKatsuhiro Suzuki v = MDSET_T_MDAUTO_AUTO | MDSET_T_FFTS_MODE3 | MDSET_T_GI_1_8; 4560f408ce8SKatsuhiro Suzuki regmap_update_bits(r_t, MDSET_T, m, v); 4570f408ce8SKatsuhiro Suzuki 4580f408ce8SKatsuhiro Suzuki regmap_write(r_t, MDASET_T, 0); 4590f408ce8SKatsuhiro Suzuki } 4600f408ce8SKatsuhiro Suzuki 4610f408ce8SKatsuhiro Suzuki static int mn88443x_t_read_status(struct mn88443x_priv *chip, 4620f408ce8SKatsuhiro Suzuki struct dtv_frontend_properties *c, 4630f408ce8SKatsuhiro Suzuki enum fe_status *status) 4640f408ce8SKatsuhiro Suzuki { 4650f408ce8SKatsuhiro Suzuki struct regmap *r_t = chip->regmap_t; 4660f408ce8SKatsuhiro Suzuki u32 seqrd, st, flg, tmpu, tmpm, tmpl; 4670f408ce8SKatsuhiro Suzuki u64 tmp; 4680f408ce8SKatsuhiro Suzuki 4690f408ce8SKatsuhiro Suzuki /* Sync detection */ 4700f408ce8SKatsuhiro Suzuki regmap_read(r_t, SSEQRD_T, &seqrd); 4710f408ce8SKatsuhiro Suzuki st = seqrd & SSEQRD_T_SSEQSTRD_MASK; 4720f408ce8SKatsuhiro Suzuki 4730f408ce8SKatsuhiro Suzuki *status = 0; 4740f408ce8SKatsuhiro Suzuki if (st >= SSEQRD_T_SSEQSTRD_SYNC) 4750f408ce8SKatsuhiro Suzuki *status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; 4760f408ce8SKatsuhiro Suzuki if (st >= SSEQRD_T_SSEQSTRD_FRAME_SYNC) 4770f408ce8SKatsuhiro Suzuki *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER; 4780f408ce8SKatsuhiro Suzuki 4790f408ce8SKatsuhiro Suzuki /* Signal strength */ 4800f408ce8SKatsuhiro Suzuki c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 4810f408ce8SKatsuhiro Suzuki 4820f408ce8SKatsuhiro Suzuki if (*status & FE_HAS_SIGNAL) { 4830f408ce8SKatsuhiro Suzuki u32 agc; 4840f408ce8SKatsuhiro Suzuki 4850f408ce8SKatsuhiro Suzuki regmap_read(r_t, AGCRDU_T, &tmpu); 4860f408ce8SKatsuhiro Suzuki regmap_read(r_t, AGCRDL_T, &tmpl); 4870f408ce8SKatsuhiro Suzuki agc = (tmpu << 8) | tmpl; 4880f408ce8SKatsuhiro Suzuki 4890f408ce8SKatsuhiro Suzuki c->strength.len = 1; 4900f408ce8SKatsuhiro Suzuki c->strength.stat[0].scale = FE_SCALE_RELATIVE; 4910f408ce8SKatsuhiro Suzuki c->strength.stat[0].uvalue = agc; 4920f408ce8SKatsuhiro Suzuki } 4930f408ce8SKatsuhiro Suzuki 4940f408ce8SKatsuhiro Suzuki /* C/N rate */ 4950f408ce8SKatsuhiro Suzuki c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 4960f408ce8SKatsuhiro Suzuki 4970f408ce8SKatsuhiro Suzuki if (*status & FE_HAS_VITERBI) { 4980f408ce8SKatsuhiro Suzuki u32 cnr; 4990f408ce8SKatsuhiro Suzuki 5000f408ce8SKatsuhiro Suzuki regmap_read(r_t, CNRDU_T, &tmpu); 5010f408ce8SKatsuhiro Suzuki regmap_read(r_t, CNRDL_T, &tmpl); 5020f408ce8SKatsuhiro Suzuki 5030f408ce8SKatsuhiro Suzuki if (tmpu || tmpl) { 5040f408ce8SKatsuhiro Suzuki /* CNR[dB]: 10 * (log10(65536 / value) + 0.2) */ 5050f408ce8SKatsuhiro Suzuki /* intlog10(65536) = 80807124, 0.2 * 2^24 = 3355443 */ 5060f408ce8SKatsuhiro Suzuki tmp = (u64)80807124 - intlog10((tmpu << 8) | tmpl) 5070f408ce8SKatsuhiro Suzuki + 3355443; 5080f408ce8SKatsuhiro Suzuki cnr = div_u64(tmp * 10000, 1 << 24); 5090f408ce8SKatsuhiro Suzuki } else { 5100f408ce8SKatsuhiro Suzuki cnr = 0; 5110f408ce8SKatsuhiro Suzuki } 5120f408ce8SKatsuhiro Suzuki 5130f408ce8SKatsuhiro Suzuki c->cnr.len = 1; 5140f408ce8SKatsuhiro Suzuki c->cnr.stat[0].scale = FE_SCALE_DECIBEL; 5150f408ce8SKatsuhiro Suzuki c->cnr.stat[0].uvalue = cnr; 5160f408ce8SKatsuhiro Suzuki } 5170f408ce8SKatsuhiro Suzuki 5180f408ce8SKatsuhiro Suzuki /* BER */ 5190f408ce8SKatsuhiro Suzuki c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 5200f408ce8SKatsuhiro Suzuki c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 5210f408ce8SKatsuhiro Suzuki 5220f408ce8SKatsuhiro Suzuki regmap_read(r_t, BERFLG_T, &flg); 5230f408ce8SKatsuhiro Suzuki 5240f408ce8SKatsuhiro Suzuki if ((*status & FE_HAS_VITERBI) && (flg & BERFLG_T_BERVRDYA)) { 5250f408ce8SKatsuhiro Suzuki u32 bit_err, bit_cnt; 5260f408ce8SKatsuhiro Suzuki 5270f408ce8SKatsuhiro Suzuki regmap_read(r_t, BERRDU_T, &tmpu); 5280f408ce8SKatsuhiro Suzuki regmap_read(r_t, BERRDM_T, &tmpm); 5290f408ce8SKatsuhiro Suzuki regmap_read(r_t, BERRDL_T, &tmpl); 5300f408ce8SKatsuhiro Suzuki bit_err = (tmpu << 16) | (tmpm << 8) | tmpl; 5310f408ce8SKatsuhiro Suzuki 5320f408ce8SKatsuhiro Suzuki regmap_read(r_t, BERLENRDU_T, &tmpu); 5330f408ce8SKatsuhiro Suzuki regmap_read(r_t, BERLENRDL_T, &tmpl); 5340f408ce8SKatsuhiro Suzuki bit_cnt = ((tmpu << 8) | tmpl) * 203 * 8; 5350f408ce8SKatsuhiro Suzuki 5360f408ce8SKatsuhiro Suzuki if (bit_cnt) { 5370f408ce8SKatsuhiro Suzuki c->post_bit_error.len = 1; 5380f408ce8SKatsuhiro Suzuki c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; 5390f408ce8SKatsuhiro Suzuki c->post_bit_error.stat[0].uvalue = bit_err; 5400f408ce8SKatsuhiro Suzuki c->post_bit_count.len = 1; 5410f408ce8SKatsuhiro Suzuki c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; 5420f408ce8SKatsuhiro Suzuki c->post_bit_count.stat[0].uvalue = bit_cnt; 5430f408ce8SKatsuhiro Suzuki } 5440f408ce8SKatsuhiro Suzuki } 5450f408ce8SKatsuhiro Suzuki 5460f408ce8SKatsuhiro Suzuki return 0; 5470f408ce8SKatsuhiro Suzuki } 5480f408ce8SKatsuhiro Suzuki 5490f408ce8SKatsuhiro Suzuki static int mn88443x_sleep(struct dvb_frontend *fe) 5500f408ce8SKatsuhiro Suzuki { 5510f408ce8SKatsuhiro Suzuki struct mn88443x_priv *chip = fe->demodulator_priv; 5520f408ce8SKatsuhiro Suzuki 5530f408ce8SKatsuhiro Suzuki mn88443x_s_sleep(chip); 5540f408ce8SKatsuhiro Suzuki mn88443x_t_sleep(chip); 5550f408ce8SKatsuhiro Suzuki 5560f408ce8SKatsuhiro Suzuki return 0; 5570f408ce8SKatsuhiro Suzuki } 5580f408ce8SKatsuhiro Suzuki 5590f408ce8SKatsuhiro Suzuki static int mn88443x_set_frontend(struct dvb_frontend *fe) 5600f408ce8SKatsuhiro Suzuki { 5610f408ce8SKatsuhiro Suzuki struct mn88443x_priv *chip = fe->demodulator_priv; 5620f408ce8SKatsuhiro Suzuki struct dtv_frontend_properties *c = &fe->dtv_property_cache; 5630f408ce8SKatsuhiro Suzuki struct regmap *r_s = chip->regmap_s; 5640f408ce8SKatsuhiro Suzuki struct regmap *r_t = chip->regmap_t; 5650f408ce8SKatsuhiro Suzuki u8 tssel = 0, intsel = 0; 5660f408ce8SKatsuhiro Suzuki 5670f408ce8SKatsuhiro Suzuki if (c->delivery_system == SYS_ISDBS) { 5680f408ce8SKatsuhiro Suzuki mn88443x_s_wake(chip); 5690f408ce8SKatsuhiro Suzuki mn88443x_t_sleep(chip); 5700f408ce8SKatsuhiro Suzuki 5710f408ce8SKatsuhiro Suzuki tssel = TSSET1_TSASEL_ISDBS; 5720f408ce8SKatsuhiro Suzuki intsel = TSSET3_INTASEL_S; 5730f408ce8SKatsuhiro Suzuki } else if (c->delivery_system == SYS_ISDBT) { 5740f408ce8SKatsuhiro Suzuki mn88443x_s_sleep(chip); 5750f408ce8SKatsuhiro Suzuki mn88443x_t_wake(chip); 5760f408ce8SKatsuhiro Suzuki 5770f408ce8SKatsuhiro Suzuki mn88443x_t_set_freq(chip); 5780f408ce8SKatsuhiro Suzuki 5790f408ce8SKatsuhiro Suzuki tssel = TSSET1_TSASEL_ISDBT; 5800f408ce8SKatsuhiro Suzuki intsel = TSSET3_INTASEL_T; 5810f408ce8SKatsuhiro Suzuki } 5820f408ce8SKatsuhiro Suzuki 5830f408ce8SKatsuhiro Suzuki regmap_update_bits(r_t, TSSET1, 5840f408ce8SKatsuhiro Suzuki TSSET1_TSASEL_MASK | TSSET1_TSBSEL_MASK, 5850f408ce8SKatsuhiro Suzuki tssel | TSSET1_TSBSEL_NONE); 5860f408ce8SKatsuhiro Suzuki regmap_write(r_t, TSSET2, 0); 5870f408ce8SKatsuhiro Suzuki regmap_update_bits(r_t, TSSET3, 5880f408ce8SKatsuhiro Suzuki TSSET3_INTASEL_MASK | TSSET3_INTBSEL_MASK, 5890f408ce8SKatsuhiro Suzuki intsel | TSSET3_INTBSEL_NONE); 5900f408ce8SKatsuhiro Suzuki 5910f408ce8SKatsuhiro Suzuki regmap_write(r_t, DOSET1_T, 0x95); 5920f408ce8SKatsuhiro Suzuki regmap_write(r_s, DOSET1_S, 0x80); 5930f408ce8SKatsuhiro Suzuki 5940f408ce8SKatsuhiro Suzuki if (c->delivery_system == SYS_ISDBS) 5950f408ce8SKatsuhiro Suzuki mn88443x_s_tune(chip, c); 5960f408ce8SKatsuhiro Suzuki else if (c->delivery_system == SYS_ISDBT) 5970f408ce8SKatsuhiro Suzuki mn88443x_t_tune(chip, c); 5980f408ce8SKatsuhiro Suzuki 5990f408ce8SKatsuhiro Suzuki if (fe->ops.tuner_ops.set_params) { 6000f408ce8SKatsuhiro Suzuki if (fe->ops.i2c_gate_ctrl) 6010f408ce8SKatsuhiro Suzuki fe->ops.i2c_gate_ctrl(fe, 1); 6020f408ce8SKatsuhiro Suzuki fe->ops.tuner_ops.set_params(fe); 6030f408ce8SKatsuhiro Suzuki if (fe->ops.i2c_gate_ctrl) 6040f408ce8SKatsuhiro Suzuki fe->ops.i2c_gate_ctrl(fe, 0); 6050f408ce8SKatsuhiro Suzuki } 6060f408ce8SKatsuhiro Suzuki 6070f408ce8SKatsuhiro Suzuki return 0; 6080f408ce8SKatsuhiro Suzuki } 6090f408ce8SKatsuhiro Suzuki 6100f408ce8SKatsuhiro Suzuki static int mn88443x_get_tune_settings(struct dvb_frontend *fe, 6110f408ce8SKatsuhiro Suzuki struct dvb_frontend_tune_settings *s) 6120f408ce8SKatsuhiro Suzuki { 6130f408ce8SKatsuhiro Suzuki struct dtv_frontend_properties *c = &fe->dtv_property_cache; 6140f408ce8SKatsuhiro Suzuki 6150f408ce8SKatsuhiro Suzuki s->min_delay_ms = 850; 6160f408ce8SKatsuhiro Suzuki 6170f408ce8SKatsuhiro Suzuki if (c->delivery_system == SYS_ISDBS) { 6180f408ce8SKatsuhiro Suzuki s->max_drift = 30000 * 2 + 1; 6190f408ce8SKatsuhiro Suzuki s->step_size = 30000; 6200f408ce8SKatsuhiro Suzuki } else if (c->delivery_system == SYS_ISDBT) { 6210f408ce8SKatsuhiro Suzuki s->max_drift = 142857 * 2 + 1; 6220f408ce8SKatsuhiro Suzuki s->step_size = 142857 * 2; 6230f408ce8SKatsuhiro Suzuki } 6240f408ce8SKatsuhiro Suzuki 6250f408ce8SKatsuhiro Suzuki return 0; 6260f408ce8SKatsuhiro Suzuki } 6270f408ce8SKatsuhiro Suzuki 6280f408ce8SKatsuhiro Suzuki static int mn88443x_read_status(struct dvb_frontend *fe, enum fe_status *status) 6290f408ce8SKatsuhiro Suzuki { 6300f408ce8SKatsuhiro Suzuki struct mn88443x_priv *chip = fe->demodulator_priv; 6310f408ce8SKatsuhiro Suzuki struct dtv_frontend_properties *c = &fe->dtv_property_cache; 6320f408ce8SKatsuhiro Suzuki 6330f408ce8SKatsuhiro Suzuki if (c->delivery_system == SYS_ISDBS) 6340f408ce8SKatsuhiro Suzuki return mn88443x_s_read_status(chip, c, status); 6350f408ce8SKatsuhiro Suzuki 6360f408ce8SKatsuhiro Suzuki if (c->delivery_system == SYS_ISDBT) 6370f408ce8SKatsuhiro Suzuki return mn88443x_t_read_status(chip, c, status); 6380f408ce8SKatsuhiro Suzuki 6390f408ce8SKatsuhiro Suzuki return -EINVAL; 6400f408ce8SKatsuhiro Suzuki } 6410f408ce8SKatsuhiro Suzuki 6420f408ce8SKatsuhiro Suzuki static const struct dvb_frontend_ops mn88443x_ops = { 6430f408ce8SKatsuhiro Suzuki .delsys = { SYS_ISDBS, SYS_ISDBT }, 6440f408ce8SKatsuhiro Suzuki .info = { 6450f408ce8SKatsuhiro Suzuki .name = "Socionext MN88443x", 6460f408ce8SKatsuhiro Suzuki .frequency_min_hz = 470 * MHz, 6470f408ce8SKatsuhiro Suzuki .frequency_max_hz = 2071 * MHz, 6480f408ce8SKatsuhiro Suzuki .symbol_rate_min = 28860000, 6490f408ce8SKatsuhiro Suzuki .symbol_rate_max = 28860000, 6500f408ce8SKatsuhiro Suzuki .caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_AUTO | 6510f408ce8SKatsuhiro Suzuki FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | 6520f408ce8SKatsuhiro Suzuki FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO, 6530f408ce8SKatsuhiro Suzuki }, 6540f408ce8SKatsuhiro Suzuki 6550f408ce8SKatsuhiro Suzuki .sleep = mn88443x_sleep, 6560f408ce8SKatsuhiro Suzuki .set_frontend = mn88443x_set_frontend, 6570f408ce8SKatsuhiro Suzuki .get_tune_settings = mn88443x_get_tune_settings, 6580f408ce8SKatsuhiro Suzuki .read_status = mn88443x_read_status, 6590f408ce8SKatsuhiro Suzuki }; 6600f408ce8SKatsuhiro Suzuki 6610f408ce8SKatsuhiro Suzuki static const struct regmap_config regmap_config = { 6620f408ce8SKatsuhiro Suzuki .reg_bits = 8, 6630f408ce8SKatsuhiro Suzuki .val_bits = 8, 6640f408ce8SKatsuhiro Suzuki .cache_type = REGCACHE_NONE, 6650f408ce8SKatsuhiro Suzuki }; 6660f408ce8SKatsuhiro Suzuki 6670f408ce8SKatsuhiro Suzuki static int mn88443x_probe(struct i2c_client *client, 6680f408ce8SKatsuhiro Suzuki const struct i2c_device_id *id) 6690f408ce8SKatsuhiro Suzuki { 6700f408ce8SKatsuhiro Suzuki struct mn88443x_config *conf = client->dev.platform_data; 6710f408ce8SKatsuhiro Suzuki struct mn88443x_priv *chip; 6720f408ce8SKatsuhiro Suzuki struct device *dev = &client->dev; 6730f408ce8SKatsuhiro Suzuki int ret; 6740f408ce8SKatsuhiro Suzuki 6750f408ce8SKatsuhiro Suzuki chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); 6760f408ce8SKatsuhiro Suzuki if (!chip) 6770f408ce8SKatsuhiro Suzuki return -ENOMEM; 6780f408ce8SKatsuhiro Suzuki 6790f408ce8SKatsuhiro Suzuki if (dev->of_node) 6800f408ce8SKatsuhiro Suzuki chip->spec = of_device_get_match_data(dev); 6810f408ce8SKatsuhiro Suzuki else 6820f408ce8SKatsuhiro Suzuki chip->spec = (struct mn88443x_spec *)id->driver_data; 6830f408ce8SKatsuhiro Suzuki if (!chip->spec) 6840f408ce8SKatsuhiro Suzuki return -EINVAL; 6850f408ce8SKatsuhiro Suzuki 6860f408ce8SKatsuhiro Suzuki chip->mclk = devm_clk_get(dev, "mclk"); 6870f408ce8SKatsuhiro Suzuki if (IS_ERR(chip->mclk) && !conf) { 6880f408ce8SKatsuhiro Suzuki dev_err(dev, "Failed to request mclk: %ld\n", 6890f408ce8SKatsuhiro Suzuki PTR_ERR(chip->mclk)); 6900f408ce8SKatsuhiro Suzuki return PTR_ERR(chip->mclk); 6910f408ce8SKatsuhiro Suzuki } 6920f408ce8SKatsuhiro Suzuki 6930f408ce8SKatsuhiro Suzuki ret = of_property_read_u32(dev->of_node, "if-frequency", 6940f408ce8SKatsuhiro Suzuki &chip->if_freq); 6950f408ce8SKatsuhiro Suzuki if (ret && !conf) { 6960f408ce8SKatsuhiro Suzuki dev_err(dev, "Failed to load IF frequency: %d.\n", ret); 6970f408ce8SKatsuhiro Suzuki return ret; 6980f408ce8SKatsuhiro Suzuki } 6990f408ce8SKatsuhiro Suzuki 7000f408ce8SKatsuhiro Suzuki chip->reset_gpio = devm_gpiod_get_optional(dev, "reset", 7010f408ce8SKatsuhiro Suzuki GPIOD_OUT_HIGH); 7020f408ce8SKatsuhiro Suzuki if (IS_ERR(chip->reset_gpio)) { 7030f408ce8SKatsuhiro Suzuki dev_err(dev, "Failed to request reset_gpio: %ld\n", 7040f408ce8SKatsuhiro Suzuki PTR_ERR(chip->reset_gpio)); 7050f408ce8SKatsuhiro Suzuki return PTR_ERR(chip->reset_gpio); 7060f408ce8SKatsuhiro Suzuki } 7070f408ce8SKatsuhiro Suzuki 7080f408ce8SKatsuhiro Suzuki if (conf) { 7090f408ce8SKatsuhiro Suzuki chip->mclk = conf->mclk; 7100f408ce8SKatsuhiro Suzuki chip->if_freq = conf->if_freq; 7110f408ce8SKatsuhiro Suzuki chip->reset_gpio = conf->reset_gpio; 7120f408ce8SKatsuhiro Suzuki 7130f408ce8SKatsuhiro Suzuki *conf->fe = &chip->fe; 7140f408ce8SKatsuhiro Suzuki } 7150f408ce8SKatsuhiro Suzuki 7160f408ce8SKatsuhiro Suzuki chip->client_s = client; 7170f408ce8SKatsuhiro Suzuki chip->regmap_s = devm_regmap_init_i2c(chip->client_s, ®map_config); 7180f408ce8SKatsuhiro Suzuki if (IS_ERR(chip->regmap_s)) 7190f408ce8SKatsuhiro Suzuki return PTR_ERR(chip->regmap_s); 7200f408ce8SKatsuhiro Suzuki 7210f408ce8SKatsuhiro Suzuki /* 7220f408ce8SKatsuhiro Suzuki * Chip has two I2C addresses for each satellite/terrestrial system. 7230f408ce8SKatsuhiro Suzuki * ISDB-T uses address ISDB-S + 4, so we register a dummy client. 7240f408ce8SKatsuhiro Suzuki */ 7250a6ed11fSWolfram Sang chip->client_t = i2c_new_dummy_device(client->adapter, client->addr + 4); 7260a6ed11fSWolfram Sang if (IS_ERR(chip->client_t)) 7270a6ed11fSWolfram Sang return PTR_ERR(chip->client_t); 7280f408ce8SKatsuhiro Suzuki 7290f408ce8SKatsuhiro Suzuki chip->regmap_t = devm_regmap_init_i2c(chip->client_t, ®map_config); 7300f408ce8SKatsuhiro Suzuki if (IS_ERR(chip->regmap_t)) { 7310f408ce8SKatsuhiro Suzuki ret = PTR_ERR(chip->regmap_t); 7320f408ce8SKatsuhiro Suzuki goto err_i2c_t; 7330f408ce8SKatsuhiro Suzuki } 7340f408ce8SKatsuhiro Suzuki 7350f408ce8SKatsuhiro Suzuki chip->clk_freq = clk_get_rate(chip->mclk); 7360f408ce8SKatsuhiro Suzuki 7370f408ce8SKatsuhiro Suzuki memcpy(&chip->fe.ops, &mn88443x_ops, sizeof(mn88443x_ops)); 7380f408ce8SKatsuhiro Suzuki chip->fe.demodulator_priv = chip; 7390f408ce8SKatsuhiro Suzuki i2c_set_clientdata(client, chip); 7400f408ce8SKatsuhiro Suzuki 7410f408ce8SKatsuhiro Suzuki mn88443x_cmn_power_on(chip); 7420f408ce8SKatsuhiro Suzuki mn88443x_s_sleep(chip); 7430f408ce8SKatsuhiro Suzuki mn88443x_t_sleep(chip); 7440f408ce8SKatsuhiro Suzuki 7450f408ce8SKatsuhiro Suzuki return 0; 7460f408ce8SKatsuhiro Suzuki 7470f408ce8SKatsuhiro Suzuki err_i2c_t: 7480f408ce8SKatsuhiro Suzuki i2c_unregister_device(chip->client_t); 7490f408ce8SKatsuhiro Suzuki 7500f408ce8SKatsuhiro Suzuki return ret; 7510f408ce8SKatsuhiro Suzuki } 7520f408ce8SKatsuhiro Suzuki 7530f408ce8SKatsuhiro Suzuki static int mn88443x_remove(struct i2c_client *client) 7540f408ce8SKatsuhiro Suzuki { 7550f408ce8SKatsuhiro Suzuki struct mn88443x_priv *chip = i2c_get_clientdata(client); 7560f408ce8SKatsuhiro Suzuki 7570f408ce8SKatsuhiro Suzuki mn88443x_cmn_power_off(chip); 7580f408ce8SKatsuhiro Suzuki 7590f408ce8SKatsuhiro Suzuki i2c_unregister_device(chip->client_t); 7600f408ce8SKatsuhiro Suzuki 7610f408ce8SKatsuhiro Suzuki return 0; 7620f408ce8SKatsuhiro Suzuki } 7630f408ce8SKatsuhiro Suzuki 7640f408ce8SKatsuhiro Suzuki static const struct mn88443x_spec mn88443x_spec_pri = { 7650f408ce8SKatsuhiro Suzuki .primary = true, 7660f408ce8SKatsuhiro Suzuki }; 7670f408ce8SKatsuhiro Suzuki 7680f408ce8SKatsuhiro Suzuki static const struct mn88443x_spec mn88443x_spec_sec = { 7690f408ce8SKatsuhiro Suzuki .primary = false, 7700f408ce8SKatsuhiro Suzuki }; 7710f408ce8SKatsuhiro Suzuki 7720f408ce8SKatsuhiro Suzuki static const struct of_device_id mn88443x_of_match[] = { 7730f408ce8SKatsuhiro Suzuki { .compatible = "socionext,mn884433", .data = &mn88443x_spec_pri, }, 7740f408ce8SKatsuhiro Suzuki { .compatible = "socionext,mn884434-0", .data = &mn88443x_spec_pri, }, 7750f408ce8SKatsuhiro Suzuki { .compatible = "socionext,mn884434-1", .data = &mn88443x_spec_sec, }, 7760f408ce8SKatsuhiro Suzuki {} 7770f408ce8SKatsuhiro Suzuki }; 7780f408ce8SKatsuhiro Suzuki MODULE_DEVICE_TABLE(of, mn88443x_of_match); 7790f408ce8SKatsuhiro Suzuki 7800f408ce8SKatsuhiro Suzuki static const struct i2c_device_id mn88443x_i2c_id[] = { 7810f408ce8SKatsuhiro Suzuki { "mn884433", (kernel_ulong_t)&mn88443x_spec_pri }, 7820f408ce8SKatsuhiro Suzuki { "mn884434-0", (kernel_ulong_t)&mn88443x_spec_pri }, 7830f408ce8SKatsuhiro Suzuki { "mn884434-1", (kernel_ulong_t)&mn88443x_spec_sec }, 7840f408ce8SKatsuhiro Suzuki {} 7850f408ce8SKatsuhiro Suzuki }; 7860f408ce8SKatsuhiro Suzuki MODULE_DEVICE_TABLE(i2c, mn88443x_i2c_id); 7870f408ce8SKatsuhiro Suzuki 7880f408ce8SKatsuhiro Suzuki static struct i2c_driver mn88443x_driver = { 7890f408ce8SKatsuhiro Suzuki .driver = { 7900f408ce8SKatsuhiro Suzuki .name = "mn88443x", 7910f408ce8SKatsuhiro Suzuki .of_match_table = of_match_ptr(mn88443x_of_match), 7920f408ce8SKatsuhiro Suzuki }, 7930f408ce8SKatsuhiro Suzuki .probe = mn88443x_probe, 7940f408ce8SKatsuhiro Suzuki .remove = mn88443x_remove, 7950f408ce8SKatsuhiro Suzuki .id_table = mn88443x_i2c_id, 7960f408ce8SKatsuhiro Suzuki }; 7970f408ce8SKatsuhiro Suzuki 7980f408ce8SKatsuhiro Suzuki module_i2c_driver(mn88443x_driver); 7990f408ce8SKatsuhiro Suzuki 8000f408ce8SKatsuhiro Suzuki MODULE_AUTHOR("Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>"); 8010f408ce8SKatsuhiro Suzuki MODULE_DESCRIPTION("Socionext MN88443x series demodulator driver."); 8020f408ce8SKatsuhiro Suzuki MODULE_LICENSE("GPL v2"); 803