|
@@ -14,7 +14,14 @@
|
|
|
#include <drm/bridge/dw_mipi_dsi.h>
|
|
|
#include <video/mipi_display.h>
|
|
|
|
|
|
-/* DSI wrapper register & bit definitions */
|
|
|
+#define HWVER_130 0x31333000 /* IP version 1.30 */
|
|
|
+#define HWVER_131 0x31333100 /* IP version 1.31 */
|
|
|
+
|
|
|
+/* DSI digital registers & bit definitions */
|
|
|
+#define DSI_VERSION 0x00
|
|
|
+#define VERSION GENMASK(31, 8)
|
|
|
+
|
|
|
+/* DSI wrapper registers & bit definitions */
|
|
|
/* Note: registers are named as in the Reference Manual */
|
|
|
#define DSI_WCFGR 0x0400 /* Wrapper ConFiGuration Reg */
|
|
|
#define WCFGR_DSIM BIT(0) /* DSI Mode */
|
|
@@ -66,6 +73,9 @@ struct dw_mipi_dsi_stm {
|
|
|
void __iomem *base;
|
|
|
struct clk *pllref_clk;
|
|
|
struct dw_mipi_dsi *dsi;
|
|
|
+ u32 hw_version;
|
|
|
+ int lane_min_kbps;
|
|
|
+ int lane_max_kbps;
|
|
|
};
|
|
|
|
|
|
static inline void dsi_write(struct dw_mipi_dsi_stm *dsi, u32 reg, u32 val)
|
|
@@ -122,7 +132,8 @@ static int dsi_pll_get_clkout_khz(int clkin_khz, int idf, int ndiv, int odf)
|
|
|
return DIV_ROUND_CLOSEST(clkin_khz * ndiv, divisor);
|
|
|
}
|
|
|
|
|
|
-static int dsi_pll_get_params(int clkin_khz, int clkout_khz,
|
|
|
+static int dsi_pll_get_params(struct dw_mipi_dsi_stm *dsi,
|
|
|
+ int clkin_khz, int clkout_khz,
|
|
|
int *idf, int *ndiv, int *odf)
|
|
|
{
|
|
|
int i, o, n, n_min, n_max;
|
|
@@ -132,8 +143,8 @@ static int dsi_pll_get_params(int clkin_khz, int clkout_khz,
|
|
|
if (clkin_khz <= 0 || clkout_khz <= 0)
|
|
|
return -EINVAL;
|
|
|
|
|
|
- fvco_min = LANE_MIN_KBPS * 2 * ODF_MAX;
|
|
|
- fvco_max = LANE_MAX_KBPS * 2 * ODF_MIN;
|
|
|
+ fvco_min = dsi->lane_min_kbps * 2 * ODF_MAX;
|
|
|
+ fvco_max = dsi->lane_max_kbps * 2 * ODF_MIN;
|
|
|
|
|
|
best_delta = 1000000; /* big started value (1000000khz) */
|
|
|
|
|
@@ -213,6 +224,15 @@ dw_mipi_dsi_get_lane_mbps(void *priv_data, struct drm_display_mode *mode,
|
|
|
int ret, bpp;
|
|
|
u32 val;
|
|
|
|
|
|
+ /* Update lane capabilities according to hw version */
|
|
|
+ dsi->hw_version = dsi_read(dsi, DSI_VERSION) & VERSION;
|
|
|
+ dsi->lane_min_kbps = LANE_MIN_KBPS;
|
|
|
+ dsi->lane_max_kbps = LANE_MAX_KBPS;
|
|
|
+ if (dsi->hw_version == HWVER_131) {
|
|
|
+ dsi->lane_min_kbps *= 2;
|
|
|
+ dsi->lane_max_kbps *= 2;
|
|
|
+ }
|
|
|
+
|
|
|
pll_in_khz = (unsigned int)(clk_get_rate(dsi->pllref_clk) / 1000);
|
|
|
|
|
|
/* Compute requested pll out */
|
|
@@ -220,12 +240,12 @@ dw_mipi_dsi_get_lane_mbps(void *priv_data, struct drm_display_mode *mode,
|
|
|
pll_out_khz = mode->clock * bpp / lanes;
|
|
|
/* Add 20% to pll out to be higher than pixel bw (burst mode only) */
|
|
|
pll_out_khz = (pll_out_khz * 12) / 10;
|
|
|
- if (pll_out_khz > LANE_MAX_KBPS) {
|
|
|
- pll_out_khz = LANE_MAX_KBPS;
|
|
|
+ if (pll_out_khz > dsi->lane_max_kbps) {
|
|
|
+ pll_out_khz = dsi->lane_max_kbps;
|
|
|
DRM_WARN("Warning max phy mbps is used\n");
|
|
|
}
|
|
|
- if (pll_out_khz < LANE_MIN_KBPS) {
|
|
|
- pll_out_khz = LANE_MIN_KBPS;
|
|
|
+ if (pll_out_khz < dsi->lane_min_kbps) {
|
|
|
+ pll_out_khz = dsi->lane_min_kbps;
|
|
|
DRM_WARN("Warning min phy mbps is used\n");
|
|
|
}
|
|
|
|
|
@@ -233,7 +253,8 @@ dw_mipi_dsi_get_lane_mbps(void *priv_data, struct drm_display_mode *mode,
|
|
|
idf = 0;
|
|
|
ndiv = 0;
|
|
|
odf = 0;
|
|
|
- ret = dsi_pll_get_params(pll_in_khz, pll_out_khz, &idf, &ndiv, &odf);
|
|
|
+ ret = dsi_pll_get_params(dsi, pll_in_khz, pll_out_khz,
|
|
|
+ &idf, &ndiv, &odf);
|
|
|
if (ret)
|
|
|
DRM_WARN("Warning dsi_pll_get_params(): bad params\n");
|
|
|
|