// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2025 Rockchip Electronics Co.Ltd
* Author:
* Guochun Huang <hero.huang@rock-chips.com>
*/
#include <dt-bindings/phy/phy.h>
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/of.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/reset.h>
#define FIELD_PREP_HIWORD(_mask, _val) \
( \
FIELD_PREP((_mask), (_val)) | \
((_mask) << 16 ) \
)
#define BIAS_CON0 0 x0000
#define I_RES_CNTL_MASK GENMASK(6 , 4 )
#define I_RES_CNTL(x) FIELD_PREP(I_RES_CNTL_MASK, x)
#define I_RES_059_2UA I_RES_CNTL(0 )
#define I_RES_100_2UA I_RES_CNTL(1 )
#define I_RES_094_2UA I_RES_CNTL(2 )
#define I_RES_113_8UA I_RES_CNTL(3 )
#define I_RES_089_7UA I_RES_CNTL(4 )
#define I_RES_111_8UA I_RES_CNTL(5 )
#define I_RES_108_2UA I_RES_CNTL(6 )
#define I_RES_120_8UA I_RES_CNTL(7 )
#define I_DEV_SEL_MASK GENMASK(1 , 0 )
#define I_DEV_SEL(x) FIELD_PREP(I_DEV_SEL_MASK, x)
#define I_DEV_DIV_6 I_DEV_SEL(0 )
#define I_DEV_DIV_12 I_DEV_SEL(1 )
#define I_DEV_DIV_20 I_DEV_SEL(2 )
#define I_DEV_DIV_40 I_DEV_SEL(3 )
#define BIAS_CON1 0 x0004
#define I_VBG_SEL_MASK GENMASK(9 , 8 )
#define I_VBG_SEL(x) FIELD_PREP(I_VBG_SEL_MASK, x)
#define I_VBG_SEL_780MV I_VBG_SEL(0 )
#define I_VBG_SEL_820MV I_VBG_SEL(1 )
#define I_VBG_SEL_860MV I_VBG_SEL(2 )
#define I_VBG_SEL_900MV I_VBG_SEL(3 )
#define I_BGR_VREF_SEL_MASK GENMASK(5 , 4 )
#define I_BGR_VREF_SEL(x) FIELD_PREP(I_BGR_VREF_SEL_MASK, x)
#define I_BGR_VREF_810MV I_BGR_VREF_SEL(0 )
#define I_BGR_VREF_820MV I_BGR_VREF_SEL(1 )
#define I_BGR_VREF_830MV I_BGR_VREF_SEL(2 )
#define I_BGR_VREF_840MV I_BGR_VREF_SEL(3 )
#define I_LADDER_SEL_MASK GENMASK(2 , 0 )
#define I_LADDER_SEL(x) FIELD_PREP(I_LADDER_SEL_MASK, x)
#define I_LADDER_1_00V I_LADDER_SEL(0 )
#define I_LADDER_0_96V I_LADDER_SEL(1 )
#define I_LADDER_0_92V I_LADDER_SEL(2 )
#define I_LADDER_0_88V I_LADDER_SEL(3 )
#define I_LADDER_0_84V I_LADDER_SEL(4 )
#define I_LADDER_0_80V I_LADDER_SEL(5 )
#define I_LADDER_0_76V I_LADDER_SEL(6 )
#define I_LADDER_0_72V I_LADDER_SEL(7 )
/*
* Voltage corrections around reference voltages
* The selection between the 400-based or 200-based values for REG_400M
* is done by the hw depending on I_MUX below being 400MV or 200MV.
*/
#define BIAS_CON2 0 x0008
#define REG_325M_MASK GENMASK(14 , 12 )
#define REG_325M(x) FIELD_PREP(REG_325M_MASK, x)
#define REG_325M_295MV REG_325M(0 )
#define REG_325M_305MV REG_325M(1 )
#define REG_325M_315MV REG_325M(2 )
#define REG_325M_325MV REG_325M(3 )
#define REG_325M_335MV REG_325M(4 )
#define REG_325M_345MV REG_325M(5 )
#define REG_325M_355MV REG_325M(6 )
#define REG_325M_365MV REG_325M(7 )
#define REG_LP_400M_MASK GENMASK(10 , 8 )
#define REG_LP_400M(x) FIELD_PREP(REG_LP_400M_MASK, x)
#define REG_LP_400M_380MV REG_LP_400M(0 )
#define REG_LP_400M_390MV REG_LP_400M(1 )
#define REG_LP_400M_400MV REG_LP_400M(2 )
#define REG_LP_400M_410MV REG_LP_400M(3 )
#define REG_LP_400M_420MV REG_LP_400M(4 )
#define REG_LP_400M_430MV REG_LP_400M(5 )
#define REG_LP_400M_440MV REG_LP_400M(6 )
#define REG_LP_400M_450MV REG_LP_400M(7 )
#define REG_400M_MASK GENMASK(6 , 4 )
#define REG_400M(x) FIELD_PREP(REG_400M_MASK, x)
#define REG_400M_380MV REG_400M(0 )
#define REG_400M_390MV REG_400M(1 )
#define REG_400M_400MV REG_400M(2 )
#define REG_400M_410MV REG_400M(3 )
#define REG_400M_420MV REG_400M(4 )
#define REG_400M_430MV REG_400M(5 )
#define REG_400M_440MV REG_400M(6 )
#define REG_400M_450MV REG_400M(7 )
#define REG_400M_230MV REG_400M(0 )
#define REG_400M_220MV REG_400M(1 )
#define REG_400M_210MV REG_400M(2 )
#define REG_400M_200MV REG_400M(3 )
#define REG_400M_190MV REG_400M(4 )
#define REG_400M_180MV REG_400M(5 )
#define REG_400M_170MV REG_400M(6 )
#define REG_400M_160MV REG_400M(7 )
#define REG_645M_MASK GENMASK(2 , 0 )
#define REG_645M(x) FIELD_PREP(REG_645M_MASK, x)
#define REG_645M_605MV REG_645M(0 )
#define REG_645M_625MV REG_645M(1 )
#define REG_645M_635MV REG_645M(2 )
#define REG_645M_645MV REG_645M(3 )
#define REG_645M_655MV REG_645M(4 )
#define REG_645M_665MV REG_645M(5 )
#define REG_645M_685MV REG_645M(6 )
#define REG_645M_725MV REG_645M(7 )
#define BIAS_CON4 0 x0010
#define I_MUX_SEL_MASK GENMASK(6 , 5 )
#define I_MUX_SEL(x) FIELD_PREP(I_MUX_SEL_MASK, x)
#define I_MUX_400MV I_MUX_SEL(0 )
#define I_MUX_200MV I_MUX_SEL(1 )
#define I_MUX_530MV I_MUX_SEL(2 )
#define PLL_CON0 0 x0100
#define PLL_EN BIT(12 )
#define S_MASK GENMASK(10 , 8 )
#define S(x) FIELD_PREP(S_MASK, x)
#define P_MASK GENMASK(5 , 0 )
#define P(x) FIELD_PREP(P_MASK, x)
#define PLL_CON1 0 x0104
#define PLL_CON2 0 x0108
#define M_MASK GENMASK(9 , 0 )
#define M(x) FIELD_PREP(M_MASK, x)
#define PLL_CON3 0 x010c
#define MRR_MASK GENMASK(13 , 8 )
#define MRR(x) FIELD_PREP(MRR_MASK, x)
#define MFR_MASK GENMASK(7 , 0 )
#define MFR(x) FIELD_PREP(MFR_MASK, x)
#define PLL_CON4 0 x0110
#define SSCG_EN BIT(11 )
#define PLL_CON5 0 x0114
#define RESET_N_SEL BIT(10 )
#define PLL_ENABLE_SEL BIT(8 )
#define PLL_CON6 0 x0118
#define PLL_CON7 0 x011c
#define PLL_LOCK_CNT(x) FIELD_PREP(GENMASK(15 , 0 ), x)
#define PLL_CON8 0 x0120
#define PLL_STB_CNT(x) FIELD_PREP(GENMASK(15 , 0 ), x)
#define PLL_STAT0 0 x0140
#define PLL_LOCK BIT(0 )
#define DPHY_MC_GNR_CON0 0 x0300
#define PHY_READY BIT(1 )
#define PHY_ENABLE BIT(0 )
#define DPHY_MC_GNR_CON1 0 x0304
#define T_PHY_READY(x) FIELD_PREP(GENMASK(15 , 0 ), x)
#define DPHY_MC_ANA_CON0 0 x0308
#define EDGE_CON(x) FIELD_PREP(GENMASK(14 , 12 ), x)
#define EDGE_CON_DIR(x) FIELD_PREP(BIT(9 ), x)
#define EDGE_CON_EN BIT(8 )
#define RES_UP(x) FIELD_PREP(GENMASK(7 , 4 ), x)
#define RES_DN(x) FIELD_PREP(GENMASK(3 , 0 ), x)
#define DPHY_MC_ANA_CON1 0 x030c
#define DPHY_MC_ANA_CON2 0 x0310
#define HS_VREG_AMP_ICON(x) FIELD_PREP(GENMASK(1 , 0 ), x)
#define DPHY_MC_TIME_CON0 0 x0330
#define HSTX_CLK_SEL BIT(12 )
#define T_LPX(x) FIELD_PREP(GENMASK(11 , 4 ), x)
#define DPHY_MC_TIME_CON1 0 x0334
#define T_CLK_ZERO(x) FIELD_PREP(GENMASK(15 , 8 ), x)
#define T_CLK_PREPARE(x) FIELD_PREP(GENMASK(7 , 0 ), x)
#define DPHY_MC_TIME_CON2 0 x0338
#define T_HS_EXIT(x) FIELD_PREP(GENMASK(15 , 8 ), x)
#define T_CLK_TRAIL(x) FIELD_PREP(GENMASK(7 , 0 ), x)
#define DPHY_MC_TIME_CON3 0 x033c
#define T_CLK_POST(x) FIELD_PREP(GENMASK(7 , 0 ), x)
#define DPHY_MC_TIME_CON4 0 x0340
#define T_ULPS_EXIT(x) FIELD_PREP(GENMASK(9 , 0 ), x)
#define DPHY_MC_DESKEW_CON0 0 x0350
#define SKEW_CAL_RUN_TIME(x) FIELD_PREP(GENMASK(15 , 12 ), x)
#define SKEW_CAL_INIT_RUN_TIME(x) FIELD_PREP(GENMASK(11 , 8 ), x)
#define SKEW_CAL_INIT_WAIT_TIME(x) FIELD_PREP(GENMASK(7 , 4 ), x)
#define SKEW_CAL_EN BIT(0 )
#define COMBO_MD0_GNR_CON0 0 x0400
#define COMBO_MD0_GNR_CON1 0 x0404
#define COMBO_MD0_ANA_CON0 0 x0408
#define COMBO_MD0_ANA_CON1 0 x040c
#define COMBO_MD0_ANA_CON2 0 x0410
#define COMBO_MD0_TIME_CON0 0 x0430
#define COMBO_MD0_TIME_CON1 0 x0434
#define COMBO_MD0_TIME_CON2 0 x0438
#define COMBO_MD0_TIME_CON3 0 x043c
#define COMBO_MD0_TIME_CON4 0 x0440
#define COMBO_MD0_DATA_CON0 0 x0444
#define COMBO_MD1_GNR_CON0 0 x0500
#define COMBO_MD1_GNR_CON1 0 x0504
#define COMBO_MD1_ANA_CON0 0 x0508
#define COMBO_MD1_ANA_CON1 0 x050c
#define COMBO_MD1_ANA_CON2 0 x0510
#define COMBO_MD1_TIME_CON0 0 x0530
#define COMBO_MD1_TIME_CON1 0 x0534
#define COMBO_MD1_TIME_CON2 0 x0538
#define COMBO_MD1_TIME_CON3 0 x053c
#define COMBO_MD1_TIME_CON4 0 x0540
#define COMBO_MD1_DATA_CON0 0 x0544
#define COMBO_MD2_GNR_CON0 0 x0600
#define COMBO_MD2_GNR_CON1 0 x0604
#define COMBO_MD2_ANA_CON0 0 X0608
#define COMBO_MD2_ANA_CON1 0 X060c
#define COMBO_MD2_ANA_CON2 0 X0610
#define COMBO_MD2_TIME_CON0 0 x0630
#define COMBO_MD2_TIME_CON1 0 x0634
#define COMBO_MD2_TIME_CON2 0 x0638
#define COMBO_MD2_TIME_CON3 0 x063c
#define COMBO_MD2_TIME_CON4 0 x0640
#define COMBO_MD2_DATA_CON0 0 x0644
#define DPHY_MD3_GNR_CON0 0 x0700
#define DPHY_MD3_GNR_CON1 0 x0704
#define DPHY_MD3_ANA_CON0 0 X0708
#define DPHY_MD3_ANA_CON1 0 X070c
#define DPHY_MD3_ANA_CON2 0 X0710
#define DPHY_MD3_TIME_CON0 0 x0730
#define DPHY_MD3_TIME_CON1 0 x0734
#define DPHY_MD3_TIME_CON2 0 x0738
#define DPHY_MD3_TIME_CON3 0 x073c
#define DPHY_MD3_TIME_CON4 0 x0740
#define DPHY_MD3_DATA_CON0 0 x0744
#define T_LP_EXIT_SKEW(x) FIELD_PREP(GENMASK(3 , 2 ), x)
#define T_LP_ENTRY_SKEW(x) FIELD_PREP(GENMASK(1 , 0 ), x)
#define T_HS_ZERO(x) FIELD_PREP(GENMASK(15 , 8 ), x)
#define T_HS_PREPARE(x) FIELD_PREP(GENMASK(7 , 0 ), x)
#define T_HS_EXIT(x) FIELD_PREP(GENMASK(15 , 8 ), x)
#define T_HS_TRAIL(x) FIELD_PREP(GENMASK(7 , 0 ), x)
#define T_TA_GET(x) FIELD_PREP(GENMASK(7 , 4 ), x)
#define T_TA_GO(x) FIELD_PREP(GENMASK(3 , 0 ), x)
/* MIPI_CDPHY_GRF registers */
#define MIPI_DCPHY_GRF_CON0 0 x0000
#define S_CPHY_MODE FIELD_PREP_HIWORD(BIT(3 ), 1 )
#define M_CPHY_MODE FIELD_PREP_HIWORD(BIT(0 ), 1 )
enum hs_drv_res_ohm {
STRENGTH_30_OHM = 0 x8,
STRENGTH_31_2_OHM,
STRENGTH_32_5_OHM,
STRENGTH_34_OHM,
STRENGTH_35_5_OHM,
STRENGTH_37_OHM,
STRENGTH_39_OHM,
STRENGTH_41_OHM,
STRENGTH_43_OHM = 0 x0,
STRENGTH_46_OHM,
STRENGTH_49_OHM,
STRENGTH_52_OHM,
STRENGTH_56_OHM,
STRENGTH_60_OHM,
STRENGTH_66_OHM,
STRENGTH_73_OHM,
};
struct hs_drv_res_cfg {
enum hs_drv_res_ohm clk_hs_drv_up_ohm;
enum hs_drv_res_ohm clk_hs_drv_down_ohm;
enum hs_drv_res_ohm data_hs_drv_up_ohm;
enum hs_drv_res_ohm data_hs_drv_down_ohm;
};
struct samsung_mipi_dcphy_plat_data {
const struct hs_drv_res_cfg *dphy_hs_drv_res_cfg;
u32 dphy_tx_max_lane_kbps;
};
struct samsung_mipi_dcphy {
struct device *dev;
struct clk *ref_clk;
struct clk *pclk;
struct regmap *regmap;
struct regmap *grf_regmap;
struct reset_control *m_phy_rst;
struct reset_control *s_phy_rst;
struct reset_control *apb_rst;
struct reset_control *grf_apb_rst;
unsigned int lanes;
struct phy *phy;
u8 type;
const struct samsung_mipi_dcphy_plat_data *pdata;
struct {
unsigned long long rate;
u8 prediv;
u16 fbdiv;
long dsm;
u8 scaler;
bool ssc_en;
u8 mfr;
u8 mrr;
} pll;
};
struct samsung_mipi_dphy_timing {
unsigned int max_lane_mbps;
u8 clk_prepare;
u8 clk_zero;
u8 clk_post;
u8 clk_trail_eot;
u8 hs_prepare;
u8 hs_zero;
u8 hs_trail_eot;
u8 lpx;
u8 hs_exit;
u8 hs_settle;
};
/*
* Timing values taken from rk3588 vendor kernel.
* Not documented in hw documentation.
*/
static const
struct samsung_mipi_dphy_timing samsung_mipi_dphy_timing_table[] = {
{6500 , 32 , 117 , 31 , 28 , 30 , 56 , 27 , 24 , 44 , 37 },
{6490 , 32 , 116 , 31 , 28 , 30 , 56 , 27 , 24 , 44 , 37 },
{6480 , 32 , 116 , 31 , 28 , 30 , 56 , 27 , 24 , 44 , 37 },
{6470 , 32 , 116 , 31 , 28 , 30 , 56 , 27 , 24 , 44 , 37 },
{6460 , 32 , 116 , 31 , 28 , 30 , 56 , 27 , 24 , 44 , 37 },
{6450 , 32 , 115 , 31 , 28 , 30 , 56 , 27 , 24 , 44 , 37 },
{6440 , 32 , 115 , 31 , 28 , 30 , 56 , 27 , 24 , 44 , 37 },
{6430 , 31 , 116 , 31 , 28 , 30 , 55 , 27 , 24 , 44 , 37 },
{6420 , 31 , 116 , 31 , 28 , 30 , 55 , 27 , 24 , 44 , 37 },
{6410 , 31 , 116 , 31 , 27 , 30 , 55 , 27 , 24 , 44 , 37 },
{6400 , 31 , 115 , 30 , 27 , 30 , 55 , 27 , 23 , 43 , 36 },
{6390 , 31 , 115 , 30 , 27 , 30 , 55 , 27 , 23 , 43 , 36 },
{6380 , 31 , 115 , 30 , 27 , 30 , 55 , 27 , 23 , 43 , 36 },
{6370 , 31 , 115 , 30 , 27 , 30 , 55 , 26 , 23 , 43 , 36 },
{6360 , 31 , 114 , 30 , 27 , 30 , 54 , 26 , 23 , 43 , 36 },
{6350 , 31 , 114 , 30 , 27 , 30 , 54 , 26 , 23 , 43 , 36 },
{6340 , 31 , 114 , 30 , 27 , 30 , 54 , 26 , 23 , 43 , 36 },
{6330 , 31 , 114 , 30 , 27 , 30 , 54 , 26 , 23 , 43 , 36 },
{6320 , 31 , 113 , 30 , 27 , 30 , 54 , 26 , 23 , 43 , 36 },
{6310 , 31 , 113 , 30 , 27 , 30 , 54 , 26 , 23 , 43 , 36 },
{6300 , 31 , 113 , 30 , 27 , 30 , 54 , 26 , 23 , 43 , 36 },
{6290 , 31 , 113 , 30 , 27 , 29 , 54 , 26 , 23 , 43 , 36 },
{6280 , 31 , 112 , 30 , 27 , 29 , 54 , 26 , 23 , 43 , 36 },
{6270 , 31 , 112 , 30 , 27 , 29 , 54 , 26 , 23 , 43 , 36 },
{6260 , 31 , 112 , 30 , 27 , 29 , 54 , 26 , 23 , 43 , 36 },
{6250 , 31 , 112 , 30 , 27 , 29 , 54 , 26 , 23 , 42 , 36 },
{6240 , 30 , 113 , 30 , 27 , 29 , 54 , 26 , 23 , 42 , 36 },
{6230 , 30 , 112 , 30 , 27 , 29 , 54 , 26 , 23 , 42 , 35 },
{6220 , 30 , 112 , 30 , 27 , 29 , 53 , 26 , 23 , 42 , 35 },
{6210 , 30 , 112 , 30 , 27 , 29 , 53 , 26 , 23 , 42 , 35 },
{6200 , 30 , 112 , 29 , 27 , 29 , 53 , 26 , 23 , 42 , 35 },
{6190 , 30 , 111 , 29 , 27 , 29 , 53 , 26 , 23 , 42 , 35 },
{6180 , 30 , 111 , 29 , 27 , 29 , 53 , 26 , 23 , 42 , 35 },
{6170 , 30 , 111 , 29 , 26 , 29 , 53 , 26 , 23 , 42 , 35 },
{6160 , 30 , 111 , 29 , 26 , 29 , 53 , 26 , 23 , 42 , 35 },
{6150 , 30 , 110 , 29 , 26 , 29 , 53 , 26 , 23 , 42 , 35 },
{6140 , 30 , 110 , 29 , 26 , 29 , 52 , 26 , 23 , 42 , 35 },
{6130 , 30 , 110 , 29 , 26 , 29 , 52 , 25 , 22 , 42 , 35 },
{6120 , 30 , 110 , 29 , 26 , 29 , 52 , 25 , 22 , 42 , 35 },
{6110 , 30 , 110 , 29 , 26 , 29 , 52 , 25 , 22 , 42 , 35 },
{6100 , 30 , 109 , 29 , 26 , 29 , 52 , 25 , 22 , 41 , 35 },
{6090 , 30 , 109 , 29 , 26 , 29 , 52 , 25 , 22 , 41 , 35 },
{6080 , 30 , 109 , 29 , 26 , 28 , 53 , 25 , 22 , 41 , 35 },
{6070 , 30 , 109 , 29 , 26 , 28 , 52 , 25 , 22 , 41 , 34 },
{6060 , 30 , 108 , 29 , 26 , 28 , 52 , 25 , 22 , 41 , 34 },
{6050 , 30 , 108 , 29 , 26 , 28 , 52 , 25 , 22 , 41 , 34 },
{6040 , 29 , 109 , 29 , 26 , 28 , 52 , 25 , 22 , 41 , 34 },
{6030 , 29 , 109 , 29 , 26 , 28 , 52 , 25 , 22 , 41 , 34 },
{6020 , 29 , 108 , 29 , 26 , 28 , 52 , 25 , 22 , 41 , 34 },
{6010 , 29 , 108 , 29 , 26 , 28 , 52 , 25 , 22 , 41 , 34 },
{6000 , 29 , 108 , 28 , 26 , 28 , 51 , 25 , 22 , 41 , 34 },
{5990 , 29 , 108 , 28 , 26 , 28 , 51 , 25 , 22 , 41 , 34 },
{5980 , 29 , 107 , 28 , 26 , 28 , 51 , 25 , 22 , 41 , 34 },
{5970 , 29 , 107 , 28 , 26 , 28 , 51 , 25 , 22 , 41 , 34 },
{5960 , 29 , 107 , 28 , 26 , 28 , 51 , 25 , 22 , 40 , 34 },
{5950 , 29 , 107 , 28 , 26 , 28 , 51 , 25 , 22 , 40 , 34 },
{5940 , 29 , 107 , 28 , 25 , 28 , 51 , 25 , 22 , 40 , 34 },
{5930 , 29 , 106 , 28 , 25 , 28 , 50 , 25 , 22 , 40 , 34 },
{5920 , 29 , 106 , 28 , 25 , 28 , 50 , 25 , 22 , 40 , 34 },
{5910 , 29 , 106 , 28 , 25 , 28 , 50 , 25 , 22 , 40 , 34 },
{5900 , 29 , 106 , 28 , 25 , 28 , 50 , 24 , 22 , 40 , 33 },
{5890 , 29 , 105 , 28 , 25 , 28 , 50 , 24 , 22 , 40 , 33 },
{5880 , 29 , 105 , 28 , 25 , 28 , 50 , 24 , 22 , 40 , 33 },
{5870 , 29 , 105 , 28 , 25 , 27 , 51 , 24 , 22 , 40 , 33 },
{5860 , 29 , 105 , 28 , 25 , 27 , 51 , 24 , 21 , 40 , 33 },
{5850 , 29 , 104 , 28 , 25 , 27 , 50 , 24 , 21 , 40 , 33 },
{5840 , 28 , 105 , 28 , 25 , 27 , 50 , 24 , 21 , 40 , 33 },
{5830 , 28 , 105 , 28 , 25 , 27 , 50 , 24 , 21 , 40 , 33 },
{5820 , 28 , 105 , 28 , 25 , 27 , 50 , 24 , 21 , 40 , 33 },
{5810 , 28 , 104 , 28 , 25 , 27 , 50 , 24 , 21 , 39 , 33 },
{5800 , 28 , 104 , 27 , 25 , 27 , 50 , 24 , 21 , 39 , 33 },
{5790 , 28 , 104 , 27 , 25 , 27 , 50 , 24 , 21 , 39 , 33 },
{5780 , 28 , 104 , 27 , 25 , 27 , 49 , 24 , 21 , 39 , 33 },
{5770 , 28 , 104 , 27 , 25 , 27 , 49 , 24 , 21 , 39 , 33 },
{5760 , 28 , 103 , 27 , 25 , 27 , 49 , 24 , 21 , 39 , 33 },
{5750 , 28 , 103 , 27 , 25 , 27 , 49 , 24 , 21 , 39 , 33 },
{5740 , 28 , 103 , 27 , 25 , 27 , 49 , 24 , 21 , 39 , 33 },
{5730 , 28 , 103 , 27 , 25 , 27 , 49 , 24 , 21 , 39 , 32 },
{5720 , 28 , 102 , 27 , 25 , 27 , 49 , 24 , 21 , 39 , 32 },
{5710 , 28 , 102 , 27 , 25 , 27 , 48 , 24 , 21 , 39 , 32 },
{5700 , 28 , 102 , 27 , 24 , 27 , 48 , 24 , 21 , 39 , 32 },
{5690 , 28 , 102 , 27 , 24 , 27 , 48 , 24 , 21 , 39 , 32 },
{5680 , 28 , 101 , 27 , 24 , 27 , 48 , 24 , 21 , 39 , 32 },
{5670 , 28 , 101 , 27 , 24 , 27 , 48 , 23 , 21 , 38 , 32 },
{5660 , 28 , 101 , 27 , 24 , 26 , 49 , 23 , 21 , 38 , 32 },
{5650 , 28 , 101 , 27 , 24 , 26 , 49 , 23 , 21 , 38 , 32 },
{5640 , 27 , 101 , 27 , 24 , 26 , 48 , 23 , 21 , 38 , 32 },
{5630 , 27 , 101 , 27 , 24 , 26 , 48 , 23 , 21 , 38 , 32 },
{5620 , 27 , 101 , 27 , 24 , 26 , 48 , 23 , 21 , 38 , 32 },
{5610 , 27 , 101 , 27 , 24 , 26 , 48 , 23 , 21 , 38 , 32 },
{5600 , 27 , 101 , 26 , 24 , 26 , 48 , 23 , 20 , 38 , 32 },
{5590 , 27 , 100 , 26 , 24 , 26 , 48 , 23 , 20 , 38 , 32 },
{5580 , 27 , 100 , 26 , 24 , 26 , 48 , 23 , 20 , 38 , 32 },
{5570 , 27 , 100 , 26 , 24 , 26 , 48 , 23 , 20 , 38 , 31 },
{5560 , 27 , 100 , 26 , 24 , 26 , 47 , 23 , 20 , 38 , 31 },
{5550 , 27 , 99 , 26 , 24 , 26 , 47 , 23 , 20 , 38 , 31 },
{5540 , 27 , 99 , 26 , 24 , 26 , 47 , 23 , 20 , 38 , 31 },
{5530 , 27 , 99 , 26 , 24 , 26 , 47 , 23 , 20 , 38 , 31 },
{5520 , 27 , 99 , 26 , 24 , 26 , 47 , 23 , 20 , 37 , 31 },
{5510 , 27 , 98 , 26 , 24 , 26 , 47 , 23 , 20 , 37 , 31 },
{5500 , 27 , 98 , 26 , 24 , 26 , 47 , 23 , 20 , 37 , 31 },
{5490 , 27 , 98 , 26 , 24 , 26 , 46 , 23 , 20 , 37 , 31 },
{5480 , 27 , 98 , 26 , 24 , 26 , 46 , 23 , 20 , 37 , 31 },
{5470 , 27 , 97 , 26 , 23 , 26 , 46 , 23 , 20 , 37 , 31 },
{5460 , 27 , 97 , 26 , 23 , 26 , 46 , 23 , 20 , 37 , 31 },
{5450 , 27 , 97 , 26 , 23 , 25 , 47 , 23 , 20 , 37 , 31 },
{5440 , 26 , 98 , 26 , 23 , 25 , 47 , 23 , 20 , 37 , 31 },
{5430 , 26 , 98 , 26 , 23 , 25 , 47 , 22 , 20 , 37 , 31 },
{5420 , 26 , 97 , 26 , 23 , 25 , 46 , 22 , 20 , 37 , 31 },
{5410 , 26 , 97 , 26 , 23 , 25 , 46 , 22 , 20 , 37 , 31 },
{5400 , 26 , 97 , 25 , 23 , 25 , 46 , 22 , 20 , 37 , 30 },
{5390 , 26 , 97 , 25 , 23 , 25 , 46 , 22 , 20 , 37 , 30 },
{5380 , 26 , 96 , 25 , 23 , 25 , 46 , 22 , 20 , 36 , 30 },
{5370 , 26 , 96 , 25 , 23 , 25 , 46 , 22 , 20 , 36 , 30 },
{5360 , 26 , 96 , 25 , 23 , 25 , 46 , 22 , 20 , 36 , 30 },
{5350 , 26 , 96 , 25 , 23 , 25 , 46 , 22 , 20 , 36 , 30 },
{5340 , 26 , 95 , 25 , 23 , 25 , 45 , 22 , 20 , 36 , 30 },
{5330 , 26 , 95 , 25 , 23 , 25 , 45 , 22 , 19 , 36 , 30 },
{5320 , 26 , 95 , 25 , 23 , 25 , 45 , 22 , 19 , 36 , 30 },
{5310 , 26 , 95 , 25 , 23 , 25 , 45 , 22 , 19 , 36 , 30 },
{5300 , 26 , 95 , 25 , 23 , 25 , 45 , 22 , 19 , 36 , 30 },
{5290 , 26 , 94 , 25 , 23 , 25 , 45 , 22 , 19 , 36 , 30 },
{5280 , 26 , 94 , 25 , 23 , 25 , 45 , 22 , 19 , 36 , 30 },
{5270 , 26 , 94 , 25 , 23 , 25 , 44 , 22 , 19 , 36 , 30 },
{5260 , 26 , 94 , 25 , 23 , 25 , 44 , 22 , 19 , 36 , 30 },
{5250 , 25 , 94 , 25 , 23 , 24 , 45 , 22 , 19 , 36 , 30 },
{5240 , 25 , 94 , 25 , 23 , 24 , 45 , 22 , 19 , 36 , 29 },
{5230 , 25 , 94 , 25 , 22 , 24 , 45 , 22 , 19 , 35 , 29 },
{5220 , 25 , 94 , 25 , 22 , 24 , 45 , 22 , 19 , 35 , 29 },
{5210 , 25 , 93 , 25 , 22 , 24 , 45 , 22 , 19 , 35 , 29 },
{5200 , 25 , 93 , 24 , 22 , 24 , 44 , 21 , 19 , 35 , 29 },
{5190 , 25 , 93 , 24 , 22 , 24 , 44 , 21 , 19 , 35 , 29 },
{5180 , 25 , 93 , 24 , 22 , 24 , 44 , 21 , 19 , 35 , 29 },
{5170 , 25 , 92 , 24 , 22 , 24 , 44 , 21 , 19 , 35 , 29 },
{5160 , 25 , 92 , 24 , 22 , 24 , 44 , 21 , 19 , 35 , 29 },
{5150 , 25 , 92 , 24 , 22 , 24 , 44 , 21 , 19 , 35 , 29 },
{5140 , 25 , 92 , 24 , 22 , 24 , 44 , 21 , 19 , 35 , 29 },
{5130 , 25 , 92 , 24 , 22 , 24 , 43 , 21 , 19 , 35 , 29 },
{5120 , 25 , 91 , 24 , 22 , 24 , 43 , 21 , 19 , 35 , 29 },
{5110 , 25 , 91 , 24 , 22 , 24 , 43 , 21 , 19 , 35 , 29 },
{5100 , 25 , 91 , 24 , 22 , 24 , 43 , 21 , 19 , 35 , 29 },
{5090 , 25 , 91 , 24 , 22 , 24 , 43 , 21 , 19 , 34 , 29 },
{5080 , 25 , 90 , 24 , 22 , 24 , 43 , 21 , 19 , 34 , 29 },
{5070 , 25 , 90 , 24 , 22 , 24 , 43 , 21 , 19 , 34 , 28 },
{5060 , 25 , 90 , 24 , 22 , 24 , 43 , 21 , 18 , 34 , 28 },
{5050 , 24 , 91 , 24 , 22 , 24 , 42 , 21 , 18 , 34 , 28 },
{5040 , 24 , 90 , 24 , 22 , 23 , 43 , 21 , 18 , 34 , 28 },
{5030 , 24 , 90 , 24 , 22 , 23 , 43 , 21 , 18 , 34 , 28 },
{5020 , 24 , 90 , 24 , 22 , 23 , 43 , 21 , 18 , 34 , 28 },
{5010 , 24 , 90 , 24 , 22 , 23 , 43 , 21 , 18 , 34 , 28 },
{5000 , 24 , 89 , 23 , 21 , 23 , 43 , 21 , 18 , 34 , 28 },
{4990 , 24 , 89 , 23 , 21 , 23 , 43 , 21 , 18 , 34 , 28 },
{4980 , 24 , 89 , 23 , 21 , 23 , 42 , 21 , 18 , 34 , 28 },
{4970 , 24 , 89 , 23 , 21 , 23 , 42 , 21 , 18 , 34 , 28 },
{4960 , 24 , 89 , 23 , 21 , 23 , 42 , 20 , 18 , 34 , 28 },
{4950 , 24 , 88 , 23 , 21 , 23 , 42 , 20 , 18 , 34 , 28 },
{4940 , 24 , 88 , 23 , 21 , 23 , 42 , 20 , 18 , 33 , 28 },
{4930 , 24 , 88 , 23 , 21 , 23 , 42 , 20 , 18 , 33 , 28 },
{4920 , 24 , 88 , 23 , 21 , 23 , 42 , 20 , 18 , 33 , 28 },
{4910 , 24 , 87 , 23 , 21 , 23 , 41 , 20 , 18 , 33 , 28 },
{4900 , 24 , 87 , 23 , 21 , 23 , 41 , 20 , 18 , 33 , 27 },
{4890 , 24 , 87 , 23 , 21 , 23 , 41 , 20 , 18 , 33 , 27 },
{4880 , 24 , 87 , 23 , 21 , 23 , 41 , 20 , 18 , 33 , 27 },
{4870 , 24 , 86 , 23 , 21 , 23 , 41 , 20 , 18 , 33 , 27 },
{4860 , 24 , 86 , 23 , 21 , 23 , 41 , 20 , 18 , 33 , 27 },
{4850 , 23 , 87 , 23 , 21 , 23 , 41 , 20 , 18 , 33 , 27 },
{4840 , 23 , 87 , 23 , 21 , 23 , 40 , 20 , 18 , 33 , 27 },
{4830 , 23 , 86 , 23 , 21 , 22 , 41 , 20 , 18 , 33 , 27 },
{4820 , 23 , 86 , 23 , 21 , 22 , 41 , 20 , 18 , 33 , 27 },
{4810 , 23 , 86 , 23 , 21 , 22 , 41 , 20 , 18 , 33 , 27 },
{4800 , 23 , 86 , 22 , 21 , 22 , 41 , 20 , 17 , 32 , 27 },
{4790 , 23 , 86 , 22 , 21 , 22 , 41 , 20 , 17 , 32 , 27 },
{4780 , 23 , 85 , 22 , 21 , 22 , 41 , 20 , 17 , 32 , 27 },
{4770 , 23 , 85 , 22 , 21 , 22 , 41 , 20 , 17 , 32 , 27 },
{4760 , 23 , 85 , 22 , 20 , 22 , 40 , 20 , 17 , 32 , 27 },
{4750 , 23 , 85 , 22 , 20 , 22 , 40 , 20 , 17 , 32 , 27 },
{4740 , 23 , 84 , 22 , 20 , 22 , 40 , 20 , 17 , 32 , 26 },
{4730 , 23 , 84 , 22 , 20 , 22 , 40 , 19 , 17 , 32 , 26 },
{4720 , 23 , 84 , 22 , 20 , 22 , 40 , 19 , 17 , 32 , 26 },
{4710 , 23 , 84 , 22 , 20 , 22 , 40 , 19 , 17 , 32 , 26 },
{4700 , 23 , 83 , 22 , 20 , 22 , 40 , 19 , 17 , 32 , 26 },
{4690 , 23 , 83 , 22 , 20 , 22 , 39 , 19 , 17 , 32 , 26 },
{4680 , 23 , 83 , 22 , 20 , 22 , 39 , 19 , 17 , 32 , 26 },
{4670 , 23 , 83 , 22 , 20 , 22 , 39 , 19 , 17 , 32 , 26 },
{4660 , 23 , 82 , 22 , 20 , 22 , 39 , 19 , 17 , 32 , 26 },
{4650 , 22 , 83 , 22 , 20 , 22 , 39 , 19 , 17 , 31 , 26 },
{4640 , 22 , 83 , 22 , 20 , 22 , 39 , 19 , 17 , 31 , 26 },
{4630 , 22 , 83 , 22 , 20 , 22 , 39 , 19 , 17 , 31 , 26 },
{4620 , 22 , 83 , 22 , 20 , 21 , 39 , 19 , 17 , 31 , 26 },
{4610 , 22 , 82 , 22 , 20 , 21 , 39 , 19 , 17 , 31 , 26 },
{4600 , 22 , 82 , 21 , 20 , 21 , 39 , 19 , 17 , 31 , 26 },
{4590 , 22 , 82 , 21 , 20 , 21 , 39 , 19 , 17 , 31 , 26 },
{4580 , 22 , 82 , 21 , 20 , 21 , 39 , 19 , 17 , 31 , 26 },
{4570 , 22 , 81 , 21 , 20 , 21 , 39 , 19 , 17 , 31 , 25 },
{4560 , 22 , 81 , 21 , 20 , 21 , 39 , 19 , 17 , 31 , 25 },
{4550 , 22 , 81 , 21 , 20 , 21 , 38 , 19 , 17 , 31 , 25 },
{4540 , 22 , 81 , 21 , 20 , 21 , 38 , 19 , 17 , 31 , 25 },
{4530 , 22 , 80 , 21 , 19 , 21 , 38 , 19 , 16 , 31 , 25 },
{4520 , 22 , 80 , 21 , 19 , 21 , 38 , 19 , 16 , 31 , 25 },
{4510 , 22 , 80 , 21 , 19 , 21 , 38 , 19 , 16 , 31 , 25 },
{4500 , 22 , 80 , 21 , 19 , 21 , 38 , 19 , 16 , 30 , 25 },
{4490 , 22 , 80 , 21 , 19 , 21 , 38 , 18 , 16 , 30 , 25 },
{4480 , 22 , 79 , 21 , 19 , 21 , 38 , 18 , 16 , 30 , 25 },
{4470 , 22 , 79 , 21 , 19 , 21 , 37 , 18 , 16 , 30 , 25 },
{4460 , 22 , 79 , 21 , 19 , 21 , 37 , 18 , 16 , 30 , 25 },
{4450 , 21 , 80 , 21 , 19 , 21 , 37 , 18 , 16 , 30 , 25 },
{4440 , 21 , 79 , 21 , 19 , 21 , 37 , 18 , 16 , 30 , 25 },
{4430 , 21 , 79 , 21 , 19 , 21 , 37 , 18 , 16 , 30 , 25 },
{4420 , 21 , 79 , 21 , 19 , 21 , 37 , 18 , 16 , 30 , 25 },
{4410 , 21 , 79 , 21 , 19 , 20 , 38 , 18 , 16 , 30 , 25 },
{4400 , 21 , 78 , 20 , 19 , 20 , 37 , 18 , 16 , 30 , 24 },
{4390 , 21 , 78 , 20 , 19 , 20 , 37 , 18 , 16 , 30 , 24 },
{4380 , 21 , 78 , 20 , 19 , 20 , 37 , 18 , 16 , 30 , 24 },
{4370 , 21 , 78 , 20 , 19 , 20 , 37 , 18 , 16 , 30 , 24 },
{4360 , 21 , 77 , 20 , 19 , 20 , 37 , 18 , 16 , 29 , 24 },
{4350 , 21 , 77 , 20 , 19 , 20 , 37 , 18 , 16 , 29 , 24 },
{4340 , 21 , 77 , 20 , 19 , 20 , 37 , 18 , 16 , 29 , 24 },
{4330 , 21 , 77 , 20 , 19 , 20 , 36 , 18 , 16 , 29 , 24 },
{4320 , 21 , 77 , 20 , 19 , 20 , 36 , 18 , 16 , 29 , 24 },
{4310 , 21 , 76 , 20 , 19 , 20 , 36 , 18 , 16 , 29 , 24 },
{4300 , 21 , 76 , 20 , 18 , 20 , 36 , 18 , 16 , 29 , 24 },
{4290 , 21 , 76 , 20 , 18 , 20 , 36 , 18 , 16 , 29 , 24 },
{4280 , 21 , 76 , 20 , 18 , 20 , 36 , 18 , 16 , 29 , 24 },
{4270 , 21 , 75 , 20 , 18 , 20 , 36 , 18 , 16 , 29 , 24 },
{4260 , 21 , 75 , 20 , 18 , 20 , 35 , 17 , 15 , 29 , 24 },
{4250 , 20 , 76 , 20 , 18 , 20 , 35 , 17 , 15 , 29 , 24 },
{4240 , 20 , 76 , 20 , 18 , 20 , 35 , 17 , 15 , 29 , 23 },
{4230 , 20 , 75 , 20 , 18 , 20 , 35 , 17 , 15 , 29 , 23 },
{4220 , 20 , 75 , 20 , 18 , 20 , 35 , 17 , 15 , 29 , 23 },
{4210 , 20 , 75 , 20 , 18 , 20 , 35 , 17 , 15 , 28 , 23 },
{4200 , 20 , 75 , 19 , 18 , 19 , 36 , 17 , 15 , 28 , 23 },
{4190 , 20 , 74 , 19 , 18 , 19 , 36 , 17 , 15 , 28 , 23 },
{4180 , 20 , 74 , 19 , 18 , 19 , 35 , 17 , 15 , 28 , 23 },
{4170 , 20 , 74 , 19 , 18 , 19 , 35 , 17 , 15 , 28 , 23 },
{4160 , 20 , 74 , 19 , 18 , 19 , 35 , 17 , 15 , 28 , 23 },
{4150 , 20 , 74 , 19 , 18 , 19 , 35 , 17 , 15 , 28 , 23 },
{4140 , 20 , 73 , 19 , 18 , 19 , 35 , 17 , 15 , 28 , 23 },
{4130 , 20 , 73 , 19 , 18 , 19 , 35 , 17 , 15 , 28 , 23 },
{4120 , 20 , 73 , 19 , 18 , 19 , 35 , 17 , 15 , 28 , 23 },
{4110 , 20 , 73 , 19 , 18 , 19 , 34 , 17 , 15 , 28 , 23 },
{4100 , 20 , 72 , 19 , 18 , 19 , 34 , 17 , 15 , 28 , 23 },
{4090 , 20 , 72 , 19 , 18 , 19 , 34 , 17 , 15 , 28 , 23 },
{4080 , 20 , 72 , 19 , 18 , 19 , 34 , 17 , 15 , 28 , 23 },
{4070 , 20 , 72 , 19 , 18 , 19 , 34 , 17 , 15 , 27 , 22 },
{4060 , 19 , 72 , 19 , 17 , 19 , 34 , 17 , 15 , 27 , 22 },
{4050 , 19 , 72 , 19 , 17 , 19 , 34 , 17 , 15 , 27 , 22 },
{4040 , 19 , 72 , 19 , 17 , 19 , 33 , 17 , 15 , 27 , 22 },
{4030 , 19 , 72 , 19 , 17 , 19 , 33 , 17 , 15 , 27 , 22 },
{4020 , 19 , 71 , 19 , 17 , 19 , 33 , 16 , 15 , 27 , 22 },
{4010 , 19 , 71 , 19 , 17 , 19 , 33 , 16 , 15 , 27 , 22 },
{4000 , 19 , 71 , 18 , 17 , 19 , 33 , 16 , 14 , 27 , 22 },
{3990 , 19 , 71 , 18 , 17 , 18 , 34 , 16 , 14 , 27 , 22 },
{3980 , 19 , 71 , 18 , 17 , 18 , 34 , 16 , 14 , 27 , 22 },
{3970 , 19 , 70 , 18 , 17 , 18 , 33 , 16 , 14 , 27 , 22 },
{3960 , 19 , 70 , 18 , 17 , 18 , 33 , 16 , 14 , 27 , 22 },
{3950 , 19 , 70 , 18 , 17 , 18 , 33 , 16 , 14 , 27 , 22 },
{3940 , 19 , 70 , 18 , 17 , 18 , 33 , 16 , 14 , 27 , 22 },
{3930 , 19 , 69 , 18 , 17 , 18 , 33 , 16 , 14 , 27 , 22 },
{3920 , 19 , 69 , 18 , 17 , 18 , 33 , 16 , 14 , 26 , 22 },
{3910 , 19 , 69 , 18 , 17 , 18 , 33 , 16 , 14 , 26 , 22 },
{3900 , 19 , 69 , 18 , 17 , 18 , 33 , 16 , 14 , 26 , 21 },
{3890 , 19 , 68 , 18 , 17 , 18 , 32 , 16 , 14 , 26 , 21 },
{3880 , 19 , 68 , 18 , 17 , 18 , 32 , 16 , 14 , 26 , 21 },
{3870 , 19 , 68 , 18 , 17 , 18 , 32 , 16 , 14 , 26 , 21 },
{3860 , 18 , 69 , 18 , 17 , 18 , 32 , 16 , 14 , 26 , 21 },
{3850 , 18 , 68 , 18 , 17 , 18 , 32 , 16 , 14 , 26 , 21 },
{3840 , 18 , 68 , 18 , 17 , 18 , 32 , 16 , 14 , 26 , 21 },
{3830 , 18 , 68 , 18 , 16 , 18 , 32 , 16 , 14 , 26 , 21 },
{3820 , 18 , 68 , 18 , 16 , 18 , 31 , 16 , 14 , 26 , 21 },
{3810 , 18 , 68 , 18 , 16 , 18 , 31 , 16 , 14 , 26 , 21 },
{3800 , 18 , 67 , 17 , 16 , 18 , 31 , 16 , 14 , 26 , 21 },
{3790 , 18 , 67 , 17 , 16 , 17 , 32 , 15 , 14 , 26 , 21 },
{3780 , 18 , 67 , 17 , 16 , 17 , 32 , 15 , 14 , 25 , 21 },
{3770 , 18 , 67 , 17 , 16 , 17 , 32 , 15 , 14 , 25 , 21 },
{3760 , 18 , 66 , 17 , 16 , 17 , 32 , 15 , 14 , 25 , 21 },
{3750 , 18 , 66 , 17 , 16 , 17 , 31 , 15 , 14 , 25 , 21 },
{3740 , 18 , 66 , 17 , 16 , 17 , 31 , 15 , 14 , 25 , 20 },
{3730 , 18 , 66 , 17 , 16 , 17 , 31 , 15 , 13 , 25 , 20 },
{3720 , 18 , 65 , 17 , 16 , 17 , 31 , 15 , 13 , 25 , 20 },
{3710 , 18 , 65 , 17 , 16 , 17 , 31 , 15 , 13 , 25 , 20 },
{3700 , 18 , 65 , 17 , 16 , 17 , 31 , 15 , 13 , 25 , 20 },
{3690 , 18 , 65 , 17 , 16 , 17 , 31 , 15 , 13 , 25 , 20 },
{3680 , 18 , 64 , 17 , 16 , 17 , 31 , 15 , 13 , 25 , 20 },
{3670 , 18 , 64 , 17 , 16 , 17 , 30 , 15 , 13 , 25 , 20 },
{3660 , 17 , 65 , 17 , 16 , 17 , 30 , 15 , 13 , 25 , 20 },
{3650 , 17 , 65 , 17 , 16 , 17 , 30 , 15 , 13 , 25 , 20 },
{3640 , 17 , 65 , 17 , 16 , 17 , 30 , 15 , 13 , 25 , 20 },
{3630 , 17 , 64 , 17 , 16 , 17 , 30 , 15 , 13 , 24 , 20 },
{3620 , 17 , 64 , 17 , 16 , 17 , 30 , 15 , 13 , 24 , 20 },
{3610 , 17 , 64 , 17 , 16 , 17 , 30 , 15 , 13 , 24 , 20 },
{3600 , 17 , 64 , 16 , 16 , 17 , 29 , 15 , 13 , 24 , 20 },
{3590 , 17 , 63 , 16 , 15 , 17 , 29 , 15 , 13 , 24 , 20 },
{3580 , 17 , 63 , 16 , 15 , 16 , 30 , 15 , 13 , 24 , 20 },
{3570 , 17 , 63 , 16 , 15 , 16 , 30 , 15 , 13 , 24 , 19 },
{3560 , 17 , 63 , 16 , 15 , 16 , 30 , 14 , 13 , 24 , 19 },
{3550 , 17 , 62 , 16 , 15 , 16 , 30 , 14 , 13 , 24 , 19 },
{3540 , 17 , 62 , 16 , 15 , 16 , 30 , 14 , 13 , 24 , 19 },
{3530 , 17 , 62 , 16 , 15 , 16 , 29 , 14 , 13 , 24 , 19 },
{3520 , 17 , 62 , 16 , 15 , 16 , 29 , 14 , 13 , 24 , 19 },
{3510 , 17 , 62 , 16 , 15 , 16 , 29 , 14 , 13 , 24 , 19 },
{3500 , 17 , 61 , 16 , 15 , 16 , 29 , 14 , 13 , 24 , 19 },
{3490 , 17 , 61 , 16 , 15 , 16 , 29 , 14 , 13 , 23 , 19 },
{3480 , 17 , 61 , 16 , 15 , 16 , 29 , 14 , 13 , 23 , 19 },
{3470 , 17 , 61 , 16 , 15 , 16 , 29 , 14 , 13 , 23 , 19 },
{3460 , 16 , 61 , 16 , 15 , 16 , 28 , 14 , 12 , 23 , 19 },
{3450 , 16 , 61 , 16 , 15 , 16 , 28 , 14 , 12 , 23 , 19 },
{3440 , 16 , 61 , 16 , 15 , 16 , 28 , 14 , 12 , 23 , 19 },
{3430 , 16 , 61 , 16 , 15 , 16 , 28 , 14 , 12 , 23 , 19 },
{3420 , 16 , 60 , 16 , 15 , 16 , 28 , 14 , 12 , 23 , 19 },
{3410 , 16 , 60 , 16 , 15 , 16 , 28 , 14 , 12 , 23 , 18 },
{3400 , 16 , 60 , 15 , 15 , 16 , 28 , 14 , 12 , 23 , 18 },
{3390 , 16 , 60 , 15 , 15 , 16 , 28 , 14 , 12 , 23 , 18 },
{3380 , 16 , 59 , 15 , 15 , 16 , 27 , 14 , 12 , 23 , 18 },
{3370 , 16 , 59 , 15 , 15 , 15 , 28 , 14 , 12 , 23 , 18 },
{3360 , 16 , 59 , 15 , 14 , 15 , 28 , 14 , 12 , 23 , 18 },
{3350 , 16 , 59 , 15 , 14 , 15 , 28 , 14 , 12 , 23 , 18 },
{3340 , 16 , 59 , 15 , 14 , 15 , 28 , 14 , 12 , 22 , 18 },
{3330 , 16 , 58 , 15 , 14 , 15 , 28 , 14 , 12 , 22 , 18 },
{3320 , 16 , 58 , 15 , 14 , 15 , 28 , 13 , 12 , 22 , 18 },
{3310 , 16 , 58 , 15 , 14 , 15 , 27 , 13 , 12 , 22 , 18 },
{3300 , 16 , 58 , 15 , 14 , 15 , 27 , 13 , 12 , 22 , 18 },
{3290 , 16 , 57 , 15 , 14 , 15 , 27 , 13 , 12 , 22 , 18 },
{3280 , 16 , 57 , 15 , 14 , 15 , 27 , 13 , 12 , 22 , 18 },
{3270 , 16 , 57 , 15 , 14 , 15 , 27 , 13 , 12 , 22 , 18 },
{3260 , 15 , 58 , 15 , 14 , 15 , 27 , 13 , 12 , 22 , 18 },
{3250 , 15 , 57 , 15 , 14 , 15 , 27 , 13 , 12 , 22 , 18 },
{3240 , 15 , 57 , 15 , 14 , 15 , 26 , 13 , 12 , 22 , 17 },
{3230 , 15 , 57 , 15 , 14 , 15 , 26 , 13 , 12 , 22 , 17 },
{3220 , 15 , 57 , 15 , 14 , 15 , 26 , 13 , 12 , 22 , 17 },
{3210 , 15 , 56 , 15 , 14 , 15 , 26 , 13 , 12 , 22 , 17 },
{3200 , 15 , 56 , 14 , 14 , 15 , 26 , 13 , 11 , 21 , 17 },
{3190 , 15 , 56 , 14 , 14 , 15 , 26 , 13 , 11 , 21 , 17 },
{3180 , 15 , 56 , 14 , 14 , 15 , 26 , 13 , 11 , 21 , 17 },
{3170 , 15 , 56 , 14 , 14 , 15 , 25 , 13 , 11 , 21 , 17 },
{3160 , 15 , 55 , 14 , 14 , 14 , 26 , 13 , 11 , 21 , 17 },
{3150 , 15 , 55 , 14 , 14 , 14 , 26 , 13 , 11 , 21 , 17 },
{3140 , 15 , 55 , 14 , 14 , 14 , 26 , 13 , 11 , 21 , 17 },
{3130 , 15 , 55 , 14 , 14 , 14 , 26 , 13 , 11 , 21 , 17 },
{3120 , 15 , 54 , 14 , 13 , 14 , 26 , 13 , 11 , 21 , 17 },
{3110 , 15 , 54 , 14 , 13 , 14 , 26 , 13 , 11 , 21 , 17 },
{3100 , 15 , 54 , 14 , 13 , 14 , 26 , 13 , 11 , 21 , 17 },
{3090 , 15 , 54 , 14 , 13 , 14 , 25 , 12 , 11 , 21 , 17 },
{3080 , 15 , 53 , 14 , 13 , 14 , 25 , 12 , 11 , 21 , 17 },
{3070 , 14 , 54 , 14 , 13 , 14 , 25 , 12 , 11 , 21 , 16 },
{3060 , 14 , 54 , 14 , 13 , 14 , 25 , 12 , 11 , 21 , 16 },
{3050 , 14 , 54 , 14 , 13 , 14 , 25 , 12 , 11 , 20 , 16 },
{3040 , 14 , 53 , 14 , 13 , 14 , 25 , 12 , 11 , 20 , 16 },
{3030 , 14 , 53 , 14 , 13 , 14 , 25 , 12 , 11 , 20 , 16 },
{3020 , 14 , 53 , 14 , 13 , 14 , 24 , 12 , 11 , 20 , 16 },
{3010 , 14 , 53 , 14 , 13 , 14 , 24 , 12 , 11 , 20 , 16 },
{3000 , 14 , 53 , 13 , 13 , 14 , 24 , 12 , 11 , 20 , 16 },
{2990 , 14 , 52 , 13 , 13 , 14 , 24 , 12 , 11 , 20 , 16 },
{2980 , 14 , 52 , 13 , 13 , 14 , 24 , 12 , 11 , 20 , 16 },
{2970 , 14 , 52 , 13 , 13 , 14 , 24 , 12 , 11 , 20 , 16 },
{2960 , 14 , 52 , 13 , 13 , 14 , 24 , 12 , 11 , 20 , 16 },
{2950 , 14 , 51 , 13 , 13 , 13 , 24 , 12 , 11 , 20 , 16 },
{2940 , 14 , 51 , 13 , 13 , 13 , 24 , 12 , 11 , 20 , 16 },
{2930 , 14 , 51 , 13 , 13 , 13 , 24 , 12 , 10 , 20 , 16 },
{2920 , 14 , 51 , 13 , 13 , 13 , 24 , 12 , 10 , 20 , 16 },
{2910 , 14 , 50 , 13 , 13 , 13 , 24 , 12 , 10 , 20 , 15 },
{2900 , 14 , 50 , 13 , 13 , 13 , 24 , 12 , 10 , 19 , 15 },
{2890 , 14 , 50 , 13 , 12 , 13 , 24 , 12 , 10 , 19 , 15 },
{2880 , 14 , 50 , 13 , 12 , 13 , 23 , 12 , 10 , 19 , 15 },
{2870 , 13 , 50 , 13 , 12 , 13 , 23 , 12 , 10 , 19 , 15 },
{2860 , 13 , 50 , 13 , 12 , 13 , 23 , 12 , 10 , 19 , 15 },
{2850 , 13 , 50 , 13 , 12 , 13 , 23 , 11 , 10 , 19 , 15 },
{2840 , 13 , 50 , 13 , 12 , 13 , 23 , 11 , 10 , 19 , 15 },
{2830 , 13 , 50 , 13 , 12 , 13 , 23 , 11 , 10 , 19 , 15 },
{2820 , 13 , 49 , 13 , 12 , 13 , 23 , 11 , 10 , 19 , 15 },
{2810 , 13 , 49 , 13 , 12 , 13 , 23 , 11 , 10 , 19 , 15 },
{2800 , 13 , 49 , 12 , 12 , 13 , 22 , 11 , 10 , 19 , 15 },
{2790 , 13 , 49 , 12 , 12 , 13 , 22 , 11 , 10 , 19 , 15 },
{2780 , 13 , 48 , 12 , 12 , 13 , 22 , 11 , 10 , 19 , 15 },
{2770 , 13 , 48 , 12 , 12 , 13 , 22 , 11 , 10 , 19 , 15 },
{2760 , 13 , 48 , 12 , 12 , 13 , 22 , 11 , 10 , 18 , 15 },
{2750 , 13 , 48 , 12 , 12 , 13 , 22 , 11 , 10 , 18 , 15 },
{2740 , 13 , 47 , 12 , 12 , 12 , 23 , 11 , 10 , 18 , 14 },
{2730 , 13 , 47 , 12 , 12 , 12 , 22 , 11 , 10 , 18 , 14 },
{2720 , 13 , 47 , 12 , 12 , 12 , 22 , 11 , 10 , 18 , 14 },
{2710 , 13 , 47 , 12 , 12 , 12 , 22 , 11 , 10 , 18 , 14 },
{2700 , 13 , 47 , 12 , 12 , 12 , 22 , 11 , 10 , 18 , 14 },
{2690 , 13 , 46 , 12 , 12 , 12 , 22 , 11 , 10 , 18 , 14 },
{2680 , 13 , 46 , 12 , 12 , 12 , 22 , 11 , 10 , 18 , 14 },
{2670 , 12 , 47 , 12 , 12 , 12 , 22 , 11 , 10 , 18 , 14 },
{2660 , 12 , 47 , 12 , 12 , 12 , 21 , 11 , 9 , 18 , 14 },
{2650 , 12 , 46 , 12 , 11 , 12 , 21 , 11 , 9 , 18 , 14 },
{2640 , 12 , 46 , 12 , 11 , 12 , 21 , 11 , 9 , 18 , 14 },
{2630 , 12 , 46 , 12 , 11 , 12 , 21 , 11 , 9 , 18 , 14 },
{2620 , 12 , 46 , 12 , 11 , 12 , 21 , 10 , 9 , 18 , 14 },
{2610 , 12 , 45 , 12 , 11 , 12 , 21 , 10 , 9 , 17 , 14 },
{2600 , 12 , 45 , 11 , 11 , 12 , 21 , 10 , 9 , 17 , 14 },
{2590 , 12 , 45 , 11 , 11 , 12 , 20 , 10 , 9 , 17 , 14 },
{2580 , 12 , 45 , 11 , 11 , 12 , 20 , 10 , 9 , 17 , 14 },
{2570 , 12 , 44 , 11 , 11 , 12 , 20 , 10 , 9 , 17 , 13 },
{2560 , 12 , 44 , 11 , 11 , 12 , 20 , 10 , 9 , 17 , 13 },
{2550 , 12 , 44 , 11 , 11 , 12 , 20 , 10 , 9 , 17 , 13 },
{2540 , 12 , 44 , 11 , 11 , 11 , 21 , 10 , 9 , 17 , 13 },
{2530 , 12 , 44 , 11 , 11 , 11 , 21 , 10 , 9 , 17 , 13 },
{2520 , 12 , 43 , 11 , 11 , 11 , 21 , 10 , 9 , 17 , 13 },
{2510 , 12 , 43 , 11 , 11 , 11 , 20 , 10 , 9 , 17 , 13 },
{2500 , 12 , 43 , 11 , 11 , 11 , 20 , 10 , 9 , 17 , 13 },
{2490 , 12 , 43 , 11 , 11 , 11 , 20 , 10 , 9 , 17 , 13 },
{2480 , 12 , 42 , 11 , 11 , 11 , 20 , 10 , 9 , 17 , 13 },
{2470 , 11 , 43 , 11 , 11 , 11 , 20 , 10 , 9 , 16 , 13 },
{2460 , 11 , 43 , 11 , 11 , 11 , 20 , 10 , 9 , 16 , 13 },
{2450 , 11 , 43 , 11 , 11 , 11 , 20 , 10 , 9 , 16 , 13 },
{2440 , 11 , 42 , 11 , 11 , 11 , 19 , 10 , 9 , 16 , 13 },
{2430 , 11 , 42 , 11 , 11 , 11 , 19 , 10 , 9 , 16 , 13 },
{2420 , 11 , 42 , 11 , 10 , 11 , 19 , 10 , 9 , 16 , 13 },
{2410 , 11 , 42 , 11 , 10 , 11 , 19 , 10 , 9 , 16 , 12 },
{2400 , 11 , 41 , 10 , 10 , 11 , 19 , 10 , 8 , 16 , 12 },
{2390 , 11 , 41 , 10 , 10 , 11 , 19 , 10 , 8 , 16 , 12 },
{2380 , 11 , 41 , 10 , 10 , 11 , 19 , 9 , 8 , 16 , 12 },
{2370 , 11 , 41 , 10 , 10 , 11 , 18 , 9 , 8 , 16 , 12 },
{2360 , 11 , 41 , 10 , 10 , 11 , 18 , 9 , 8 , 16 , 12 },
{2350 , 11 , 40 , 10 , 10 , 11 , 18 , 9 , 8 , 16 , 12 },
{2340 , 11 , 40 , 10 , 10 , 11 , 18 , 9 , 8 , 16 , 12 },
{2330 , 11 , 40 , 10 , 10 , 10 , 19 , 9 , 8 , 16 , 12 },
{2320 , 11 , 40 , 10 , 10 , 10 , 19 , 9 , 8 , 15 , 12 },
{2310 , 11 , 39 , 10 , 10 , 10 , 19 , 9 , 8 , 15 , 12 },
{2300 , 11 , 39 , 10 , 10 , 10 , 18 , 9 , 8 , 15 , 12 },
{2290 , 11 , 39 , 10 , 10 , 10 , 18 , 9 , 8 , 15 , 12 },
{2280 , 11 , 39 , 10 , 10 , 10 , 18 , 9 , 8 , 15 , 12 },
{2270 , 10 , 39 , 10 , 10 , 10 , 18 , 9 , 8 , 15 , 12 },
{2260 , 10 , 39 , 10 , 10 , 10 , 18 , 9 , 8 , 15 , 12 },
{2250 , 10 , 39 , 10 , 10 , 10 , 18 , 9 , 8 , 15 , 12 },
{2240 , 10 , 39 , 10 , 10 , 10 , 18 , 9 , 8 , 15 , 11 },
{2230 , 10 , 38 , 10 , 10 , 10 , 18 , 9 , 8 , 15 , 11 },
{2220 , 10 , 38 , 10 , 10 , 10 , 17 , 9 , 8 , 15 , 11 },
{2210 , 10 , 38 , 10 , 10 , 10 , 17 , 9 , 8 , 15 , 11 },
{2200 , 10 , 38 , 9 , 10 , 10 , 17 , 9 , 8 , 15 , 11 },
{2190 , 10 , 38 , 9 , 9 , 10 , 17 , 9 , 8 , 15 , 11 },
{2180 , 10 , 37 , 9 , 9 , 10 , 17 , 9 , 8 , 14 , 11 },
{2170 , 10 , 37 , 9 , 9 , 10 , 17 , 9 , 8 , 14 , 11 },
{2160 , 10 , 37 , 9 , 9 , 10 , 17 , 9 , 8 , 14 , 11 },
{2150 , 10 , 37 , 9 , 9 , 10 , 16 , 8 , 8 , 14 , 11 },
{2140 , 10 , 36 , 9 , 9 , 10 , 16 , 8 , 8 , 14 , 11 },
{2130 , 10 , 36 , 9 , 9 , 10 , 16 , 8 , 7 , 14 , 11 },
{2120 , 10 , 36 , 9 , 9 , 9 , 17 , 8 , 7 , 14 , 11 },
{2110 , 10 , 36 , 9 , 9 , 9 , 17 , 8 , 7 , 14 , 11 },
{2100 , 10 , 35 , 9 , 9 , 9 , 17 , 8 , 7 , 14 , 11 },
{2090 , 10 , 35 , 9 , 9 , 9 , 17 , 8 , 7 , 14 , 11 },
{2080 , 9 , 36 , 9 , 9 , 9 , 16 , 8 , 7 , 14 , 11 },
{2070 , 9 , 36 , 9 , 9 , 9 , 16 , 8 , 7 , 14 , 10 },
{2060 , 9 , 35 , 9 , 9 , 9 , 16 , 8 , 7 , 14 , 10 },
{2050 , 9 , 35 , 9 , 9 , 9 , 16 , 8 , 7 , 14 , 10 },
{2040 , 9 , 35 , 9 , 9 , 9 , 16 , 8 , 7 , 14 , 10 },
{2030 , 9 , 35 , 9 , 9 , 9 , 16 , 8 , 7 , 13 , 10 },
{2020 , 9 , 35 , 9 , 9 , 9 , 16 , 8 , 7 , 13 , 10 },
{2010 , 9 , 34 , 9 , 9 , 9 , 15 , 8 , 7 , 13 , 10 },
{2000 , 9 , 34 , 8 , 9 , 9 , 15 , 8 , 7 , 13 , 10 },
{1990 , 9 , 34 , 8 , 9 , 9 , 15 , 8 , 7 , 13 , 10 },
{1980 , 9 , 34 , 8 , 9 , 9 , 15 , 8 , 7 , 13 , 10 },
{1970 , 9 , 33 , 8 , 9 , 9 , 15 , 8 , 7 , 13 , 10 },
{1960 , 9 , 33 , 8 , 9 , 9 , 15 , 8 , 7 , 13 , 10 },
{1950 , 9 , 33 , 8 , 8 , 9 , 15 , 8 , 7 , 13 , 10 },
{1940 , 9 , 33 , 8 , 8 , 9 , 15 , 8 , 7 , 13 , 10 },
{1930 , 9 , 32 , 8 , 8 , 9 , 14 , 8 , 7 , 13 , 10 },
{1920 , 9 , 32 , 8 , 8 , 9 , 14 , 8 , 7 , 13 , 10 },
{1910 , 9 , 32 , 8 , 8 , 8 , 15 , 7 , 7 , 13 , 9 },
{1900 , 9 , 32 , 8 , 8 , 8 , 15 , 7 , 7 , 13 , 9 },
{1890 , 9 , 31 , 8 , 8 , 8 , 15 , 7 , 7 , 12 , 9 },
{1880 , 8 , 32 , 8 , 8 , 8 , 15 , 7 , 7 , 12 , 9 },
{1870 , 8 , 32 , 8 , 8 , 8 , 15 , 7 , 7 , 12 , 9 },
{1860 , 8 , 32 , 8 , 8 , 8 , 14 , 7 , 6 , 12 , 9 },
{1850 , 8 , 32 , 8 , 8 , 8 , 14 , 7 , 6 , 12 , 9 },
{1840 , 8 , 31 , 8 , 8 , 8 , 14 , 7 , 6 , 12 , 9 },
{1830 , 8 , 31 , 8 , 8 , 8 , 14 , 7 , 6 , 12 , 9 },
{1820 , 8 , 31 , 8 , 8 , 8 , 14 , 7 , 6 , 12 , 9 },
{1810 , 8 , 31 , 8 , 8 , 8 , 14 , 7 , 6 , 12 , 9 },
{1800 , 8 , 30 , 7 , 8 , 8 , 14 , 7 , 6 , 12 , 9 },
{1790 , 8 , 30 , 7 , 8 , 8 , 13 , 7 , 6 , 12 , 9 },
{1780 , 8 , 30 , 7 , 8 , 8 , 13 , 7 , 6 , 12 , 9 },
{1770 , 8 , 30 , 7 , 8 , 8 , 13 , 7 , 6 , 12 , 9 },
{1760 , 8 , 29 , 7 , 8 , 8 , 13 , 7 , 6 , 12 , 9 },
{1750 , 8 , 29 , 7 , 8 , 8 , 13 , 7 , 6 , 12 , 9 },
{1740 , 8 , 29 , 7 , 8 , 8 , 13 , 7 , 6 , 11 , 8 },
{1730 , 8 , 29 , 7 , 8 , 8 , 13 , 7 , 6 , 11 , 8 },
{1720 , 8 , 29 , 7 , 7 , 8 , 13 , 7 , 6 , 11 , 8 },
{1710 , 8 , 28 , 7 , 7 , 8 , 12 , 7 , 6 , 11 , 8 },
{1700 , 8 , 28 , 7 , 7 , 7 , 13 , 7 , 6 , 11 , 8 },
{1690 , 8 , 28 , 7 , 7 , 7 , 13 , 7 , 6 , 11 , 8 },
{1680 , 7 , 29 , 7 , 7 , 7 , 13 , 6 , 6 , 11 , 8 },
{1670 , 7 , 28 , 7 , 7 , 7 , 13 , 6 , 6 , 11 , 8 },
{1660 , 7 , 28 , 7 , 7 , 7 , 13 , 6 , 6 , 11 , 8 },
{1650 , 7 , 28 , 7 , 7 , 7 , 13 , 6 , 6 , 11 , 8 },
{1640 , 7 , 28 , 7 , 7 , 7 , 12 , 6 , 6 , 11 , 8 },
{1630 , 7 , 27 , 7 , 7 , 7 , 12 , 6 , 6 , 11 , 8 },
{1620 , 7 , 27 , 7 , 7 , 7 , 12 , 6 , 6 , 11 , 8 },
{1610 , 7 , 27 , 7 , 7 , 7 , 12 , 6 , 6 , 11 , 8 },
{1600 , 7 , 27 , 6 , 7 , 7 , 12 , 6 , 5 , 10 , 8 },
{1590 , 7 , 26 , 6 , 7 , 7 , 12 , 6 , 5 , 10 , 8 },
{1580 , 7 , 26 , 6 , 7 , 7 , 12 , 6 , 5 , 10 , 7 },
{1570 , 7 , 26 , 6 , 7 , 7 , 11 , 6 , 5 , 10 , 7 },
{1560 , 7 , 26 , 6 , 7 , 7 , 11 , 6 , 5 , 10 , 7 },
{1550 , 7 , 26 , 6 , 7 , 7 , 11 , 6 , 5 , 10 , 7 },
{1540 , 7 , 25 , 6 , 7 , 7 , 11 , 6 , 5 , 10 , 7 },
{1530 , 7 , 25 , 6 , 7 , 7 , 11 , 6 , 5 , 10 , 7 },
{1520 , 7 , 25 , 6 , 7 , 7 , 11 , 6 , 5 , 10 , 7 },
{1510 , 7 , 25 , 6 , 7 , 7 , 11 , 6 , 5 , 10 , 7 },
{1500 , 7 , 24 , 6 , 7 , 7 , 10 , 6 , 5 , 10 , 7 },
{1490 , 59 , 25 , 6 , 77 , 59 , 10 , 70 , 44 , 9 , 73 },
{1480 , 59 , 24 , 6 , 76 , 58 , 10 , 70 , 44 , 9 , 73 },
{1470 , 58 , 24 , 6 , 76 , 58 , 10 , 69 , 44 , 9 , 72 },
{1460 , 58 , 24 , 6 , 76 , 58 , 10 , 69 , 43 , 9 , 72 },
{1450 , 58 , 24 , 6 , 75 , 57 , 10 , 68 , 43 , 9 , 71 },
{1440 , 57 , 24 , 6 , 75 , 57 , 10 , 68 , 43 , 9 , 71 },
{1430 , 57 , 23 , 6 , 75 , 57 , 10 , 68 , 43 , 8 , 70 },
{1420 , 56 , 23 , 6 , 74 , 57 , 9 , 67 , 43 , 8 , 70 },
{1410 , 56 , 23 , 6 , 74 , 57 , 9 , 67 , 43 , 8 , 69 },
{1400 , 56 , 23 , 5 , 74 , 55 , 9 , 67 , 41 , 8 , 69 },
{1390 , 55 , 23 , 5 , 73 , 55 , 9 , 66 , 41 , 8 , 68 },
{1380 , 55 , 23 , 5 , 73 , 54 , 9 , 66 , 41 , 8 , 68 },
{1370 , 54 , 22 , 5 , 72 , 54 , 9 , 66 , 41 , 8 , 67 },
{1360 , 54 , 22 , 5 , 72 , 54 , 9 , 65 , 40 , 8 , 67 },
{1350 , 54 , 22 , 5 , 72 , 53 , 9 , 65 , 40 , 8 , 66 },
{1340 , 53 , 22 , 5 , 71 , 53 , 9 , 65 , 40 , 8 , 66 },
{1330 , 53 , 22 , 5 , 71 , 53 , 9 , 64 , 39 , 8 , 65 },
{1320 , 52 , 22 , 5 , 71 , 53 , 8 , 64 , 40 , 8 , 65 },
{1310 , 52 , 21 , 5 , 70 , 53 , 8 , 64 , 40 , 8 , 64 },
{1300 , 51 , 21 , 5 , 70 , 51 , 8 , 63 , 38 , 8 , 64 },
{1290 , 51 , 21 , 5 , 70 , 51 , 8 , 63 , 38 , 7 , 64 },
{1280 , 51 , 21 , 5 , 69 , 51 , 8 , 63 , 38 , 7 , 63 },
{1270 , 50 , 21 , 5 , 69 , 50 , 8 , 62 , 38 , 7 , 63 },
{1260 , 50 , 20 , 5 , 69 , 50 , 8 , 62 , 37 , 7 , 62 },
{1250 , 49 , 20 , 5 , 68 , 49 , 8 , 62 , 37 , 7 , 62 },
{1240 , 49 , 20 , 5 , 68 , 49 , 8 , 61 , 37 , 7 , 61 },
{1230 , 49 , 20 , 5 , 68 , 49 , 8 , 61 , 36 , 7 , 61 },
{1220 , 48 , 20 , 5 , 67 , 48 , 8 , 61 , 36 , 7 , 60 },
{1210 , 48 , 19 , 5 , 67 , 48 , 7 , 60 , 36 , 7 , 60 },
{1200 , 49 , 19 , 4 , 67 , 49 , 7 , 60 , 36 , 7 , 59 },
{1190 , 48 , 19 , 4 , 66 , 48 , 7 , 60 , 36 , 7 , 59 },
{1180 , 48 , 19 , 4 , 66 , 48 , 7 , 59 , 36 , 7 , 58 },
{1170 , 46 , 19 , 4 , 66 , 46 , 7 , 59 , 35 , 7 , 58 },
{1160 , 46 , 18 , 4 , 65 , 46 , 7 , 59 , 34 , 7 , 57 },
{1150 , 45 , 18 , 4 , 65 , 46 , 7 , 58 , 34 , 7 , 57 },
{1140 , 45 , 18 , 4 , 65 , 45 , 7 , 58 , 34 , 6 , 56 },
{1130 , 45 , 18 , 4 , 64 , 45 , 7 , 58 , 33 , 6 , 56 },
{1120 , 44 , 18 , 4 , 64 , 44 , 7 , 57 , 33 , 6 , 55 },
{1110 , 44 , 18 , 4 , 64 , 44 , 7 , 57 , 33 , 6 , 55 },
{1100 , 43 , 17 , 4 , 63 , 44 , 6 , 57 , 32 , 6 , 54 },
{1090 , 43 , 17 , 4 , 63 , 44 , 6 , 56 , 33 , 6 , 54 },
{1080 , 43 , 17 , 4 , 63 , 44 , 6 , 56 , 33 , 6 , 53 },
{1070 , 42 , 17 , 4 , 62 , 44 , 6 , 56 , 33 , 6 , 53 },
{1060 , 42 , 17 , 4 , 62 , 42 , 6 , 55 , 31 , 6 , 52 },
{1050 , 41 , 17 , 4 , 62 , 42 , 6 , 55 , 31 , 6 , 52 },
{1040 , 41 , 16 , 4 , 61 , 41 , 6 , 54 , 31 , 6 , 52 },
{1030 , 41 , 16 , 4 , 61 , 41 , 6 , 54 , 30 , 6 , 51 },
{1020 , 40 , 16 , 4 , 61 , 41 , 6 , 54 , 30 , 6 , 51 },
{1010 , 40 , 16 , 4 , 60 , 40 , 6 , 53 , 30 , 6 , 50 },
{1000 , 39 , 16 , 3 , 60 , 40 , 6 , 53 , 29 , 5 , 50 },
{ 990 , 39 , 15 , 3 , 60 , 39 , 6 , 53 , 29 , 5 , 49 },
{ 980 , 39 , 15 , 3 , 59 , 39 , 5 , 52 , 29 , 5 , 49 },
{ 970 , 38 , 15 , 3 , 59 , 39 , 5 , 52 , 29 , 5 , 48 },
{ 960 , 38 , 15 , 3 , 59 , 39 , 5 , 52 , 29 , 5 , 48 },
{ 950 , 37 , 15 , 3 , 58 , 39 , 5 , 51 , 29 , 5 , 47 },
{ 940 , 37 , 14 , 3 , 58 , 39 , 5 , 51 , 29 , 5 , 47 },
{ 930 , 37 , 14 , 3 , 57 , 37 , 5 , 51 , 27 , 5 , 46 },
{ 920 , 36 , 14 , 3 , 57 , 37 , 5 , 50 , 27 , 5 , 46 },
{ 910 , 36 , 14 , 3 , 57 , 36 , 5 , 50 , 27 , 5 , 45 },
{ 900 , 35 , 14 , 3 , 56 , 36 , 5 , 50 , 26 , 5 , 45 },
{ 890 , 35 , 14 , 3 , 56 , 36 , 5 , 49 , 26 , 5 , 44 },
{ 880 , 35 , 13 , 3 , 56 , 35 , 5 , 49 , 26 , 5 , 44 },
{ 870 , 34 , 13 , 3 , 55 , 35 , 4 , 49 , 26 , 5 , 43 },
{ 860 , 34 , 13 , 3 , 55 , 35 , 4 , 48 , 25 , 5 , 43 },
{ 850 , 33 , 13 , 3 , 55 , 35 , 4 , 48 , 26 , 4 , 42 },
{ 840 , 33 , 13 , 3 , 54 , 35 , 4 , 48 , 26 , 4 , 42 },
{ 830 , 33 , 12 , 3 , 54 , 33 , 4 , 47 , 24 , 4 , 41 },
{ 820 , 32 , 12 , 3 , 54 , 33 , 4 , 47 , 24 , 4 , 41 },
{ 810 , 32 , 12 , 3 , 53 , 33 , 4 , 47 , 24 , 4 , 40 },
{ 800 , 31 , 12 , 2 , 53 , 32 , 4 , 46 , 23 , 4 , 40 },
{ 790 , 31 , 12 , 2 , 53 , 32 , 4 , 46 , 23 , 4 , 39 },
{ 780 , 30 , 12 , 2 , 52 , 31 , 4 , 46 , 23 , 4 , 39 },
{ 770 , 30 , 11 , 2 , 52 , 31 , 4 , 45 , 23 , 4 , 39 },
{ 760 , 30 , 11 , 2 , 52 , 31 , 3 , 45 , 22 , 4 , 38 },
{ 750 , 29 , 11 , 2 , 51 , 30 , 3 , 45 , 22 , 4 , 38 },
{ 740 , 29 , 11 , 2 , 51 , 30 , 3 , 44 , 22 , 4 , 37 },
{ 730 , 28 , 11 , 2 , 51 , 31 , 3 , 44 , 22 , 4 , 37 },
{ 720 , 28 , 10 , 2 , 50 , 30 , 3 , 44 , 22 , 4 , 36 },
{ 710 , 28 , 10 , 2 , 50 , 30 , 3 , 43 , 22 , 4 , 36 },
{ 700 , 27 , 10 , 2 , 50 , 28 , 3 , 43 , 20 , 3 , 35 },
{ 690 , 27 , 10 , 2 , 49 , 28 , 3 , 43 , 20 , 3 , 35 },
{ 680 , 26 , 10 , 2 , 49 , 28 , 3 , 42 , 20 , 3 , 34 },
{ 670 , 26 , 10 , 2 , 49 , 27 , 3 , 42 , 20 , 3 , 34 },
{ 660 , 26 , 9 , 2 , 48 , 27 , 3 , 42 , 19 , 3 , 33 },
{ 650 , 25 , 9 , 2 , 48 , 26 , 3 , 41 , 19 , 3 , 33 },
{ 640 , 25 , 9 , 2 , 48 , 26 , 2 , 41 , 19 , 3 , 32 },
{ 630 , 24 , 9 , 2 , 47 , 26 , 2 , 40 , 18 , 3 , 32 },
{ 620 , 24 , 9 , 2 , 47 , 26 , 2 , 40 , 19 , 3 , 31 },
{ 610 , 24 , 8 , 2 , 47 , 26 , 2 , 40 , 19 , 3 , 31 },
{ 600 , 23 , 8 , 1 , 46 , 26 , 2 , 39 , 18 , 3 , 30 },
{ 590 , 23 , 8 , 1 , 46 , 24 , 2 , 39 , 17 , 3 , 30 },
{ 580 , 22 , 8 , 1 , 46 , 24 , 2 , 39 , 17 , 3 , 29 },
{ 570 , 22 , 8 , 1 , 45 , 23 , 2 , 38 , 17 , 3 , 29 },
{ 560 , 22 , 7 , 1 , 45 , 23 , 2 , 38 , 16 , 2 , 28 },
{ 550 , 21 , 7 , 1 , 45 , 23 , 2 , 38 , 16 , 2 , 28 },
{ 540 , 21 , 7 , 1 , 44 , 22 , 2 , 37 , 16 , 2 , 27 },
{ 530 , 20 , 7 , 1 , 44 , 22 , 1 , 37 , 15 , 2 , 27 },
{ 520 , 20 , 7 , 1 , 43 , 21 , 1 , 37 , 15 , 2 , 27 },
{ 510 , 20 , 6 , 1 , 43 , 21 , 1 , 36 , 15 , 2 , 26 },
{ 500 , 19 , 6 , 1 , 43 , 22 , 1 , 36 , 15 , 2 , 26 },
{ 490 , 19 , 6 , 1 , 42 , 21 , 1 , 36 , 15 , 2 , 25 },
{ 480 , 18 , 6 , 1 , 42 , 21 , 1 , 35 , 15 , 2 , 25 },
{ 470 , 18 , 6 , 1 , 42 , 21 , 1 , 35 , 15 , 2 , 24 },
{ 460 , 18 , 6 , 1 , 41 , 19 , 1 , 35 , 13 , 2 , 24 },
{ 450 , 17 , 5 , 1 , 41 , 19 , 1 , 34 , 13 , 2 , 23 },
{ 440 , 17 , 5 , 1 , 41 , 18 , 1 , 34 , 13 , 2 , 23 },
{ 430 , 16 , 5 , 1 , 40 , 18 , 0 , 34 , 12 , 2 , 22 },
{ 420 , 16 , 5 , 1 , 40 , 18 , 0 , 33 , 12 , 2 , 22 },
{ 410 , 16 , 5 , 1 , 40 , 17 , 0 , 33 , 12 , 1 , 21 },
{ 400 , 15 , 5 , 0 , 39 , 17 , 0 , 33 , 11 , 1 , 21 },
{ 390 , 15 , 4 , 0 , 39 , 17 , 0 , 32 , 12 , 1 , 20 },
{ 380 , 14 , 4 , 0 , 39 , 17 , 0 , 32 , 12 , 1 , 20 },
{ 370 , 14 , 4 , 0 , 38 , 17 , 0 , 32 , 12 , 1 , 19 },
{ 360 , 14 , 4 , 0 , 38 , 15 , 0 , 31 , 10 , 1 , 19 },
{ 350 , 13 , 4 , 0 , 38 , 15 , 0 , 31 , 10 , 1 , 18 },
{ 340 , 13 , 3 , 0 , 37 , 15 , 0 , 31 , 10 , 1 , 18 },
{ 330 , 12 , 3 , 0 , 37 , 14 , 0 , 30 , 9 , 1 , 17 },
{ 320 , 12 , 3 , 0 , 37 , 14 , 0 , 30 , 9 , 1 , 17 },
{ 310 , 12 , 3 , 0 , 36 , 13 , 0 , 30 , 9 , 1 , 16 },
{ 300 , 11 , 3 , 0 , 36 , 13 , 0 , 29 , 8 , 1 , 16 },
{ 290 , 11 , 2 , 0 , 36 , 13 , 0 , 29 , 8 , 1 , 15 },
{ 280 , 10 , 2 , 0 , 35 , 12 , 0 , 29 , 8 , 1 , 15 },
{ 270 , 10 , 2 , 0 , 35 , 12 , 0 , 28 , 8 , 0 , 14 },
{ 260 , 9 , 2 , 0 , 35 , 12 , 0 , 28 , 8 , 0 , 14 },
{ 250 , 9 , 2 , 0 , 34 , 12 , 0 , 28 , 8 , 0 , 14 },
{ 240 , 9 , 2 , 0 , 34 , 12 , 0 , 27 , 8 , 0 , 13 },
{ 230 , 8 , 1 , 0 , 34 , 10 , 0 , 27 , 6 , 0 , 13 },
{ 220 , 8 , 1 , 0 , 33 , 10 , 0 , 27 , 6 , 0 , 12 },
{ 210 , 7 , 1 , 0 , 33 , 10 , 0 , 26 , 6 , 0 , 12 },
{ 200 , 7 , 1 , 0 , 33 , 9 , 0 , 26 , 5 , 0 , 11 },
{ 190 , 7 , 1 , 0 , 32 , 9 , 0 , 25 , 5 , 0 , 11 },
{ 180 , 6 , 1 , 0 , 32 , 8 , 0 , 25 , 5 , 0 , 10 },
{ 170 , 6 , 0 , 0 , 32 , 8 , 0 , 25 , 5 , 0 , 10 },
{ 160 , 5 , 0 , 0 , 31 , 8 , 0 , 24 , 4 , 0 , 9 },
{ 150 , 5 , 0 , 0 , 31 , 8 , 0 , 24 , 5 , 0 , 9 },
{ 140 , 5 , 0 , 0 , 31 , 8 , 0 , 24 , 5 , 0 , 8 },
{ 130 , 4 , 0 , 0 , 30 , 6 , 0 , 23 , 3 , 0 , 8 },
{ 120 , 4 , 0 , 0 , 30 , 6 , 0 , 23 , 3 , 0 , 7 },
{ 110 , 3 , 0 , 0 , 30 , 6 , 0 , 23 , 3 , 0 , 7 },
{ 100 , 3 , 0 , 0 , 29 , 5 , 0 , 22 , 2 , 0 , 6 },
{ 90 , 3 , 0 , 0 , 29 , 5 , 0 , 22 , 2 , 0 , 6 },
{ 80 , 2 , 0 , 0 , 28 , 5 , 0 , 22 , 2 , 0 , 5 },
};
static void samsung_mipi_dcphy_bias_block_enable(struct samsung_mipi_dcphy *samsung)
{
regmap_write(samsung->regmap, BIAS_CON0, I_DEV_DIV_6 | I_RES_100_2UA);
regmap_write(samsung->regmap, BIAS_CON1, I_VBG_SEL_820MV | I_BGR_VREF_820MV |
I_LADDER_1_00V);
regmap_write(samsung->regmap, BIAS_CON2, REG_325M_325MV | REG_LP_400M_400MV |
REG_400M_400MV | REG_645M_645MV);
/* default output voltage select:
* dphy: 400mv
* cphy: 530mv
*/
regmap_update_bits(samsung->regmap, BIAS_CON4,
I_MUX_SEL_MASK, I_MUX_400MV);
}
static void samsung_mipi_dphy_lane_enable(struct samsung_mipi_dcphy *samsung)
{
regmap_write(samsung->regmap, DPHY_MC_GNR_CON1, T_PHY_READY(0 x2000));
regmap_update_bits(samsung->regmap, DPHY_MC_GNR_CON0,
PHY_ENABLE, PHY_ENABLE);
switch (samsung->lanes) {
case 4 :
regmap_write(samsung->regmap, DPHY_MD3_GNR_CON1,
T_PHY_READY(0 x2000));
regmap_update_bits(samsung->regmap, DPHY_MD3_GNR_CON0,
PHY_ENABLE, PHY_ENABLE);
fallthrough;
case 3 :
regmap_write(samsung->regmap, COMBO_MD2_GNR_CON1,
T_PHY_READY(0 x2000));
regmap_update_bits(samsung->regmap, COMBO_MD2_GNR_CON0,
PHY_ENABLE, PHY_ENABLE);
fallthrough;
case 2 :
regmap_write(samsung->regmap, COMBO_MD1_GNR_CON1,
T_PHY_READY(0 x2000));
regmap_update_bits(samsung->regmap, COMBO_MD1_GNR_CON0,
PHY_ENABLE, PHY_ENABLE);
fallthrough;
case 1 :
default :
regmap_write(samsung->regmap, COMBO_MD0_GNR_CON1,
T_PHY_READY(0 x2000));
regmap_update_bits(samsung->regmap, COMBO_MD0_GNR_CON0,
PHY_ENABLE, PHY_ENABLE);
break ;
}
}
static void samsung_mipi_dphy_lane_disable(struct samsung_mipi_dcphy *samsung)
{
switch (samsung->lanes) {
case 4 :
regmap_update_bits(samsung->regmap, DPHY_MD3_GNR_CON0,
PHY_ENABLE, 0 );
fallthrough;
case 3 :
regmap_update_bits(samsung->regmap, COMBO_MD2_GNR_CON0,
PHY_ENABLE, 0 );
fallthrough;
case 2 :
regmap_update_bits(samsung->regmap, COMBO_MD1_GNR_CON0,
PHY_ENABLE, 0 );
fallthrough;
case 1 :
default :
regmap_update_bits(samsung->regmap, COMBO_MD0_GNR_CON0,
PHY_ENABLE, 0 );
break ;
}
regmap_update_bits(samsung->regmap, DPHY_MC_GNR_CON0, PHY_ENABLE, 0 );
}
static void samsung_mipi_dcphy_pll_configure(struct samsung_mipi_dcphy *samsung)
{
regmap_update_bits(samsung->regmap, PLL_CON0, S_MASK | P_MASK,
S(samsung->pll.scaler) | P(samsung->pll.prediv));
if (samsung->pll.dsm < 0 ) {
u16 dsm_tmp;
/* Using opposite number subtraction to find complement */
dsm_tmp = abs(samsung->pll.dsm);
dsm_tmp = dsm_tmp - 1 ;
dsm_tmp ^= 0 xffff;
regmap_write(samsung->regmap, PLL_CON1, dsm_tmp);
} else {
regmap_write(samsung->regmap, PLL_CON1, samsung->pll.dsm);
}
regmap_update_bits(samsung->regmap, PLL_CON2,
M_MASK, M(samsung->pll.fbdiv));
if (samsung->pll.ssc_en) {
regmap_write(samsung->regmap, PLL_CON3,
MRR(samsung->pll.mrr) | MFR(samsung->pll.mfr));
regmap_update_bits(samsung->regmap, PLL_CON4, SSCG_EN, SSCG_EN);
}
regmap_write(samsung->regmap, PLL_CON5, RESET_N_SEL | PLL_ENABLE_SEL);
regmap_write(samsung->regmap, PLL_CON7, PLL_LOCK_CNT(0 xf000));
regmap_write(samsung->regmap, PLL_CON8, PLL_STB_CNT(0 xf000));
}
static int samsung_mipi_dcphy_pll_enable(struct samsung_mipi_dcphy *samsung)
{
u32 sts;
int ret;
regmap_update_bits(samsung->regmap, PLL_CON0, PLL_EN, PLL_EN);
ret = regmap_read_poll_timeout(samsung->regmap, PLL_STAT0,
sts, (sts & PLL_LOCK), 1000 , 20000 );
if (ret < 0 )
dev_err(samsung->dev, "DC-PHY pll failed to lock\n" );
return ret;
}
static void samsung_mipi_dcphy_pll_disable(struct samsung_mipi_dcphy *samsung)
{
regmap_update_bits(samsung->regmap, PLL_CON0, PLL_EN, 0 );
}
static const struct samsung_mipi_dphy_timing *
samsung_mipi_dphy_get_timing(struct samsung_mipi_dcphy *samsung)
{
const struct samsung_mipi_dphy_timing *timings;
unsigned int num_timings;
unsigned int lane_mbps = div64_ul(samsung->pll.rate, USEC_PER_SEC);
unsigned int i;
timings = samsung_mipi_dphy_timing_table;
num_timings = ARRAY_SIZE(samsung_mipi_dphy_timing_table);
for (i = num_timings; i > 1 ; i--)
if (lane_mbps <= timings[i - 1 ].max_lane_mbps)
break ;
return &timings[i - 1 ];
}
static unsigned long
samsung_mipi_dcphy_pll_round_rate(struct samsung_mipi_dcphy *samsung,
unsigned long prate, unsigned long rate,
u8 *prediv, u16 *fbdiv, int *dsm, u8 *scaler)
{
u32 max_fout = samsung->pdata->dphy_tx_max_lane_kbps;
u64 best_freq = 0 ;
u64 fin, fvco, fout;
u8 min_prediv, max_prediv;
u8 _prediv, best_prediv = 1 ;
u16 _fbdiv, best_fbdiv = 1 ;
u8 _scaler, best_scaler = 0 ;
u32 min_delta = UINT_MAX;
long _dsm, best_dsm = 0 ;
if (!prate) {
dev_err(samsung->dev, "parent rate of PLL can not be zero\n" );
return 0 ;
}
/*
* The PLL output frequency can be calculated using a simple formula:
* Fvco = ((m+k/65536) x 2 x Fin) / p
* Fout = ((m+k/65536) x 2 x Fin) / (p x 2^s)
*/
fin = div64_ul(prate, MSEC_PER_SEC);
while (!best_freq) {
fout = div64_ul(rate, MSEC_PER_SEC);
if (fout > max_fout)
fout = max_fout;
/* 0 ≤ S[2:0] ≤ 6 */
for (_scaler = 0 ; _scaler < 7 ; _scaler++) {
fvco = fout << _scaler;
/*
* 2600MHz ≤ FVCO ≤ 6600MHz
*/
if (fvco < 2600 * MSEC_PER_SEC || fvco > 6600 * MSEC_PER_SEC)
continue ;
/* 6MHz ≤ Fref(Fin / p) ≤ 30MHz */
min_prediv = DIV_ROUND_UP_ULL(fin, 30 * MSEC_PER_SEC);
max_prediv = DIV_ROUND_CLOSEST_ULL(fin, 6 * MSEC_PER_SEC);
for (_prediv = min_prediv; _prediv <= max_prediv; _prediv++) {
u64 delta, tmp;
_fbdiv = DIV_ROUND_CLOSEST_ULL(fvco * _prediv, 2 * fin);
/* 64 ≤ M[9:0] ≤ 1023 */
if (_fbdiv < 64 || _fbdiv > 1023 )
continue ;
/* -32767 ≤ K[15:0] ≤ 32767 */
_dsm = ((_prediv * fvco) - (2 * _fbdiv * fin));
_dsm = DIV_ROUND_UP_ULL(_dsm << 15 , fin);
if (abs(_dsm) > 32767 )
continue ;
tmp = DIV_ROUND_CLOSEST_ULL((_fbdiv * fin * 2 * 1000 ), _prediv);
tmp += DIV_ROUND_CLOSEST_ULL((_dsm * fin * 1000 ), _prediv << 15 );
delta = abs(fvco * MSEC_PER_SEC - tmp);
if (delta < min_delta) {
best_prediv = _prediv;
best_fbdiv = _fbdiv;
best_dsm = _dsm;
best_scaler = _scaler;
min_delta = delta;
best_freq = DIV_ROUND_CLOSEST_ULL(tmp, 1000 ) * MSEC_PER_SEC;
}
}
}
rate += 100 * MSEC_PER_SEC;
}
*prediv = best_prediv;
*fbdiv = best_fbdiv;
*dsm = (int )best_dsm & 0 xffff;
*scaler = best_scaler;
dev_dbg(samsung->dev, "p: %d, m: %d, dsm:%ld, scaler: %d\n" ,
best_prediv, best_fbdiv, best_dsm, best_scaler);
return best_freq >> best_scaler;
}
static void
samsung_mipi_dphy_clk_lane_timing_init(struct samsung_mipi_dcphy *samsung)
{
const struct samsung_mipi_dphy_timing *timing;
unsigned int lane_hs_rate = div64_ul(samsung->pll.rate, USEC_PER_SEC);
u32 val, res_up, res_down;
timing = samsung_mipi_dphy_get_timing(samsung);
regmap_write(samsung->regmap, DPHY_MC_GNR_CON0, 0 xf000);
/*
* The Drive-Strength / Voltage-Amplitude is adjusted by setting
* the Driver-Up Resistor and Driver-Down Resistor.
*/
res_up = samsung->pdata->dphy_hs_drv_res_cfg->clk_hs_drv_up_ohm;
res_down = samsung->pdata->dphy_hs_drv_res_cfg->clk_hs_drv_down_ohm;
val = EDGE_CON(7 ) | EDGE_CON_DIR(0 ) | EDGE_CON_EN |
RES_UP(res_up) | RES_DN(res_down);
regmap_write(samsung->regmap, DPHY_MC_ANA_CON0, val);
if (lane_hs_rate >= 4500 )
regmap_write(samsung->regmap, DPHY_MC_ANA_CON1, 0 x0001);
val = 0 ;
/*
* Divide-by-2 Clock from Serial Clock. Use this when data rate is under
* 1500Mbps, otherwise divide-by-16 Clock from Serial Clock
*/
if (lane_hs_rate < 1500 )
val = HSTX_CLK_SEL;
val |= T_LPX(timing->lpx);
/* T_LP_EXIT_SKEW/T_LP_ENTRY_SKEW unconfig */
regmap_write(samsung->regmap, DPHY_MC_TIME_CON0, val);
val = T_CLK_ZERO(timing->clk_zero) | T_CLK_PREPARE(timing->clk_prepare);
regmap_write(samsung->regmap, DPHY_MC_TIME_CON1, val);
val = T_HS_EXIT(timing->hs_exit) | T_CLK_TRAIL(timing->clk_trail_eot);
regmap_write(samsung->regmap, DPHY_MC_TIME_CON2, val);
val = T_CLK_POST(timing->clk_post);
regmap_write(samsung->regmap, DPHY_MC_TIME_CON3, val);
/* Escape Clock is 20.00MHz */
regmap_write(samsung->regmap, DPHY_MC_TIME_CON4, 0 x1f4);
/*
* skew calibration should be off, if the operation data rate is
* under 1.5Gbps or equal to 1.5Gbps.
*/
if (lane_hs_rate > 1500 )
regmap_write(samsung->regmap, DPHY_MC_DESKEW_CON0, 0 x9cb1);
}
static void
samsung_mipi_dphy_data_lane_timing_init(struct samsung_mipi_dcphy *samsung)
{
const struct samsung_mipi_dphy_timing *timing;
unsigned int lane_hs_rate = div64_ul(samsung->pll.rate, USEC_PER_SEC);
u32 val, res_up, res_down;
timing = samsung_mipi_dphy_get_timing(samsung);
/*
* The Drive-Strength / Voltage-Amplitude is adjusted by adjusting the
* Driver-Up Resistor and Driver-Down Resistor.
*/
res_up = samsung->pdata->dphy_hs_drv_res_cfg->data_hs_drv_up_ohm;
res_down = samsung->pdata->dphy_hs_drv_res_cfg->data_hs_drv_down_ohm;
val = EDGE_CON(7 ) | EDGE_CON_DIR(0 ) | EDGE_CON_EN |
RES_UP(res_up) | RES_DN(res_down);
regmap_write(samsung->regmap, COMBO_MD0_ANA_CON0, val);
regmap_write(samsung->regmap, COMBO_MD1_ANA_CON0, val);
regmap_write(samsung->regmap, COMBO_MD2_ANA_CON0, val);
regmap_write(samsung->regmap, DPHY_MD3_ANA_CON0, val);
if (lane_hs_rate >= 4500 ) {
regmap_write(samsung->regmap, COMBO_MD0_ANA_CON1, 0 x0001);
regmap_write(samsung->regmap, COMBO_MD1_ANA_CON1, 0 x0001);
regmap_write(samsung->regmap, COMBO_MD2_ANA_CON1, 0 x0001);
regmap_write(samsung->regmap, DPHY_MD3_ANA_CON1, 0 x0001);
}
val = 0 ;
/*
* Divide-by-2 Clock from Serial Clock. Use this when data rate is under
* 1500Mbps, otherwise divide-by-16 Clock from Serial Clock
*/
if (lane_hs_rate < 1500 )
val = HSTX_CLK_SEL;
val |= T_LPX(timing->lpx);
/* T_LP_EXIT_SKEW/T_LP_ENTRY_SKEW unconfig */
regmap_write(samsung->regmap, COMBO_MD0_TIME_CON0, val);
regmap_write(samsung->regmap, COMBO_MD1_TIME_CON0, val);
regmap_write(samsung->regmap, COMBO_MD2_TIME_CON0, val);
regmap_write(samsung->regmap, DPHY_MD3_TIME_CON0, val);
val = T_HS_ZERO(timing->hs_zero) | T_HS_PREPARE(timing->hs_prepare);
regmap_write(samsung->regmap, COMBO_MD0_TIME_CON1, val);
regmap_write(samsung->regmap, COMBO_MD1_TIME_CON1, val);
regmap_write(samsung->regmap, COMBO_MD2_TIME_CON1, val);
regmap_write(samsung->regmap, DPHY_MD3_TIME_CON1, val);
val = T_HS_EXIT(timing->hs_exit) | T_HS_TRAIL(timing->hs_trail_eot);
regmap_write(samsung->regmap, COMBO_MD0_TIME_CON2, val);
regmap_write(samsung->regmap, COMBO_MD1_TIME_CON2, val);
regmap_write(samsung->regmap, COMBO_MD2_TIME_CON2, val);
regmap_write(samsung->regmap, DPHY_MD3_TIME_CON2, val);
/* TTA-GET/TTA-GO Timing Counter register use default value */
val = T_TA_GET(0 x3) | T_TA_GO(0 x0);
regmap_write(samsung->regmap, COMBO_MD0_TIME_CON3, val);
regmap_write(samsung->regmap, COMBO_MD1_TIME_CON3, val);
regmap_write(samsung->regmap, COMBO_MD2_TIME_CON3, val);
regmap_write(samsung->regmap, DPHY_MD3_TIME_CON3, val);
/* Escape Clock is 20.00MHz */
regmap_write(samsung->regmap, COMBO_MD0_TIME_CON4, 0 x1f4);
regmap_write(samsung->regmap, COMBO_MD1_TIME_CON4, 0 x1f4);
regmap_write(samsung->regmap, COMBO_MD2_TIME_CON4, 0 x1f4);
regmap_write(samsung->regmap, DPHY_MD3_TIME_CON4, 0 x1f4);
}
static int samsung_mipi_dphy_power_on(struct samsung_mipi_dcphy *samsung)
{
int ret;
reset_control_assert(samsung->m_phy_rst);
samsung_mipi_dcphy_bias_block_enable(samsung);
samsung_mipi_dcphy_pll_configure(samsung);
samsung_mipi_dphy_clk_lane_timing_init(samsung);
samsung_mipi_dphy_data_lane_timing_init(samsung);
ret = samsung_mipi_dcphy_pll_enable(samsung);
if (ret < 0 )
return ret;
samsung_mipi_dphy_lane_enable(samsung);
reset_control_deassert(samsung->m_phy_rst);
/* The TSKEWCAL maximum is 100 µsec
* at initial calibration.
*/
usleep_range(100 , 110 );
return 0 ;
}
static int samsung_mipi_dcphy_power_on(struct phy *phy)
{
struct samsung_mipi_dcphy *samsung = phy_get_drvdata(phy);
reset_control_assert(samsung->apb_rst);
udelay(1 );
reset_control_deassert(samsung->apb_rst);
switch (samsung->type) {
case PHY_TYPE_DPHY:
return samsung_mipi_dphy_power_on(samsung);
default :
/* CPHY part to be implemented later */
return -EOPNOTSUPP;
}
return 0 ;
}
static int samsung_mipi_dcphy_power_off(struct phy *phy)
{
struct samsung_mipi_dcphy *samsung = phy_get_drvdata(phy);
switch (samsung->type) {
case PHY_TYPE_DPHY:
samsung_mipi_dphy_lane_disable(samsung);
break ;
default :
/* CPHY part to be implemented later */
return -EOPNOTSUPP;
}
samsung_mipi_dcphy_pll_disable(samsung);
return 0 ;
}
static int
samsung_mipi_dcphy_pll_ssc_modulation_calc(struct samsung_mipi_dcphy *samsung,
u8 *mfr, u8 *mrr)
{
unsigned long fin = div64_ul(clk_get_rate(samsung->ref_clk), MSEC_PER_SEC);
u16 prediv = samsung->pll.prediv;
u16 fbdiv = samsung->pll.fbdiv;
u16 min_mfr, max_mfr;
u16 _mfr, best_mfr = 0 ;
u16 mr, _mrr, best_mrr = 0 ;
/* 20KHz ≤ MF ≤ 150KHz */
max_mfr = DIV_ROUND_UP(fin, (20 * prediv) << 5 );
min_mfr = div64_ul(fin, ((150 * prediv) << 5 ));
/*0 ≤ mfr ≤ 255 */
if (max_mfr > 256 )
max_mfr = 256 ;
for (_mfr = min_mfr; _mfr < max_mfr; _mfr++) {
/* 1 ≤ mrr ≤ 31 */
for (_mrr = 1 ; _mrr < 32 ; _mrr++) {
mr = DIV_ROUND_UP(_mfr * _mrr * 100 , fbdiv << 6 );
/* 0 ≤ MR ≤ 5% */
if (mr > 5 )
continue ;
if (_mfr * _mrr < 513 ) {
best_mfr = _mfr;
best_mrr = _mrr;
break ;
}
}
}
if (best_mrr) {
*mfr = best_mfr & 0 xff;
*mrr = best_mrr & 0 x3f;
} else {
dev_err(samsung->dev, "failed to calc ssc parameter mfr and mrr\n" );
return -EINVAL;
}
return 0 ;
}
static void
samsung_mipi_dcphy_pll_calc_rate(struct samsung_mipi_dcphy *samsung,
unsigned long long rate)
{
unsigned long prate = clk_get_rate(samsung->ref_clk);
unsigned long fout;
u8 scaler = 0 , mfr = 0 , mrr = 0 ;
u16 fbdiv = 0 ;
u8 prediv = 1 ;
int dsm = 0 ;
int ret;
fout = samsung_mipi_dcphy_pll_round_rate(samsung, prate, rate,
&prediv, &fbdiv, &dsm,
&scaler);
dev_dbg(samsung->dev, "%s: fin=%lu, req_rate=%llu\n" ,
__func__, prate, rate);
dev_dbg(samsung->dev, "%s: fout=%lu, prediv=%u, fbdiv=%u\n" ,
__func__, fout, prediv, fbdiv);
samsung->pll.prediv = prediv;
samsung->pll.fbdiv = fbdiv;
samsung->pll.dsm = dsm;
samsung->pll.scaler = scaler;
samsung->pll.rate = fout;
/*
* All DPHY 2.0 compliant Transmitters shall support SSC operating above
* 2.5 Gbps
*/
if (fout > 2500000000 LL) {
ret = samsung_mipi_dcphy_pll_ssc_modulation_calc(samsung,
&mfr, &mrr);
if (!ret) {
samsung->pll.ssc_en = true ;
samsung->pll.mfr = mfr;
samsung->pll.mrr = mrr;
}
}
}
static int samsung_mipi_dcphy_configure(struct phy *phy,
union phy_configure_opts *opts)
{
struct samsung_mipi_dcphy *samsung = phy_get_drvdata(phy);
unsigned long long target_rate = opts->mipi_dphy.hs_clk_rate;
samsung->lanes = opts->mipi_dphy.lanes > 4 ? 4 : opts->mipi_dphy.lanes;
samsung_mipi_dcphy_pll_calc_rate(samsung, target_rate);
opts->mipi_dphy.hs_clk_rate = samsung->pll.rate;
return 0 ;
}
static int samsung_mipi_dcphy_init(struct phy *phy)
{
struct samsung_mipi_dcphy *samsung = phy_get_drvdata(phy);
return pm_runtime_resume_and_get(samsung->dev);
}
static int samsung_mipi_dcphy_exit(struct phy *phy)
{
struct samsung_mipi_dcphy *samsung = phy_get_drvdata(phy);
return pm_runtime_put(samsung->dev);
}
static const struct phy_ops samsung_mipi_dcphy_ops = {
.configure = samsung_mipi_dcphy_configure,
.power_on = samsung_mipi_dcphy_power_on,
.power_off = samsung_mipi_dcphy_power_off,
.init = samsung_mipi_dcphy_init,
.exit = samsung_mipi_dcphy_exit,
.owner = THIS_MODULE,
};
static const struct regmap_config samsung_mipi_dcphy_regmap_config = {
.name = "dcphy" ,
.reg_bits = 32 ,
.val_bits = 32 ,
.reg_stride = 4 ,
.max_register = 0 x10000,
};
static struct phy *samsung_mipi_dcphy_xlate(struct device *dev,
const struct of_phandle_args *args)
{
struct samsung_mipi_dcphy *samsung = dev_get_drvdata(dev);
if (args->args_count != 1 ) {
dev_err(dev, "invalid number of arguments\n" );
return ERR_PTR(-EINVAL);
}
if (samsung->type != PHY_NONE && samsung->type != args->args[0 ])
dev_warn(dev, "phy type select %d overwriting type %d\n" ,
args->args[0 ], samsung->type);
samsung->type = args->args[0 ];
return samsung->phy;
}
static int samsung_mipi_dcphy_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct samsung_mipi_dcphy *samsung;
struct phy_provider *phy_provider;
struct resource *res;
void __iomem *regs;
int ret;
samsung = devm_kzalloc(dev, sizeof (*samsung), GFP_KERNEL);
if (!samsung)
return -ENOMEM;
samsung->dev = dev;
samsung->pdata = device_get_match_data(dev);
platform_set_drvdata(pdev, samsung);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0 );
regs = devm_ioremap_resource(dev, res);
if (IS_ERR(regs))
return PTR_ERR(regs);
samsung->regmap = devm_regmap_init_mmio(dev, regs,
&samsung_mipi_dcphy_regmap_config);
if (IS_ERR(samsung->regmap))
return dev_err_probe(dev, PTR_ERR(samsung->regmap), "Failed to init regmap\n" );
samsung->grf_regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,grf" );
if (IS_ERR(samsung->grf_regmap))
return dev_err_probe(dev, PTR_ERR(samsung->grf_regmap),
"Unable to get rockchip,grf\n" );
samsung->ref_clk = devm_clk_get(dev, "ref" );
if (IS_ERR(samsung->ref_clk))
return dev_err_probe(dev, PTR_ERR(samsung->ref_clk),
"Failed to get reference clock\n" );
samsung->pclk = devm_clk_get(dev, "pclk" );
if (IS_ERR(samsung->pclk))
return dev_err_probe(dev, PTR_ERR(samsung->pclk), "Failed to get pclk\n" );
samsung->m_phy_rst = devm_reset_control_get(dev, "m_phy" );
if (IS_ERR(samsung->m_phy_rst))
return dev_err_probe(dev, PTR_ERR(samsung->m_phy_rst),
"Failed to get system m_phy_rst control\n" );
samsung->s_phy_rst = devm_reset_control_get(dev, "s_phy" );
if (IS_ERR(samsung->s_phy_rst))
return dev_err_probe(dev, PTR_ERR(samsung->s_phy_rst),
"Failed to get system s_phy_rst control\n" );
samsung->apb_rst = devm_reset_control_get(dev, "apb" );
if (IS_ERR(samsung->apb_rst))
return dev_err_probe(dev, PTR_ERR(samsung->apb_rst),
"Failed to get system apb_rst control\n" );
samsung->grf_apb_rst = devm_reset_control_get(dev, "grf" );
if (IS_ERR(samsung->grf_apb_rst))
return dev_err_probe(dev, PTR_ERR(samsung->grf_apb_rst),
"Failed to get system grf_apb_rst control\n" );
samsung->phy = devm_phy_create(dev, NULL, &samsung_mipi_dcphy_ops);
if (IS_ERR(samsung->phy))
return dev_err_probe(dev, PTR_ERR(samsung->phy), "Failed to create MIPI DC-PHY\n" );
phy_set_drvdata(samsung->phy, samsung);
ret = devm_pm_runtime_enable(dev);
if (ret)
return dev_err_probe(dev, ret, "Failed to enable runtime PM\n" );
phy_provider = devm_of_phy_provider_register(dev, samsung_mipi_dcphy_xlate);
if (IS_ERR(phy_provider))
return dev_err_probe(dev, PTR_ERR(phy_provider),
"Failed to register phy provider\n" );
return 0 ;
}
static __maybe_unused int samsung_mipi_dcphy_runtime_suspend(struct device *dev)
{
struct samsung_mipi_dcphy *samsung = dev_get_drvdata(dev);
clk_disable_unprepare(samsung->ref_clk);
clk_disable_unprepare(samsung->pclk);
return 0 ;
}
static __maybe_unused int samsung_mipi_dcphy_runtime_resume(struct device *dev)
{
struct samsung_mipi_dcphy *samsung = dev_get_drvdata(dev);
int ret;
ret = clk_prepare_enable(samsung->pclk);
if (ret) {
dev_err(samsung->dev, "Failed to enable pclk, %d\n" , ret);
return ret;
}
ret = clk_prepare_enable(samsung->ref_clk);
if (ret) {
dev_err(samsung->dev, "Failed to enable reference clock, %d\n" , ret);
clk_disable_unprepare(samsung->pclk);
return ret;
}
return 0 ;
}
static const struct dev_pm_ops samsung_mipi_dcphy_pm_ops = {
SET_RUNTIME_PM_OPS(samsung_mipi_dcphy_runtime_suspend,
samsung_mipi_dcphy_runtime_resume, NULL)
};
static const struct hs_drv_res_cfg rk3576_dphy_hs_drv_res_cfg = {
.clk_hs_drv_up_ohm = STRENGTH_52_OHM,
.clk_hs_drv_down_ohm = STRENGTH_52_OHM,
.data_hs_drv_up_ohm = STRENGTH_39_OHM,
.data_hs_drv_down_ohm = STRENGTH_39_OHM,
};
static const struct hs_drv_res_cfg rk3588_dphy_hs_drv_res_cfg = {
.clk_hs_drv_up_ohm = STRENGTH_34_OHM,
.clk_hs_drv_down_ohm = STRENGTH_34_OHM,
.data_hs_drv_up_ohm = STRENGTH_43_OHM,
.data_hs_drv_down_ohm = STRENGTH_43_OHM,
};
static const struct samsung_mipi_dcphy_plat_data rk3576_samsung_mipi_dcphy_plat_data = {
.dphy_hs_drv_res_cfg = &rk3576_dphy_hs_drv_res_cfg,
.dphy_tx_max_lane_kbps = 2500000 L,
};
static const struct samsung_mipi_dcphy_plat_data rk3588_samsung_mipi_dcphy_plat_data = {
.dphy_hs_drv_res_cfg = &rk3588_dphy_hs_drv_res_cfg,
.dphy_tx_max_lane_kbps = 4500000 L,
};
static const struct of_device_id samsung_mipi_dcphy_of_match[] = {
{
.compatible = "rockchip,rk3576-mipi-dcphy" ,
.data = &rk3576_samsung_mipi_dcphy_plat_data,
}, {
.compatible = "rockchip,rk3588-mipi-dcphy" ,
.data = &rk3588_samsung_mipi_dcphy_plat_data,
},
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, samsung_mipi_dcphy_of_match);
static struct platform_driver samsung_mipi_dcphy_driver = {
.driver = {
.name = "samsung-mipi-dcphy" ,
.of_match_table = samsung_mipi_dcphy_of_match,
.pm = &samsung_mipi_dcphy_pm_ops,
},
.probe = samsung_mipi_dcphy_probe,
};
module_platform_driver(samsung_mipi_dcphy_driver);
MODULE_AUTHOR("Guochun Huang <hero.huang@rock-chips.com>" );
MODULE_DESCRIPTION("Samsung MIPI DCPHY Driver" );
MODULE_LICENSE("GPL" );
Messung V0.5 in Prozent C=96 H=95 G=95