mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 03:15:31 +09:00
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:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user