From patchwork Fri May 25 21:26:06 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeykumar Sankaran X-Patchwork-Id: 10428539 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 5A65D601D5 for ; Fri, 25 May 2018 21:26:47 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 405F129803 for ; Fri, 25 May 2018 21:26:47 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 33D6929805; Fri, 25 May 2018 21:26:47 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00, MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 3004A29803 for ; Fri, 25 May 2018 21:26:42 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 991876EB13; Fri, 25 May 2018 21:26:39 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from smtp.codeaurora.org (smtp.codeaurora.org [198.145.29.96]) by gabe.freedesktop.org (Postfix) with ESMTPS id 4C3F86EB12; Fri, 25 May 2018 21:26:38 +0000 (UTC) Received: by smtp.codeaurora.org (Postfix, from userid 1000) id 3251B60262; Fri, 25 May 2018 21:26:35 +0000 (UTC) Received: from jeykumar-linux.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: jsanka@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id D385960F6D; Fri, 25 May 2018 21:26:26 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org D385960F6D From: Jeykumar Sankaran To: dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, linux-arm-msm@vger.kernel.org Subject: [DPU PATCH v3 5/6] drm/msm: hook up DPU with upstream DSI Date: Fri, 25 May 2018 14:26:06 -0700 Message-Id: <1527283567-6546-6-git-send-email-jsanka@codeaurora.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1527283567-6546-1-git-send-email-jsanka@codeaurora.org> References: <1527283567-6546-1-git-send-email-jsanka@codeaurora.org> X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: hoegsberg@google.com, Rajesh Yadav MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP Switch DPU from dsi-staging to upstream dsi driver. To make the switch atomic, this change includes: - remove dpu connector layers - clean up dpu connector dependencies in encoder/crtc - compile out writeback and display port drivers - compile out dsi-staging driver (separate patch submitted to remove the driver) - adapt upstream device hierarchy changes in v2: - remove files not applicable upstream (Sean Paul) - remove compiled out non-dsi display init (Sean Paul) - split unrelated changes into separate patch set (Sean Paul) changes in v3: - fix compilation warning - compile out dsi staging Signed-off-by: Jeykumar Sankaran Signed-off-by: Sean Paul Signed-off-by: Rajesh Yadav --- drivers/gpu/drm/msm/Makefile | 22 - drivers/gpu/drm/msm/disp/dpu1/dpu_connector.c | 1185 -------------------- drivers/gpu/drm/msm/disp/dpu1/dpu_connector.h | 555 --------- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 9 - drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 179 +-- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 10 +- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 8 +- .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 6 +- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 488 +------- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 6 - drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 56 +- drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 11 + drivers/gpu/drm/msm/dpu_dbg.c | 3 - drivers/gpu/drm/msm/msm_drv.c | 47 +- drivers/gpu/drm/msm/msm_drv.h | 39 - 15 files changed, 159 insertions(+), 2465 deletions(-) delete mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_connector.c delete mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_connector.h diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index d947f2a..d7558ed 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -1,7 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 ccflags-y := -Idrivers/gpu/drm/msm ccflags-y += -Idrivers/gpu/drm/msm/disp/dpu1 -ccflags-y += -Idrivers/gpu/drm/msm/dsi-staging ccflags-$(CONFIG_DRM_MSM_DSI) += -Idrivers/gpu/drm/msm/dsi msm-y := \ @@ -48,7 +47,6 @@ msm-y := \ disp/mdp5/mdp5_plane.o \ disp/mdp5/mdp5_smp.o \ disp/dpu1/dpu_color_processing.o \ - disp/dpu1/dpu_connector.o \ disp/dpu1/dpu_core_irq.o \ disp/dpu1/dpu_core_perf.o \ disp/dpu1/dpu_crtc.o \ @@ -141,26 +139,6 @@ msm-$(CONFIG_DRM_MSM_DSI) += dsi/dsi.o \ dsi/phy/dsi_phy.o \ disp/mdp5/mdp5_cmd_encoder.o -msm-$(CONFIG_DRM_MSM_DSI_STAGING) += dsi-staging/dsi_phy.o \ - dsi-staging/dsi_pwr.o \ - dsi-staging/dsi_phy.o \ - dsi-staging/dsi_phy_hw_v2_0.o \ - dsi-staging/dsi_phy_hw_v3_0.o \ - dsi-staging/dsi_phy_timing_calc.o \ - dsi-staging/dsi_phy_timing_v2_0.o \ - dsi-staging/dsi_phy_timing_v3_0.o \ - dsi-staging/dsi_ctrl_hw_cmn.o \ - dsi-staging/dsi_ctrl_hw_1_4.o \ - dsi-staging/dsi_ctrl_hw_2_0.o \ - dsi-staging/dsi_ctrl_hw_2_2.o \ - dsi-staging/dsi_ctrl.o \ - dsi-staging/dsi_catalog.o \ - dsi-staging/dsi_drm.o \ - dsi-staging/dsi_display.o \ - dsi-staging/dsi_panel.o \ - dsi-staging/dsi_clk_manager.o \ - dsi-staging/dsi_display_test.o - msm-$(CONFIG_DRM_MSM_DSI_28NM_PHY) += dsi/phy/dsi_phy_28nm.o msm-$(CONFIG_DRM_MSM_DSI_20NM_PHY) += dsi/phy/dsi_phy_20nm.o msm-$(CONFIG_DRM_MSM_DSI_28NM_8960_PHY) += dsi/phy/dsi_phy_28nm_8960.o diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.c deleted file mode 100644 index 969919f..0000000 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.c +++ /dev/null @@ -1,1185 +0,0 @@ -/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__ -#include "msm_drv.h" -#include "dpu_dbg.h" - -#include "dpu_kms.h" -#include "dpu_connector.h" -#ifdef CONFIG_DRM_MSM_DSI_STAGING -#include -#include "dsi_drm.h" -#include "dsi_display.h" -#endif - -#define BL_NODE_NAME_SIZE 32 - -#define DPU_DEBUG_CONN(c, fmt, ...) DPU_DEBUG("conn%d " fmt,\ - (c) ? (c)->base.base.id : -1, ##__VA_ARGS__) - -#define DPU_ERROR_CONN(c, fmt, ...) DPU_ERROR("conn%d " fmt,\ - (c) ? (c)->base.base.id : -1, ##__VA_ARGS__) - -static const struct drm_prop_enum_list e_topology_name[] = { - {DPU_RM_TOPOLOGY_NONE, "dpu_none"}, - {DPU_RM_TOPOLOGY_SINGLEPIPE, "dpu_singlepipe"}, - {DPU_RM_TOPOLOGY_DUALPIPE, "dpu_dualpipe"}, - {DPU_RM_TOPOLOGY_DUALPIPE_3DMERGE, "dpu_dualpipemerge"}, -}; - -static const struct drm_prop_enum_list e_topology_control[] = { - {DPU_RM_TOPCTL_RESERVE_LOCK, "reserve_lock"}, - {DPU_RM_TOPCTL_RESERVE_CLEAR, "reserve_clear"}, - {DPU_RM_TOPCTL_DSPP, "dspp"}, -}; -static const struct drm_prop_enum_list e_power_mode[] = { - {DPU_MODE_DPMS_ON, "ON"}, - {DPU_MODE_DPMS_LP1, "LP1"}, - {DPU_MODE_DPMS_LP2, "LP2"}, - {DPU_MODE_DPMS_OFF, "OFF"}, -}; - -#ifdef CONFIG_DRM_MSM_DSI_STAGING -static int dpu_backlight_device_update_status(struct backlight_device *bd) -{ - int brightness; - struct dsi_display *display; - struct dpu_connector *c_conn; - int bl_lvl; - struct drm_event event; - - brightness = bd->props.brightness; - - if ((bd->props.power != FB_BLANK_UNBLANK) || - (bd->props.state & BL_CORE_FBBLANK) || - (bd->props.state & BL_CORE_SUSPENDED)) - brightness = 0; - - c_conn = bl_get_data(bd); - display = (struct dsi_display *) c_conn->display; - if (brightness > display->panel->bl_config.bl_max_level) - brightness = display->panel->bl_config.bl_max_level; - - /* map UI brightness into driver backlight level with rounding */ - bl_lvl = mult_frac(brightness, display->panel->bl_config.bl_max_level, - display->panel->bl_config.brightness_max_level); - - if (!bl_lvl && brightness) - bl_lvl = 1; - - if (c_conn->ops.set_backlight) { - event.type = DRM_EVENT_SYS_BACKLIGHT; - event.length = sizeof(u32); - msm_mode_object_event_notify(&c_conn->base.base, - c_conn->base.dev, &event, (u8 *)&brightness); - c_conn->ops.set_backlight(c_conn->display, bl_lvl); - } - - return 0; -} - -static int dpu_backlight_device_get_brightness(struct backlight_device *bd) -{ - return 0; -} - -static const struct backlight_ops dpu_backlight_device_ops = { - .update_status = dpu_backlight_device_update_status, - .get_brightness = dpu_backlight_device_get_brightness, -}; - -static int dpu_backlight_setup(struct dpu_connector *c_conn, - struct drm_device *dev) -{ - struct backlight_properties props; - struct dsi_display *display; - struct dsi_backlight_config *bl_config; - static int display_count; - char bl_node_name[BL_NODE_NAME_SIZE]; - - if (!c_conn || !dev || !dev->dev) { - DPU_ERROR("invalid param\n"); - return -EINVAL; - } else if (c_conn->connector_type != DRM_MODE_CONNECTOR_DSI) { - return 0; - } - - memset(&props, 0, sizeof(props)); - props.type = BACKLIGHT_RAW; - props.power = FB_BLANK_UNBLANK; - - display = (struct dsi_display *) c_conn->display; - bl_config = &display->panel->bl_config; - props.max_brightness = bl_config->brightness_max_level; - props.brightness = bl_config->brightness_max_level; - snprintf(bl_node_name, BL_NODE_NAME_SIZE, "panel%u-backlight", - display_count); - c_conn->bl_device = backlight_device_register(bl_node_name, dev->dev, - c_conn, &dpu_backlight_device_ops, &props); - if (IS_ERR_OR_NULL(c_conn->bl_device)) { - DPU_ERROR("Failed to register backlight: %ld\n", - PTR_ERR(c_conn->bl_device)); - c_conn->bl_device = NULL; - return -ENODEV; - } - display_count++; - - return 0; -} -#endif - -int dpu_connector_trigger_event(void *drm_connector, - uint32_t event_idx, uint32_t instance_idx, - uint32_t data0, uint32_t data1, - uint32_t data2, uint32_t data3) -{ - struct dpu_connector *c_conn; - unsigned long irq_flags; - void (*cb_func)(uint32_t event_idx, - uint32_t instance_idx, void *usr, - uint32_t data0, uint32_t data1, - uint32_t data2, uint32_t data3); - void *usr; - int rc = 0; - - /* - * This function may potentially be called from an ISR context, so - * avoid excessive logging/etc. - */ - if (!drm_connector) - return -EINVAL; - else if (event_idx >= DPU_CONN_EVENT_COUNT) - return -EINVAL; - c_conn = to_dpu_connector(drm_connector); - - spin_lock_irqsave(&c_conn->event_lock, irq_flags); - cb_func = c_conn->event_table[event_idx].cb_func; - usr = c_conn->event_table[event_idx].usr; - spin_unlock_irqrestore(&c_conn->event_lock, irq_flags); - - if (cb_func) - cb_func(event_idx, instance_idx, usr, - data0, data1, data2, data3); - else - rc = -EAGAIN; - - return rc; -} - -int dpu_connector_register_event(struct drm_connector *connector, - uint32_t event_idx, - void (*cb_func)(uint32_t event_idx, - uint32_t instance_idx, void *usr, - uint32_t data0, uint32_t data1, - uint32_t data2, uint32_t data3), - void *usr) -{ - struct dpu_connector *c_conn; - unsigned long irq_flags; - - if (!connector) { - DPU_ERROR("invalid connector\n"); - return -EINVAL; - } else if (event_idx >= DPU_CONN_EVENT_COUNT) { - DPU_ERROR("conn%d, invalid event %d\n", - connector->base.id, event_idx); - return -EINVAL; - } - c_conn = to_dpu_connector(connector); - - spin_lock_irqsave(&c_conn->event_lock, irq_flags); - c_conn->event_table[event_idx].cb_func = cb_func; - c_conn->event_table[event_idx].usr = usr; - spin_unlock_irqrestore(&c_conn->event_lock, irq_flags); - - /* optionally notify display of event registration */ - if (c_conn->ops.enable_event && c_conn->display) - c_conn->ops.enable_event(connector, event_idx, - cb_func != NULL, c_conn->display); - return 0; -} - -void dpu_connector_unregister_event(struct drm_connector *connector, - uint32_t event_idx) -{ - (void)dpu_connector_register_event(connector, event_idx, 0, 0); -} - -#ifdef CONFIG_DRM_MSM_DSI_STAGING -static u32 dither_matrix[DITHER_MATRIX_SZ] = { - 15, 7, 13, 5, 3, 11, 1, 9, 12, 4, 14, 6, 0, 8, 2, 10 -}; - -static int _dpu_connector_get_default_dither_cfg_v1( - struct dpu_connector *c_conn, void *cfg) -{ - struct drm_msm_dither *dither_cfg = (struct drm_msm_dither *)cfg; - enum dsi_pixel_format dst_format = DSI_PIXEL_FORMAT_MAX; - - if (!c_conn || !cfg) { - DPU_ERROR("invalid argument(s), c_conn %pK, cfg %pK\n", - c_conn, cfg); - return -EINVAL; - } - - if (!c_conn->ops.get_dst_format) { - DPU_DEBUG("get_dst_format is unavailable\n"); - return 0; - } - - dst_format = c_conn->ops.get_dst_format(c_conn->display); - switch (dst_format) { - case DSI_PIXEL_FORMAT_RGB888: - dither_cfg->c0_bitdepth = 8; - dither_cfg->c1_bitdepth = 8; - dither_cfg->c2_bitdepth = 8; - dither_cfg->c3_bitdepth = 8; - break; - case DSI_PIXEL_FORMAT_RGB666: - case DSI_PIXEL_FORMAT_RGB666_LOOSE: - dither_cfg->c0_bitdepth = 6; - dither_cfg->c1_bitdepth = 6; - dither_cfg->c2_bitdepth = 6; - dither_cfg->c3_bitdepth = 6; - break; - default: - DPU_DEBUG("no default dither config for dst_format %d\n", - dst_format); - return -ENODATA; - } - - memcpy(&dither_cfg->matrix, dither_matrix, - sizeof(u32) * DITHER_MATRIX_SZ); - dither_cfg->temporal_en = 0; - return 0; -} - -static void _dpu_connector_install_dither_property(struct drm_device *dev, - struct dpu_kms *dpu_kms, struct dpu_connector *c_conn) -{ - char prop_name[DRM_PROP_NAME_LEN]; - struct dpu_mdss_cfg *catalog = NULL; - struct drm_property_blob *blob_ptr; - void *cfg; - int ret = 0; - u32 version = 0, len = 0; - bool defalut_dither_needed = false; - - if (!dev || !dpu_kms || !c_conn) { - DPU_ERROR("invld args (s), dev %pK, dpu_kms %pK, c_conn %pK\n", - dev, dpu_kms, c_conn); - return; - } - - catalog = dpu_kms->catalog; - version = DPU_COLOR_PROCESS_MAJOR( - catalog->pingpong[0].sblk->dither.version); - snprintf(prop_name, ARRAY_SIZE(prop_name), "%s%d", - "DPU_PP_DITHER_V", version); - switch (version) { - case 1: - msm_property_install_blob(&c_conn->property_info, prop_name, - DRM_MODE_PROP_BLOB, - CONNECTOR_PROP_PP_DITHER); - len = sizeof(struct drm_msm_dither); - cfg = kzalloc(len, GFP_KERNEL); - if (!cfg) - return; - - ret = _dpu_connector_get_default_dither_cfg_v1(c_conn, cfg); - if (!ret) - defalut_dither_needed = true; - break; - default: - DPU_ERROR("unsupported dither version %d\n", version); - return; - } - - if (defalut_dither_needed) { - blob_ptr = drm_property_create_blob(dev, len, cfg); - if (IS_ERR_OR_NULL(blob_ptr)) - goto exit; - c_conn->blob_dither = blob_ptr; - } -exit: - kfree(cfg); -} -#endif - -int dpu_connector_get_dither_cfg(struct drm_connector *conn, - struct drm_connector_state *state, void **cfg, - size_t *len) -{ - struct dpu_connector *c_conn = NULL; - struct dpu_connector_state *c_state = NULL; - size_t dither_sz = 0; - - if (!conn || !state || !(*cfg)) - return -EINVAL; - - c_conn = to_dpu_connector(conn); - c_state = to_dpu_connector_state(state); - - /* try to get user config data first */ - *cfg = msm_property_get_blob(&c_conn->property_info, - &c_state->property_state, - &dither_sz, - CONNECTOR_PROP_PP_DITHER); - /* if user config data doesn't exist, use default dither blob */ - if (*cfg == NULL && c_conn->blob_dither) { - *cfg = &c_conn->blob_dither->data; - dither_sz = c_conn->blob_dither->length; - } - *len = dither_sz; - return 0; -} - -int dpu_connector_get_info(struct drm_connector *connector, - struct msm_display_info *info) -{ - struct dpu_connector *c_conn; - - if (!connector || !info) { - DPU_ERROR("invalid argument(s), conn %pK, info %pK\n", - connector, info); - return -EINVAL; - } - - c_conn = to_dpu_connector(connector); - - if (!c_conn->display || !c_conn->ops.get_info) { - DPU_ERROR("display info not supported for %pK\n", - c_conn->display); - return -EINVAL; - } - - return c_conn->ops.get_info(info, c_conn->display); -} - -static int _dpu_connector_update_power_locked(struct dpu_connector *c_conn) -{ - struct drm_connector *connector; - void *display; - int (*set_power)(struct drm_connector *, int, void *); - int mode, rc = 0; - - if (!c_conn) - return -EINVAL; - connector = &c_conn->base; - - switch (c_conn->dpms_mode) { - case DRM_MODE_DPMS_ON: - mode = c_conn->lp_mode; - break; - case DRM_MODE_DPMS_STANDBY: - mode = DPU_MODE_DPMS_STANDBY; - break; - case DRM_MODE_DPMS_SUSPEND: - mode = DPU_MODE_DPMS_SUSPEND; - break; - case DRM_MODE_DPMS_OFF: - mode = DPU_MODE_DPMS_OFF; - break; - default: - mode = c_conn->lp_mode; - DPU_ERROR("conn %d dpms set to unrecognized mode %d\n", - connector->base.id, mode); - break; - } - - DPU_EVT32(connector->base.id, c_conn->dpms_mode, c_conn->lp_mode, mode); - DPU_DEBUG("conn %d - dpms %d, lp %d, panel %d\n", connector->base.id, - c_conn->dpms_mode, c_conn->lp_mode, mode); - - if (mode != c_conn->last_panel_power_mode && c_conn->ops.set_power) { - display = c_conn->display; - set_power = c_conn->ops.set_power; - - mutex_unlock(&c_conn->lock); - rc = set_power(connector, mode, display); - mutex_lock(&c_conn->lock); - } - c_conn->last_panel_power_mode = mode; - - return rc; -} - -int dpu_connector_pre_kickoff(struct drm_connector *connector) -{ - struct dpu_connector *c_conn; - struct dpu_connector_state *c_state; - int idx, rc = 0; - - if (!connector) { - DPU_ERROR("invalid argument\n"); - return -EINVAL; - } - - c_conn = to_dpu_connector(connector); - c_state = to_dpu_connector_state(connector->state); - - if (!c_conn->display) { - DPU_ERROR("invalid argument\n"); - return -EINVAL; - } -#ifdef CONFIG_DRM_MSM_DSI_STAGING - if (c_conn->ops.set_backlight) { - DPU_DEBUG("conn%d: Set backlight to 255\n", connector->base.id); - c_conn->ops.set_backlight(c_conn->display, 255); - } -#endif - - while ((idx = msm_property_pop_dirty(&c_conn->property_info, - &c_state->property_state)) >= 0) { - switch (idx) { - case CONNECTOR_PROP_LP: - mutex_lock(&c_conn->lock); - c_conn->lp_mode = dpu_connector_get_property( - connector->state, CONNECTOR_PROP_LP); - _dpu_connector_update_power_locked(c_conn); - mutex_unlock(&c_conn->lock); - break; - default: - /* nothing to do for most properties */ - break; - } - } - - DPU_EVT32_VERBOSE(connector->base.id); - - return rc; -} - -void dpu_connector_clk_ctrl(struct drm_connector *connector, bool enable) -{ -#ifdef CONFIG_DRM_MSM_DSI_STAGING - struct dpu_connector *c_conn; - struct dsi_display *display; - u32 state = enable ? DSI_CLK_ON : DSI_CLK_OFF; - - if (!connector) { - DPU_ERROR("invalid connector\n"); - return; - } - - c_conn = to_dpu_connector(connector); - display = (struct dsi_display *) c_conn->display; - - if (display && c_conn->ops.clk_ctrl) - c_conn->ops.clk_ctrl(display->mdp_clk_handle, - DSI_ALL_CLKS, state); -#endif -} - -static void dpu_connector_destroy(struct drm_connector *connector) -{ - struct dpu_connector *c_conn; - - if (!connector) { - DPU_ERROR("invalid connector\n"); - return; - } - - c_conn = to_dpu_connector(connector); - - if (c_conn->ops.put_modes) - c_conn->ops.put_modes(connector, c_conn->display); - - if (c_conn->blob_caps) - drm_property_blob_put(c_conn->blob_caps); - if (c_conn->blob_hdr) - drm_property_blob_put(c_conn->blob_hdr); - if (c_conn->blob_dither) - drm_property_blob_put(c_conn->blob_dither); - msm_property_destroy(&c_conn->property_info); - - if (c_conn->bl_device) - backlight_device_unregister(c_conn->bl_device); - drm_connector_unregister(connector); - mutex_destroy(&c_conn->lock); - drm_connector_cleanup(connector); - kfree(c_conn); -} - -/** - * _dpu_connector_destroy_fb - clean up connector state's out_fb buffer - * @c_conn: Pointer to dpu connector structure - * @c_state: Pointer to dpu connector state structure - */ -static void _dpu_connector_destroy_fb(struct dpu_connector *c_conn, - struct dpu_connector_state *c_state) -{ - if (!c_state || !c_state->out_fb) { - DPU_ERROR("invalid state %pK\n", c_state); - return; - } - - drm_framebuffer_put(c_state->out_fb); - c_state->out_fb = NULL; - - if (c_conn) - c_state->property_values[CONNECTOR_PROP_OUT_FB].value = - msm_property_get_default(&c_conn->property_info, - CONNECTOR_PROP_OUT_FB); - else - c_state->property_values[CONNECTOR_PROP_OUT_FB].value = ~0; -} - -static void dpu_connector_atomic_destroy_state(struct drm_connector *connector, - struct drm_connector_state *state) -{ - struct dpu_connector *c_conn = NULL; - struct dpu_connector_state *c_state = NULL; - - if (!state) { - DPU_ERROR("invalid state\n"); - return; - } - - /* - * The base DRM framework currently always passes in a NULL - * connector pointer. This is not correct, but attempt to - * handle that case as much as possible. - */ - if (connector) - c_conn = to_dpu_connector(connector); - c_state = to_dpu_connector_state(state); - - if (c_state->out_fb) - _dpu_connector_destroy_fb(c_conn, c_state); - - if (!c_conn) { - kfree(c_state); - } else { - /* destroy value helper */ - msm_property_destroy_state(&c_conn->property_info, c_state, - &c_state->property_state); - } -} - -static void dpu_connector_atomic_reset(struct drm_connector *connector) -{ - struct dpu_connector *c_conn; - struct dpu_connector_state *c_state; - - if (!connector) { - DPU_ERROR("invalid connector\n"); - return; - } - - c_conn = to_dpu_connector(connector); - - if (connector->state) { - dpu_connector_atomic_destroy_state(connector, connector->state); - connector->state = 0; - } - - c_state = msm_property_alloc_state(&c_conn->property_info); - if (!c_state) { - DPU_ERROR("state alloc failed\n"); - return; - } - - /* reset value helper, zero out state structure and reset properties */ - msm_property_reset_state(&c_conn->property_info, c_state, - &c_state->property_state, - c_state->property_values); - - c_state->base.connector = connector; - connector->state = &c_state->base; -} - -static struct drm_connector_state * -dpu_connector_atomic_duplicate_state(struct drm_connector *connector) -{ - struct dpu_connector *c_conn; - struct dpu_connector_state *c_state, *c_oldstate; - - if (!connector || !connector->state) { - DPU_ERROR("invalid connector %pK\n", connector); - return NULL; - } - - c_conn = to_dpu_connector(connector); - c_oldstate = to_dpu_connector_state(connector->state); - c_state = msm_property_alloc_state(&c_conn->property_info); - if (!c_state) { - DPU_ERROR("state alloc failed\n"); - return NULL; - } - - /* duplicate value helper */ - msm_property_duplicate_state(&c_conn->property_info, - c_oldstate, c_state, - &c_state->property_state, c_state->property_values); - - /* additional handling for drm framebuffer objects */ - if (c_state->out_fb) - drm_framebuffer_get(c_state->out_fb); - - return &c_state->base; -} - -static int _dpu_connector_update_bl_scale(struct dpu_connector *c_conn, - int idx, - uint64_t value) -{ -#ifdef CONFIG_DRM_MSM_DSI_STAGING - struct dsi_display *dsi_display = c_conn->display; - struct dsi_backlight_config *bl_config; - int rc = 0; - - if (!dsi_display || !dsi_display->panel) { - pr_err("Invalid params(s) dsi_display %pK, panel %pK\n", - dsi_display, - ((dsi_display) ? dsi_display->panel : NULL)); - return -EINVAL; - } - - bl_config = &dsi_display->panel->bl_config; - if (idx == CONNECTOR_PROP_BL_SCALE) { - bl_config->bl_scale = value; - if (value > MAX_BL_SCALE_LEVEL) - bl_config->bl_scale = MAX_BL_SCALE_LEVEL; - DPU_DEBUG("set to panel: bl_scale = %u, bl_level = %u\n", - bl_config->bl_scale, bl_config->bl_level); - rc = c_conn->ops.set_backlight(dsi_display, - bl_config->bl_level); - } else if (idx == CONNECTOR_PROP_AD_BL_SCALE) { - bl_config->bl_scale_ad = value; - if (value > MAX_AD_BL_SCALE_LEVEL) - bl_config->bl_scale_ad = MAX_AD_BL_SCALE_LEVEL; - DPU_DEBUG("set to panel: bl_scale_ad = %u, bl_level = %u\n", - bl_config->bl_scale_ad, bl_config->bl_level); - rc = c_conn->ops.set_backlight(dsi_display, - bl_config->bl_level); - } - return rc; -#else - return 0; -#endif -} - -static int dpu_connector_atomic_set_property(struct drm_connector *connector, - struct drm_connector_state *state, - struct drm_property *property, - uint64_t val) -{ - struct dpu_connector *c_conn; - struct dpu_connector_state *c_state; - int idx, rc; - - if (!connector || !state || !property) { - DPU_ERROR("invalid argument(s), conn %pK, state %pK, prp %pK\n", - connector, state, property); - return -EINVAL; - } - - c_conn = to_dpu_connector(connector); - c_state = to_dpu_connector_state(state); - - /* generic property handling */ - rc = msm_property_atomic_set(&c_conn->property_info, - &c_state->property_state, property, val); - if (rc) - goto end; - - /* connector-specific property handling */ - idx = msm_property_index(&c_conn->property_info, property); - switch (idx) { - case CONNECTOR_PROP_OUT_FB: - /* clear old fb, if present */ - if (c_state->out_fb) - _dpu_connector_destroy_fb(c_conn, c_state); - - /* convert fb val to drm framebuffer and prepare it */ - c_state->out_fb = - drm_framebuffer_lookup(connector->dev, NULL, val); - if (!c_state->out_fb && val) { - DPU_ERROR("failed to look up fb %lld\n", val); - rc = -EFAULT; - } else if (!c_state->out_fb && !val) { - DPU_DEBUG("cleared fb_id\n"); - rc = 0; - } - break; - case CONNECTOR_PROP_BL_SCALE: - case CONNECTOR_PROP_AD_BL_SCALE: - rc = _dpu_connector_update_bl_scale(c_conn, idx, val); - break; - default: - break; - } - - /* check for custom property handling */ - if (!rc && c_conn->ops.set_property) { - rc = c_conn->ops.set_property(connector, - state, - idx, - val, - c_conn->display); - - /* potentially clean up out_fb if rc != 0 */ - if ((idx == CONNECTOR_PROP_OUT_FB) && rc) - _dpu_connector_destroy_fb(c_conn, c_state); - } -end: - return rc; -} - -static int dpu_connector_set_property(struct drm_connector *connector, - struct drm_property *property, - uint64_t val) -{ - if (!connector) { - DPU_ERROR("invalid connector\n"); - return -EINVAL; - } - - return dpu_connector_atomic_set_property(connector, - connector->state, property, val); -} - -static int dpu_connector_atomic_get_property(struct drm_connector *connector, - const struct drm_connector_state *state, - struct drm_property *property, - uint64_t *val) -{ - struct dpu_connector *c_conn; - struct dpu_connector_state *c_state; - int idx, rc = -EINVAL; - - if (!connector || !state) { - DPU_ERROR("invalid argument(s), conn %pK, state %pK\n", - connector, state); - return -EINVAL; - } - - c_conn = to_dpu_connector(connector); - c_state = to_dpu_connector_state(state); - - idx = msm_property_index(&c_conn->property_info, property); - /* get cached property value */ - rc = msm_property_atomic_get(&c_conn->property_info, - &c_state->property_state, property, val); - - /* allow for custom override */ - if (c_conn->ops.get_property) - rc = c_conn->ops.get_property(connector, - (struct drm_connector_state *)state, - idx, - val, - c_conn->display); - return rc; -} - -static enum drm_connector_status -dpu_connector_detect(struct drm_connector *connector, bool force) -{ - enum drm_connector_status status = connector_status_unknown; - struct dpu_connector *c_conn; - - if (!connector) { - DPU_ERROR("invalid connector\n"); - return status; - } - - c_conn = to_dpu_connector(connector); - - if (c_conn->ops.detect) - status = c_conn->ops.detect(connector, - force, - c_conn->display); - - return status; -} - -int dpu_connector_get_dpms(struct drm_connector *connector) -{ - struct dpu_connector *c_conn; - int rc; - - if (!connector) { - DPU_DEBUG("invalid connector\n"); - return DRM_MODE_DPMS_OFF; - } - - c_conn = to_dpu_connector(connector); - - mutex_lock(&c_conn->lock); - rc = c_conn->dpms_mode; - mutex_unlock(&c_conn->lock); - - return rc; -} - -int dpu_connector_set_property_for_commit(struct drm_connector *connector, - struct drm_atomic_state *atomic_state, - uint32_t property_idx, uint64_t value) -{ - struct drm_connector_state *state; - struct drm_property *property; - struct dpu_connector *c_conn; - - if (!connector || !atomic_state) { - DPU_ERROR("invalid argument(s), conn %d, state %d\n", - connector != NULL, atomic_state != NULL); - return -EINVAL; - } - - c_conn = to_dpu_connector(connector); - property = msm_property_index_to_drm_property( - &c_conn->property_info, property_idx); - if (!property) { - DPU_ERROR("invalid property index %d\n", property_idx); - return -EINVAL; - } - - state = drm_atomic_get_connector_state(atomic_state, connector); - if (IS_ERR_OR_NULL(state)) { - DPU_ERROR("failed to get conn %d state\n", - connector->base.id); - return -EINVAL; - } - - return dpu_connector_atomic_set_property( - connector, state, property, value); -} - -#ifdef CONFIG_DEBUG_FS -/** - * dpu_connector_init_debugfs - initialize connector debugfs - * @connector: Pointer to drm connector - */ -static int dpu_connector_init_debugfs(struct drm_connector *connector) -{ - struct dpu_connector *dpu_connector; - - if (!connector || !connector->debugfs_entry) { - DPU_ERROR("invalid connector\n"); - return -EINVAL; - } - - dpu_connector = to_dpu_connector(connector); - - if (!debugfs_create_bool("fb_kmap", 0600, connector->debugfs_entry, - &dpu_connector->fb_kmap)) { - DPU_ERROR("failed to create connector fb_kmap\n"); - return -ENOMEM; - } - - return 0; -} -#else -static int dpu_connector_init_debugfs(struct drm_connector *connector) -{ - return 0; -} -#endif - -static int dpu_connector_late_register(struct drm_connector *connector) -{ - return dpu_connector_init_debugfs(connector); -} - -static void dpu_connector_early_unregister(struct drm_connector *connector) -{ - /* debugfs under connector->debugfs are deleted by drm_debugfs */ -} - -static const struct drm_connector_funcs dpu_connector_ops = { - .reset = dpu_connector_atomic_reset, - .detect = dpu_connector_detect, - .destroy = dpu_connector_destroy, - .fill_modes = drm_helper_probe_single_connector_modes, - .atomic_duplicate_state = dpu_connector_atomic_duplicate_state, - .atomic_destroy_state = dpu_connector_atomic_destroy_state, - .atomic_set_property = dpu_connector_atomic_set_property, - .atomic_get_property = dpu_connector_atomic_get_property, - .set_property = dpu_connector_set_property, - .late_register = dpu_connector_late_register, - .early_unregister = dpu_connector_early_unregister, -}; - -static int dpu_connector_get_modes(struct drm_connector *connector) -{ - struct dpu_connector *c_conn; - - if (!connector) { - DPU_ERROR("invalid connector\n"); - return 0; - } - - c_conn = to_dpu_connector(connector); - if (!c_conn->ops.get_modes) { - DPU_DEBUG("missing get_modes callback\n"); - return 0; - } - - return c_conn->ops.get_modes(connector, c_conn->display); -} - -static enum drm_mode_status -dpu_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) -{ - struct dpu_connector *c_conn; - - if (!connector || !mode) { - DPU_ERROR("invalid argument(s), conn %pK, mode %pK\n", - connector, mode); - return MODE_ERROR; - } - - c_conn = to_dpu_connector(connector); - - if (c_conn->ops.mode_valid) - return c_conn->ops.mode_valid(connector, mode, c_conn->display); - - /* assume all modes okay by default */ - return MODE_OK; -} - -static struct drm_encoder * -dpu_connector_best_encoder(struct drm_connector *connector) -{ - struct dpu_connector *c_conn = to_dpu_connector(connector); - - if (!connector) { - DPU_ERROR("invalid connector\n"); - return NULL; - } - - /* - * This is true for now, revisit this code when multiple encoders are - * supported. - */ - return c_conn->encoder; -} - -static const struct drm_connector_helper_funcs dpu_connector_helper_ops = { - .get_modes = dpu_connector_get_modes, - .mode_valid = dpu_connector_mode_valid, - .best_encoder = dpu_connector_best_encoder, -}; - -struct drm_connector *dpu_connector_init(struct drm_device *dev, - struct drm_encoder *encoder, - struct drm_panel *panel, - void *display, - const struct dpu_connector_ops *ops, - int connector_poll, - int connector_type) -{ - struct msm_drm_private *priv; - struct dpu_kms *dpu_kms; - struct dpu_kms_info *info; - struct dpu_connector *c_conn = NULL; - struct msm_display_info display_info; - int rc; - - if (!dev || !dev->dev_private || !encoder) { - DPU_ERROR("invalid argument(s), dev %pK, enc %pK\n", - dev, encoder); - return ERR_PTR(-EINVAL); - } - - priv = dev->dev_private; - if (!priv->kms) { - DPU_ERROR("invalid kms reference\n"); - return ERR_PTR(-EINVAL); - } - - c_conn = kzalloc(sizeof(*c_conn), GFP_KERNEL); - if (!c_conn) { - DPU_ERROR("failed to alloc dpu connector\n"); - return ERR_PTR(-ENOMEM); - } - - memset(&display_info, 0, sizeof(display_info)); - - rc = drm_connector_init(dev, - &c_conn->base, - &dpu_connector_ops, - connector_type); - if (rc) - goto error_free_conn; - - spin_lock_init(&c_conn->event_lock); - - c_conn->connector_type = connector_type; - c_conn->encoder = encoder; - c_conn->panel = panel; - c_conn->display = display; - - c_conn->dpms_mode = DRM_MODE_DPMS_ON; - c_conn->lp_mode = 0; - c_conn->last_panel_power_mode = DPU_MODE_DPMS_ON; - - dpu_kms = to_dpu_kms(priv->kms); - - if (ops) - c_conn->ops = *ops; - - c_conn->base.helper_private = &dpu_connector_helper_ops; - c_conn->base.polled = connector_poll; - c_conn->base.interlace_allowed = 0; - c_conn->base.doublescan_allowed = 0; - - snprintf(c_conn->name, - DPU_CONNECTOR_NAME_SIZE, - "conn%u", - c_conn->base.base.id); - - mutex_init(&c_conn->lock); - - rc = drm_mode_connector_attach_encoder(&c_conn->base, encoder); - if (rc) { - DPU_ERROR("failed to attach encoder to connector, %d\n", rc); - goto error_cleanup_conn; - } - -#ifdef CONFIG_DRM_MSM_DSI_STAGING - rc = dpu_backlight_setup(c_conn, dev); - if (rc) { - DPU_ERROR("failed to setup backlight, rc=%d\n", rc); - goto error_cleanup_conn; - } -#endif - - /* create properties */ - msm_property_init(&c_conn->property_info, &c_conn->base.base, dev, - priv->conn_property, c_conn->property_data, - CONNECTOR_PROP_COUNT, CONNECTOR_PROP_BLOBCOUNT, - sizeof(struct dpu_connector_state)); - - if (c_conn->ops.post_init) { - info = kmalloc(sizeof(*info), GFP_KERNEL); - if (!info) { - DPU_ERROR("failed to allocate info buffer\n"); - rc = -ENOMEM; - goto error_cleanup_conn; - } - - dpu_kms_info_reset(info); - rc = c_conn->ops.post_init(&c_conn->base, info, display); - if (rc) { - DPU_ERROR("post-init failed, %d\n", rc); - kfree(info); - goto error_cleanup_conn; - } - - msm_property_install_blob(&c_conn->property_info, - "capabilities", - DRM_MODE_PROP_IMMUTABLE, - CONNECTOR_PROP_DPU_INFO); - - msm_property_set_blob(&c_conn->property_info, - &c_conn->blob_caps, - DPU_KMS_INFO_DATA(info), - DPU_KMS_INFO_DATALEN(info), - CONNECTOR_PROP_DPU_INFO); - kfree(info); - } - -#ifdef CONFIG_DRM_MSM_DSI_STAGING - if (connector_type == DRM_MODE_CONNECTOR_DSI) { - struct dsi_display *dsi_display; - - dsi_display = (struct dsi_display *)(display); - if (dsi_display && dsi_display->panel && - dsi_display->panel->hdr_props.hdr_enabled == true) { - msm_property_install_blob(&c_conn->property_info, - "hdr_properties", - DRM_MODE_PROP_IMMUTABLE, - CONNECTOR_PROP_HDR_INFO); - - msm_property_set_blob(&c_conn->property_info, - &c_conn->blob_hdr, - &dsi_display->panel->hdr_props, - sizeof(dsi_display->panel->hdr_props), - CONNECTOR_PROP_HDR_INFO); - } - } - - /* install PP_DITHER properties */ - _dpu_connector_install_dither_property(dev, dpu_kms, c_conn); - - msm_property_install_range(&c_conn->property_info, "bl_scale", - 0x0, 0, MAX_BL_SCALE_LEVEL, MAX_BL_SCALE_LEVEL, - CONNECTOR_PROP_BL_SCALE); - - msm_property_install_range(&c_conn->property_info, "ad_bl_scale", - 0x0, 0, MAX_AD_BL_SCALE_LEVEL, MAX_AD_BL_SCALE_LEVEL, - CONNECTOR_PROP_AD_BL_SCALE); -#endif - - /* enum/bitmask properties */ - msm_property_install_enum(&c_conn->property_info, "topology_name", - DRM_MODE_PROP_IMMUTABLE, 0, e_topology_name, - ARRAY_SIZE(e_topology_name), - CONNECTOR_PROP_TOPOLOGY_NAME); - msm_property_install_enum(&c_conn->property_info, "topology_control", - 0, 1, e_topology_control, - ARRAY_SIZE(e_topology_control), - CONNECTOR_PROP_TOPOLOGY_CONTROL); - msm_property_install_enum(&c_conn->property_info, "LP", - 0, 0, e_power_mode, - ARRAY_SIZE(e_power_mode), - CONNECTOR_PROP_LP); - - rc = msm_property_install_get_status(&c_conn->property_info); - if (rc) { - DPU_ERROR("failed to create one or more properties\n"); - goto error_destroy_property; - } - - DPU_DEBUG("connector %d attach encoder %d\n", - c_conn->base.base.id, encoder->base.id); - - priv->connectors[priv->num_connectors++] = &c_conn->base; - - return &c_conn->base; - -error_destroy_property: - if (c_conn->blob_caps) - drm_property_blob_put(c_conn->blob_caps); - if (c_conn->blob_hdr) - drm_property_blob_put(c_conn->blob_hdr); - if (c_conn->blob_dither) - drm_property_blob_put(c_conn->blob_dither); - - msm_property_destroy(&c_conn->property_info); -error_cleanup_conn: - mutex_destroy(&c_conn->lock); - drm_connector_cleanup(&c_conn->base); -error_free_conn: - kfree(c_conn); - - return ERR_PTR(rc); -} - -int dpu_connector_register_custom_event(struct dpu_kms *kms, - struct drm_connector *conn_drm, u32 event, bool val) -{ - int ret = -EINVAL; - - switch (event) { - case DRM_EVENT_SYS_BACKLIGHT: - ret = 0; - break; - default: - break; - } - return ret; -} diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.h deleted file mode 100644 index ed516fb..0000000 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.h +++ /dev/null @@ -1,555 +0,0 @@ -/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef _DPU_CONNECTOR_H_ -#define _DPU_CONNECTOR_H_ - -#include -#include -#include -#include - -#include "msm_drv.h" -#include "msm_prop.h" -#include "dpu_kms.h" - -#define DPU_CONNECTOR_NAME_SIZE 16 - -struct dpu_connector; -struct dpu_connector_state; - -/** - * struct dpu_connector_ops - callback functions for generic dpu connector - * Individual callbacks documented below. - */ -struct dpu_connector_ops { - /** - * post_init - perform additional initialization steps - * @connector: Pointer to drm connector structure - * @info: Pointer to dpu connector info structure - * @display: Pointer to private display handle - * Returns: Zero on success - */ - int (*post_init)(struct drm_connector *connector, - void *info, - void *display); - - /** - * detect - determine if connector is connected - * @connector: Pointer to drm connector structure - * @force: Force detect setting from drm framework - * @display: Pointer to private display handle - * Returns: Connector 'is connected' status - */ - enum drm_connector_status (*detect)(struct drm_connector *connector, - bool force, - void *display); - - /** - * get_modes - add drm modes via drm_mode_probed_add() - * @connector: Pointer to drm connector structure - * @display: Pointer to private display handle - * Returns: Number of modes added - */ - int (*get_modes)(struct drm_connector *connector, - void *display); - - /** - * put_modes - free up drm modes of the connector - * @connector: Pointer to drm connector structure - * @display: Pointer to private display handle - */ - void (*put_modes)(struct drm_connector *connector, - void *display); - - /** - * update_pps - update pps command for the display panel - * @pps_cmd: Pointer to pps command - * @display: Pointer to private display handle - * Returns: Zero on success - */ - int (*update_pps)(char *pps_cmd, void *display); - - /** - * mode_valid - determine if specified mode is valid - * @connector: Pointer to drm connector structure - * @mode: Pointer to drm mode structure - * @display: Pointer to private display handle - * Returns: Validity status for specified mode - */ - enum drm_mode_status (*mode_valid)(struct drm_connector *connector, - struct drm_display_mode *mode, - void *display); - - /** - * set_property - set property value - * @connector: Pointer to drm connector structure - * @state: Pointer to drm connector state structure - * @property_index: DRM property index - * @value: Incoming property value - * @display: Pointer to private display structure - * Returns: Zero on success - */ - int (*set_property)(struct drm_connector *connector, - struct drm_connector_state *state, - int property_index, - uint64_t value, - void *display); - - /** - * get_property - get property value - * @connector: Pointer to drm connector structure - * @state: Pointer to drm connector state structure - * @property_index: DRM property index - * @value: Pointer to variable for accepting property value - * @display: Pointer to private display structure - * Returns: Zero on success - */ - int (*get_property)(struct drm_connector *connector, - struct drm_connector_state *state, - int property_index, - uint64_t *value, - void *display); - - /** - * get_info - get display information - * @info: Pointer to msm display info structure - * @display: Pointer to private display structure - * Returns: Zero on success - */ - int (*get_info)(struct msm_display_info *info, void *display); - - /** - * get_mode_info - retrieve mode information - * @drm_mode: Display mode set for the display - * @mode_info: Out parameter. information of the display mode - * @max_mixer_width: max width supported by HW layer mixer - * Returns: Zero on success - */ - int (*get_mode_info)(const struct drm_display_mode *drm_mode, - struct msm_mode_info *mode_info, - u32 max_mixer_width); - - /** - * enable_event - notify display of event registration/unregistration - * @connector: Pointer to drm connector structure - * @event_idx: DPU connector event index - * @enable: Whether the event is being enabled/disabled - * @display: Pointer to private display structure - */ - void (*enable_event)(struct drm_connector *connector, - uint32_t event_idx, bool enable, void *display); - - int (*set_backlight)(void *display, u32 bl_lvl); - - /** - * soft_reset - perform a soft reset on the connector - * @display: Pointer to private display structure - * Return: Zero on success, -ERROR otherwise - */ - int (*soft_reset)(void *display); - - /** - * pre_kickoff - trigger display to program kickoff-time features - * @connector: Pointer to drm connector structure - * @display: Pointer to private display structure - * Returns: Zero on success - */ - int (*pre_kickoff)(struct drm_connector *connector, - void *display); - - /** - * clk_ctrl - perform clk enable/disable on the connector - * @handle: Pointer to clk handle - * @type: Type of clks - * @enable: State of clks - */ - int (*clk_ctrl)(void *handle, u32 type, u32 state); - - /** - * set_power - update dpms setting - * @connector: Pointer to drm connector structure - * @power_mode: One of the following, - * DPU_MODE_DPMS_ON - * DPU_MODE_DPMS_LP1 - * DPU_MODE_DPMS_LP2 - * DPU_MODE_DPMS_OFF - * @display: Pointer to private display structure - * Returns: Zero on success - */ - int (*set_power)(struct drm_connector *connector, - int power_mode, void *display); - - /** - * get_dst_format - get dst_format from display - * @display: Pointer to private display handle - * Returns: dst_format of display - */ - enum dsi_pixel_format (*get_dst_format)(void *display); - - /** - * post_kickoff - display to program post kickoff-time features - * @connector: Pointer to drm connector structure - * Returns: Zero on success - */ - int (*post_kickoff)(struct drm_connector *connector); - - /** - * send_hpd_event - send HPD uevent notification to userspace - * @display: Pointer to private display structure - */ - void (*send_hpd_event)(void *display); -}; - -/** - * enum dpu_connector_events - list of recognized connector events - */ -enum dpu_connector_events { - DPU_CONN_EVENT_VID_DONE, /* video mode frame done */ - DPU_CONN_EVENT_CMD_DONE, /* command mode frame done */ - DPU_CONN_EVENT_COUNT, -}; - -/** - * struct dpu_connector_evt - local event registration entry structure - * @cb_func: Pointer to desired callback function - * @usr: User pointer to pass to callback on event trigger - */ -struct dpu_connector_evt { - void (*cb_func)(uint32_t event_idx, - uint32_t instance_idx, void *usr, - uint32_t data0, uint32_t data1, - uint32_t data2, uint32_t data3); - void *usr; -}; - -/** - * struct dpu_connector - local dpu connector structure - * @base: Base drm connector structure - * @connector_type: Set to one of DRM_MODE_CONNECTOR_ types - * @encoder: Pointer to preferred drm encoder - * @panel: Pointer to drm panel, if present - * @display: Pointer to private display data structure - * @mmu_secure: MMU id for secure buffers - * @mmu_unsecure: MMU id for unsecure buffers - * @name: ASCII name of connector - * @lock: Mutex lock object for this structure - * @ops: Local callback function pointer table - * @dpms_mode: DPMS property setting from user space - * @lp_mode: LP property setting from user space - * @last_panel_power_mode: Last consolidated dpms/lp mode setting - * @property_info: Private structure for generic property handling - * @property_data: Array of private data for generic property handling - * @blob_caps: Pointer to blob structure for 'capabilities' property - * @blob_hdr: Pointer to blob structure for 'hdr_properties' property - * @blob_dither: Pointer to blob structure for default dither config - * @fb_kmap: true if kernel mapping of framebuffer is requested - * @event_table: Array of registered events - * @event_lock: Lock object for event_table - * @bl_device: backlight device node - */ -struct dpu_connector { - struct drm_connector base; - - int connector_type; - - struct drm_encoder *encoder; - struct drm_panel *panel; - void *display; - - struct msm_gem_address_space *aspace[DPU_IOMMU_DOMAIN_MAX]; - - char name[DPU_CONNECTOR_NAME_SIZE]; - - struct mutex lock; - struct dpu_connector_ops ops; - int dpms_mode; - int lp_mode; - int last_panel_power_mode; - - struct msm_property_info property_info; - struct msm_property_data property_data[CONNECTOR_PROP_COUNT]; - struct drm_property_blob *blob_caps; - struct drm_property_blob *blob_hdr; - struct drm_property_blob *blob_dither; - - bool fb_kmap; - struct dpu_connector_evt event_table[DPU_CONN_EVENT_COUNT]; - spinlock_t event_lock; - - struct backlight_device *bl_device; -}; - -/** - * to_dpu_connector - convert drm_connector pointer to dpu connector pointer - * @X: Pointer to drm_connector structure - * Returns: Pointer to dpu_connector structure - */ -#define to_dpu_connector(x) container_of((x), struct dpu_connector, base) - -/** - * dpu_connector_get_display - get dpu connector's private display pointer - * @C: Pointer to drm connector structure - * Returns: Pointer to associated private display structure - */ -#define dpu_connector_get_display(C) \ - ((C) ? to_dpu_connector((C))->display : 0) - -/** - * dpu_connector_get_panel - get dpu connector's private panel pointer - * @C: Pointer to drm connector structure - * Returns: Pointer to associated private display structure - */ -#define dpu_connector_get_panel(C) \ - ((C) ? to_dpu_connector((C))->panel : NULL) - -/** - * dpu_connector_get_encoder - get dpu connector's private encoder pointer - * @C: Pointer to drm connector structure - * Returns: Pointer to associated private encoder structure - */ -#define dpu_connector_get_encoder(C) \ - ((C) ? to_dpu_connector((C))->encoder : 0) - -/** - * dpu_connector_get_propinfo - get dpu connector's property info pointer - * @C: Pointer to drm connector structure - * Returns: Pointer to associated private property info structure - */ -#define dpu_connector_get_propinfo(C) \ - ((C) ? &to_dpu_connector((C))->property_info : 0) - -/** - * struct dpu_connector_state - private connector status structure - * @base: Base drm connector structure - * @out_fb: Pointer to output frame buffer, if applicable - * @property_state: Local storage for msm_prop properties - * @property_values: Local cache of current connector property values - * @property_blobs: blob properties - */ -struct dpu_connector_state { - struct drm_connector_state base; - struct drm_framebuffer *out_fb; - struct msm_property_state property_state; - struct msm_property_value property_values[CONNECTOR_PROP_COUNT]; - - struct drm_property_blob *property_blobs[CONNECTOR_PROP_BLOBCOUNT]; -}; - -/** - * to_dpu_connector_state - convert drm_connector_state pointer to - * dpu connector state pointer - * @X: Pointer to drm_connector_state structure - * Returns: Pointer to dpu_connector_state structure - */ -#define to_dpu_connector_state(x) \ - container_of((x), struct dpu_connector_state, base) - -/** - * dpu_connector_get_property - query integer value of connector property - * @S: Pointer to drm connector state - * @X: Property index, from enum msm_mdp_connector_property - * Returns: Integer value of requested property - */ -#define dpu_connector_get_property(S, X) \ - ((S) && ((X) < CONNECTOR_PROP_COUNT) ? \ - (to_dpu_connector_state((S))->property_values[(X)].value) : 0) - -/** - * dpu_connector_get_property_state - retrieve property state cache - * @S: Pointer to drm connector state - * Returns: Pointer to local property state structure - */ -#define dpu_connector_get_property_state(S) \ - ((S) ? (&to_dpu_connector_state((S))->property_state) : NULL) - -/** - * dpu_connector_get_out_fb - query out_fb value from dpu connector state - * @S: Pointer to drm connector state - * Returns: Output fb associated with specified connector state - */ -#define dpu_connector_get_out_fb(S) \ - ((S) ? to_dpu_connector_state((S))->out_fb : 0) - -/** - * dpu_connector_get_topology_name - helper accessor to retrieve topology_name - * @connector: pointer to drm connector - * Returns: value of the CONNECTOR_PROP_TOPOLOGY_NAME property or 0 - */ -static inline uint64_t dpu_connector_get_topology_name( - struct drm_connector *connector) -{ - if (!connector || !connector->state) - return 0; - return dpu_connector_get_property(connector->state, - CONNECTOR_PROP_TOPOLOGY_NAME); -} - -/** - * dpu_connector_get_lp - helper accessor to retrieve LP state - * @connector: pointer to drm connector - * Returns: value of the CONNECTOR_PROP_LP property or 0 - */ -static inline uint64_t dpu_connector_get_lp( - struct drm_connector *connector) -{ - if (!connector || !connector->state) - return 0; - return dpu_connector_get_property(connector->state, - CONNECTOR_PROP_LP); -} - -/** - * dpu_connector_set_property_for_commit - add property set to atomic state - * Add a connector state property update for the specified property index - * to the atomic state in preparation for a drm_atomic_commit. - * @connector: Pointer to drm connector - * @atomic_state: Pointer to DRM atomic state structure for commit - * @property_idx: Connector property index - * @value: Updated property value - * Returns: Zero on success - */ -int dpu_connector_set_property_for_commit(struct drm_connector *connector, - struct drm_atomic_state *atomic_state, - uint32_t property_idx, uint64_t value); - -/** - * dpu_connector_init - create drm connector object for a given display - * @dev: Pointer to drm device struct - * @encoder: Pointer to associated encoder - * @panel: Pointer to associated panel, can be NULL - * @display: Pointer to associated display object - * @ops: Pointer to callback operations function table - * @connector_poll: Set to appropriate DRM_CONNECTOR_POLL_ setting - * @connector_type: Set to appropriate DRM_MODE_CONNECTOR_ type - * Returns: Pointer to newly created drm connector struct - */ -struct drm_connector *dpu_connector_init(struct drm_device *dev, - struct drm_encoder *encoder, - struct drm_panel *panel, - void *display, - const struct dpu_connector_ops *ops, - int connector_poll, - int connector_type); - -/** - * dpu_connector_get_info - query display specific information - * @connector: Pointer to drm connector object - * @info: Pointer to msm display information structure - * Returns: Zero on success - */ -int dpu_connector_get_info(struct drm_connector *connector, - struct msm_display_info *info); - -/** - * dpu_connector_clk_ctrl - enables/disables the connector clks - * @connector: Pointer to drm connector object - * @enable: true/false to enable/disable - */ -void dpu_connector_clk_ctrl(struct drm_connector *connector, bool enable); - -/** - * dpu_connector_get_dpms - query dpms setting - * @connector: Pointer to drm connector structure - * Returns: Current DPMS setting for connector - */ -int dpu_connector_get_dpms(struct drm_connector *connector); - -/** - * dpu_connector_trigger_event - indicate that an event has occurred - * Any callbacks that have been registered against this event will - * be called from the same thread context. - * @connector: Pointer to drm connector structure - * @event_idx: Index of event to trigger - * @instance_idx: Event-specific "instance index" to pass to callback - * @data0: Event-specific "data" to pass to callback - * @data1: Event-specific "data" to pass to callback - * @data2: Event-specific "data" to pass to callback - * @data3: Event-specific "data" to pass to callback - * Returns: Zero on success - */ -int dpu_connector_trigger_event(void *drm_connector, - uint32_t event_idx, uint32_t instance_idx, - uint32_t data0, uint32_t data1, - uint32_t data2, uint32_t data3); - -/** - * dpu_connector_register_event - register a callback function for an event - * @connector: Pointer to drm connector structure - * @event_idx: Index of event to register - * @cb_func: Pointer to desired callback function - * @usr: User pointer to pass to callback on event trigger - * Returns: Zero on success - */ -int dpu_connector_register_event(struct drm_connector *connector, - uint32_t event_idx, - void (*cb_func)(uint32_t event_idx, - uint32_t instance_idx, void *usr, - uint32_t data0, uint32_t data1, - uint32_t data2, uint32_t data3), - void *usr); - -/** - * dpu_connector_unregister_event - unregister all callbacks for an event - * @connector: Pointer to drm connector structure - * @event_idx: Index of event to register - */ -void dpu_connector_unregister_event(struct drm_connector *connector, - uint32_t event_idx); - -/** - * dpu_connector_register_custom_event - register for async events - * @kms: Pointer to dpu_kms - * @conn_drm: Pointer to drm connector object - * @event: Event for which request is being sent - * @en: Flag to enable/disable the event - * Returns: Zero on success - */ -int dpu_connector_register_custom_event(struct dpu_kms *kms, - struct drm_connector *conn_drm, u32 event, bool en); - -/** - * dpu_connector_pre_kickoff - trigger kickoff time feature programming - * @connector: Pointer to drm connector object - * Returns: Zero on success - */ -int dpu_connector_pre_kickoff(struct drm_connector *connector); - -/** - * dpu_connector_needs_offset - adjust the output fence offset based on - * display type - * @connector: Pointer to drm connector object - * Returns: true if offset is required, false for all other cases. - */ -static inline bool dpu_connector_needs_offset(struct drm_connector *connector) -{ - struct dpu_connector *c_conn; - - if (!connector) - return false; - - c_conn = to_dpu_connector(connector); - return (c_conn->connector_type != DRM_MODE_CONNECTOR_VIRTUAL); -} - -/** - * dpu_connector_get_dither_cfg - get dither property data - * @conn: Pointer to drm_connector struct - * @state: Pointer to drm_connector_state struct - * @cfg: Pointer to pointer to dither cfg - * @len: length of the dither data - * Returns: Zero on success - */ -int dpu_connector_get_dither_cfg(struct drm_connector *conn, - struct drm_connector_state *state, void **cfg, size_t *len); - -#endif /* _DPU_CONNECTOR_H_ */ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index c0e8035..48920b05 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -33,7 +33,6 @@ #include "dpu_plane.h" #include "dpu_color_processing.h" #include "dpu_encoder.h" -#include "dpu_connector.h" #include "dpu_vbif.h" #include "dpu_power_handle.h" #include "dpu_core_perf.h" @@ -3347,7 +3346,6 @@ static int dpu_crtc_atomic_get_property(struct drm_crtc *crtc, struct dpu_crtc_state *cstate; struct drm_encoder *encoder; int i, ret = -EINVAL; - bool conn_offset = 0; bool is_cmd = true; if (!crtc || !state) { @@ -3356,13 +3354,6 @@ static int dpu_crtc_atomic_get_property(struct drm_crtc *crtc, dpu_crtc = to_dpu_crtc(crtc); cstate = to_dpu_crtc_state(state); - for (i = 0; i < cstate->num_connectors; ++i) { - conn_offset = dpu_connector_needs_offset( - cstate->connectors[i]); - if (conn_offset) - break; - } - /** * set the cmd flag only when all the encoders attached * to the crtc are in cmd mode. Consider all other cases diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 3854410..4386360 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -70,6 +70,8 @@ #define IDLE_SHORT_TIMEOUT 1 +#define MAX_VDISPLAY_SPLIT 1080 + /** * enum dpu_enc_rc_events - events for resource control state machine * @DPU_ENC_RC_EVENT_KICKOFF: @@ -172,7 +174,6 @@ enum dpu_enc_rc_states { * @frame_done_timer: watchdog timer for frame done event * @vsync_event_timer: vsync timer * @disp_info: local copy of msm_display_info struct - * @mode_info: local copy of msm_mode_info struct * @misr_enable: misr enable/disable status * @misr_frame_count: misr frame count before start capturing the data * @idle_pc_supported: indicate if idle power collaps is supported @@ -214,7 +215,6 @@ struct dpu_encoder_virt { struct timer_list vsync_event_timer; struct msm_display_info disp_info; - struct msm_mode_info mode_info; bool misr_enable; u32 misr_frame_count; @@ -497,8 +497,6 @@ void dpu_encoder_get_hw_resources(struct drm_encoder *drm_enc, if (phys && phys->ops.get_hw_resources) phys->ops.get_hw_resources(phys, hw_res, conn_state); } - - hw_res->topology = dpu_enc->mode_info.topology; } void dpu_encoder_destroy(struct drm_encoder *drm_enc) @@ -605,6 +603,25 @@ static void _dpu_encoder_adjust_mode(struct drm_connector *connector, } } +static struct msm_display_topology dpu_encoder_get_topology( + struct dpu_encoder_virt *dpu_enc, + struct dpu_kms *dpu_kms, + struct drm_display_mode *mode) +{ + struct msm_display_topology topology; + int i, intf_count = 0; + + for (i = 0; i < MAX_PHYS_ENCODERS_PER_VIRTUAL; i++) + if (dpu_enc->phys_encs[i]) + intf_count++; + + /* User split topology for width > 1080 */ + topology.num_lm = (mode->vdisplay > MAX_VDISPLAY_SPLIT) ? 2 : 1; + topology.num_enc = 0; + topology.num_intf = intf_count; + + return topology; +} static int dpu_encoder_virt_atomic_check( struct drm_encoder *drm_enc, struct drm_crtc_state *crtc_state, @@ -615,6 +632,7 @@ static int dpu_encoder_virt_atomic_check( struct dpu_kms *dpu_kms; const struct drm_display_mode *mode; struct drm_display_mode *adj_mode; + struct msm_display_topology topology; int i = 0; int ret = 0; @@ -660,6 +678,8 @@ static int dpu_encoder_virt_atomic_check( } } + topology = dpu_encoder_get_topology(dpu_enc, dpu_kms, adj_mode); + /* Reserve dynamic resources now. Indicating AtomicTest phase */ if (!ret) { /* @@ -669,7 +689,7 @@ static int dpu_encoder_virt_atomic_check( if (drm_atomic_crtc_needs_modeset(crtc_state) && dpu_enc->mode_set_complete) { ret = dpu_rm_reserve(&dpu_kms->rm, drm_enc, crtc_state, - conn_state, true); + conn_state, topology, true); dpu_enc->mode_set_complete = false; } } @@ -690,7 +710,6 @@ static void _dpu_encoder_update_vsync_source(struct dpu_encoder_virt *dpu_enc, struct dpu_kms *dpu_kms; struct dpu_hw_mdp *hw_mdptop; struct drm_encoder *drm_enc; - struct msm_mode_info *mode_info; int i; if (!dpu_enc || !disp_info) { @@ -720,19 +739,12 @@ static void _dpu_encoder_update_vsync_source(struct dpu_encoder_virt *dpu_enc, return; } - mode_info = &dpu_enc->mode_info; - if (!mode_info) { - DPU_ERROR("invalid mode info\n"); - return; - } - if (hw_mdptop->ops.setup_vsync_source && disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE) { for (i = 0; i < dpu_enc->num_phys_encs; i++) vsync_cfg.ppnumber[i] = dpu_enc->hw_pp[i]->idx; vsync_cfg.pp_count = dpu_enc->num_phys_encs; - vsync_cfg.frame_rate = mode_info->frame_rate; if (disp_info->is_te_using_watchdog_timer) vsync_cfg.vsync_source = DPU_VSYNC_SOURCE_WD_TIMER_0; else @@ -789,9 +801,6 @@ static void _dpu_encoder_resource_control_helper(struct drm_encoder *drm_enc, dpu_power_resource_enable(&priv->phandle, dpu_kms->core_client, true); - /* enable DSI clks */ - dpu_connector_clk_ctrl(dpu_enc->cur_master->connector, true); - /* enable all the irq */ _dpu_encoder_irq_control(drm_enc, true); @@ -799,9 +808,6 @@ static void _dpu_encoder_resource_control_helper(struct drm_encoder *drm_enc, /* disable all the irq */ _dpu_encoder_irq_control(drm_enc, false); - /* disable DSI clks */ - dpu_connector_clk_ctrl(dpu_enc->cur_master->connector, false); - /* disable DPU core clks */ dpu_power_resource_enable(&priv->phandle, dpu_kms->core_client, false); @@ -813,7 +819,6 @@ static void _dpu_encoder_resource_control_helper(struct drm_encoder *drm_enc, static int dpu_encoder_resource_control(struct drm_encoder *drm_enc, u32 sw_event) { - unsigned int lp, idle_timeout; struct dpu_encoder_virt *dpu_enc; struct msm_drm_private *priv; struct msm_drm_thread *disp_thread; @@ -919,25 +924,13 @@ static int dpu_encoder_resource_control(struct drm_encoder *drm_enc, return 0; } - /* set idle timeout based on master connector's lp value */ - if (dpu_enc->cur_master) - lp = dpu_connector_get_lp( - dpu_enc->cur_master->connector); - else - lp = DPU_MODE_DPMS_ON; - - if (lp == DPU_MODE_DPMS_LP2) - idle_timeout = IDLE_SHORT_TIMEOUT; - else - idle_timeout = dpu_enc->idle_timeout; - kthread_queue_delayed_work( &disp_thread->worker, &dpu_enc->delayed_off_work, - msecs_to_jiffies(idle_timeout)); + msecs_to_jiffies(dpu_enc->idle_timeout)); DPU_EVT32(DRMID(drm_enc), sw_event, dpu_enc->rc_state, - idle_timeout, DPU_EVTLOG_FUNC_CASE2); + dpu_enc->idle_timeout, DPU_EVTLOG_FUNC_CASE2); DPU_DEBUG_ENC(dpu_enc, "sw_event:%d, work scheduled\n", sw_event); break; @@ -1132,8 +1125,9 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc, struct dpu_kms *dpu_kms; struct list_head *connector_list; struct drm_connector *conn = NULL, *conn_iter; - struct dpu_connector *dpu_conn = NULL; struct dpu_rm_hw_iter pp_iter; + struct msm_display_topology topology; + enum dpu_rm_topology_name topology_name; int i = 0, ret; if (!drm_enc) { @@ -1162,33 +1156,11 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc, return; } - dpu_conn = to_dpu_connector(conn); - if (dpu_conn) { - ret = dpu_conn->ops.get_mode_info(adj_mode, &dpu_enc->mode_info, - dpu_kms->catalog->caps->max_mixer_width); - if (ret) { - DPU_ERROR_ENC(dpu_enc, - "invalid topology for the mode\n"); - return; - } - } - - /* release resources before seamless mode change */ - if (msm_is_mode_seamless_dms(adj_mode)) { - /* restore resource state before releasing them */ - ret = dpu_encoder_resource_control(drm_enc, - DPU_ENC_RC_EVENT_PRE_MODESET); - if (ret) { - DPU_ERROR_ENC(dpu_enc, - "dpu resource control failed: %d\n", - ret); - return; - } - } + topology = dpu_encoder_get_topology(dpu_enc, dpu_kms, adj_mode); /* Reserve dynamic resources now. Indicating non-AtomicTest phase */ ret = dpu_rm_reserve(&dpu_kms->rm, drm_enc, drm_enc->crtc->state, - conn->state, false); + conn->state, topology, false); if (ret) { DPU_ERROR_ENC(dpu_enc, "failed to reserve hw resources, %d\n", ret); @@ -1203,6 +1175,7 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc, dpu_enc->hw_pp[i] = (struct dpu_hw_pingpong *) pp_iter.hw; } + topology_name = dpu_rm_get_topology_name(topology); for (i = 0; i < dpu_enc->num_phys_encs; i++) { struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i]; @@ -1214,6 +1187,7 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc, } phys->hw_pp = dpu_enc->hw_pp[i]; phys->connector = conn->state->connector; + phys->topology_name = topology_name; if (phys->ops.mode_set) phys->ops.mode_set(phys, mode, adj_mode); } @@ -1711,8 +1685,6 @@ int dpu_encoder_helper_wait_event_timeout( void dpu_encoder_helper_hw_reset(struct dpu_encoder_phys *phys_enc) { struct dpu_encoder_virt *dpu_enc; - struct dpu_connector *dpu_con; - void *dpu_con_disp; struct dpu_hw_ctl *ctl; int rc; @@ -1729,22 +1701,6 @@ void dpu_encoder_helper_hw_reset(struct dpu_encoder_phys *phys_enc) DPU_DEBUG_ENC(dpu_enc, "ctl %d reset\n", ctl->idx); DPU_EVT32(DRMID(phys_enc->parent), ctl->idx); - if (phys_enc->ops.is_master && phys_enc->ops.is_master(phys_enc) && - phys_enc->connector) { - dpu_con = to_dpu_connector(phys_enc->connector); - dpu_con_disp = dpu_connector_get_display(phys_enc->connector); - - if (dpu_con->ops.soft_reset) { - rc = dpu_con->ops.soft_reset(dpu_con_disp); - if (rc) { - DPU_ERROR_ENC(dpu_enc, - "connector soft reset failure\n"); - DPU_DBG_DUMP("all", "dbg_bus", "vbif_dbg_bus", - "panic"); - } - } - } - rc = ctl->ops.reset(ctl); if (rc) { DPU_ERROR_ENC(dpu_enc, "ctl %d reset failure\n", ctl->idx); @@ -1862,22 +1818,6 @@ void dpu_encoder_trigger_kickoff_pending(struct drm_encoder *drm_enc) } } -static void _dpu_encoder_setup_dither(struct dpu_encoder_phys *phys) -{ - void *dither_cfg; - int ret = 0; - size_t len = 0; - - if (!phys || !phys->connector || !phys->hw_pp || - !phys->hw_pp->ops.setup_dither) - return; - - ret = dpu_connector_get_dither_cfg(phys->connector, - phys->connector->state, &dither_cfg, &len); - if (!ret) - phys->hw_pp->ops.setup_dither(phys->hw_pp, dither_cfg, len); -} - static u32 _dpu_encoder_calculate_linetime(struct dpu_encoder_virt *dpu_enc, struct drm_display_mode *mode) { @@ -2028,7 +1968,6 @@ void dpu_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, struct dpu_encoder_phys *phys; bool needs_hw_reset = false; unsigned int i; - int rc; if (!drm_enc || !params) { DPU_ERROR("invalid args\n"); @@ -2048,7 +1987,6 @@ void dpu_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, phys->ops.prepare_for_kickoff(phys, params); if (phys->enable_state == DPU_ENC_ERR_NEEDS_HW_RESET) needs_hw_reset = true; - _dpu_encoder_setup_dither(phys); } } DPU_ATRACE_END("enc_prepare_for_kickoff"); @@ -2064,14 +2002,6 @@ void dpu_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, phys->ops.hw_reset(phys); } } - - if (dpu_enc->cur_master && dpu_enc->cur_master->connector) { - rc = dpu_connector_pre_kickoff(dpu_enc->cur_master->connector); - if (rc) - DPU_ERROR_ENC(dpu_enc, "kickoff conn%d failed rc %d\n", - dpu_enc->cur_master->connector->base.id, - rc); - } } void dpu_encoder_kickoff(struct drm_encoder *drm_enc) @@ -2704,8 +2634,7 @@ static void dpu_encoder_frame_done_timeout(struct timer_list *t) .early_unregister = dpu_encoder_early_unregister, }; -struct drm_encoder *dpu_encoder_init( - struct drm_device *dev, +int dpu_encoder_setup(struct drm_device *dev, struct drm_encoder *enc, struct msm_display_info *disp_info) { struct msm_drm_private *priv = dev->dev_private; @@ -2715,11 +2644,7 @@ struct drm_encoder *dpu_encoder_init( int drm_enc_mode = DRM_MODE_ENCODER_NONE; int ret = 0; - dpu_enc = kzalloc(sizeof(*dpu_enc), GFP_KERNEL); - if (!dpu_enc) { - ret = -ENOMEM; - goto fail; - } + dpu_enc = to_dpu_encoder_virt(enc); mutex_init(&dpu_enc->enc_lock); ret = dpu_encoder_setup_display(dpu_enc, dpu_kms, disp_info, @@ -2729,16 +2654,12 @@ struct drm_encoder *dpu_encoder_init( dpu_enc->cur_master = NULL; spin_lock_init(&dpu_enc->enc_spinlock); - drm_enc = &dpu_enc->base; - drm_encoder_init(dev, drm_enc, &dpu_encoder_funcs, drm_enc_mode, NULL); - drm_encoder_helper_add(drm_enc, &dpu_encoder_helper_funcs); atomic_set(&dpu_enc->frame_done_timeout, 0); timer_setup(&dpu_enc->frame_done_timer, dpu_encoder_frame_done_timeout, 0); - if ((disp_info->intf_type == DRM_MODE_CONNECTOR_DSI) && - disp_info->is_primary) + if (disp_info->intf_type == DRM_MODE_CONNECTOR_DSI) timer_setup(&dpu_enc->vsync_event_timer, dpu_encoder_vsync_event_handler, 0); @@ -2756,14 +2677,38 @@ struct drm_encoder *dpu_encoder_init( DPU_DEBUG_ENC(dpu_enc, "created\n"); - return drm_enc; + return ret; fail: DPU_ERROR("failed to create encoder\n"); if (drm_enc) dpu_encoder_destroy(drm_enc); - return ERR_PTR(ret); + return ret; + + +} + +struct drm_encoder *dpu_encoder_init(struct drm_device *dev, + int drm_enc_mode) +{ + struct dpu_encoder_virt *dpu_enc = NULL; + int rc = 0; + + dpu_enc = devm_kzalloc(dev->dev, sizeof(*dpu_enc), GFP_KERNEL); + if (!dpu_enc) + return ERR_PTR(ENOMEM); + + rc = drm_encoder_init(dev, &dpu_enc->base, &dpu_encoder_funcs, + drm_enc_mode, NULL); + if (rc) { + devm_kfree(dev->dev, dpu_enc); + return ERR_PTR(rc); + } + + drm_encoder_helper_add(&dpu_enc->base, &dpu_encoder_helper_funcs); + + return &dpu_enc->base; } int dpu_encoder_wait_for_event(struct drm_encoder *drm_enc, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h index b25619d..d853ad9 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h @@ -45,7 +45,6 @@ struct dpu_encoder_hw_resources { enum dpu_intf_mode wbs[WB_MAX]; bool needs_cdm; u32 display_num_of_h_tiles; - struct msm_display_topology topology; }; /** @@ -160,6 +159,15 @@ int dpu_encoder_wait_for_event(struct drm_encoder *drm_encoder, */ struct drm_encoder *dpu_encoder_init( struct drm_device *dev, + int drm_enc_mode); + +/** + * dpu_encoder_setup - setup dpu_encoder for the display probed + * @dev: Pointer to drm device structure + * @enc: Pointer to the drm_encoder + * @disp_info: Pointer to the display info + */ +int dpu_encoder_setup(struct drm_device *dev, struct drm_encoder *enc, struct msm_display_info *disp_info); /** diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h index 576c475..35beefa 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h @@ -25,7 +25,6 @@ #include "dpu_hw_wb.h" #include "dpu_hw_cdm.h" #include "dpu_encoder.h" -#include "dpu_connector.h" #define DPU_ENCODER_NAME_MAX 16 @@ -221,6 +220,7 @@ struct dpu_encoder_irq { * @split_role: Role to play in a split-panel configuration * @intf_mode: Interface mode * @intf_idx: Interface index on dpu hardware + * @topology_name: topology selected for the display * @enc_spinlock: Virtual-Encoder-Wide Spin Lock for IRQ purposes * @enable_state: Enable state tracking * @vblank_refcount: Reference count of vblank request @@ -250,6 +250,7 @@ struct dpu_encoder_phys { enum dpu_enc_split_role split_role; enum dpu_intf_mode intf_mode; enum dpu_intf intf_idx; + enum dpu_rm_topology_name topology_name; spinlock_t *enc_spinlock; enum dpu_enc_enable_state enable_state; atomic_t vblank_refcount; @@ -443,14 +444,11 @@ int dpu_encoder_helper_wait_event_timeout( static inline enum dpu_3d_blend_mode dpu_encoder_helper_get_3d_blend_mode( struct dpu_encoder_phys *phys_enc) { - enum dpu_rm_topology_name topology; - if (!phys_enc || phys_enc->enable_state == DPU_ENC_DISABLING) return BLEND_3D_NONE; - topology = dpu_connector_get_topology_name(phys_enc->connector); if (phys_enc->split_role == ENC_ROLE_SOLO && - topology == DPU_RM_TOPOLOGY_DUALPIPE_3DMERGE) + phys_enc->topology_name == DPU_RM_TOPOLOGY_DUALPIPE_3DMERGE) return BLEND_3D_H_ROW_INT; return BLEND_3D_NONE; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c index b680718..73e5938 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c @@ -15,7 +15,6 @@ #include "dpu_hw_interrupts.h" #include "dpu_core_irq.h" #include "dpu_formats.h" -#include "dsi_display.h" #include "dpu_trace.h" #define DPU_DEBUG_VIDENC(e, fmt, ...) DPU_DEBUG("enc%d intf%d " fmt, \ @@ -356,13 +355,10 @@ static void dpu_encoder_phys_vid_underrun_irq(void *arg, int irq_idx) static bool _dpu_encoder_phys_is_dual_ctl(struct dpu_encoder_phys *phys_enc) { - enum dpu_rm_topology_name topology; - if (!phys_enc) return false; - topology = dpu_connector_get_topology_name(phys_enc->connector); - if (topology == DPU_RM_TOPOLOGY_DUALPIPE) + if (phys_enc->topology_name == DPU_RM_TOPOLOGY_DUALPIPE) return true; return false; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 0fbeb75..37c7c66 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -27,18 +27,6 @@ #include "msm_mmu.h" #include "msm_gem.h" -#ifdef CONFIG_DRM_MSM_DSI_STAGING -#include "dsi_display.h" -#include "dsi_drm.h" -#endif -#ifdef CONFIG_DRM_MSM_WRITEBACK -#include "dpu_wb.h" -#endif -#ifdef CONFIG_DRM_MSM_DISPLAYPORT -#include "dp/dp_display.h" -#include "dp_drm.h" -#endif -#include "dpu_connector.h" #include "dpu_kms.h" #include "dpu_core_irq.h" #include "dpu_formats.h" @@ -473,9 +461,7 @@ static void dpu_kms_complete_commit(struct msm_kms *kms, struct msm_drm_private *priv; struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state; - struct drm_connector *conn; - struct drm_connector_state *old_conn_state; - int i, rc = 0; + int i; if (!kms || !old_state) return; @@ -488,19 +474,6 @@ static void dpu_kms_complete_commit(struct msm_kms *kms, for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i) dpu_crtc_complete_commit(crtc, old_crtc_state); - for_each_old_connector_in_state(old_state, conn, old_conn_state, i) { - struct dpu_connector *c_conn; - - c_conn = to_dpu_connector(conn); - if (!c_conn->ops.post_kickoff) - continue; - rc = c_conn->ops.post_kickoff(conn); - if (rc) { - pr_err("Connector Post kickoff failed rc=%d\n", - rc); - } - } - dpu_power_resource_enable(&priv->phandle, dpu_kms->core_client, false); pm_runtime_put_sync(dpu_kms->dev->dev); @@ -553,317 +526,36 @@ static void dpu_kms_wait_for_commit_done(struct msm_kms *kms, drm_crtc_vblank_put(crtc); } -/** - * _dpu_kms_get_displays - query for underlying display handles and cache them - * @dpu_kms: Pointer to dpu kms structure - * Returns: Zero on success - */ -static int _dpu_kms_get_displays(struct dpu_kms *dpu_kms) -{ - int rc = -ENOMEM; - - if (!dpu_kms) { - DPU_ERROR("invalid dpu kms\n"); - return -EINVAL; - } - -#ifdef CONFIG_DRM_MSM_DSI_STAGING - /* dsi */ - dpu_kms->dsi_displays = NULL; - dpu_kms->dsi_display_count = dsi_display_get_num_of_displays(); - if (dpu_kms->dsi_display_count) { - dpu_kms->dsi_displays = kcalloc(dpu_kms->dsi_display_count, - sizeof(void *), - GFP_KERNEL); - if (!dpu_kms->dsi_displays) { - DPU_ERROR("failed to allocate dsi displays\n"); - goto exit_deinit_dsi; - } - dpu_kms->dsi_display_count = - dsi_display_get_active_displays(dpu_kms->dsi_displays, - dpu_kms->dsi_display_count); - } -#endif - -#ifdef CONFIG_DRM_MSM_WRITEBACK - /* wb */ - dpu_kms->wb_displays = NULL; - dpu_kms->wb_display_count = dpu_wb_get_num_of_displays(); - if (dpu_kms->wb_display_count) { - dpu_kms->wb_displays = kcalloc(dpu_kms->wb_display_count, - sizeof(void *), - GFP_KERNEL); - if (!dpu_kms->wb_displays) { - DPU_ERROR("failed to allocate wb displays\n"); - goto exit_deinit_wb; - } - dpu_kms->wb_display_count = - wb_display_get_displays(dpu_kms->wb_displays, - dpu_kms->wb_display_count); - } -#endif - -#ifdef CONFIG_DRM_MSM_DISPLAYPORT - /* dp */ - dpu_kms->dp_displays = NULL; - dpu_kms->dp_display_count = dp_display_get_num_of_displays(); - if (dpu_kms->dp_display_count) { - dpu_kms->dp_displays = kcalloc(dpu_kms->dp_display_count, - sizeof(void *), GFP_KERNEL); - if (!dpu_kms->dp_displays) { - DPU_ERROR("failed to allocate dp displays\n"); - goto exit_deinit_dp; - } - dpu_kms->dp_display_count = - dp_display_get_displays(dpu_kms->dp_displays, - dpu_kms->dp_display_count); - } -#endif - - return 0; - -#ifdef CONFIG_DRM_MSM_DISPLAYPORT -exit_deinit_dp: - kfree(dpu_kms->dp_displays); - dpu_kms->dp_display_count = 0; - dpu_kms->dp_displays = NULL; -#endif -#ifdef CONFIG_DRM_MSM_WRITEBACK -exit_deinit_wb: - kfree(dpu_kms->wb_displays); - dpu_kms->wb_display_count = 0; - dpu_kms->wb_displays = NULL; -#endif -#ifdef CONFIG_DRM_MSM_DSI_STAGING -exit_deinit_dsi: - kfree(dpu_kms->dsi_displays); - dpu_kms->dsi_display_count = 0; - dpu_kms->dsi_displays = NULL; - return rc; -#else - return rc; -#endif -} - -/** - * _dpu_kms_release_displays - release cache of underlying display handles - * @dpu_kms: Pointer to dpu kms structure - */ -static void _dpu_kms_release_displays(struct dpu_kms *dpu_kms) -{ - if (!dpu_kms) { - DPU_ERROR("invalid dpu kms\n"); - return; - } - - kfree(dpu_kms->wb_displays); - dpu_kms->wb_displays = NULL; - dpu_kms->wb_display_count = 0; - - kfree(dpu_kms->dsi_displays); - dpu_kms->dsi_displays = NULL; - dpu_kms->dsi_display_count = 0; -} - -#ifdef CONFIG_DRM_MSM_DSI_STAGING static void _dpu_kms_initialize_dsi(struct drm_device *dev, struct msm_drm_private *priv, - struct dpu_kms *dpu_kms, - unsigned max_encoders) -{ - static const struct dpu_connector_ops dsi_ops = { - .post_init = dsi_conn_post_init, - .detect = dsi_conn_detect, - .get_modes = dsi_connector_get_modes, - .put_modes = dsi_connector_put_modes, - .mode_valid = dsi_conn_mode_valid, - .get_info = dsi_display_get_info, - .set_backlight = dsi_display_set_backlight, - .soft_reset = dsi_display_soft_reset, - .pre_kickoff = dsi_conn_pre_kickoff, - .clk_ctrl = dsi_display_clk_ctrl, - .set_power = dsi_display_set_power, - .get_mode_info = dsi_conn_get_mode_info, - .get_dst_format = dsi_display_get_dst_format, - .post_kickoff = dsi_conn_post_kickoff - }; - struct msm_display_info info; - struct drm_encoder *encoder; - void *display, *connector; - int i, rc; - - /* dsi */ - for (i = 0; i < dpu_kms->dsi_display_count && - priv->num_encoders < max_encoders; ++i) { - display = dpu_kms->dsi_displays[i]; - encoder = NULL; - - memset(&info, 0x0, sizeof(info)); - rc = dsi_display_get_info(&info, display); - if (rc) { - DPU_ERROR("dsi get_info %d failed\n", i); - continue; - } - - encoder = dpu_encoder_init(dev, &info); - if (IS_ERR_OR_NULL(encoder)) { - DPU_ERROR("encoder init failed for dsi %d\n", i); - continue; - } - - rc = dsi_display_drm_bridge_init(display, encoder); - if (rc) { - DPU_ERROR("dsi bridge %d init failed, %d\n", i, rc); - dpu_encoder_destroy(encoder); - continue; - } - - connector = dpu_connector_init(dev, - encoder, - 0, - display, - &dsi_ops, - DRM_CONNECTOR_POLL_HPD, - DRM_MODE_CONNECTOR_DSI); - if (connector) { - priv->encoders[priv->num_encoders++] = encoder; - } else { - DPU_ERROR("dsi %d connector init failed\n", i); - dsi_display_drm_bridge_deinit(display); - dpu_encoder_destroy(encoder); - } - } -} -#endif - -#ifdef CONFIG_DRM_MSM_WRITEBACK -static void _dpu_kms_initialize_wb(struct drm_device *dev, - struct msm_drm_private *priv, - struct dpu_kms *dpu_kms, - unsigned max_encoders) + struct dpu_kms *dpu_kms) { - static const struct dpu_connector_ops wb_ops = { - .post_init = dpu_wb_connector_post_init, - .detect = dpu_wb_connector_detect, - .get_modes = dpu_wb_connector_get_modes, - .set_property = dpu_wb_connector_set_property, - .get_info = dpu_wb_get_info, - .soft_reset = NULL, - .get_mode_info = dpu_wb_get_mode_info, - .get_dst_format = NULL - }; - struct msm_display_info info; - struct drm_encoder *encoder; - void *display, *connector; + struct drm_encoder *encoder = NULL; int i, rc; - /* wb */ - for (i = 0; i < dpu_kms->wb_display_count && - priv->num_encoders < max_encoders; ++i) { - display = dpu_kms->wb_displays[i]; - encoder = NULL; - - memset(&info, 0x0, sizeof(info)); - rc = dpu_wb_get_info(&info, display); - if (rc) { - DPU_ERROR("wb get_info %d failed\n", i); - continue; - } - - encoder = dpu_encoder_init(dev, &info); - if (IS_ERR_OR_NULL(encoder)) { - DPU_ERROR("encoder init failed for wb %d\n", i); - continue; - } - - rc = dpu_wb_drm_init(display, encoder); - if (rc) { - DPU_ERROR("wb bridge %d init failed, %d\n", i, rc); - dpu_encoder_destroy(encoder); - continue; - } - - connector = dpu_connector_init(dev, - encoder, - 0, - display, - &wb_ops, - DRM_CONNECTOR_POLL_HPD, - DRM_MODE_CONNECTOR_VIRTUAL); - if (connector) { - priv->encoders[priv->num_encoders++] = encoder; - } else { - DPU_ERROR("wb %d connector init failed\n", i); - dpu_wb_drm_deinit(display); - dpu_encoder_destroy(encoder); - } + /*TODO: Support two independent DSI connectors */ + encoder = dpu_encoder_init(dev, DRM_MODE_CONNECTOR_DSI); + if (IS_ERR_OR_NULL(encoder)) { + DPU_ERROR("encoder init failed for dsi display\n"); + return; } -} -#endif - -#ifdef CONFIG_DRM_MSM_DISPLAYPORT -static void _dpu_kms_initialize_dp(struct drm_device *dev, - struct msm_drm_private *priv, - struct dpu_kms *dpu_kms, - unsigned max_encoders) -{ - static const struct dpu_connector_ops dp_ops = { - .post_init = dp_connector_post_init, - .detect = dp_connector_detect, - .get_modes = dp_connector_get_modes, - .mode_valid = dp_connector_mode_valid, - .get_info = dp_connector_get_info, - .get_mode_info = dp_connector_get_mode_info, - .send_hpd_event = dp_connector_send_hpd_event, - }; - struct msm_display_info info; - struct drm_encoder *encoder; - void *display, *connector; - int i, rc; - /* dp */ - for (i = 0; i < dpu_kms->dp_display_count && - priv->num_encoders < max_encoders; ++i) { - display = dpu_kms->dp_displays[i]; - encoder = NULL; + priv->encoders[priv->num_encoders++] = encoder; - memset(&info, 0x0, sizeof(info)); - rc = dp_connector_get_info(&info, display); - if (rc) { - DPU_ERROR("dp get_info %d failed\n", i); - continue; + for (i = 0; i < ARRAY_SIZE(priv->dsi); i++) { + if (!priv->dsi[i]) { + DPU_DEBUG("invalid msm_dsi for ctrl %d\n", i); + return; } - encoder = dpu_encoder_init(dev, &info); - if (IS_ERR_OR_NULL(encoder)) { - DPU_ERROR("dp encoder init failed %d\n", i); - continue; - } - - rc = dp_drm_bridge_init(display, encoder); + rc = msm_dsi_modeset_init(priv->dsi[i], dev, encoder); if (rc) { - DPU_ERROR("dp bridge %d init failed, %d\n", i, rc); - dpu_encoder_destroy(encoder); + DPU_ERROR("modeset_init failed for dsi[%d], rc = %d\n", + i, rc); continue; } - - connector = dpu_connector_init(dev, - encoder, - NULL, - display, - &dp_ops, - DRM_CONNECTOR_POLL_HPD, - DRM_MODE_CONNECTOR_DisplayPort); - if (connector) { - priv->encoders[priv->num_encoders++] = encoder; - } else { - DPU_ERROR("dp %d connector init failed\n", i); - dp_drm_bridge_deinit(display); - dpu_encoder_destroy(encoder); - } } } -#endif /** * _dpu_kms_setup_displays - create encoders, bridges and connectors @@ -877,26 +569,12 @@ static void _dpu_kms_setup_displays(struct drm_device *dev, struct msm_drm_private *priv, struct dpu_kms *dpu_kms) { - unsigned max_encoders; - - max_encoders = dpu_kms->dsi_display_count + dpu_kms->wb_display_count + - dpu_kms->dp_display_count; - if (max_encoders > ARRAY_SIZE(priv->encoders)) { - max_encoders = ARRAY_SIZE(priv->encoders); - DPU_ERROR("capping number of displays to %d", max_encoders); - } - -#ifdef CONFIG_DRM_MSM_DSI_STAGING - _dpu_kms_initialize_dsi(dev, priv, dpu_kms, max_encoders); -#endif + _dpu_kms_initialize_dsi(dev, priv, dpu_kms); -#ifdef CONFIG_DRM_MSM_WRITEBACK - _dpu_kms_initialize_wb(dev, priv, dpu_kms, max_encoders); -#endif - -#ifdef CONFIG_DRM_MSM_DISPLAYPORT - _dpu_kms_initialize_dp(dev, priv, dpu_kms, max_encoders); -#endif + /** + * Extend this function to initialize other + * types of displays + */ } static void _dpu_kms_drm_obj_destroy(struct dpu_kms *dpu_kms) @@ -931,8 +609,6 @@ static void _dpu_kms_drm_obj_destroy(struct dpu_kms *dpu_kms) for (i = 0; i < priv->num_encoders; i++) priv->encoders[i]->funcs->destroy(priv->encoders[i]); priv->num_encoders = 0; - - _dpu_kms_release_displays(dpu_kms); } static int _dpu_kms_drm_obj_init(struct dpu_kms *dpu_kms) @@ -963,12 +639,12 @@ static int _dpu_kms_drm_obj_init(struct dpu_kms *dpu_kms) ret = dpu_core_irq_domain_add(dpu_kms); if (ret) goto fail_irq; + /* - * Query for underlying display drivers, and create connectors, - * bridges and encoders for them. + * Create encoder and query display drivers to create + * bridges and connectors */ - if (!_dpu_kms_get_displays(dpu_kms)) - (void)_dpu_kms_setup_displays(dev, priv, dpu_kms); + _dpu_kms_setup_displays(dev, priv, dpu_kms); max_crtc_count = min(catalog->mixer_count, priv->num_encoders); @@ -1386,8 +1062,6 @@ static void _dpu_kms_hw_destroy(struct dpu_kms *dpu_kms, dpu_power_handle_unregister_event( &priv->phandle, dpu_kms->power_event); - _dpu_kms_release_displays(dpu_kms); - /* safe to call these more than once during shutdown */ _dpu_debugfs_destroy(dpu_kms); _dpu_kms_mmu_destroy(dpu_kms); @@ -1590,53 +1264,10 @@ static int dpu_kms_atomic_check(struct msm_kms *kms, dpu_kms->aspace[domain] : NULL; } -static void _dpu_kms_post_open(struct msm_kms *kms, struct drm_file *file) -{ - struct drm_device *dev = NULL; - struct dpu_kms *dpu_kms = NULL; - struct drm_connector *connector = NULL; - struct drm_connector_list_iter conn_iter; - struct dpu_connector *dpu_conn = NULL; - - if (!kms) { - DPU_ERROR("invalid kms\n"); - return; - } - - dpu_kms = to_dpu_kms(kms); - dev = dpu_kms->dev; - - if (!dev) { - DPU_ERROR("invalid device\n"); - return; - } - - if (!dev->mode_config.poll_enabled) - return; - - mutex_lock(&dev->mode_config.mutex); - drm_connector_list_iter_begin(dev, &conn_iter); - drm_for_each_connector_iter(connector, &conn_iter) { - /* Only handle HPD capable connectors. */ - if (!(connector->polled & DRM_CONNECTOR_POLL_HPD)) - continue; - - dpu_conn = to_dpu_connector(connector); - - if (dpu_conn->ops.send_hpd_event) - dpu_conn->ops.send_hpd_event(dpu_conn->display); - } - drm_connector_list_iter_end(&conn_iter); - mutex_unlock(&dev->mode_config.mutex); - -} - static int dpu_kms_pm_suspend(struct device *dev) { struct drm_device *ddev; struct drm_modeset_acquire_ctx ctx; - struct drm_connector *conn; - struct drm_connector_list_iter conn_iter; struct drm_atomic_state *state; struct dpu_kms *dpu_kms; int ret = 0, num_crtcs = 0; @@ -1680,45 +1311,6 @@ static int dpu_kms_pm_suspend(struct device *dev) } state->acquire_ctx = &ctx; - drm_connector_list_iter_begin(ddev, &conn_iter); - drm_for_each_connector_iter(conn, &conn_iter) { - struct drm_crtc_state *crtc_state; - uint64_t lp; - - if (!conn->state || !conn->state->crtc || - conn->dpms != DRM_MODE_DPMS_ON) - continue; - - lp = dpu_connector_get_lp(conn); - if (lp == DPU_MODE_DPMS_LP1) { - /* transition LP1->LP2 on pm suspend */ - ret = dpu_connector_set_property_for_commit(conn, state, - CONNECTOR_PROP_LP, DPU_MODE_DPMS_LP2); - if (ret) { - DRM_ERROR("failed to set lp2 for conn %d\n", - conn->base.id); - drm_atomic_state_put(state); - goto unlock; - } - } - - if (lp != DPU_MODE_DPMS_LP2) { - /* force CRTC to be inactive */ - crtc_state = drm_atomic_get_crtc_state(state, - conn->state->crtc); - if (IS_ERR_OR_NULL(crtc_state)) { - DRM_ERROR("failed to get crtc %d state\n", - conn->state->crtc->base.id); - drm_atomic_state_put(state); - goto unlock; - } - - if (lp != DPU_MODE_DPMS_LP1) - crtc_state->active = false; - ++num_crtcs; - } - } - drm_connector_list_iter_end(&conn_iter); /* check for nothing to do */ if (num_crtcs == 0) { @@ -1790,6 +1382,34 @@ static int dpu_kms_pm_resume(struct device *dev) return 0; } +void _dpu_kms_set_encoder_mode(struct msm_kms *kms, + struct drm_encoder *encoder, + bool cmd_mode) +{ + struct msm_display_info info; + struct msm_drm_private *priv = encoder->dev->dev_private; + int i, rc = 0; + + memset(&info, 0, sizeof(info)); + + info.intf_type = encoder->encoder_type; + info.capabilities = cmd_mode ? MSM_DISPLAY_CAP_CMD_MODE : + MSM_DISPLAY_CAP_VID_MODE; + + /* TODO: No support for DSI swap */ + for (i = 0; i < ARRAY_SIZE(priv->dsi); i++) { + if (priv->dsi[i]) { + info.h_tile_instance[info.num_of_h_tiles] = i; + info.num_of_h_tiles++; + } + } + + rc = dpu_encoder_setup(encoder->dev, encoder, &info); + if (rc) + DPU_ERROR("failed to setup DPU encoder %d: rc:%d\n", + encoder->base.id, rc); +} + static const struct msm_kms_funcs kms_funcs = { .hw_init = dpu_kms_hw_init, .postinit = dpu_kms_postinit, @@ -1813,7 +1433,7 @@ static int dpu_kms_pm_resume(struct device *dev) .pm_resume = dpu_kms_pm_resume, .destroy = dpu_kms_destroy, .get_address_space = _dpu_kms_get_address_space, - .postopen = _dpu_kms_post_open, + .set_encoder_mode = _dpu_kms_set_encoder_mode, }; /* the caller api needs to turn on clock before calling it */ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h index 3711daf8..5b0c081 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h @@ -200,12 +200,6 @@ struct dpu_kms { struct dpu_hw_vbif *hw_vbif[VBIF_MAX]; struct dpu_hw_mdp *hw_mdp; - int dsi_display_count; - void **dsi_displays; - int wb_display_count; - void **wb_displays; - int dp_display_count; - void **dp_displays; bool has_danger_ctrl; }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c index c8c12d3..bf1bc10 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c @@ -23,7 +23,6 @@ #include "dpu_hw_intf.h" #include "dpu_hw_wb.h" #include "dpu_encoder.h" -#include "dpu_connector.h" #define RESERVED_BY_OTHER(h, r) \ ((h)->rsvp && ((h)->rsvp->enc_id != (r)->enc_id)) @@ -158,6 +157,18 @@ struct dpu_hw_mdp *dpu_rm_get_mdp(struct dpu_rm *rm) return rm->hw_mdp; } +enum dpu_rm_topology_name +dpu_rm_get_topology_name(struct msm_display_topology topology) +{ + int i; + + for (i = 0; i < DPU_RM_TOPOLOGY_MAX; i++) + if (RM_IS_TOPOLOGY_MATCH(g_top_table[i], topology)) + return g_top_table[i].top_name; + + return DPU_RM_TOPOLOGY_NONE; +} + void dpu_rm_init_hw_iter( struct dpu_rm_hw_iter *iter, uint32_t enc_id, @@ -954,20 +965,19 @@ static int _dpu_rm_populate_requirements( struct drm_encoder *enc, struct drm_crtc_state *crtc_state, struct drm_connector_state *conn_state, - struct dpu_rm_requirements *reqs) + struct dpu_rm_requirements *reqs, + struct msm_display_topology req_topology) { const struct drm_display_mode *mode = &crtc_state->mode; int i; memset(reqs, 0, sizeof(*reqs)); - reqs->top_ctrl = dpu_connector_get_property(conn_state, - CONNECTOR_PROP_TOPOLOGY_CONTROL); dpu_encoder_get_hw_resources(enc, &reqs->hw_res, conn_state); for (i = 0; i < DPU_RM_TOPOLOGY_MAX; i++) { if (RM_IS_TOPOLOGY_MATCH(g_top_table[i], - reqs->hw_res.topology)) { + req_topology)) { reqs->topology = &g_top_table[i]; break; } @@ -978,10 +988,6 @@ static int _dpu_rm_populate_requirements( return -EINVAL; } - /* DSC blocks are hardwired for control path 0 and 1 */ - if (reqs->topology->num_comp_enc) - reqs->top_ctrl |= BIT(DPU_RM_TOPCTL_DSPP); - /** * Set the requirement based on caps if not set from user space * This will ensure to select LM tied with DS blocks @@ -1089,7 +1095,7 @@ void dpu_rm_release(struct dpu_rm *rm, struct drm_encoder *enc) { struct dpu_rm_rsvp *rsvp; struct drm_connector *conn; - uint64_t top_ctrl; + uint64_t top_ctrl = 0; if (!rm || !enc) { DPU_ERROR("invalid params\n"); @@ -1110,9 +1116,6 @@ void dpu_rm_release(struct dpu_rm *rm, struct drm_encoder *enc) goto end; } - top_ctrl = dpu_connector_get_property(conn->state, - CONNECTOR_PROP_TOPOLOGY_CONTROL); - if (top_ctrl & BIT(DPU_RM_TOPCTL_RESERVE_LOCK)) { DPU_DEBUG("rsvp[s%de%d] not releasing locked resources\n", rsvp->seq, rsvp->enc_id); @@ -1120,12 +1123,6 @@ void dpu_rm_release(struct dpu_rm *rm, struct drm_encoder *enc) DPU_DEBUG("release rsvp[s%de%d]\n", rsvp->seq, rsvp->enc_id); _dpu_rm_release_rsvp(rm, rsvp, conn); - - (void) msm_property_set_property( - dpu_connector_get_propinfo(conn), - dpu_connector_get_property_state(conn->state), - CONNECTOR_PROP_TOPOLOGY_NAME, - DPU_RM_TOPOLOGY_NONE); } end: @@ -1141,18 +1138,6 @@ static int _dpu_rm_commit_rsvp( enum dpu_hw_blk_type type; int ret = 0; - ret = msm_property_set_property( - dpu_connector_get_propinfo(conn_state->connector), - dpu_connector_get_property_state(conn_state), - CONNECTOR_PROP_TOPOLOGY_NAME, - rsvp->topology); - if (ret) { - DPU_ERROR("failed to set topology name property, ret %d\n", - ret); - _dpu_rm_release_rsvp(rm, rsvp, conn_state->connector); - return ret; - } - /* Swap next rsvp to be the active */ for (type = 0; type < DPU_HW_BLK_MAX; type++) { list_for_each_entry(blk, &rm->hw_blks[type], list) { @@ -1177,6 +1162,7 @@ int dpu_rm_reserve( struct drm_encoder *enc, struct drm_crtc_state *crtc_state, struct drm_connector_state *conn_state, + struct msm_display_topology topology, bool test_only) { struct dpu_rm_rsvp *rsvp_cur, *rsvp_nxt; @@ -1202,7 +1188,7 @@ int dpu_rm_reserve( _dpu_rm_print_rsvps(rm, DPU_RM_STAGE_BEGIN); ret = _dpu_rm_populate_requirements(rm, enc, crtc_state, - conn_state, &reqs); + conn_state, &reqs, topology); if (ret) { DPU_ERROR("failed to populate hw requirements\n"); goto end; @@ -1237,12 +1223,6 @@ int dpu_rm_reserve( _dpu_rm_release_rsvp(rm, rsvp_cur, conn_state->connector); rsvp_cur = NULL; _dpu_rm_print_rsvps(rm, DPU_RM_STAGE_AFTER_CLEAR); - (void) msm_property_set_property( - dpu_connector_get_propinfo( - conn_state->connector), - dpu_connector_get_property_state(conn_state), - CONNECTOR_PROP_TOPOLOGY_NAME, - DPU_RM_TOPOLOGY_NONE); } /* Check the proposed reservation, store it in hw's "next" field */ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h index 8a6cbcf..4c77874 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h @@ -128,6 +128,7 @@ int dpu_rm_init(struct dpu_rm *rm, * @drm_enc: DRM Encoder handle * @crtc_state: Proposed Atomic DRM CRTC State handle * @conn_state: Proposed Atomic DRM Connector State handle + * @topology: Pointer to topology info for the display * @test_only: Atomic-Test phase, discard results (unless property overrides) * @Return: 0 on Success otherwise -ERROR */ @@ -135,6 +136,7 @@ int dpu_rm_reserve(struct dpu_rm *rm, struct drm_encoder *drm_enc, struct drm_crtc_state *crtc_state, struct drm_connector_state *conn_state, + struct msm_display_topology topology, bool test_only); /** @@ -187,4 +189,13 @@ void dpu_rm_init_hw_iter( */ int dpu_rm_check_property_topctl(uint64_t val); +/** + * dpu_rm_get_topology_name - returns the name of the the given topology + * definition + * @topology: topology definition + * @Return: name of the topology + */ +enum dpu_rm_topology_name +dpu_rm_get_topology_name(struct msm_display_topology topology); + #endif /* __DPU_RM_H__ */ diff --git a/drivers/gpu/drm/msm/dpu_dbg.c b/drivers/gpu/drm/msm/dpu_dbg.c index 54ea631..4a39b82 100644 --- a/drivers/gpu/drm/msm/dpu_dbg.c +++ b/drivers/gpu/drm/msm/dpu_dbg.c @@ -2547,9 +2547,6 @@ static void _dpu_dump_array(struct dpu_dbg_reg_base *blk_arr[], if (dump_dbgbus_vbif_rt) _dpu_dbg_dump_vbif_dbg_bus(&dpu_dbg_base.dbgbus_vbif_rt); - if (dpu_dbg_base.dsi_dbg_bus || dump_all) - dsi_ctrl_debug_dump(); - if (do_panic && dpu_dbg_base.panic_on_err) panic(name); } diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index a6fe3a1..ebc40a9 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -47,12 +47,6 @@ #include "msm_fence.h" #include "msm_gpu.h" #include "msm_kms.h" -#ifdef CONFIG_DRM_MSM_WRITEBACK -#include "dpu_wb.h" -#endif -#ifdef CONFIG_DRM_MSM_DSI_STAGING -#include "dsi_display.h" -#endif #ifdef CONFIG_DRM_MSM_DPU #include "dpu_dbg.h" #endif @@ -1297,9 +1291,6 @@ int msm_ioctl_rmfb2(struct drm_device *dev, void *data, DRM_IOCTL_DEF_DRV(MSM_GEM_MADVISE, msm_ioctl_gem_madvise, DRM_AUTH|DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_NEW, msm_ioctl_submitqueue_new, DRM_AUTH|DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_CLOSE, msm_ioctl_submitqueue_close, DRM_AUTH|DRM_RENDER_ALLOW), -#ifdef CONFIG_DRM_MSM_WRITEBACK - DRM_IOCTL_DEF_DRV(DPU_WB_CONFIG, dpu_wb_config, DRM_UNLOCKED|DRM_AUTH), -#endif DRM_IOCTL_DEF_DRV(MSM_RMFB2, msm_ioctl_rmfb2, DRM_CONTROL_ALLOW|DRM_UNLOCKED), }; @@ -1541,42 +1532,6 @@ static int add_display_components(struct device *dev, struct device *mdp_dev = NULL; int ret; -#ifdef CONFIG_DRM_MSM_DPU - struct device_node *node; - const char *name; - - if (of_device_is_compatible(dev->of_node, "qcom,dpu-kms")) { - struct device_node *np = dev->of_node; - unsigned int i; - bool found = false; - -#ifdef CONFIG_DRM_MSM_DSI_STAGING - for (i = 0; i < MAX_DSI_ACTIVE_DISPLAY; i++) { - node = dsi_display_get_boot_display(i); - - if (node != NULL) { - name = of_get_property(node, "label", NULL); - component_match_add(dev, matchptr, compare_of, - node); - pr_debug("Added component = %s\n", name); - found = true; - } - } - if (!found) - return -EPROBE_DEFER; -#endif - - for (i = 0; ; i++) { - node = of_parse_phandle(np, "connectors", i); - if (!node) - break; - - component_match_add(dev, matchptr, compare_of, node); - } - return 0; - } -#endif - /* * MDP5 based devices don't have a flat hierarchy. There is a top level * parent: MDSS, and children: MDP5, DSI, HDMI, eDP etc. Populate the @@ -1600,7 +1555,7 @@ static int add_display_components(struct device *dev, put_device(mdp_dev); /* add the MDP component itself */ - component_match_add(dev, matchptr, compare_of, + drm_of_component_match_add(dev, matchptr, compare_of, mdp_dev->of_node); } else { /* MDP4 */ diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index eaf2b6a..90a2521 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -159,8 +159,6 @@ enum msm_mdp_conn_property { CONNECTOR_PROP_AD_BL_SCALE, /* enum/bitmask properties */ - CONNECTOR_PROP_TOPOLOGY_NAME, - CONNECTOR_PROP_TOPOLOGY_CONTROL, CONNECTOR_PROP_AUTOREFRESH, CONNECTOR_PROP_LP, @@ -331,57 +329,20 @@ struct msm_display_topology { }; /** - * struct msm_mode_info - defines all msm custom mode info - * @frame_rate: frame_rate of the mode - * @vtotal: vtotal calculated for the mode - * @prefill_lines: prefill lines based on porches. - * @jitter_numer: display panel jitter numerator configuration - * @jitter_denom: display panel jitter denominator configuration - * @topology: supported topology for the mode - */ -struct msm_mode_info { - uint32_t frame_rate; - uint32_t vtotal; - uint32_t prefill_lines; - uint32_t jitter_numer; - uint32_t jitter_denom; - struct msm_display_topology topology; -}; - -/** * struct msm_display_info - defines display properties * @intf_type: DRM_MODE_CONNECTOR_ display type * @capabilities: Bitmask of display flags * @num_of_h_tiles: Number of horizontal tiles in case of split interface * @h_tile_instance: Controller instance used per tile. Number of elements is * based on num_of_h_tiles - * @is_connected: Set to true if display is connected - * @width_mm: Physical width - * @height_mm: Physical height - * @max_width: Max width of display. In case of hot pluggable display - * this is max width supported by controller - * @max_height: Max height of display. In case of hot pluggable display - * this is max height supported by controller - * @is_primary: Set to true if display is primary display * @is_te_using_watchdog_timer: Boolean to indicate watchdog TE is * used instead of panel TE in cmd mode panels */ struct msm_display_info { int intf_type; uint32_t capabilities; - uint32_t num_of_h_tiles; uint32_t h_tile_instance[MAX_H_TILES_PER_DISPLAY]; - - bool is_connected; - - unsigned int width_mm; - unsigned int height_mm; - - uint32_t max_width; - uint32_t max_height; - - bool is_primary; bool is_te_using_watchdog_timer; };