diff --git a/drivers/gpu/drm/bridge/nwl-dsi.c b/drivers/gpu/drm/bridge/nwl-dsi.c index 2a6ac6a085d52976299c4640e9b7cd925004948c..9e1d4141803f41156cedaab7739f62b3c19b4611 100644 --- a/drivers/gpu/drm/bridge/nwl-dsi.c +++ b/drivers/gpu/drm/bridge/nwl-dsi.c @@ -24,6 +24,7 @@ #include <linux/time64.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_atomic_state_helper.h> #include <drm/drm_bridge.h> #include <drm/drm_mipi_dsi.h> #include <drm/drm_of.h> @@ -841,7 +842,9 @@ static int nwl_dsi_disable(struct nwl_dsi *dsi) return 0; } -static void nwl_dsi_bridge_disable(struct drm_bridge *bridge) +static void +nwl_dsi_bridge_atomic_disable(struct drm_bridge *bridge, + struct drm_bridge_state *old_bridge_state) { struct nwl_dsi *dsi = bridge_to_dsi(bridge); int ret; @@ -1106,29 +1109,63 @@ static int nwl_dsi_get_dphy_params(struct nwl_dsi *dsi, return 0; } -static bool nwl_dsi_bridge_mode_fixup(struct drm_bridge *bridge, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted) +static enum drm_mode_status +nwl_dsi_bridge_mode_valid(struct drm_bridge *bridge, + const struct drm_display_info *info, + const struct drm_display_mode *mode) { struct nwl_dsi *dsi = bridge_to_dsi(bridge); struct mode_config *config; unsigned long pll_rate; + int bit_rate; + + bit_rate = nwl_dsi_get_bit_clock(dsi, mode->clock * 1000, dsi->lanes); + + DRM_DEV_DEBUG_DRIVER(dsi->dev, "Validating mode:"); + drm_mode_debug_printmodeline(mode); + + if (bit_rate > MBPS(1500)) + return MODE_CLOCK_HIGH; + + if (bit_rate < MBPS(80)) + return MODE_CLOCK_LOW; + + config = nwl_dsi_mode_probe(dsi, mode); + if (!config) + return MODE_NOCLOCK; + + pll_rate = config->pll_rates[config->phy_rate_idx]; + if (dsi->pll_clk && !pll_rate) + nwl_dsi_setup_pll_config(config, dsi->clk_drop_lvl); + + return MODE_OK; +} + +static int nwl_dsi_bridge_atomic_check(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + struct drm_display_mode *adjusted = &crtc_state->adjusted_mode; + struct nwl_dsi *dsi = bridge_to_dsi(bridge); + struct mode_config *config; + unsigned long pll_rate; DRM_DEV_DEBUG_DRIVER(dsi->dev, "Fixup mode:\n"); drm_mode_debug_printmodeline(adjusted); config = nwl_dsi_mode_probe(dsi, adjusted); if (!config) - return false; + return -EINVAL; DRM_DEV_DEBUG_DRIVER(dsi->dev, "lanes=%u, data_rate=%lu\n", config->lanes, config->bitclock); if (config->lanes < 2 || config->lanes > 4) - return false; + return -EINVAL; /* Max data rate for this controller is 1.5Gbps */ if (config->bitclock > 1500000000) - return false; + return -EINVAL; pll_rate = config->pll_rates[config->phy_rate_idx]; if (dsi->pll_clk && pll_rate) { @@ -1160,39 +1197,11 @@ static bool nwl_dsi_bridge_mode_fixup(struct drm_bridge *bridge, adjusted->flags |= (DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC); } - return true; -} - -static enum drm_mode_status -nwl_dsi_bridge_mode_valid(struct drm_bridge *bridge, - const struct drm_display_info *info, - const struct drm_display_mode *mode) -{ - struct nwl_dsi *dsi = bridge_to_dsi(bridge); - struct mode_config *config; - unsigned long pll_rate; - int bit_rate; - - bit_rate = nwl_dsi_get_bit_clock(dsi, mode->clock * 1000, dsi->lanes); - - DRM_DEV_DEBUG_DRIVER(dsi->dev, "Validating mode:"); - drm_mode_debug_printmodeline(mode); + /* Do a full modeset if crtc_state->active is changed to be true. */ + if (crtc_state->active_changed && crtc_state->active) + crtc_state->mode_changed = true; - if (bit_rate > MBPS(1500)) - return MODE_CLOCK_HIGH; - - if (bit_rate < MBPS(80)) - return MODE_CLOCK_LOW; - - config = nwl_dsi_mode_probe(dsi, mode); - if (!config) - return MODE_NOCLOCK; - - pll_rate = config->pll_rates[config->phy_rate_idx]; - if (dsi->pll_clk && !pll_rate) - nwl_dsi_setup_pll_config(config, dsi->clk_drop_lvl); - - return MODE_OK; + return 0; } static void @@ -1250,7 +1259,9 @@ nwl_dsi_bridge_mode_set(struct drm_bridge *bridge, memcpy(&dsi->phy_cfg, &new_cfg, sizeof(new_cfg)); } -static void nwl_dsi_bridge_pre_enable(struct drm_bridge *bridge) +static void +nwl_dsi_bridge_atomic_pre_enable(struct drm_bridge *bridge, + struct drm_bridge_state *old_bridge_state) { struct nwl_dsi *dsi = bridge_to_dsi(bridge); int ret; @@ -1296,7 +1307,9 @@ static void nwl_dsi_bridge_pre_enable(struct drm_bridge *bridge) drm_bridge_chain_enable(dsi->panel_bridge); } -static void nwl_dsi_bridge_enable(struct drm_bridge *bridge) +static void +nwl_dsi_bridge_atomic_enable(struct drm_bridge *bridge, + struct drm_bridge_state *old_bridge_state) { struct nwl_dsi *dsi = bridge_to_dsi(bridge); int ret; @@ -1364,14 +1377,17 @@ static void nwl_dsi_bridge_detach(struct drm_bridge *bridge) } static const struct drm_bridge_funcs nwl_dsi_bridge_funcs = { - .pre_enable = nwl_dsi_bridge_pre_enable, - .enable = nwl_dsi_bridge_enable, - .disable = nwl_dsi_bridge_disable, - .mode_fixup = nwl_dsi_bridge_mode_fixup, - .mode_set = nwl_dsi_bridge_mode_set, - .mode_valid = nwl_dsi_bridge_mode_valid, - .attach = nwl_dsi_bridge_attach, - .detach = nwl_dsi_bridge_detach, + .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, + .atomic_reset = drm_atomic_helper_bridge_reset, + .atomic_check = nwl_dsi_bridge_atomic_check, + .atomic_pre_enable = nwl_dsi_bridge_atomic_pre_enable, + .atomic_enable = nwl_dsi_bridge_atomic_enable, + .atomic_disable = nwl_dsi_bridge_atomic_disable, + .mode_set = nwl_dsi_bridge_mode_set, + .mode_valid = nwl_dsi_bridge_mode_valid, + .attach = nwl_dsi_bridge_attach, + .detach = nwl_dsi_bridge_detach, }; static void nwl_dsi_encoder_destroy(struct drm_encoder *encoder)