18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci//
38c2ecf20Sopenharmony_ci// Socionext MN88443x series demodulator driver for ISDB-S/ISDB-T.
48c2ecf20Sopenharmony_ci//
58c2ecf20Sopenharmony_ci// Copyright (c) 2018 Socionext Inc.
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include <linux/bitfield.h>
88c2ecf20Sopenharmony_ci#include <linux/clk.h>
98c2ecf20Sopenharmony_ci#include <linux/delay.h>
108c2ecf20Sopenharmony_ci#include <linux/gpio/consumer.h>
118c2ecf20Sopenharmony_ci#include <linux/of_device.h>
128c2ecf20Sopenharmony_ci#include <linux/regmap.h>
138c2ecf20Sopenharmony_ci#include <media/dvb_math.h>
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci#include "mn88443x.h"
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci/* ISDB-S registers */
188c2ecf20Sopenharmony_ci#define ATSIDU_S                                    0x2f
198c2ecf20Sopenharmony_ci#define ATSIDL_S                                    0x30
208c2ecf20Sopenharmony_ci#define TSSET_S                                     0x31
218c2ecf20Sopenharmony_ci#define AGCREAD_S                                   0x5a
228c2ecf20Sopenharmony_ci#define CPMON1_S                                    0x5e
238c2ecf20Sopenharmony_ci#define   CPMON1_S_FSYNC                              BIT(5)
248c2ecf20Sopenharmony_ci#define   CPMON1_S_ERRMON                             BIT(4)
258c2ecf20Sopenharmony_ci#define   CPMON1_S_SIGOFF                             BIT(3)
268c2ecf20Sopenharmony_ci#define   CPMON1_S_W2LOCK                             BIT(2)
278c2ecf20Sopenharmony_ci#define   CPMON1_S_W1LOCK                             BIT(1)
288c2ecf20Sopenharmony_ci#define   CPMON1_S_DW1LOCK                            BIT(0)
298c2ecf20Sopenharmony_ci#define TRMON_S                                     0x60
308c2ecf20Sopenharmony_ci#define BERCNFLG_S                                  0x68
318c2ecf20Sopenharmony_ci#define   BERCNFLG_S_BERVRDY                          BIT(5)
328c2ecf20Sopenharmony_ci#define   BERCNFLG_S_BERVCHK                          BIT(4)
338c2ecf20Sopenharmony_ci#define   BERCNFLG_S_BERDRDY                          BIT(3)
348c2ecf20Sopenharmony_ci#define   BERCNFLG_S_BERDCHK                          BIT(2)
358c2ecf20Sopenharmony_ci#define CNRDXU_S                                    0x69
368c2ecf20Sopenharmony_ci#define CNRDXL_S                                    0x6a
378c2ecf20Sopenharmony_ci#define CNRDYU_S                                    0x6b
388c2ecf20Sopenharmony_ci#define CNRDYL_S                                    0x6c
398c2ecf20Sopenharmony_ci#define BERVRDU_S                                   0x71
408c2ecf20Sopenharmony_ci#define BERVRDL_S                                   0x72
418c2ecf20Sopenharmony_ci#define DOSET1_S                                    0x73
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci/* Primary ISDB-T */
448c2ecf20Sopenharmony_ci#define PLLASET1                                    0x00
458c2ecf20Sopenharmony_ci#define PLLASET2                                    0x01
468c2ecf20Sopenharmony_ci#define PLLBSET1                                    0x02
478c2ecf20Sopenharmony_ci#define PLLBSET2                                    0x03
488c2ecf20Sopenharmony_ci#define PLLSET                                      0x04
498c2ecf20Sopenharmony_ci#define OUTCSET                                     0x08
508c2ecf20Sopenharmony_ci#define   OUTCSET_CHDRV_8MA                           0xff
518c2ecf20Sopenharmony_ci#define   OUTCSET_CHDRV_4MA                           0x00
528c2ecf20Sopenharmony_ci#define PLDWSET                                     0x09
538c2ecf20Sopenharmony_ci#define   PLDWSET_NORMAL                             0x00
548c2ecf20Sopenharmony_ci#define   PLDWSET_PULLDOWN                           0xff
558c2ecf20Sopenharmony_ci#define HIZSET1                                     0x0a
568c2ecf20Sopenharmony_ci#define HIZSET2                                     0x0b
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci/* Secondary ISDB-T (for MN884434 only) */
598c2ecf20Sopenharmony_ci#define RCVSET                                      0x00
608c2ecf20Sopenharmony_ci#define TSSET1_M                                    0x01
618c2ecf20Sopenharmony_ci#define TSSET2_M                                    0x02
628c2ecf20Sopenharmony_ci#define TSSET3_M                                    0x03
638c2ecf20Sopenharmony_ci#define INTACSET                                    0x08
648c2ecf20Sopenharmony_ci#define HIZSET3                                     0x0b
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci/* ISDB-T registers */
678c2ecf20Sopenharmony_ci#define TSSET1                                      0x05
688c2ecf20Sopenharmony_ci#define   TSSET1_TSASEL_MASK                          GENMASK(4, 3)
698c2ecf20Sopenharmony_ci#define   TSSET1_TSASEL_ISDBT                         (0x0 << 3)
708c2ecf20Sopenharmony_ci#define   TSSET1_TSASEL_ISDBS                         (0x1 << 3)
718c2ecf20Sopenharmony_ci#define   TSSET1_TSASEL_NONE                          (0x2 << 3)
728c2ecf20Sopenharmony_ci#define   TSSET1_TSBSEL_MASK                          GENMASK(2, 1)
738c2ecf20Sopenharmony_ci#define   TSSET1_TSBSEL_ISDBS                         (0x0 << 1)
748c2ecf20Sopenharmony_ci#define   TSSET1_TSBSEL_ISDBT                         (0x1 << 1)
758c2ecf20Sopenharmony_ci#define   TSSET1_TSBSEL_NONE                          (0x2 << 1)
768c2ecf20Sopenharmony_ci#define TSSET2                                      0x06
778c2ecf20Sopenharmony_ci#define TSSET3                                      0x07
788c2ecf20Sopenharmony_ci#define   TSSET3_INTASEL_MASK                         GENMASK(7, 6)
798c2ecf20Sopenharmony_ci#define   TSSET3_INTASEL_T                            (0x0 << 6)
808c2ecf20Sopenharmony_ci#define   TSSET3_INTASEL_S                            (0x1 << 6)
818c2ecf20Sopenharmony_ci#define   TSSET3_INTASEL_NONE                         (0x2 << 6)
828c2ecf20Sopenharmony_ci#define   TSSET3_INTBSEL_MASK                         GENMASK(5, 4)
838c2ecf20Sopenharmony_ci#define   TSSET3_INTBSEL_S                            (0x0 << 4)
848c2ecf20Sopenharmony_ci#define   TSSET3_INTBSEL_T                            (0x1 << 4)
858c2ecf20Sopenharmony_ci#define   TSSET3_INTBSEL_NONE                         (0x2 << 4)
868c2ecf20Sopenharmony_ci#define OUTSET2                                     0x0d
878c2ecf20Sopenharmony_ci#define PWDSET                                      0x0f
888c2ecf20Sopenharmony_ci#define   PWDSET_OFDMPD_MASK                          GENMASK(3, 2)
898c2ecf20Sopenharmony_ci#define   PWDSET_OFDMPD_DOWN                          BIT(3)
908c2ecf20Sopenharmony_ci#define   PWDSET_PSKPD_MASK                           GENMASK(1, 0)
918c2ecf20Sopenharmony_ci#define   PWDSET_PSKPD_DOWN                           BIT(1)
928c2ecf20Sopenharmony_ci#define CLKSET1_T                                   0x11
938c2ecf20Sopenharmony_ci#define MDSET_T                                     0x13
948c2ecf20Sopenharmony_ci#define   MDSET_T_MDAUTO_MASK                         GENMASK(7, 4)
958c2ecf20Sopenharmony_ci#define   MDSET_T_MDAUTO_AUTO                         (0xf << 4)
968c2ecf20Sopenharmony_ci#define   MDSET_T_MDAUTO_MANUAL                       (0x0 << 4)
978c2ecf20Sopenharmony_ci#define   MDSET_T_FFTS_MASK                           GENMASK(3, 2)
988c2ecf20Sopenharmony_ci#define   MDSET_T_FFTS_MODE1                          (0x0 << 2)
998c2ecf20Sopenharmony_ci#define   MDSET_T_FFTS_MODE2                          (0x1 << 2)
1008c2ecf20Sopenharmony_ci#define   MDSET_T_FFTS_MODE3                          (0x2 << 2)
1018c2ecf20Sopenharmony_ci#define   MDSET_T_GI_MASK                             GENMASK(1, 0)
1028c2ecf20Sopenharmony_ci#define   MDSET_T_GI_1_32                             (0x0 << 0)
1038c2ecf20Sopenharmony_ci#define   MDSET_T_GI_1_16                             (0x1 << 0)
1048c2ecf20Sopenharmony_ci#define   MDSET_T_GI_1_8                              (0x2 << 0)
1058c2ecf20Sopenharmony_ci#define   MDSET_T_GI_1_4                              (0x3 << 0)
1068c2ecf20Sopenharmony_ci#define MDASET_T                                    0x14
1078c2ecf20Sopenharmony_ci#define ADCSET1_T                                   0x20
1088c2ecf20Sopenharmony_ci#define   ADCSET1_T_REFSEL_MASK                       GENMASK(1, 0)
1098c2ecf20Sopenharmony_ci#define   ADCSET1_T_REFSEL_2V                         (0x3 << 0)
1108c2ecf20Sopenharmony_ci#define   ADCSET1_T_REFSEL_1_5V                       (0x2 << 0)
1118c2ecf20Sopenharmony_ci#define   ADCSET1_T_REFSEL_1V                         (0x1 << 0)
1128c2ecf20Sopenharmony_ci#define NCOFREQU_T                                  0x24
1138c2ecf20Sopenharmony_ci#define NCOFREQM_T                                  0x25
1148c2ecf20Sopenharmony_ci#define NCOFREQL_T                                  0x26
1158c2ecf20Sopenharmony_ci#define FADU_T                                      0x27
1168c2ecf20Sopenharmony_ci#define FADM_T                                      0x28
1178c2ecf20Sopenharmony_ci#define FADL_T                                      0x29
1188c2ecf20Sopenharmony_ci#define AGCSET2_T                                   0x2c
1198c2ecf20Sopenharmony_ci#define   AGCSET2_T_IFPOLINV_INC                      BIT(0)
1208c2ecf20Sopenharmony_ci#define   AGCSET2_T_RFPOLINV_INC                      BIT(1)
1218c2ecf20Sopenharmony_ci#define AGCV3_T                                     0x3e
1228c2ecf20Sopenharmony_ci#define MDRD_T                                      0xa2
1238c2ecf20Sopenharmony_ci#define   MDRD_T_SEGID_MASK                           GENMASK(5, 4)
1248c2ecf20Sopenharmony_ci#define   MDRD_T_SEGID_13                             (0x0 << 4)
1258c2ecf20Sopenharmony_ci#define   MDRD_T_SEGID_1                              (0x1 << 4)
1268c2ecf20Sopenharmony_ci#define   MDRD_T_SEGID_3                              (0x2 << 4)
1278c2ecf20Sopenharmony_ci#define   MDRD_T_FFTS_MASK                            GENMASK(3, 2)
1288c2ecf20Sopenharmony_ci#define   MDRD_T_FFTS_MODE1                           (0x0 << 2)
1298c2ecf20Sopenharmony_ci#define   MDRD_T_FFTS_MODE2                           (0x1 << 2)
1308c2ecf20Sopenharmony_ci#define   MDRD_T_FFTS_MODE3                           (0x2 << 2)
1318c2ecf20Sopenharmony_ci#define   MDRD_T_GI_MASK                              GENMASK(1, 0)
1328c2ecf20Sopenharmony_ci#define   MDRD_T_GI_1_32                              (0x0 << 0)
1338c2ecf20Sopenharmony_ci#define   MDRD_T_GI_1_16                              (0x1 << 0)
1348c2ecf20Sopenharmony_ci#define   MDRD_T_GI_1_8                               (0x2 << 0)
1358c2ecf20Sopenharmony_ci#define   MDRD_T_GI_1_4                               (0x3 << 0)
1368c2ecf20Sopenharmony_ci#define SSEQRD_T                                    0xa3
1378c2ecf20Sopenharmony_ci#define   SSEQRD_T_SSEQSTRD_MASK                      GENMASK(3, 0)
1388c2ecf20Sopenharmony_ci#define   SSEQRD_T_SSEQSTRD_RESET                     (0x0 << 0)
1398c2ecf20Sopenharmony_ci#define   SSEQRD_T_SSEQSTRD_TUNING                    (0x1 << 0)
1408c2ecf20Sopenharmony_ci#define   SSEQRD_T_SSEQSTRD_AGC                       (0x2 << 0)
1418c2ecf20Sopenharmony_ci#define   SSEQRD_T_SSEQSTRD_SEARCH                    (0x3 << 0)
1428c2ecf20Sopenharmony_ci#define   SSEQRD_T_SSEQSTRD_CLOCK_SYNC                (0x4 << 0)
1438c2ecf20Sopenharmony_ci#define   SSEQRD_T_SSEQSTRD_FREQ_SYNC                 (0x8 << 0)
1448c2ecf20Sopenharmony_ci#define   SSEQRD_T_SSEQSTRD_FRAME_SYNC                (0x9 << 0)
1458c2ecf20Sopenharmony_ci#define   SSEQRD_T_SSEQSTRD_SYNC                      (0xa << 0)
1468c2ecf20Sopenharmony_ci#define   SSEQRD_T_SSEQSTRD_LOCK                      (0xb << 0)
1478c2ecf20Sopenharmony_ci#define AGCRDU_T                                    0xa8
1488c2ecf20Sopenharmony_ci#define AGCRDL_T                                    0xa9
1498c2ecf20Sopenharmony_ci#define CNRDU_T                                     0xbe
1508c2ecf20Sopenharmony_ci#define CNRDL_T                                     0xbf
1518c2ecf20Sopenharmony_ci#define BERFLG_T                                    0xc0
1528c2ecf20Sopenharmony_ci#define   BERFLG_T_BERDRDY                            BIT(7)
1538c2ecf20Sopenharmony_ci#define   BERFLG_T_BERDCHK                            BIT(6)
1548c2ecf20Sopenharmony_ci#define   BERFLG_T_BERVRDYA                           BIT(5)
1558c2ecf20Sopenharmony_ci#define   BERFLG_T_BERVCHKA                           BIT(4)
1568c2ecf20Sopenharmony_ci#define   BERFLG_T_BERVRDYB                           BIT(3)
1578c2ecf20Sopenharmony_ci#define   BERFLG_T_BERVCHKB                           BIT(2)
1588c2ecf20Sopenharmony_ci#define   BERFLG_T_BERVRDYC                           BIT(1)
1598c2ecf20Sopenharmony_ci#define   BERFLG_T_BERVCHKC                           BIT(0)
1608c2ecf20Sopenharmony_ci#define BERRDU_T                                    0xc1
1618c2ecf20Sopenharmony_ci#define BERRDM_T                                    0xc2
1628c2ecf20Sopenharmony_ci#define BERRDL_T                                    0xc3
1638c2ecf20Sopenharmony_ci#define BERLENRDU_T                                 0xc4
1648c2ecf20Sopenharmony_ci#define BERLENRDL_T                                 0xc5
1658c2ecf20Sopenharmony_ci#define ERRFLG_T                                    0xc6
1668c2ecf20Sopenharmony_ci#define   ERRFLG_T_BERDOVF                            BIT(7)
1678c2ecf20Sopenharmony_ci#define   ERRFLG_T_BERVOVFA                           BIT(6)
1688c2ecf20Sopenharmony_ci#define   ERRFLG_T_BERVOVFB                           BIT(5)
1698c2ecf20Sopenharmony_ci#define   ERRFLG_T_BERVOVFC                           BIT(4)
1708c2ecf20Sopenharmony_ci#define   ERRFLG_T_NERRFA                             BIT(3)
1718c2ecf20Sopenharmony_ci#define   ERRFLG_T_NERRFB                             BIT(2)
1728c2ecf20Sopenharmony_ci#define   ERRFLG_T_NERRFC                             BIT(1)
1738c2ecf20Sopenharmony_ci#define   ERRFLG_T_NERRF                              BIT(0)
1748c2ecf20Sopenharmony_ci#define DOSET1_T                                    0xcf
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci#define CLK_LOW            4000000
1778c2ecf20Sopenharmony_ci#define CLK_DIRECT         20200000
1788c2ecf20Sopenharmony_ci#define CLK_MAX            25410000
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci#define S_T_FREQ           8126984 /* 512 / 63 MHz */
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_cistruct mn88443x_spec {
1838c2ecf20Sopenharmony_ci	bool primary;
1848c2ecf20Sopenharmony_ci};
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_cistruct mn88443x_priv {
1878c2ecf20Sopenharmony_ci	const struct mn88443x_spec *spec;
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci	struct dvb_frontend fe;
1908c2ecf20Sopenharmony_ci	struct clk *mclk;
1918c2ecf20Sopenharmony_ci	struct gpio_desc *reset_gpio;
1928c2ecf20Sopenharmony_ci	u32 clk_freq;
1938c2ecf20Sopenharmony_ci	u32 if_freq;
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci	/* Common */
1968c2ecf20Sopenharmony_ci	bool use_clkbuf;
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci	/* ISDB-S */
1998c2ecf20Sopenharmony_ci	struct i2c_client *client_s;
2008c2ecf20Sopenharmony_ci	struct regmap *regmap_s;
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci	/* ISDB-T */
2038c2ecf20Sopenharmony_ci	struct i2c_client *client_t;
2048c2ecf20Sopenharmony_ci	struct regmap *regmap_t;
2058c2ecf20Sopenharmony_ci};
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_cistatic int mn88443x_cmn_power_on(struct mn88443x_priv *chip)
2088c2ecf20Sopenharmony_ci{
2098c2ecf20Sopenharmony_ci	struct device *dev = &chip->client_s->dev;
2108c2ecf20Sopenharmony_ci	struct regmap *r_t = chip->regmap_t;
2118c2ecf20Sopenharmony_ci	int ret;
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci	ret = clk_prepare_enable(chip->mclk);
2148c2ecf20Sopenharmony_ci	if (ret) {
2158c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to prepare and enable mclk: %d\n",
2168c2ecf20Sopenharmony_ci			ret);
2178c2ecf20Sopenharmony_ci		return ret;
2188c2ecf20Sopenharmony_ci	}
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci	gpiod_set_value_cansleep(chip->reset_gpio, 1);
2218c2ecf20Sopenharmony_ci	usleep_range(100, 1000);
2228c2ecf20Sopenharmony_ci	gpiod_set_value_cansleep(chip->reset_gpio, 0);
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	if (chip->spec->primary) {
2258c2ecf20Sopenharmony_ci		regmap_write(r_t, OUTCSET, OUTCSET_CHDRV_8MA);
2268c2ecf20Sopenharmony_ci		regmap_write(r_t, PLDWSET, PLDWSET_NORMAL);
2278c2ecf20Sopenharmony_ci		regmap_write(r_t, HIZSET1, 0x80);
2288c2ecf20Sopenharmony_ci		regmap_write(r_t, HIZSET2, 0xe0);
2298c2ecf20Sopenharmony_ci	} else {
2308c2ecf20Sopenharmony_ci		regmap_write(r_t, HIZSET3, 0x8f);
2318c2ecf20Sopenharmony_ci	}
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci	return 0;
2348c2ecf20Sopenharmony_ci}
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_cistatic void mn88443x_cmn_power_off(struct mn88443x_priv *chip)
2378c2ecf20Sopenharmony_ci{
2388c2ecf20Sopenharmony_ci	gpiod_set_value_cansleep(chip->reset_gpio, 1);
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci	clk_disable_unprepare(chip->mclk);
2418c2ecf20Sopenharmony_ci}
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_cistatic void mn88443x_s_sleep(struct mn88443x_priv *chip)
2448c2ecf20Sopenharmony_ci{
2458c2ecf20Sopenharmony_ci	struct regmap *r_t = chip->regmap_t;
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	regmap_update_bits(r_t, PWDSET, PWDSET_PSKPD_MASK,
2488c2ecf20Sopenharmony_ci			   PWDSET_PSKPD_DOWN);
2498c2ecf20Sopenharmony_ci}
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_cistatic void mn88443x_s_wake(struct mn88443x_priv *chip)
2528c2ecf20Sopenharmony_ci{
2538c2ecf20Sopenharmony_ci	struct regmap *r_t = chip->regmap_t;
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci	regmap_update_bits(r_t, PWDSET, PWDSET_PSKPD_MASK, 0);
2568c2ecf20Sopenharmony_ci}
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_cistatic void mn88443x_s_tune(struct mn88443x_priv *chip,
2598c2ecf20Sopenharmony_ci			    struct dtv_frontend_properties *c)
2608c2ecf20Sopenharmony_ci{
2618c2ecf20Sopenharmony_ci	struct regmap *r_s = chip->regmap_s;
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci	regmap_write(r_s, ATSIDU_S, c->stream_id >> 8);
2648c2ecf20Sopenharmony_ci	regmap_write(r_s, ATSIDL_S, c->stream_id);
2658c2ecf20Sopenharmony_ci	regmap_write(r_s, TSSET_S, 0);
2668c2ecf20Sopenharmony_ci}
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_cistatic int mn88443x_s_read_status(struct mn88443x_priv *chip,
2698c2ecf20Sopenharmony_ci				  struct dtv_frontend_properties *c,
2708c2ecf20Sopenharmony_ci				  enum fe_status *status)
2718c2ecf20Sopenharmony_ci{
2728c2ecf20Sopenharmony_ci	struct regmap *r_s = chip->regmap_s;
2738c2ecf20Sopenharmony_ci	u32 cpmon, tmpu, tmpl, flg;
2748c2ecf20Sopenharmony_ci	u64 tmp;
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci	/* Sync detection */
2778c2ecf20Sopenharmony_ci	regmap_read(r_s, CPMON1_S, &cpmon);
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci	*status = 0;
2808c2ecf20Sopenharmony_ci	if (cpmon & CPMON1_S_FSYNC)
2818c2ecf20Sopenharmony_ci		*status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
2828c2ecf20Sopenharmony_ci	if (cpmon & CPMON1_S_W2LOCK)
2838c2ecf20Sopenharmony_ci		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci	/* Signal strength */
2868c2ecf20Sopenharmony_ci	c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci	if (*status & FE_HAS_SIGNAL) {
2898c2ecf20Sopenharmony_ci		u32 agc;
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci		regmap_read(r_s, AGCREAD_S, &tmpu);
2928c2ecf20Sopenharmony_ci		agc = tmpu << 8;
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci		c->strength.len = 1;
2958c2ecf20Sopenharmony_ci		c->strength.stat[0].scale = FE_SCALE_RELATIVE;
2968c2ecf20Sopenharmony_ci		c->strength.stat[0].uvalue = agc;
2978c2ecf20Sopenharmony_ci	}
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci	/* C/N rate */
3008c2ecf20Sopenharmony_ci	c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci	if (*status & FE_HAS_VITERBI) {
3038c2ecf20Sopenharmony_ci		u32 cnr = 0, x, y, d;
3048c2ecf20Sopenharmony_ci		u64 d_3 = 0;
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ci		regmap_read(r_s, CNRDXU_S, &tmpu);
3078c2ecf20Sopenharmony_ci		regmap_read(r_s, CNRDXL_S, &tmpl);
3088c2ecf20Sopenharmony_ci		x = (tmpu << 8) | tmpl;
3098c2ecf20Sopenharmony_ci		regmap_read(r_s, CNRDYU_S, &tmpu);
3108c2ecf20Sopenharmony_ci		regmap_read(r_s, CNRDYL_S, &tmpl);
3118c2ecf20Sopenharmony_ci		y = (tmpu << 8) | tmpl;
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_ci		/* CNR[dB]: 10 * log10(D) - 30.74 / D^3 - 3 */
3148c2ecf20Sopenharmony_ci		/*   D = x^2 / (2^15 * y - x^2) */
3158c2ecf20Sopenharmony_ci		d = (y << 15) - x * x;
3168c2ecf20Sopenharmony_ci		if (d > 0) {
3178c2ecf20Sopenharmony_ci			/* (2^4 * D)^3 = 2^12 * D^3 */
3188c2ecf20Sopenharmony_ci			/* 3.074 * 2^(12 + 24) = 211243671486 */
3198c2ecf20Sopenharmony_ci			d_3 = div_u64(16 * x * x, d);
3208c2ecf20Sopenharmony_ci			d_3 = d_3 * d_3 * d_3;
3218c2ecf20Sopenharmony_ci			if (d_3)
3228c2ecf20Sopenharmony_ci				d_3 = div_u64(211243671486ULL, d_3);
3238c2ecf20Sopenharmony_ci		}
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci		if (d_3) {
3268c2ecf20Sopenharmony_ci			/* 0.3 * 2^24 = 5033164 */
3278c2ecf20Sopenharmony_ci			tmp = (s64)2 * intlog10(x) - intlog10(abs(d)) - d_3
3288c2ecf20Sopenharmony_ci				- 5033164;
3298c2ecf20Sopenharmony_ci			cnr = div_u64(tmp * 10000, 1 << 24);
3308c2ecf20Sopenharmony_ci		}
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci		if (cnr) {
3338c2ecf20Sopenharmony_ci			c->cnr.len = 1;
3348c2ecf20Sopenharmony_ci			c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
3358c2ecf20Sopenharmony_ci			c->cnr.stat[0].uvalue = cnr;
3368c2ecf20Sopenharmony_ci		}
3378c2ecf20Sopenharmony_ci	}
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_ci	/* BER */
3408c2ecf20Sopenharmony_ci	c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
3418c2ecf20Sopenharmony_ci	c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci	regmap_read(r_s, BERCNFLG_S, &flg);
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_ci	if ((*status & FE_HAS_VITERBI) && (flg & BERCNFLG_S_BERVRDY)) {
3468c2ecf20Sopenharmony_ci		u32 bit_err, bit_cnt;
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_ci		regmap_read(r_s, BERVRDU_S, &tmpu);
3498c2ecf20Sopenharmony_ci		regmap_read(r_s, BERVRDL_S, &tmpl);
3508c2ecf20Sopenharmony_ci		bit_err = (tmpu << 8) | tmpl;
3518c2ecf20Sopenharmony_ci		bit_cnt = (1 << 13) * 204;
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ci		if (bit_cnt) {
3548c2ecf20Sopenharmony_ci			c->post_bit_error.len = 1;
3558c2ecf20Sopenharmony_ci			c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
3568c2ecf20Sopenharmony_ci			c->post_bit_error.stat[0].uvalue = bit_err;
3578c2ecf20Sopenharmony_ci			c->post_bit_count.len = 1;
3588c2ecf20Sopenharmony_ci			c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
3598c2ecf20Sopenharmony_ci			c->post_bit_count.stat[0].uvalue = bit_cnt;
3608c2ecf20Sopenharmony_ci		}
3618c2ecf20Sopenharmony_ci	}
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_ci	return 0;
3648c2ecf20Sopenharmony_ci}
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_cistatic void mn88443x_t_sleep(struct mn88443x_priv *chip)
3678c2ecf20Sopenharmony_ci{
3688c2ecf20Sopenharmony_ci	struct regmap *r_t = chip->regmap_t;
3698c2ecf20Sopenharmony_ci
3708c2ecf20Sopenharmony_ci	regmap_update_bits(r_t, PWDSET, PWDSET_OFDMPD_MASK,
3718c2ecf20Sopenharmony_ci			   PWDSET_OFDMPD_DOWN);
3728c2ecf20Sopenharmony_ci}
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_cistatic void mn88443x_t_wake(struct mn88443x_priv *chip)
3758c2ecf20Sopenharmony_ci{
3768c2ecf20Sopenharmony_ci	struct regmap *r_t = chip->regmap_t;
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_ci	regmap_update_bits(r_t, PWDSET, PWDSET_OFDMPD_MASK, 0);
3798c2ecf20Sopenharmony_ci}
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_cistatic bool mn88443x_t_is_valid_clk(u32 adckt, u32 if_freq)
3828c2ecf20Sopenharmony_ci{
3838c2ecf20Sopenharmony_ci	if (if_freq == DIRECT_IF_57MHZ) {
3848c2ecf20Sopenharmony_ci		if (adckt >= CLK_DIRECT && adckt <= 21000000)
3858c2ecf20Sopenharmony_ci			return true;
3868c2ecf20Sopenharmony_ci		if (adckt >= 25300000 && adckt <= CLK_MAX)
3878c2ecf20Sopenharmony_ci			return true;
3888c2ecf20Sopenharmony_ci	} else if (if_freq == DIRECT_IF_44MHZ) {
3898c2ecf20Sopenharmony_ci		if (adckt >= 25000000 && adckt <= CLK_MAX)
3908c2ecf20Sopenharmony_ci			return true;
3918c2ecf20Sopenharmony_ci	} else if (if_freq >= LOW_IF_4MHZ && if_freq < DIRECT_IF_44MHZ) {
3928c2ecf20Sopenharmony_ci		if (adckt >= CLK_DIRECT && adckt <= CLK_MAX)
3938c2ecf20Sopenharmony_ci			return true;
3948c2ecf20Sopenharmony_ci	}
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci	return false;
3978c2ecf20Sopenharmony_ci}
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_cistatic int mn88443x_t_set_freq(struct mn88443x_priv *chip)
4008c2ecf20Sopenharmony_ci{
4018c2ecf20Sopenharmony_ci	struct device *dev = &chip->client_s->dev;
4028c2ecf20Sopenharmony_ci	struct regmap *r_t = chip->regmap_t;
4038c2ecf20Sopenharmony_ci	s64 adckt, nco, ad_t;
4048c2ecf20Sopenharmony_ci	u32 m, v;
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_ci	/* Clock buffer (but not supported) or XTAL */
4078c2ecf20Sopenharmony_ci	if (chip->clk_freq >= CLK_LOW && chip->clk_freq < CLK_DIRECT) {
4088c2ecf20Sopenharmony_ci		chip->use_clkbuf = true;
4098c2ecf20Sopenharmony_ci		regmap_write(r_t, CLKSET1_T, 0x07);
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci		adckt = 0;
4128c2ecf20Sopenharmony_ci	} else {
4138c2ecf20Sopenharmony_ci		chip->use_clkbuf = false;
4148c2ecf20Sopenharmony_ci		regmap_write(r_t, CLKSET1_T, 0x00);
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci		adckt = chip->clk_freq;
4178c2ecf20Sopenharmony_ci	}
4188c2ecf20Sopenharmony_ci	if (!mn88443x_t_is_valid_clk(adckt, chip->if_freq)) {
4198c2ecf20Sopenharmony_ci		dev_err(dev, "Invalid clock, CLK:%d, ADCKT:%lld, IF:%d\n",
4208c2ecf20Sopenharmony_ci			chip->clk_freq, adckt, chip->if_freq);
4218c2ecf20Sopenharmony_ci		return -EINVAL;
4228c2ecf20Sopenharmony_ci	}
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_ci	/* Direct IF or Low IF */
4258c2ecf20Sopenharmony_ci	if (chip->if_freq == DIRECT_IF_57MHZ ||
4268c2ecf20Sopenharmony_ci	    chip->if_freq == DIRECT_IF_44MHZ)
4278c2ecf20Sopenharmony_ci		nco = adckt * 2 - chip->if_freq;
4288c2ecf20Sopenharmony_ci	else
4298c2ecf20Sopenharmony_ci		nco = -((s64)chip->if_freq);
4308c2ecf20Sopenharmony_ci	nco = div_s64(nco << 24, adckt);
4318c2ecf20Sopenharmony_ci	ad_t = div_s64(adckt << 22, S_T_FREQ);
4328c2ecf20Sopenharmony_ci
4338c2ecf20Sopenharmony_ci	regmap_write(r_t, NCOFREQU_T, nco >> 16);
4348c2ecf20Sopenharmony_ci	regmap_write(r_t, NCOFREQM_T, nco >> 8);
4358c2ecf20Sopenharmony_ci	regmap_write(r_t, NCOFREQL_T, nco);
4368c2ecf20Sopenharmony_ci	regmap_write(r_t, FADU_T, ad_t >> 16);
4378c2ecf20Sopenharmony_ci	regmap_write(r_t, FADM_T, ad_t >> 8);
4388c2ecf20Sopenharmony_ci	regmap_write(r_t, FADL_T, ad_t);
4398c2ecf20Sopenharmony_ci
4408c2ecf20Sopenharmony_ci	/* Level of IF */
4418c2ecf20Sopenharmony_ci	m = ADCSET1_T_REFSEL_MASK;
4428c2ecf20Sopenharmony_ci	v = ADCSET1_T_REFSEL_1_5V;
4438c2ecf20Sopenharmony_ci	regmap_update_bits(r_t, ADCSET1_T, m, v);
4448c2ecf20Sopenharmony_ci
4458c2ecf20Sopenharmony_ci	/* Polarity of AGC */
4468c2ecf20Sopenharmony_ci	v = AGCSET2_T_IFPOLINV_INC | AGCSET2_T_RFPOLINV_INC;
4478c2ecf20Sopenharmony_ci	regmap_update_bits(r_t, AGCSET2_T, v, v);
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_ci	/* Lower output level of AGC */
4508c2ecf20Sopenharmony_ci	regmap_write(r_t, AGCV3_T, 0x00);
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_ci	regmap_write(r_t, MDSET_T, 0xfa);
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci	return 0;
4558c2ecf20Sopenharmony_ci}
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_cistatic void mn88443x_t_tune(struct mn88443x_priv *chip,
4588c2ecf20Sopenharmony_ci			    struct dtv_frontend_properties *c)
4598c2ecf20Sopenharmony_ci{
4608c2ecf20Sopenharmony_ci	struct regmap *r_t = chip->regmap_t;
4618c2ecf20Sopenharmony_ci	u32 m, v;
4628c2ecf20Sopenharmony_ci
4638c2ecf20Sopenharmony_ci	m = MDSET_T_MDAUTO_MASK | MDSET_T_FFTS_MASK | MDSET_T_GI_MASK;
4648c2ecf20Sopenharmony_ci	v = MDSET_T_MDAUTO_AUTO | MDSET_T_FFTS_MODE3 | MDSET_T_GI_1_8;
4658c2ecf20Sopenharmony_ci	regmap_update_bits(r_t, MDSET_T, m, v);
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_ci	regmap_write(r_t, MDASET_T, 0);
4688c2ecf20Sopenharmony_ci}
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_cistatic int mn88443x_t_read_status(struct mn88443x_priv *chip,
4718c2ecf20Sopenharmony_ci				  struct dtv_frontend_properties *c,
4728c2ecf20Sopenharmony_ci				  enum fe_status *status)
4738c2ecf20Sopenharmony_ci{
4748c2ecf20Sopenharmony_ci	struct regmap *r_t = chip->regmap_t;
4758c2ecf20Sopenharmony_ci	u32 seqrd, st, flg, tmpu, tmpm, tmpl;
4768c2ecf20Sopenharmony_ci	u64 tmp;
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_ci	/* Sync detection */
4798c2ecf20Sopenharmony_ci	regmap_read(r_t, SSEQRD_T, &seqrd);
4808c2ecf20Sopenharmony_ci	st = seqrd & SSEQRD_T_SSEQSTRD_MASK;
4818c2ecf20Sopenharmony_ci
4828c2ecf20Sopenharmony_ci	*status = 0;
4838c2ecf20Sopenharmony_ci	if (st >= SSEQRD_T_SSEQSTRD_SYNC)
4848c2ecf20Sopenharmony_ci		*status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
4858c2ecf20Sopenharmony_ci	if (st >= SSEQRD_T_SSEQSTRD_FRAME_SYNC)
4868c2ecf20Sopenharmony_ci		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_ci	/* Signal strength */
4898c2ecf20Sopenharmony_ci	c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
4908c2ecf20Sopenharmony_ci
4918c2ecf20Sopenharmony_ci	if (*status & FE_HAS_SIGNAL) {
4928c2ecf20Sopenharmony_ci		u32 agc;
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_ci		regmap_read(r_t, AGCRDU_T, &tmpu);
4958c2ecf20Sopenharmony_ci		regmap_read(r_t, AGCRDL_T, &tmpl);
4968c2ecf20Sopenharmony_ci		agc = (tmpu << 8) | tmpl;
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ci		c->strength.len = 1;
4998c2ecf20Sopenharmony_ci		c->strength.stat[0].scale = FE_SCALE_RELATIVE;
5008c2ecf20Sopenharmony_ci		c->strength.stat[0].uvalue = agc;
5018c2ecf20Sopenharmony_ci	}
5028c2ecf20Sopenharmony_ci
5038c2ecf20Sopenharmony_ci	/* C/N rate */
5048c2ecf20Sopenharmony_ci	c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ci	if (*status & FE_HAS_VITERBI) {
5078c2ecf20Sopenharmony_ci		u32 cnr;
5088c2ecf20Sopenharmony_ci
5098c2ecf20Sopenharmony_ci		regmap_read(r_t, CNRDU_T, &tmpu);
5108c2ecf20Sopenharmony_ci		regmap_read(r_t, CNRDL_T, &tmpl);
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_ci		if (tmpu || tmpl) {
5138c2ecf20Sopenharmony_ci			/* CNR[dB]: 10 * (log10(65536 / value) + 0.2) */
5148c2ecf20Sopenharmony_ci			/* intlog10(65536) = 80807124, 0.2 * 2^24 = 3355443 */
5158c2ecf20Sopenharmony_ci			tmp = (u64)80807124 - intlog10((tmpu << 8) | tmpl)
5168c2ecf20Sopenharmony_ci				+ 3355443;
5178c2ecf20Sopenharmony_ci			cnr = div_u64(tmp * 10000, 1 << 24);
5188c2ecf20Sopenharmony_ci		} else {
5198c2ecf20Sopenharmony_ci			cnr = 0;
5208c2ecf20Sopenharmony_ci		}
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_ci		c->cnr.len = 1;
5238c2ecf20Sopenharmony_ci		c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
5248c2ecf20Sopenharmony_ci		c->cnr.stat[0].uvalue = cnr;
5258c2ecf20Sopenharmony_ci	}
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_ci	/* BER */
5288c2ecf20Sopenharmony_ci	c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
5298c2ecf20Sopenharmony_ci	c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_ci	regmap_read(r_t, BERFLG_T, &flg);
5328c2ecf20Sopenharmony_ci
5338c2ecf20Sopenharmony_ci	if ((*status & FE_HAS_VITERBI) && (flg & BERFLG_T_BERVRDYA)) {
5348c2ecf20Sopenharmony_ci		u32 bit_err, bit_cnt;
5358c2ecf20Sopenharmony_ci
5368c2ecf20Sopenharmony_ci		regmap_read(r_t, BERRDU_T, &tmpu);
5378c2ecf20Sopenharmony_ci		regmap_read(r_t, BERRDM_T, &tmpm);
5388c2ecf20Sopenharmony_ci		regmap_read(r_t, BERRDL_T, &tmpl);
5398c2ecf20Sopenharmony_ci		bit_err = (tmpu << 16) | (tmpm << 8) | tmpl;
5408c2ecf20Sopenharmony_ci
5418c2ecf20Sopenharmony_ci		regmap_read(r_t, BERLENRDU_T, &tmpu);
5428c2ecf20Sopenharmony_ci		regmap_read(r_t, BERLENRDL_T, &tmpl);
5438c2ecf20Sopenharmony_ci		bit_cnt = ((tmpu << 8) | tmpl) * 203 * 8;
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_ci		if (bit_cnt) {
5468c2ecf20Sopenharmony_ci			c->post_bit_error.len = 1;
5478c2ecf20Sopenharmony_ci			c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
5488c2ecf20Sopenharmony_ci			c->post_bit_error.stat[0].uvalue = bit_err;
5498c2ecf20Sopenharmony_ci			c->post_bit_count.len = 1;
5508c2ecf20Sopenharmony_ci			c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
5518c2ecf20Sopenharmony_ci			c->post_bit_count.stat[0].uvalue = bit_cnt;
5528c2ecf20Sopenharmony_ci		}
5538c2ecf20Sopenharmony_ci	}
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_ci	return 0;
5568c2ecf20Sopenharmony_ci}
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_cistatic int mn88443x_sleep(struct dvb_frontend *fe)
5598c2ecf20Sopenharmony_ci{
5608c2ecf20Sopenharmony_ci	struct mn88443x_priv *chip = fe->demodulator_priv;
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ci	mn88443x_s_sleep(chip);
5638c2ecf20Sopenharmony_ci	mn88443x_t_sleep(chip);
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_ci	return 0;
5668c2ecf20Sopenharmony_ci}
5678c2ecf20Sopenharmony_ci
5688c2ecf20Sopenharmony_cistatic int mn88443x_set_frontend(struct dvb_frontend *fe)
5698c2ecf20Sopenharmony_ci{
5708c2ecf20Sopenharmony_ci	struct mn88443x_priv *chip = fe->demodulator_priv;
5718c2ecf20Sopenharmony_ci	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
5728c2ecf20Sopenharmony_ci	struct regmap *r_s = chip->regmap_s;
5738c2ecf20Sopenharmony_ci	struct regmap *r_t = chip->regmap_t;
5748c2ecf20Sopenharmony_ci	u8 tssel = 0, intsel = 0;
5758c2ecf20Sopenharmony_ci
5768c2ecf20Sopenharmony_ci	if (c->delivery_system == SYS_ISDBS) {
5778c2ecf20Sopenharmony_ci		mn88443x_s_wake(chip);
5788c2ecf20Sopenharmony_ci		mn88443x_t_sleep(chip);
5798c2ecf20Sopenharmony_ci
5808c2ecf20Sopenharmony_ci		tssel = TSSET1_TSASEL_ISDBS;
5818c2ecf20Sopenharmony_ci		intsel = TSSET3_INTASEL_S;
5828c2ecf20Sopenharmony_ci	} else if (c->delivery_system == SYS_ISDBT) {
5838c2ecf20Sopenharmony_ci		mn88443x_s_sleep(chip);
5848c2ecf20Sopenharmony_ci		mn88443x_t_wake(chip);
5858c2ecf20Sopenharmony_ci
5868c2ecf20Sopenharmony_ci		mn88443x_t_set_freq(chip);
5878c2ecf20Sopenharmony_ci
5888c2ecf20Sopenharmony_ci		tssel = TSSET1_TSASEL_ISDBT;
5898c2ecf20Sopenharmony_ci		intsel = TSSET3_INTASEL_T;
5908c2ecf20Sopenharmony_ci	}
5918c2ecf20Sopenharmony_ci
5928c2ecf20Sopenharmony_ci	regmap_update_bits(r_t, TSSET1,
5938c2ecf20Sopenharmony_ci			   TSSET1_TSASEL_MASK | TSSET1_TSBSEL_MASK,
5948c2ecf20Sopenharmony_ci			   tssel | TSSET1_TSBSEL_NONE);
5958c2ecf20Sopenharmony_ci	regmap_write(r_t, TSSET2, 0);
5968c2ecf20Sopenharmony_ci	regmap_update_bits(r_t, TSSET3,
5978c2ecf20Sopenharmony_ci			   TSSET3_INTASEL_MASK | TSSET3_INTBSEL_MASK,
5988c2ecf20Sopenharmony_ci			   intsel | TSSET3_INTBSEL_NONE);
5998c2ecf20Sopenharmony_ci
6008c2ecf20Sopenharmony_ci	regmap_write(r_t, DOSET1_T, 0x95);
6018c2ecf20Sopenharmony_ci	regmap_write(r_s, DOSET1_S, 0x80);
6028c2ecf20Sopenharmony_ci
6038c2ecf20Sopenharmony_ci	if (c->delivery_system == SYS_ISDBS)
6048c2ecf20Sopenharmony_ci		mn88443x_s_tune(chip, c);
6058c2ecf20Sopenharmony_ci	else if (c->delivery_system == SYS_ISDBT)
6068c2ecf20Sopenharmony_ci		mn88443x_t_tune(chip, c);
6078c2ecf20Sopenharmony_ci
6088c2ecf20Sopenharmony_ci	if (fe->ops.tuner_ops.set_params) {
6098c2ecf20Sopenharmony_ci		if (fe->ops.i2c_gate_ctrl)
6108c2ecf20Sopenharmony_ci			fe->ops.i2c_gate_ctrl(fe, 1);
6118c2ecf20Sopenharmony_ci		fe->ops.tuner_ops.set_params(fe);
6128c2ecf20Sopenharmony_ci		if (fe->ops.i2c_gate_ctrl)
6138c2ecf20Sopenharmony_ci			fe->ops.i2c_gate_ctrl(fe, 0);
6148c2ecf20Sopenharmony_ci	}
6158c2ecf20Sopenharmony_ci
6168c2ecf20Sopenharmony_ci	return 0;
6178c2ecf20Sopenharmony_ci}
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_cistatic int mn88443x_get_tune_settings(struct dvb_frontend *fe,
6208c2ecf20Sopenharmony_ci				      struct dvb_frontend_tune_settings *s)
6218c2ecf20Sopenharmony_ci{
6228c2ecf20Sopenharmony_ci	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
6238c2ecf20Sopenharmony_ci
6248c2ecf20Sopenharmony_ci	s->min_delay_ms = 850;
6258c2ecf20Sopenharmony_ci
6268c2ecf20Sopenharmony_ci	if (c->delivery_system == SYS_ISDBS) {
6278c2ecf20Sopenharmony_ci		s->max_drift = 30000 * 2 + 1;
6288c2ecf20Sopenharmony_ci		s->step_size = 30000;
6298c2ecf20Sopenharmony_ci	} else if (c->delivery_system == SYS_ISDBT) {
6308c2ecf20Sopenharmony_ci		s->max_drift = 142857 * 2 + 1;
6318c2ecf20Sopenharmony_ci		s->step_size = 142857 * 2;
6328c2ecf20Sopenharmony_ci	}
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_ci	return 0;
6358c2ecf20Sopenharmony_ci}
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_cistatic int mn88443x_read_status(struct dvb_frontend *fe, enum fe_status *status)
6388c2ecf20Sopenharmony_ci{
6398c2ecf20Sopenharmony_ci	struct mn88443x_priv *chip = fe->demodulator_priv;
6408c2ecf20Sopenharmony_ci	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
6418c2ecf20Sopenharmony_ci
6428c2ecf20Sopenharmony_ci	if (c->delivery_system == SYS_ISDBS)
6438c2ecf20Sopenharmony_ci		return mn88443x_s_read_status(chip, c, status);
6448c2ecf20Sopenharmony_ci
6458c2ecf20Sopenharmony_ci	if (c->delivery_system == SYS_ISDBT)
6468c2ecf20Sopenharmony_ci		return mn88443x_t_read_status(chip, c, status);
6478c2ecf20Sopenharmony_ci
6488c2ecf20Sopenharmony_ci	return -EINVAL;
6498c2ecf20Sopenharmony_ci}
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_cistatic const struct dvb_frontend_ops mn88443x_ops = {
6528c2ecf20Sopenharmony_ci	.delsys = { SYS_ISDBS, SYS_ISDBT },
6538c2ecf20Sopenharmony_ci	.info = {
6548c2ecf20Sopenharmony_ci		.name = "Socionext MN88443x",
6558c2ecf20Sopenharmony_ci		.frequency_min_hz =  470 * MHz,
6568c2ecf20Sopenharmony_ci		.frequency_max_hz = 2071 * MHz,
6578c2ecf20Sopenharmony_ci		.symbol_rate_min  = 28860000,
6588c2ecf20Sopenharmony_ci		.symbol_rate_max  = 28860000,
6598c2ecf20Sopenharmony_ci		.caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_AUTO |
6608c2ecf20Sopenharmony_ci			FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
6618c2ecf20Sopenharmony_ci			FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO,
6628c2ecf20Sopenharmony_ci	},
6638c2ecf20Sopenharmony_ci
6648c2ecf20Sopenharmony_ci	.sleep                   = mn88443x_sleep,
6658c2ecf20Sopenharmony_ci	.set_frontend            = mn88443x_set_frontend,
6668c2ecf20Sopenharmony_ci	.get_tune_settings       = mn88443x_get_tune_settings,
6678c2ecf20Sopenharmony_ci	.read_status             = mn88443x_read_status,
6688c2ecf20Sopenharmony_ci};
6698c2ecf20Sopenharmony_ci
6708c2ecf20Sopenharmony_cistatic const struct regmap_config regmap_config = {
6718c2ecf20Sopenharmony_ci	.reg_bits   = 8,
6728c2ecf20Sopenharmony_ci	.val_bits   = 8,
6738c2ecf20Sopenharmony_ci	.cache_type = REGCACHE_NONE,
6748c2ecf20Sopenharmony_ci};
6758c2ecf20Sopenharmony_ci
6768c2ecf20Sopenharmony_cistatic int mn88443x_probe(struct i2c_client *client,
6778c2ecf20Sopenharmony_ci			  const struct i2c_device_id *id)
6788c2ecf20Sopenharmony_ci{
6798c2ecf20Sopenharmony_ci	struct mn88443x_config *conf = client->dev.platform_data;
6808c2ecf20Sopenharmony_ci	struct mn88443x_priv *chip;
6818c2ecf20Sopenharmony_ci	struct device *dev = &client->dev;
6828c2ecf20Sopenharmony_ci	int ret;
6838c2ecf20Sopenharmony_ci
6848c2ecf20Sopenharmony_ci	chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
6858c2ecf20Sopenharmony_ci	if (!chip)
6868c2ecf20Sopenharmony_ci		return -ENOMEM;
6878c2ecf20Sopenharmony_ci
6888c2ecf20Sopenharmony_ci	if (dev->of_node)
6898c2ecf20Sopenharmony_ci		chip->spec = of_device_get_match_data(dev);
6908c2ecf20Sopenharmony_ci	else
6918c2ecf20Sopenharmony_ci		chip->spec = (struct mn88443x_spec *)id->driver_data;
6928c2ecf20Sopenharmony_ci	if (!chip->spec)
6938c2ecf20Sopenharmony_ci		return -EINVAL;
6948c2ecf20Sopenharmony_ci
6958c2ecf20Sopenharmony_ci	chip->mclk = devm_clk_get(dev, "mclk");
6968c2ecf20Sopenharmony_ci	if (IS_ERR(chip->mclk) && !conf) {
6978c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to request mclk: %ld\n",
6988c2ecf20Sopenharmony_ci			PTR_ERR(chip->mclk));
6998c2ecf20Sopenharmony_ci		return PTR_ERR(chip->mclk);
7008c2ecf20Sopenharmony_ci	}
7018c2ecf20Sopenharmony_ci
7028c2ecf20Sopenharmony_ci	ret = of_property_read_u32(dev->of_node, "if-frequency",
7038c2ecf20Sopenharmony_ci				   &chip->if_freq);
7048c2ecf20Sopenharmony_ci	if (ret && !conf) {
7058c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to load IF frequency: %d.\n", ret);
7068c2ecf20Sopenharmony_ci		return ret;
7078c2ecf20Sopenharmony_ci	}
7088c2ecf20Sopenharmony_ci
7098c2ecf20Sopenharmony_ci	chip->reset_gpio = devm_gpiod_get_optional(dev, "reset",
7108c2ecf20Sopenharmony_ci						   GPIOD_OUT_HIGH);
7118c2ecf20Sopenharmony_ci	if (IS_ERR(chip->reset_gpio)) {
7128c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to request reset_gpio: %ld\n",
7138c2ecf20Sopenharmony_ci			PTR_ERR(chip->reset_gpio));
7148c2ecf20Sopenharmony_ci		return PTR_ERR(chip->reset_gpio);
7158c2ecf20Sopenharmony_ci	}
7168c2ecf20Sopenharmony_ci
7178c2ecf20Sopenharmony_ci	if (conf) {
7188c2ecf20Sopenharmony_ci		chip->mclk = conf->mclk;
7198c2ecf20Sopenharmony_ci		chip->if_freq = conf->if_freq;
7208c2ecf20Sopenharmony_ci		chip->reset_gpio = conf->reset_gpio;
7218c2ecf20Sopenharmony_ci
7228c2ecf20Sopenharmony_ci		*conf->fe = &chip->fe;
7238c2ecf20Sopenharmony_ci	}
7248c2ecf20Sopenharmony_ci
7258c2ecf20Sopenharmony_ci	chip->client_s = client;
7268c2ecf20Sopenharmony_ci	chip->regmap_s = devm_regmap_init_i2c(chip->client_s, &regmap_config);
7278c2ecf20Sopenharmony_ci	if (IS_ERR(chip->regmap_s))
7288c2ecf20Sopenharmony_ci		return PTR_ERR(chip->regmap_s);
7298c2ecf20Sopenharmony_ci
7308c2ecf20Sopenharmony_ci	/*
7318c2ecf20Sopenharmony_ci	 * Chip has two I2C addresses for each satellite/terrestrial system.
7328c2ecf20Sopenharmony_ci	 * ISDB-T uses address ISDB-S + 4, so we register a dummy client.
7338c2ecf20Sopenharmony_ci	 */
7348c2ecf20Sopenharmony_ci	chip->client_t = i2c_new_dummy_device(client->adapter, client->addr + 4);
7358c2ecf20Sopenharmony_ci	if (IS_ERR(chip->client_t))
7368c2ecf20Sopenharmony_ci		return PTR_ERR(chip->client_t);
7378c2ecf20Sopenharmony_ci
7388c2ecf20Sopenharmony_ci	chip->regmap_t = devm_regmap_init_i2c(chip->client_t, &regmap_config);
7398c2ecf20Sopenharmony_ci	if (IS_ERR(chip->regmap_t)) {
7408c2ecf20Sopenharmony_ci		ret = PTR_ERR(chip->regmap_t);
7418c2ecf20Sopenharmony_ci		goto err_i2c_t;
7428c2ecf20Sopenharmony_ci	}
7438c2ecf20Sopenharmony_ci
7448c2ecf20Sopenharmony_ci	chip->clk_freq = clk_get_rate(chip->mclk);
7458c2ecf20Sopenharmony_ci
7468c2ecf20Sopenharmony_ci	memcpy(&chip->fe.ops, &mn88443x_ops, sizeof(mn88443x_ops));
7478c2ecf20Sopenharmony_ci	chip->fe.demodulator_priv = chip;
7488c2ecf20Sopenharmony_ci	i2c_set_clientdata(client, chip);
7498c2ecf20Sopenharmony_ci
7508c2ecf20Sopenharmony_ci	ret = mn88443x_cmn_power_on(chip);
7518c2ecf20Sopenharmony_ci	if (ret)
7528c2ecf20Sopenharmony_ci		goto err_i2c_t;
7538c2ecf20Sopenharmony_ci
7548c2ecf20Sopenharmony_ci	mn88443x_s_sleep(chip);
7558c2ecf20Sopenharmony_ci	mn88443x_t_sleep(chip);
7568c2ecf20Sopenharmony_ci
7578c2ecf20Sopenharmony_ci	return 0;
7588c2ecf20Sopenharmony_ci
7598c2ecf20Sopenharmony_cierr_i2c_t:
7608c2ecf20Sopenharmony_ci	i2c_unregister_device(chip->client_t);
7618c2ecf20Sopenharmony_ci
7628c2ecf20Sopenharmony_ci	return ret;
7638c2ecf20Sopenharmony_ci}
7648c2ecf20Sopenharmony_ci
7658c2ecf20Sopenharmony_cistatic int mn88443x_remove(struct i2c_client *client)
7668c2ecf20Sopenharmony_ci{
7678c2ecf20Sopenharmony_ci	struct mn88443x_priv *chip = i2c_get_clientdata(client);
7688c2ecf20Sopenharmony_ci
7698c2ecf20Sopenharmony_ci	mn88443x_cmn_power_off(chip);
7708c2ecf20Sopenharmony_ci
7718c2ecf20Sopenharmony_ci	i2c_unregister_device(chip->client_t);
7728c2ecf20Sopenharmony_ci
7738c2ecf20Sopenharmony_ci	return 0;
7748c2ecf20Sopenharmony_ci}
7758c2ecf20Sopenharmony_ci
7768c2ecf20Sopenharmony_cistatic const struct mn88443x_spec mn88443x_spec_pri = {
7778c2ecf20Sopenharmony_ci	.primary = true,
7788c2ecf20Sopenharmony_ci};
7798c2ecf20Sopenharmony_ci
7808c2ecf20Sopenharmony_cistatic const struct mn88443x_spec mn88443x_spec_sec = {
7818c2ecf20Sopenharmony_ci	.primary = false,
7828c2ecf20Sopenharmony_ci};
7838c2ecf20Sopenharmony_ci
7848c2ecf20Sopenharmony_cistatic const struct of_device_id mn88443x_of_match[] = {
7858c2ecf20Sopenharmony_ci	{ .compatible = "socionext,mn884433",   .data = &mn88443x_spec_pri, },
7868c2ecf20Sopenharmony_ci	{ .compatible = "socionext,mn884434-0", .data = &mn88443x_spec_pri, },
7878c2ecf20Sopenharmony_ci	{ .compatible = "socionext,mn884434-1", .data = &mn88443x_spec_sec, },
7888c2ecf20Sopenharmony_ci	{}
7898c2ecf20Sopenharmony_ci};
7908c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, mn88443x_of_match);
7918c2ecf20Sopenharmony_ci
7928c2ecf20Sopenharmony_cistatic const struct i2c_device_id mn88443x_i2c_id[] = {
7938c2ecf20Sopenharmony_ci	{ "mn884433",   (kernel_ulong_t)&mn88443x_spec_pri },
7948c2ecf20Sopenharmony_ci	{ "mn884434-0", (kernel_ulong_t)&mn88443x_spec_pri },
7958c2ecf20Sopenharmony_ci	{ "mn884434-1", (kernel_ulong_t)&mn88443x_spec_sec },
7968c2ecf20Sopenharmony_ci	{}
7978c2ecf20Sopenharmony_ci};
7988c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, mn88443x_i2c_id);
7998c2ecf20Sopenharmony_ci
8008c2ecf20Sopenharmony_cistatic struct i2c_driver mn88443x_driver = {
8018c2ecf20Sopenharmony_ci	.driver = {
8028c2ecf20Sopenharmony_ci		.name = "mn88443x",
8038c2ecf20Sopenharmony_ci		.of_match_table = mn88443x_of_match,
8048c2ecf20Sopenharmony_ci	},
8058c2ecf20Sopenharmony_ci	.probe    = mn88443x_probe,
8068c2ecf20Sopenharmony_ci	.remove   = mn88443x_remove,
8078c2ecf20Sopenharmony_ci	.id_table = mn88443x_i2c_id,
8088c2ecf20Sopenharmony_ci};
8098c2ecf20Sopenharmony_ci
8108c2ecf20Sopenharmony_cimodule_i2c_driver(mn88443x_driver);
8118c2ecf20Sopenharmony_ci
8128c2ecf20Sopenharmony_ciMODULE_AUTHOR("Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>");
8138c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Socionext MN88443x series demodulator driver.");
8148c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
815