+ return drm_edid;
+}
-static int analogix_dp_atomic_check(struct drm_connector *connector,
- struct drm_atomic_state *state)
+static int analogix_dp_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 analogix_dp_device *dp = to_dp(connector);
- struct drm_display_info *di = &connector->display_info;
- struct drm_connector_state *conn_state;
- struct drm_crtc_state *crtc_state;
+ struct analogix_dp_device *dp = to_dp(bridge);
+ struct drm_display_info *di = &conn_state->connector->display_info;
u32 mask = DRM_COLOR_FORMAT_YCBCR444 | DRM_COLOR_FORMAT_YCBCR422;
if (is_rockchip(dp->plat_data->dev_type)) {
@@ -905,35 +899,18 @@ static int analogix_dp_atomic_check(struct drm_connector
*connector,
}
}
- conn_state = drm_atomic_get_new_connector_state(state, connector);
- if (WARN_ON(!conn_state))
- return -ENODEV;
-
conn_state->self_refresh_aware = true;
- if (!conn_state->crtc)
- return 0;
-
- crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc);
- if (!crtc_state)
- return 0;
-
if (crtc_state->self_refresh_active && !dp->psr_supported)
return -EINVAL;
return 0;
}
-static const struct drm_connector_helper_funcs analogix_dp_connector_helper_funcs = {
- .get_modes = analogix_dp_get_modes,
- .best_encoder = analogix_dp_best_encoder,
- .atomic_check = analogix_dp_atomic_check,
-};
-
static enum drm_connector_status
-analogix_dp_detect(struct drm_connector *connector, bool force)
+analogix_dp_bridge_detect(struct drm_bridge *bridge, struct drm_connector
*connector)
{
- struct analogix_dp_device *dp = to_dp(connector);
+ struct analogix_dp_device *dp = to_dp(bridge);
enum drm_connector_status status = connector_status_disconnected;
if (dp->plat_data->panel)
@@ -945,21 +922,11 @@ analogix_dp_detect(struct drm_connector *connector, bool
force)
return status;
}
-static const struct drm_connector_funcs analogix_dp_connector_funcs = {
- .fill_modes = drm_helper_probe_single_connector_modes,
- .detect = analogix_dp_detect,
- .destroy = drm_connector_cleanup,
- .reset = drm_atomic_helper_connector_reset,
- .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
- .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
-};
-
static int analogix_dp_bridge_attach(struct drm_bridge *bridge,
struct drm_encoder *encoder,
enum drm_bridge_attach_flags flags)
{
struct analogix_dp_device *dp = to_dp(bridge);
- struct drm_connector *connector = NULL;
int ret = 0;
if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) {
@@ -967,31 +934,8 @@ static int analogix_dp_bridge_attach(struct drm_bridge
*bridge,
return -EINVAL;
}
- if (!dp->plat_data->next_bridge) {
- connector = &dp->connector;
- connector->polled = DRM_CONNECTOR_POLL_HPD;
-
- ret = drm_connector_init(dp->drm_dev, connector,
- &analogix_dp_connector_funcs,
- DRM_MODE_CONNECTOR_eDP);
- if (ret) {
- DRM_ERROR("Failed to initialize connector with drm\n");
- return ret;
- }
-
- drm_connector_helper_add(connector,
- &analogix_dp_connector_helper_funcs);
- drm_connector_attach_encoder(connector, encoder);
- }
-
- /*
- * NOTE: the connector registration is implemented in analogix
- * platform driver, that to say connector would be exist after
- * plat_data->attch return, that's why we record the connector
- * point after plat attached.
- */
if (dp->plat_data->attach) {
- ret = dp->plat_data->attach(dp->plat_data, bridge, connector);
+ ret = dp->plat_data->attach(dp->plat_data, bridge);
if (ret) {
DRM_ERROR("Failed at platform attach func\n");
return ret;
@@ -1095,14 +1039,21 @@ static int analogix_dp_set_bridge(struct
analogix_dp_device *dp)
}
static void analogix_dp_bridge_mode_set(struct drm_bridge *bridge,
+ struct drm_atomic_state *state,
const struct drm_display_mode *mode)
{
struct analogix_dp_device *dp = to_dp(bridge);
- struct drm_display_info *display_info = &dp->connector.display_info;
struct video_info *video = &dp->video_info;
struct device_node *dp_node = dp->dev->of_node;
+ struct drm_connector *connector;
+ struct drm_display_info *display_info;
int vic;
+ connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder);
+ if (!connector)
+ return;
+ display_info = &connector->display_info;
+
/* Input video interlaces & hsync pol & vsync pol */
video->interlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
video->v_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NVSYNC);
@@ -1186,7 +1137,7 @@ static void analogix_dp_bridge_atomic_enable(struct
drm_bridge *bridge,
new_crtc_state = drm_atomic_get_new_crtc_state(old_state, crtc);
if (!new_crtc_state)
return;
- analogix_dp_bridge_mode_set(bridge, &new_crtc_state->adjusted_mode);
+ analogix_dp_bridge_mode_set(bridge, old_state,
&new_crtc_state->adjusted_mode);
old_crtc_state = drm_atomic_get_old_crtc_state(old_state, crtc);
/* Not a full enable, just disable PSR and continue */
@@ -1302,7 +1253,11 @@ static const struct drm_bridge_funcs
analogix_dp_bridge_funcs = {
.atomic_enable = analogix_dp_bridge_atomic_enable,
.atomic_disable = analogix_dp_bridge_atomic_disable,
.atomic_post_disable = analogix_dp_bridge_atomic_post_disable,
+ .atomic_check = analogix_dp_bridge_atomic_check,
.attach = analogix_dp_bridge_attach,
+ .get_modes = analogix_dp_bridge_get_modes,
+ .edid_read = analogix_dp_bridge_edid_read,
+ .detect = analogix_dp_bridge_detect,
};
static int analogix_dp_dt_parse_pdata(struct analogix_dp_device *dp)
@@ -1532,6 +1487,7 @@ EXPORT_SYMBOL_GPL(analogix_dp_resume);
int analogix_dp_bind(struct analogix_dp_device *dp, struct drm_device *drm_dev)
{
+ struct drm_bridge *bridge = &dp->bridge;
int ret;
dp->drm_dev = drm_dev;
@@ -1545,7 +1501,23 @@ int analogix_dp_bind(struct analogix_dp_device *dp,
struct drm_device *drm_dev)
return ret;
}
- ret = drm_bridge_attach(dp->encoder, &dp->bridge, NULL, 0);
+ if (dp->plat_data->panel)
+ /* If the next is a panel, the EDID parsing is checked by the
panel driver */
+ bridge->ops = DRM_BRIDGE_OP_MODES | DRM_BRIDGE_OP_DETECT;
+ else if (dp->plat_data->next_bridge)
+ /* If the next is a bridge, the supported operations depend on
the next bridge */
+ bridge->ops = 0;