Loading msm/dp/dp_aux.c +7 −1 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. */ Loading Loading @@ -771,11 +772,16 @@ static int dp_aux_configure_aux_switch(struct dp_aux *dp_aux, aux = container_of(dp_aux, struct dp_aux_private, dp_aux); if (!aux->aux_switch_node) { DP_DEBUG("undefined fsa4480 handle\n"); DP_DEBUG("undefined aux switch handle\n"); rc = -EINVAL; goto end; } if (strcmp(aux->aux_switch_node->name, "fsa4480")) { DP_DEBUG("Not an fsa4480 aux switch\n"); goto end; } if (enable) { switch (orientation) { case ORIENTATION_CC1: Loading msm/dp/dp_debug.c +2 −0 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ Loading Loading @@ -2284,6 +2285,7 @@ struct dp_debug *dp_debug_get(struct dp_debug_in *in) dp_debug->dp_mst_connector_list.con_id = -1; dp_debug->dp_mst_connector_list.conn = NULL; dp_debug->dp_mst_connector_list.debug_en = false; mutex_init(&dp_debug->dp_mst_connector_list.lock); dp_debug->max_pclk_khz = debug->parser->max_pclk_khz; Loading msm/dp/dp_display.c +109 −40 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ Loading Loading @@ -721,6 +722,11 @@ static void dp_display_send_hpd_event(struct dp_display_private *dp) kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, envp); if (dev->mode_config.funcs->output_poll_changed) dev->mode_config.funcs->output_poll_changed(dev); drm_client_dev_hotplug(dev); if (connector->status == connector_status_connected) { dp_display_state_add(DP_STATE_CONNECT_NOTIFIED); dp_display_state_remove(DP_STATE_DISCONNECT_NOTIFIED); Loading Loading @@ -976,6 +982,8 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp) dp->dp_display.max_pclk_khz = min(dp->parser->max_pclk_khz, dp->debug->max_pclk_khz); dp->dp_display.max_hdisplay = dp->parser->max_hdisplay; dp->dp_display.max_vdisplay = dp->parser->max_vdisplay; /* * If dp video session is not restored from a previous session teardown Loading Loading @@ -2316,43 +2324,22 @@ static int dp_display_unprepare(struct dp_display *dp_display, void *panel) return 0; } static enum drm_mode_status dp_display_validate_mode( static int dp_display_validate_resources( struct dp_display *dp_display, void *panel, struct drm_display_mode *mode, const struct msm_resource_caps_info *avail_res) { struct dp_display_private *dp; u32 mode_rate_khz = 0, supported_rate_khz = 0, mode_bpp = 0; struct dp_panel *dp_panel; struct dp_debug *debug; enum drm_mode_status mode_status = MODE_BAD; bool in_list = false; struct dp_mst_connector *mst_connector; int hdis, vdis, vref, ar, _hdis, _vdis, _vref, _ar, rate; struct dp_display_mode dp_mode; u32 mode_rate_khz, supported_rate_khz, mode_bpp, num_lm; int rc, tmds_max_clock, rate; bool dsc_en; u32 num_lm = 0; int rc = 0, tmds_max_clock = 0; if (!dp_display || !mode || !panel || !avail_res || !avail_res->max_mixer_width) { DP_ERR("invalid params\n"); return mode_status; } dp = container_of(dp_display, struct dp_display_private, dp_display); mutex_lock(&dp->session_lock); dp_panel = panel; if (!dp_panel->connector) { DP_ERR("invalid connector\n"); goto end; } debug = dp->debug; if (!debug) goto end; dp_display->convert_to_dp_mode(dp_display, panel, mode, &dp_mode); Loading @@ -2366,36 +2353,65 @@ static enum drm_mode_status dp_display_validate_mode( tmds_max_clock = dp_panel->connector->display_info.max_tmds_clock; if (mode_rate_khz > supported_rate_khz) { DP_MST_DEBUG("pclk:%d, supported_rate:%d\n", DP_DEBUG("pclk:%d, supported_rate:%d\n", mode->clock, supported_rate_khz); goto end; return -EINVAL; } if (mode->clock > dp_display->max_pclk_khz) { DP_MST_DEBUG("clk:%d, max:%d\n", mode->clock, DP_DEBUG("clk:%d, max:%d\n", mode->clock, dp_display->max_pclk_khz); goto end; return -EINVAL; } if ((dp_display->max_hdisplay > 0) && (dp_display->max_vdisplay > 0) && ((mode->hdisplay > dp_display->max_hdisplay) || (mode->vdisplay > dp_display->max_vdisplay))) { DP_DEBUG("hdisplay:%d, max-hdisplay:%d", mode->hdisplay, dp_display->max_hdisplay); DP_DEBUG("vdisplay:%d, max-vdisplay:%d\n", mode->vdisplay, dp_display->max_vdisplay); return -EINVAL; } if (tmds_max_clock > 0 && mode->clock > tmds_max_clock) { DP_MST_DEBUG("clk:%d, max tmds:%d\n", mode->clock, DP_DEBUG("clk:%d, max tmds:%d\n", mode->clock, tmds_max_clock); goto end; return -EINVAL; } rc = msm_get_mixer_count(dp->priv, mode, avail_res, &num_lm); if (rc) { DP_ERR("error getting mixer count. rc:%d\n", rc); goto end; return -EINVAL; } if (num_lm > avail_res->num_lm || (num_lm == 2 && !avail_res->num_3dmux)) { DP_MST_DEBUG("num_lm:%d, req lm:%d 3dmux:%d\n", num_lm, DP_DEBUG("num_lm:%d, req lm:%d 3dmux:%d\n", num_lm, avail_res->num_lm, avail_res->num_3dmux); goto end; return -EINVAL; } return 0; } static int dp_display_check_overrides( struct dp_display *dp_display, void *panel, struct drm_display_mode *mode, const struct msm_resource_caps_info *avail_res) { struct dp_mst_connector *mst_connector; struct dp_display_private *dp; struct dp_panel *dp_panel; struct dp_debug *debug; bool in_list = false; int hdis, vdis, vref, ar, _hdis, _vdis, _vref, _ar; dp = container_of(dp_display, struct dp_display_private, dp_display); dp_panel = panel; debug = dp->debug; /* * If the connector exists in the mst connector list and if debug is * enabled for that connector, use the mst connector settings from the Loading @@ -2404,6 +2420,7 @@ static enum drm_mode_status dp_display_validate_mode( mutex_lock(&debug->dp_mst_connector_list.lock); if (list_empty(&debug->dp_mst_connector_list.list)) { DP_MST_DEBUG("MST connect list is empty\n"); mutex_unlock(&debug->dp_mst_connector_list.lock); goto verify_default; } Loading @@ -2414,10 +2431,9 @@ static enum drm_mode_status dp_display_validate_mode( in_list = true; if (!mst_connector->debug_en) { mode_status = MODE_OK; mutex_unlock( &debug->dp_mst_connector_list.lock); goto end; return 0; } hdis = mst_connector->hdisplay; Loading @@ -2432,28 +2448,76 @@ static enum drm_mode_status dp_display_validate_mode( if (hdis == _hdis && vdis == _vdis && vref == _vref && ar == _ar) { mode_status = MODE_OK; mutex_unlock( &debug->dp_mst_connector_list.lock); goto end; return 0; } break; } } mutex_unlock(&debug->dp_mst_connector_list.lock); if (in_list) goto end; return -EINVAL; verify_default: if (debug->debug_en && (mode->hdisplay != debug->hdisplay || mode->vdisplay != debug->vdisplay || mode->vrefresh != debug->vrefresh || mode->picture_aspect_ratio != debug->aspect_ratio)) return -EINVAL; return 0; } static enum drm_mode_status dp_display_validate_mode( struct dp_display *dp_display, void *panel, struct drm_display_mode *mode, const struct msm_resource_caps_info *avail_res) { struct dp_display_private *dp; struct dp_panel *dp_panel; struct dp_debug *debug; enum drm_mode_status mode_status = MODE_BAD; if (!dp_display || !mode || !panel || !avail_res || !avail_res->max_mixer_width) { DP_ERR("invalid params\n"); return mode_status; } dp = container_of(dp_display, struct dp_display_private, dp_display); mutex_lock(&dp->session_lock); dp_panel = panel; if (!dp_panel->connector) { DP_ERR("invalid connector\n"); goto end; } debug = dp->debug; if (!debug) { DP_ERR("invalid debug node\n"); goto end; } if (dp_display_validate_resources(dp_display, panel, mode, avail_res)) { DP_DEBUG("DP bad mode %dx%d@%d\n", mode->hdisplay, mode->vdisplay, mode->clock); goto end; } if (dp_display_check_overrides(dp_display, panel, mode, avail_res)) { DP_MST_DEBUG("DP overrides ignore mode %dx%d@%d\n", mode->hdisplay, mode->vdisplay, mode->clock); goto end; } DP_DEBUG("DP ok mode %dx%d@%d\n", mode->hdisplay, mode->vdisplay, mode->clock); mode_status = MODE_OK; end: mutex_unlock(&dp->session_lock); Loading Loading @@ -2656,6 +2720,11 @@ static int dp_display_init_aux_switch(struct dp_display_private *dp) goto end; } if (strcmp(dp->aux_switch_node->name, "fsa4480")) { DP_DEBUG("Not an fsa4480 aux switch\n"); goto end; } nb.notifier_call = dp_display_fsa4480_callback; nb.priority = 0; Loading msm/dp/dp_display.h +3 −0 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ Loading Loading @@ -70,6 +71,8 @@ struct dp_display { bool is_sst_connected; bool is_mst_supported; u32 max_pclk_khz; u32 max_hdisplay; u32 max_vdisplay; u32 no_mst_encoder; void *dp_mst_prv_info; bool is_primary; Loading msm/dp/dp_parser.c +11 −0 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. */ Loading Loading @@ -170,6 +171,16 @@ static int dp_parser_misc(struct dp_parser *parser) if (!parser->display_type) parser->display_type = "unknown"; rc = of_property_read_u32(of_node, "qcom,max-hdisplay", &parser->max_hdisplay); if (rc) parser->max_hdisplay = 0; rc = of_property_read_u32(of_node, "qcom,max-vdisplay", &parser->max_vdisplay); if (rc) parser->max_vdisplay = 0; return 0; } Loading Loading
msm/dp/dp_aux.c +7 −1 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. */ Loading Loading @@ -771,11 +772,16 @@ static int dp_aux_configure_aux_switch(struct dp_aux *dp_aux, aux = container_of(dp_aux, struct dp_aux_private, dp_aux); if (!aux->aux_switch_node) { DP_DEBUG("undefined fsa4480 handle\n"); DP_DEBUG("undefined aux switch handle\n"); rc = -EINVAL; goto end; } if (strcmp(aux->aux_switch_node->name, "fsa4480")) { DP_DEBUG("Not an fsa4480 aux switch\n"); goto end; } if (enable) { switch (orientation) { case ORIENTATION_CC1: Loading
msm/dp/dp_debug.c +2 −0 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ Loading Loading @@ -2284,6 +2285,7 @@ struct dp_debug *dp_debug_get(struct dp_debug_in *in) dp_debug->dp_mst_connector_list.con_id = -1; dp_debug->dp_mst_connector_list.conn = NULL; dp_debug->dp_mst_connector_list.debug_en = false; mutex_init(&dp_debug->dp_mst_connector_list.lock); dp_debug->max_pclk_khz = debug->parser->max_pclk_khz; Loading
msm/dp/dp_display.c +109 −40 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ Loading Loading @@ -721,6 +722,11 @@ static void dp_display_send_hpd_event(struct dp_display_private *dp) kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, envp); if (dev->mode_config.funcs->output_poll_changed) dev->mode_config.funcs->output_poll_changed(dev); drm_client_dev_hotplug(dev); if (connector->status == connector_status_connected) { dp_display_state_add(DP_STATE_CONNECT_NOTIFIED); dp_display_state_remove(DP_STATE_DISCONNECT_NOTIFIED); Loading Loading @@ -976,6 +982,8 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp) dp->dp_display.max_pclk_khz = min(dp->parser->max_pclk_khz, dp->debug->max_pclk_khz); dp->dp_display.max_hdisplay = dp->parser->max_hdisplay; dp->dp_display.max_vdisplay = dp->parser->max_vdisplay; /* * If dp video session is not restored from a previous session teardown Loading Loading @@ -2316,43 +2324,22 @@ static int dp_display_unprepare(struct dp_display *dp_display, void *panel) return 0; } static enum drm_mode_status dp_display_validate_mode( static int dp_display_validate_resources( struct dp_display *dp_display, void *panel, struct drm_display_mode *mode, const struct msm_resource_caps_info *avail_res) { struct dp_display_private *dp; u32 mode_rate_khz = 0, supported_rate_khz = 0, mode_bpp = 0; struct dp_panel *dp_panel; struct dp_debug *debug; enum drm_mode_status mode_status = MODE_BAD; bool in_list = false; struct dp_mst_connector *mst_connector; int hdis, vdis, vref, ar, _hdis, _vdis, _vref, _ar, rate; struct dp_display_mode dp_mode; u32 mode_rate_khz, supported_rate_khz, mode_bpp, num_lm; int rc, tmds_max_clock, rate; bool dsc_en; u32 num_lm = 0; int rc = 0, tmds_max_clock = 0; if (!dp_display || !mode || !panel || !avail_res || !avail_res->max_mixer_width) { DP_ERR("invalid params\n"); return mode_status; } dp = container_of(dp_display, struct dp_display_private, dp_display); mutex_lock(&dp->session_lock); dp_panel = panel; if (!dp_panel->connector) { DP_ERR("invalid connector\n"); goto end; } debug = dp->debug; if (!debug) goto end; dp_display->convert_to_dp_mode(dp_display, panel, mode, &dp_mode); Loading @@ -2366,36 +2353,65 @@ static enum drm_mode_status dp_display_validate_mode( tmds_max_clock = dp_panel->connector->display_info.max_tmds_clock; if (mode_rate_khz > supported_rate_khz) { DP_MST_DEBUG("pclk:%d, supported_rate:%d\n", DP_DEBUG("pclk:%d, supported_rate:%d\n", mode->clock, supported_rate_khz); goto end; return -EINVAL; } if (mode->clock > dp_display->max_pclk_khz) { DP_MST_DEBUG("clk:%d, max:%d\n", mode->clock, DP_DEBUG("clk:%d, max:%d\n", mode->clock, dp_display->max_pclk_khz); goto end; return -EINVAL; } if ((dp_display->max_hdisplay > 0) && (dp_display->max_vdisplay > 0) && ((mode->hdisplay > dp_display->max_hdisplay) || (mode->vdisplay > dp_display->max_vdisplay))) { DP_DEBUG("hdisplay:%d, max-hdisplay:%d", mode->hdisplay, dp_display->max_hdisplay); DP_DEBUG("vdisplay:%d, max-vdisplay:%d\n", mode->vdisplay, dp_display->max_vdisplay); return -EINVAL; } if (tmds_max_clock > 0 && mode->clock > tmds_max_clock) { DP_MST_DEBUG("clk:%d, max tmds:%d\n", mode->clock, DP_DEBUG("clk:%d, max tmds:%d\n", mode->clock, tmds_max_clock); goto end; return -EINVAL; } rc = msm_get_mixer_count(dp->priv, mode, avail_res, &num_lm); if (rc) { DP_ERR("error getting mixer count. rc:%d\n", rc); goto end; return -EINVAL; } if (num_lm > avail_res->num_lm || (num_lm == 2 && !avail_res->num_3dmux)) { DP_MST_DEBUG("num_lm:%d, req lm:%d 3dmux:%d\n", num_lm, DP_DEBUG("num_lm:%d, req lm:%d 3dmux:%d\n", num_lm, avail_res->num_lm, avail_res->num_3dmux); goto end; return -EINVAL; } return 0; } static int dp_display_check_overrides( struct dp_display *dp_display, void *panel, struct drm_display_mode *mode, const struct msm_resource_caps_info *avail_res) { struct dp_mst_connector *mst_connector; struct dp_display_private *dp; struct dp_panel *dp_panel; struct dp_debug *debug; bool in_list = false; int hdis, vdis, vref, ar, _hdis, _vdis, _vref, _ar; dp = container_of(dp_display, struct dp_display_private, dp_display); dp_panel = panel; debug = dp->debug; /* * If the connector exists in the mst connector list and if debug is * enabled for that connector, use the mst connector settings from the Loading @@ -2404,6 +2420,7 @@ static enum drm_mode_status dp_display_validate_mode( mutex_lock(&debug->dp_mst_connector_list.lock); if (list_empty(&debug->dp_mst_connector_list.list)) { DP_MST_DEBUG("MST connect list is empty\n"); mutex_unlock(&debug->dp_mst_connector_list.lock); goto verify_default; } Loading @@ -2414,10 +2431,9 @@ static enum drm_mode_status dp_display_validate_mode( in_list = true; if (!mst_connector->debug_en) { mode_status = MODE_OK; mutex_unlock( &debug->dp_mst_connector_list.lock); goto end; return 0; } hdis = mst_connector->hdisplay; Loading @@ -2432,28 +2448,76 @@ static enum drm_mode_status dp_display_validate_mode( if (hdis == _hdis && vdis == _vdis && vref == _vref && ar == _ar) { mode_status = MODE_OK; mutex_unlock( &debug->dp_mst_connector_list.lock); goto end; return 0; } break; } } mutex_unlock(&debug->dp_mst_connector_list.lock); if (in_list) goto end; return -EINVAL; verify_default: if (debug->debug_en && (mode->hdisplay != debug->hdisplay || mode->vdisplay != debug->vdisplay || mode->vrefresh != debug->vrefresh || mode->picture_aspect_ratio != debug->aspect_ratio)) return -EINVAL; return 0; } static enum drm_mode_status dp_display_validate_mode( struct dp_display *dp_display, void *panel, struct drm_display_mode *mode, const struct msm_resource_caps_info *avail_res) { struct dp_display_private *dp; struct dp_panel *dp_panel; struct dp_debug *debug; enum drm_mode_status mode_status = MODE_BAD; if (!dp_display || !mode || !panel || !avail_res || !avail_res->max_mixer_width) { DP_ERR("invalid params\n"); return mode_status; } dp = container_of(dp_display, struct dp_display_private, dp_display); mutex_lock(&dp->session_lock); dp_panel = panel; if (!dp_panel->connector) { DP_ERR("invalid connector\n"); goto end; } debug = dp->debug; if (!debug) { DP_ERR("invalid debug node\n"); goto end; } if (dp_display_validate_resources(dp_display, panel, mode, avail_res)) { DP_DEBUG("DP bad mode %dx%d@%d\n", mode->hdisplay, mode->vdisplay, mode->clock); goto end; } if (dp_display_check_overrides(dp_display, panel, mode, avail_res)) { DP_MST_DEBUG("DP overrides ignore mode %dx%d@%d\n", mode->hdisplay, mode->vdisplay, mode->clock); goto end; } DP_DEBUG("DP ok mode %dx%d@%d\n", mode->hdisplay, mode->vdisplay, mode->clock); mode_status = MODE_OK; end: mutex_unlock(&dp->session_lock); Loading Loading @@ -2656,6 +2720,11 @@ static int dp_display_init_aux_switch(struct dp_display_private *dp) goto end; } if (strcmp(dp->aux_switch_node->name, "fsa4480")) { DP_DEBUG("Not an fsa4480 aux switch\n"); goto end; } nb.notifier_call = dp_display_fsa4480_callback; nb.priority = 0; Loading
msm/dp/dp_display.h +3 −0 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ Loading Loading @@ -70,6 +71,8 @@ struct dp_display { bool is_sst_connected; bool is_mst_supported; u32 max_pclk_khz; u32 max_hdisplay; u32 max_vdisplay; u32 no_mst_encoder; void *dp_mst_prv_info; bool is_primary; Loading
msm/dp/dp_parser.c +11 −0 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. */ Loading Loading @@ -170,6 +171,16 @@ static int dp_parser_misc(struct dp_parser *parser) if (!parser->display_type) parser->display_type = "unknown"; rc = of_property_read_u32(of_node, "qcom,max-hdisplay", &parser->max_hdisplay); if (rc) parser->max_hdisplay = 0; rc = of_property_read_u32(of_node, "qcom,max-vdisplay", &parser->max_vdisplay); if (rc) parser->max_vdisplay = 0; return 0; } Loading