phy: rockchip: mipi-dcphy: accurately set mipi channel rate to Kbps/Ksps level

take 1280x720@60Hz which pclk is 74.25Mhz as an example, the dsi
lane rate should set 445500 Kbps/lane(pclk x bpp = lane_rate x lanes)
when mipi work in no video burst pulse/event, therefore the PLL should
output the rate of Kbps/ksps level for normal display.

Signed-off-by: Guochun Huang <hero.huang@rock-chips.com>
Change-Id: I63bf5717e2da521b7af18d88c906b86e30a71488
This commit is contained in:
Guochun Huang
2022-03-04 09:35:52 +08:00
committed by Tao Huang
parent 93010da346
commit 937265ceff

View File

@@ -147,8 +147,8 @@
#define S_CPHY_MODE HIWORD_UPDATE(1, 3, 3)
#define M_CPHY_MODE HIWORD_UPDATE(1, 0, 0)
#define PSEC_PER_NSEC 1000L
#define PSECS_PER_SEC 1000000000000LL
#define MAX_DPHY_BW 4500000L
#define MAX_CPHY_BW 2000000L
struct samsung_mipi_dphy_timing {
unsigned int max_lane_mbps;
@@ -1419,9 +1419,9 @@ 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)
{
unsigned int max_fout = samsung->c_option ? 2000 : 4500;
unsigned long best_freq = 0;
unsigned int fin, fvco, fout;
u64 max_fout = samsung->c_option ? MAX_CPHY_BW : MAX_DPHY_BW;
u64 best_freq = 0;
u64 fin, fvco, fout;
u8 min_prediv, max_prediv;
u8 _prediv, best_prediv = 1;
u16 _fbdiv, best_fbdiv = 1;
@@ -1434,10 +1434,10 @@ samsung_mipi_dcphy_pll_round_rate(struct samsung_mipi_dcphy *samsung,
* 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, USEC_PER_SEC);
fin = div64_ul(prate, MSEC_PER_SEC);
while (!best_freq) {
fout = div64_ul(rate, USEC_PER_SEC);
fout = div64_ul(rate, MSEC_PER_SEC);
if (fout > max_fout)
fout = max_fout;
@@ -1448,15 +1448,15 @@ samsung_mipi_dcphy_pll_round_rate(struct samsung_mipi_dcphy *samsung,
/*
* 2600MHz FVCO 6600MHz
*/
if (fvco < 2600 || fvco > 6600)
if (fvco < 2600 * MSEC_PER_SEC || fvco > 6600 * MSEC_PER_SEC)
continue;
/* 6MHz ≤ Fref(Fin / p) ≤ 30MHz */
min_prediv = DIV_ROUND_UP(fin, 30);
max_prediv = fin / 6;
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++) {
u32 delta, tmp;
u64 delta, tmp;
_fbdiv = DIV_ROUND_CLOSEST_ULL(fvco * _prediv, 2 * fin);
@@ -1466,26 +1466,26 @@ samsung_mipi_dcphy_pll_round_rate(struct samsung_mipi_dcphy *samsung,
/* -32767 ≤ K[15:0] ≤ 32767 */
_dsm = ((_prediv * fvco) - (2 * _fbdiv * fin));
_dsm = DIV_ROUND_UP(_dsm << 15, 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 - tmp);
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) * USEC_PER_SEC;
best_freq = DIV_ROUND_CLOSEST_ULL(tmp, 1000) * MSEC_PER_SEC;
}
}
}
rate += USEC_PER_SEC;
rate += 100 * MSEC_PER_SEC;
}
*prediv = best_prediv;