0001
0002
0003
0004
0005
0006
0007 #include <linux/errno.h>
0008 #include <linux/export.h>
0009 #include <linux/kernel.h>
0010 #include <linux/time64.h>
0011
0012 #include <linux/phy/phy.h>
0013 #include <linux/phy/phy-mipi-dphy.h>
0014
0015
0016
0017
0018
0019
0020 int phy_mipi_dphy_get_default_config(unsigned long pixel_clock,
0021 unsigned int bpp,
0022 unsigned int lanes,
0023 struct phy_configure_opts_mipi_dphy *cfg)
0024 {
0025 unsigned long long hs_clk_rate;
0026 unsigned long long ui;
0027
0028 if (!cfg)
0029 return -EINVAL;
0030
0031 hs_clk_rate = pixel_clock * bpp;
0032 do_div(hs_clk_rate, lanes);
0033
0034 ui = ALIGN(PSEC_PER_SEC, hs_clk_rate);
0035 do_div(ui, hs_clk_rate);
0036
0037 cfg->clk_miss = 0;
0038 cfg->clk_post = 60000 + 52 * ui;
0039 cfg->clk_pre = 8;
0040 cfg->clk_prepare = 38000;
0041 cfg->clk_settle = 95000;
0042 cfg->clk_term_en = 0;
0043 cfg->clk_trail = 60000;
0044 cfg->clk_zero = 262000;
0045 cfg->d_term_en = 0;
0046 cfg->eot = 0;
0047 cfg->hs_exit = 100000;
0048 cfg->hs_prepare = 40000 + 4 * ui;
0049 cfg->hs_zero = 105000 + 6 * ui;
0050 cfg->hs_settle = 85000 + 6 * ui;
0051 cfg->hs_skip = 40000;
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064 cfg->hs_trail = max(4 * 8 * ui, 60000 + 4 * 4 * ui);
0065
0066 cfg->init = 100;
0067 cfg->lpx = 50000;
0068 cfg->ta_get = 5 * cfg->lpx;
0069 cfg->ta_go = 4 * cfg->lpx;
0070 cfg->ta_sure = cfg->lpx;
0071 cfg->wakeup = 1000;
0072
0073 cfg->hs_clk_rate = hs_clk_rate;
0074 cfg->lanes = lanes;
0075
0076 return 0;
0077 }
0078 EXPORT_SYMBOL(phy_mipi_dphy_get_default_config);
0079
0080
0081
0082
0083
0084 int phy_mipi_dphy_config_validate(struct phy_configure_opts_mipi_dphy *cfg)
0085 {
0086 unsigned long long ui;
0087
0088 if (!cfg)
0089 return -EINVAL;
0090
0091 ui = ALIGN(PSEC_PER_SEC, cfg->hs_clk_rate);
0092 do_div(ui, cfg->hs_clk_rate);
0093
0094 if (cfg->clk_miss > 60000)
0095 return -EINVAL;
0096
0097 if (cfg->clk_post < (60000 + 52 * ui))
0098 return -EINVAL;
0099
0100 if (cfg->clk_pre < 8)
0101 return -EINVAL;
0102
0103 if (cfg->clk_prepare < 38000 || cfg->clk_prepare > 95000)
0104 return -EINVAL;
0105
0106 if (cfg->clk_settle < 95000 || cfg->clk_settle > 300000)
0107 return -EINVAL;
0108
0109 if (cfg->clk_term_en > 38000)
0110 return -EINVAL;
0111
0112 if (cfg->clk_trail < 60000)
0113 return -EINVAL;
0114
0115 if ((cfg->clk_prepare + cfg->clk_zero) < 300000)
0116 return -EINVAL;
0117
0118 if (cfg->d_term_en > (35000 + 4 * ui))
0119 return -EINVAL;
0120
0121 if (cfg->eot > (105000 + 12 * ui))
0122 return -EINVAL;
0123
0124 if (cfg->hs_exit < 100000)
0125 return -EINVAL;
0126
0127 if (cfg->hs_prepare < (40000 + 4 * ui) ||
0128 cfg->hs_prepare > (85000 + 6 * ui))
0129 return -EINVAL;
0130
0131 if ((cfg->hs_prepare + cfg->hs_zero) < (145000 + 10 * ui))
0132 return -EINVAL;
0133
0134 if ((cfg->hs_settle < (85000 + 6 * ui)) ||
0135 (cfg->hs_settle > (145000 + 10 * ui)))
0136 return -EINVAL;
0137
0138 if (cfg->hs_skip < 40000 || cfg->hs_skip > (55000 + 4 * ui))
0139 return -EINVAL;
0140
0141 if (cfg->hs_trail < max(8 * ui, 60000 + 4 * ui))
0142 return -EINVAL;
0143
0144 if (cfg->init < 100)
0145 return -EINVAL;
0146
0147 if (cfg->lpx < 50000)
0148 return -EINVAL;
0149
0150 if (cfg->ta_get != (5 * cfg->lpx))
0151 return -EINVAL;
0152
0153 if (cfg->ta_go != (4 * cfg->lpx))
0154 return -EINVAL;
0155
0156 if (cfg->ta_sure < cfg->lpx || cfg->ta_sure > (2 * cfg->lpx))
0157 return -EINVAL;
0158
0159 if (cfg->wakeup < 1000)
0160 return -EINVAL;
0161
0162 return 0;
0163 }
0164 EXPORT_SYMBOL(phy_mipi_dphy_config_validate);