.poweroff = &imx8qm_dsi_poweroff,
.clk_config = {
{ .id = CLK_CORE, .present = false },
- { .id = CLK_PIXEL, .present = true },
- { .id = CLK_BYPASS, .present = true },
{ .id = CLK_PHYREF, .present = true },
+ { .id = CLK_BYPASS, .present = true },
+ { .id = CLK_PIXEL, .present = true },
},
.ext_regs = IMX_REG_CSR,
.tx_ulps_reg = 0x00,
.poweroff = &imx8qxp_dsi_poweroff,
.clk_config = {
{ .id = CLK_CORE, .present = false },
- { .id = CLK_PIXEL, .present = true },
- { .id = CLK_BYPASS, .present = true },
{ .id = CLK_PHYREF, .present = true },
+ { .id = CLK_BYPASS, .present = true },
+ { .id = CLK_PIXEL, .present = true },
},
.ext_regs = IMX_REG_CSR,
.tx_ulps_reg = 0x30,
struct device *dev = dsi->dev;
const char *id;
struct clk *clk;
- unsigned long new_rate, cur_rate, phy_rate = 0;
+ unsigned long new_rate, cur_rate;
bool enabled;
size_t i;
- /*
- * PHY_REF rate should be set by the nwl-dsi bridge, depending on the
- * current mode used. We need that rate to set the PIXEL clock for
- * QM or QXP.
- */
- for (i = 0; i < dsi->clk_num; i++) {
- if (!dsi->clk_config[i].present)
- continue;
- id = dsi->clk_config[i].id;
- clk = dsi->clk_config[i].clk;
-
- if (!strcmp(id, CLK_BYPASS) || !strcmp(id, CLK_PHYREF)) {
- dsi->clk_config[i].rate = clk_get_rate(clk);
- phy_rate = dsi->clk_config[i].rate;
- break;
- }
- }
-
for (i = 0; i < dsi->clk_num; i++) {
if (!dsi->clk_config[i].present)
continue;
cur_rate = clk_get_rate(clk);
enabled = dsi->clk_config[i].enabled;
- if (!strcmp(id, CLK_PIXEL) && phy_rate)
- new_rate = phy_rate;
-
if (enable) {
if (enabled && new_rate != cur_rate)
clk_disable_unprepare(clk);
return true;
}
+static void imx_nwl_dsi_mode_set(struct imx_mipi_dsi *dsi,
+ struct drm_display_mode *mode)
+{ const char *id;
+ struct clk *clk;
+ size_t i;
+
+ for (i = 0; i < dsi->clk_num; i++) {
+ if (!dsi->clk_config[i].present)
+ continue;
+ id = dsi->clk_config[i].id;
+ clk = dsi->clk_config[i].clk;
+
+ /* Set bypass and pixel clocks to mode clock rate */
+ if (!strcmp(id, CLK_BYPASS) || !strcmp(id, CLK_PIXEL))
+ dsi->clk_config[i].rate = mode->crtc_clock * 1000;
+ }
+
+}
+
static int imx_nwl_dsi_encoder_atomic_check(struct drm_encoder *encoder,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
return !imx_nwl_dsi_mode_fixup(dsi, &crtc_state->adjusted_mode);
}
+static void imx_nwl_dsi_encoder_mode_set(struct drm_encoder *encoder,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ struct imx_mipi_dsi *dsi = encoder_to_dsi(encoder);
+
+ imx_nwl_dsi_mode_set(dsi, adjusted_mode);
+}
+
static const struct drm_encoder_helper_funcs
imx_nwl_dsi_encoder_helper_funcs = {
.enable = imx_nwl_dsi_encoder_enable,
.disable = imx_nwl_dsi_encoder_disable,
.atomic_check = imx_nwl_dsi_encoder_atomic_check,
+ .mode_set = imx_nwl_dsi_encoder_mode_set,
};
static void imx_nwl_dsi_encoder_destroy(struct drm_encoder *encoder)
return imx_nwl_dsi_mode_fixup(dsi, adjusted);
}
+static void imx_nwl_dsi_bridge_mode_set(struct drm_bridge *bridge,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted)
+{
+ struct imx_mipi_dsi *dsi = bridge->driver_private;
+
+ imx_nwl_dsi_mode_set(dsi, adjusted);
+}
+
static int imx_nwl_dsi_bridge_attach(struct drm_bridge *bridge)
{
struct imx_mipi_dsi *dsi = bridge->driver_private;
.enable = imx_nwl_dsi_bridge_enable,
.disable = imx_nwl_dsi_bridge_disable,
.mode_fixup = imx_nwl_dsi_bridge_mode_fixup,
+ .mode_set = imx_nwl_dsi_bridge_mode_set,
.attach = imx_nwl_dsi_bridge_attach,
.detach = imx_nwl_dsi_bridge_detach,
};