From patchwork Thu Aug 15 00:34:06 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 13764314 Received: from mail-pf1-f180.google.com (mail-pf1-f180.google.com [209.85.210.180]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 652644A0F for ; Thu, 15 Aug 2024 00:34:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.180 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723682066; cv=none; b=ac47+WtwxNqf/BGy7NaHLyU6mnjCaYAKF4TFLZVXNHtr4Qr775EBAq6LcpTxiDWfSmAOx7DhruKVZrTatZFRxZoTuOwq5ZUXqrCvPtznGl9XFcRLqQrHCuy00OdpGCoy+ODLF/C4ydCQiQQKEVXZ7RM2tfhIQPAzX94e8POWd9U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723682066; c=relaxed/simple; bh=oz72Q0doCA/TDcpGgSX5zcBpwt/SNMECwtIx/YvZSjs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Y2IjyyN+0VHdV3IJKNkG9HUoYCacwnDqfIwmbpSFujlx/JHEefvskHhOU+XIrnAO04jUbITvhmEBXGNWsjsHbN+5C5CKFoYS5cRSjfJaHaPz0DQwlNL/hkd+QJMVOO5QJgToMV8HGf8YX5VsOdGQyVmQTMDuif7sGLbLX+4poLs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=N9H0Y+E4; arc=none smtp.client-ip=209.85.210.180 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="N9H0Y+E4" Received: by mail-pf1-f180.google.com with SMTP id d2e1a72fcca58-710dc3015bfso296837b3a.0 for ; Wed, 14 Aug 2024 17:34:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1723682063; x=1724286863; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=h4epShKXY+hj6izJiuYDlNYe3lRcBUUzUpZVsUSgXYg=; b=N9H0Y+E4OvqigpGl9v9ifdRP5NtjiZvpErQ5VBgjm12Xg7VxQTONwp1SgN3hULcpn/ cID/mH4v6K8puG8xk/46snA27g9nPdN9kBRvUOhR23xqtPLDXZwafzXHaQ/I7qbovNsU xWFpXaX7jtepcmsK3Y8tVrupG16DXaw4lbehM= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723682063; x=1724286863; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=h4epShKXY+hj6izJiuYDlNYe3lRcBUUzUpZVsUSgXYg=; b=fAUA9qhiX7MRRts3PFXXZ5R/nbpa4e3uozF2neU/vbqmzZYM0QZ4005wpJwWKQUXam XQaD7tOo2lQ9jCPID63MhhQVD0JWYWMDOOpHvkvkLhQa/ezXG5LGRRztyrqDOqbBP1L9 QiXGnOsUNc/QgdR/bllpol+VjqbRaRHE0LThmZ71OD9ZgvzSg42rFoPXUunYKDExcP4A lQqx39xnOT59KZBjt14E8onenZjB1SpVTX2Jg0mUQwG2v22Y1Lbj4R0bO4M3XcGyFhZV K3wamkh3T8BQgsP05iSqa9H8DrSA7HVGWibQ5t+SVZ47SMnVtv8vfgH/JJVDHemiEzfS /cow== X-Gm-Message-State: AOJu0Yx7sDHgcEkShIRJopWC0q7r0lBwGfjiSa3Jx8x2xkcZ6+1ciSIg h4+t1nasmLDo6Zg5yknBoOzlNRf8vCbw5Ztqy55uDUzguxjWTnev22RmWoJAxjeLTpq0YnmRicg = X-Google-Smtp-Source: AGHT+IF50ypFbSKfbIz2hW4tW3WafhWA8ySurKjT7HVN7jCDX2prNuGHFdxWgLv6pyIkH4Ne+FXXrA== X-Received: by 2002:a05:6a20:6629:b0:1c2:8d1b:2776 with SMTP id adf61e73a8af0-1c8f85e43acmr2065931637.20.1723682063267; Wed, 14 Aug 2024 17:34:23 -0700 (PDT) Received: from localhost (210.73.125.34.bc.googleusercontent.com. [34.125.73.210]) by smtp.gmail.com with UTF8SMTPSA id d2e1a72fcca58-7127ae07443sm157338b3a.48.2024.08.14.17.34.21 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 14 Aug 2024 17:34:22 -0700 (PDT) From: Stephen Boyd To: chrome-platform@lists.linux.dev Cc: linux-kernel@vger.kernel.org, patches@lists.linux.dev, devicetree@vger.kernel.org, Douglas Anderson , Pin-yen Lin , Andrzej Hajda , Benson Leung , Conor Dooley , Daniel Vetter , David Airlie , Dmitry Baryshkov , dri-devel@lists.freedesktop.org, Guenter Roeck , Jernej Skrabec , Jonas Karlman , Krzysztof Kozlowski , Laurent Pinchart , Lee Jones , Maarten Lankhorst , Maxime Ripard , Neil Armstrong , Prashant Malani , Robert Foss , Rob Herring , Thomas Zimmermann , Tzung-Bi Shih Subject: [PATCH v2 01/11] drm/atomic-helper: Introduce lane remapping support to bridges Date: Wed, 14 Aug 2024 17:34:06 -0700 Message-ID: <20240815003417.1175506-2-swboyd@chromium.org> X-Mailer: git-send-email 2.46.0.76.ge559c4bf1a-goog In-Reply-To: <20240815003417.1175506-1-swboyd@chromium.org> References: <20240815003417.1175506-1-swboyd@chromium.org> Precedence: bulk X-Mailing-List: chrome-platform@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add support to the DRM atomic logic to support lane remapping between bridges, encoders and connectors. Typically lane mapping is handled statically in firmware, e.g. on DT we use the data-lanes property to assign lanes when connecting display bridges. Lane assignment is dynamic with USB-C DisplayPort altmodes, e.g. pin conf D assigns 2 lanes of DP to pins on the USB-C connector while pin conf C assigns 4 lanes of DP to pins on the USB-C connector. The lane assignment can't be set statically because the DP altmode repurposes USB-C pins for the DP lanes while also limiting the number of DP lanes or their pin assignment at runtime. Bridge drivers should point their 'struct drm_bus_cfg::lanes' pointer to an allocated array of 'struct drm_lane_cfg' structures and indicate the size of this allocated array with 'struct drm_bus_cfg::num_lanes' in their atomic_check() callback. The previous bridge in the bridge chain can look at this information by calling drm_bridge_next_bridge_lane_cfg() in their atomic_check() callback to figure out what lanes need to be logically assigned to the physical output lanes to satisfy the next bridge's lane assignment. Cc: Andrzej Hajda Cc: Neil Armstrong Cc: Robert Foss Cc: Laurent Pinchart Cc: Jonas Karlman Cc: Jernej Skrabec Cc: Maarten Lankhorst Cc: Maxime Ripard Cc: Thomas Zimmermann Cc: David Airlie Cc: Daniel Vetter Cc: Cc: Pin-yen Lin Cc: Dmitry Baryshkov Signed-off-by: Stephen Boyd --- drivers/gpu/drm/drm_atomic_state_helper.c | 2 ++ drivers/gpu/drm/drm_bridge.c | 34 +++++++++++++++++++++++ include/drm/drm_atomic.h | 31 +++++++++++++++++++++ include/drm/drm_bridge.h | 4 +++ 4 files changed, 71 insertions(+) diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c index 519228eb1095..12d574458e7b 100644 --- a/drivers/gpu/drm/drm_atomic_state_helper.c +++ b/drivers/gpu/drm/drm_atomic_state_helper.c @@ -779,6 +779,8 @@ EXPORT_SYMBOL(drm_atomic_helper_bridge_duplicate_state); void drm_atomic_helper_bridge_destroy_state(struct drm_bridge *bridge, struct drm_bridge_state *state) { + kfree(state->input_bus_cfg.lanes); + kfree(state->output_bus_cfg.lanes); kfree(state); } EXPORT_SYMBOL(drm_atomic_helper_bridge_destroy_state); diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c index d44f055dbe3e..bd18c1e91dee 100644 --- a/drivers/gpu/drm/drm_bridge.c +++ b/drivers/gpu/drm/drm_bridge.c @@ -822,6 +822,40 @@ void drm_atomic_bridge_chain_enable(struct drm_bridge *bridge, } EXPORT_SYMBOL(drm_atomic_bridge_chain_enable); +/** + * drm_bridge_next_bridge_lane_cfg - get the lane configuration of the next bridge + * @bridge: bridge control structure + * @state: new atomic state + * @num_lanes: will contain the size of the returned array + * + * This function is typically called from &drm_bridge_funcs.atomic_check(). + * The @bridge driver calls this function to determine what the next bridge in + * the bridge chain requires for the physical to logical lane assignments. + * + * Return: Lane configuration array of size @num_lanes for the next bridge + * after @bridge in the bridge chain, or NULL if the lane configuration is + * unchanged from the default. + */ +const struct drm_lane_cfg * +drm_bridge_next_bridge_lane_cfg(struct drm_bridge *bridge, + struct drm_atomic_state *state, + u8 *num_lanes) +{ + const struct drm_bridge_state *next_bridge_state; + struct drm_bridge *next_bridge = drm_bridge_get_next_bridge(bridge); + + next_bridge_state = drm_atomic_get_new_bridge_state(state, next_bridge); + if (!next_bridge_state) { + *num_lanes = 0; + return NULL; + } + + *num_lanes = next_bridge_state->input_bus_cfg.num_lanes; + + return next_bridge_state->input_bus_cfg.lanes; +} +EXPORT_SYMBOL(drm_bridge_next_bridge_lane_cfg); + static int drm_atomic_bridge_check(struct drm_bridge *bridge, struct drm_crtc_state *crtc_state, struct drm_connector_state *conn_state) diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index 4d7f4c5f2001..e1a38d0742f1 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -1122,6 +1122,27 @@ drm_atomic_crtc_effectively_active(const struct drm_crtc_state *state) return state->active || state->self_refresh_active; } +/** + * struct drm_lane_cfg - lane configuration + * + * This structure stores the lane configuration of a physical bus between + * two components in an output pipeline, usually between two bridges, an + * encoder and a bridge, or a bridge and a connector. + * + * The lane configuration is stored in &drm_bus_cfg. + */ +struct drm_lane_cfg { + /** + * @logical: Logical lane number + */ + u8 logical; + + /** + * @inverted: True if lane polarity is inverted, false otherwise + */ + bool inverted; +}; + /** * struct drm_bus_cfg - bus configuration * @@ -1152,6 +1173,16 @@ struct drm_bus_cfg { * @flags: DRM_BUS_* flags used on this bus */ u32 flags; + + /** + * @lanes: Lane mapping for this bus + */ + struct drm_lane_cfg *lanes; + + /** + * @num_lanes: Number of lanes in @lanes + */ + u8 num_lanes; }; /** diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h index 75019d16be64..064d3c8600a9 100644 --- a/include/drm/drm_bridge.h +++ b/include/drm/drm_bridge.h @@ -963,6 +963,10 @@ drm_atomic_helper_bridge_propagate_bus_fmt(struct drm_bridge *bridge, struct drm_connector_state *conn_state, u32 output_fmt, unsigned int *num_input_fmts); +const struct drm_lane_cfg * +drm_bridge_next_bridge_lane_cfg(struct drm_bridge *bridge, + struct drm_atomic_state *state, + u8 *num_lanes); enum drm_connector_status drm_bridge_detect(struct drm_bridge *bridge); int drm_bridge_get_modes(struct drm_bridge *bridge, From patchwork Thu Aug 15 00:34:07 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 13764315 Received: from mail-oa1-f48.google.com (mail-oa1-f48.google.com [209.85.160.48]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 35C1C79C0 for ; Thu, 15 Aug 2024 00:34:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723682067; cv=none; b=A3oSTMhC+n2IQvr2/538SFvcjTCe5eE7Py1vYn5fSCab/JKvl2Xl9eRcv9NFvprl74SAjpKSRVfB684vLeVFajIl2NHG1Ci4eCvRtZgtmNlKkZFX0j/qgWpXWBsmbsKTJtrI1ovH/VuQc6hyU23rxiVGxxUHfkQ/2M+0czifFrk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723682067; c=relaxed/simple; bh=ahxFCtg/v93x1OwOq6O28bHFegCWP8HatZ1/V+oQ4yo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=TbbJ97qcmb4KjgHtawfUA8HGBiC1LUQqxkCJkVZnqN2/SCtAzQKEE66lbLSjjkgr5sWAy85O6RziTdpYsoR4RH/oJzRJmC441+czmyTxsENp+P7LD+oqoKAsusOaVkN7A4q8YY/OKNdgiabiA9Ljzngj3zFPX8YFeSxlbfmOG2s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=LiFoiLI9; arc=none smtp.client-ip=209.85.160.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="LiFoiLI9" Received: by mail-oa1-f48.google.com with SMTP id 586e51a60fabf-2689e7a941fso372311fac.3 for ; Wed, 14 Aug 2024 17:34:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1723682065; x=1724286865; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=d8LFD02UwCQn/9JJcB/9igBsgy8I8NKOocEuza3szqI=; b=LiFoiLI9ypBzILcJOZOHXlrhZf8toIH89nME0pemMEoHB7IhNZeEewF/cEAfMc/wk1 kreSFOw2FYzbwXA6FiijVDaz8rdRp0ot8g1Gv5veL7fIRYpm9mAmHnhzM7RzOGa6yDoe 6JF9cUEdCglj8PKXKTW7BlwuwaX+5RzOSQYHs= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723682065; x=1724286865; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=d8LFD02UwCQn/9JJcB/9igBsgy8I8NKOocEuza3szqI=; b=M5NVHMKTXSlnXUFwooSqWaNPTfL8eLpuNI6B4+dY74G/1DQqGHv7Ll+XhnytvUs+5a vVAF4gmQPqArAwRsYplnyI7KbzRMwUJo5974RBtvBOh9b9Dg52VPzH9KSWuGOA7Dz/m5 snrdB2XqWsqnnC9CfB9TkxJIAYeoG8Nj/Iknnhv2hKXFOW2zOOV2PAtYuuhADGk3nhed jGRdhqS3MYAlbsmz1bDiVLunBkZRJvraOE7juRGsrzXpiMLTHDd5qxq2fT0MPq8B3TG4 3Yj0Y+pZwzuiJk6UN51hyovQlyoZ7wCJSH9qmaHbcnD06TAW5LyPJmwQwx628zNXSK+H VPFA== X-Gm-Message-State: AOJu0YyZG2yOYMPy6Z25nCNJoCGsASDJi0rlDlX75DR4sJ2cXQbJ4xxL 4ZrPFMVnRbuM4YbZXAptvA25SmdN8XYGf+hK6qDQ1lr3g2yg9ctYfNh2/BwrHY4WVDdYwjoVdKc = X-Google-Smtp-Source: AGHT+IHQ7gSlptFP9Id6oIfb1DYj5dhoaDHNDxGZJ/4xjnv8noXdgyY+U3CVRT3wmtzXjxj/nEvUrg== X-Received: by 2002:a05:6870:89a4:b0:260:f5c6:e9ec with SMTP id 586e51a60fabf-26fe5a70546mr5180121fac.17.1723682065111; Wed, 14 Aug 2024 17:34:25 -0700 (PDT) Received: from localhost (210.73.125.34.bc.googleusercontent.com. [34.125.73.210]) by smtp.gmail.com with UTF8SMTPSA id d2e1a72fcca58-7127af3fae8sm151797b3a.208.2024.08.14.17.34.23 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 14 Aug 2024 17:34:24 -0700 (PDT) From: Stephen Boyd To: chrome-platform@lists.linux.dev Cc: linux-kernel@vger.kernel.org, patches@lists.linux.dev, devicetree@vger.kernel.org, Douglas Anderson , Pin-yen Lin , Andrzej Hajda , Benson Leung , Conor Dooley , Daniel Vetter , David Airlie , Dmitry Baryshkov , dri-devel@lists.freedesktop.org, Guenter Roeck , Jernej Skrabec , Jonas Karlman , Krzysztof Kozlowski , Laurent Pinchart , Lee Jones , Maarten Lankhorst , Maxime Ripard , Neil Armstrong , Prashant Malani , Robert Foss , Rob Herring , Thomas Zimmermann , Tzung-Bi Shih Subject: [PATCH v2 02/11] drm/bridge: Verify lane assignment is going to work during atomic_check Date: Wed, 14 Aug 2024 17:34:07 -0700 Message-ID: <20240815003417.1175506-3-swboyd@chromium.org> X-Mailer: git-send-email 2.46.0.76.ge559c4bf1a-goog In-Reply-To: <20240815003417.1175506-1-swboyd@chromium.org> References: <20240815003417.1175506-1-swboyd@chromium.org> Precedence: bulk X-Mailing-List: chrome-platform@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Verify during drm_atomic_bridge_check() that the lane assignment set in a bridge's atomic_check() callback is going to be satisfied by the previous bridge. If the next bridge is requiring something besides the default 1:1 lane assignment on its input then there must be an output lane assignment on the previous bridge's output. Otherwise the next bridge won't get the lanes assigned that it needs. Cc: Andrzej Hajda Cc: Neil Armstrong Cc: Robert Foss Cc: Laurent Pinchart Cc: Jonas Karlman Cc: Jernej Skrabec Cc: Maarten Lankhorst Cc: Maxime Ripard Cc: Thomas Zimmermann Cc: David Airlie Cc: Daniel Vetter Cc: Cc: Pin-yen Lin Cc: Dmitry Baryshkov Signed-off-by: Stephen Boyd --- drivers/gpu/drm/drm_bridge.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c index bd18c1e91dee..68c7a321b9b3 100644 --- a/drivers/gpu/drm/drm_bridge.c +++ b/drivers/gpu/drm/drm_bridge.c @@ -860,6 +860,10 @@ static int drm_atomic_bridge_check(struct drm_bridge *bridge, struct drm_crtc_state *crtc_state, struct drm_connector_state *conn_state) { + u8 num_input_lanes, num_output_lanes = 0; + const struct drm_lane_cfg *input_lanes; + int i; + if (bridge->funcs->atomic_check) { struct drm_bridge_state *bridge_state; int ret; @@ -873,12 +877,24 @@ static int drm_atomic_bridge_check(struct drm_bridge *bridge, crtc_state, conn_state); if (ret) return ret; + num_output_lanes = bridge_state->output_bus_cfg.num_lanes; } else if (bridge->funcs->mode_fixup) { if (!bridge->funcs->mode_fixup(bridge, &crtc_state->mode, &crtc_state->adjusted_mode)) return -EINVAL; } + input_lanes = drm_bridge_next_bridge_lane_cfg(bridge, + crtc_state->state, + &num_input_lanes); + /* + * Ensure this bridge is aware that the next bridge wants to + * reassign lanes. + */ + for (i = 0; i < num_input_lanes; i++) + if (i != input_lanes[i].logical && !num_output_lanes) + return -ENOTSUPP; + return 0; } From patchwork Thu Aug 15 00:34:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 13764316 Received: from mail-pl1-f172.google.com (mail-pl1-f172.google.com [209.85.214.172]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F051BB665 for ; Thu, 15 Aug 2024 00:34:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723682069; cv=none; b=YX2Wm7zm0KIFX8HoxDPeEufnthN54LcJ8gzXkGxFLj+pLXPFpCXO0GwV70teA+IH2R1B4SI99BgwQWdezNSDVI4JvQ0yFnHQ/BSdvNIJMo/a4xJd229NDDuCGMiKo6kFsteaqiw0iQhZ4MwqNG75IG9asgK69EBymExcN8bfqF0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723682069; c=relaxed/simple; bh=+XndPNFiAFV/Vul4cGPnVBmNkn9o8Yh4sbKxszH6Quc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=T5N7G7cAYPAttfEir2aw3nG470qREHJGO/dpFC1dOlLrtcsMOJe9BeeMAF8Kr1SJXLlfvGcZJiITkfKt0Fg9c8IvyNN0dH7334VvCBFeXfd2STl35WJdW/1uIrqbU9+VetBgCgTvdHKXApdxQri6Jj9UUCjAqX8UWJ0a3ekcFtI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=IqBJ1f5Y; arc=none smtp.client-ip=209.85.214.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="IqBJ1f5Y" Received: by mail-pl1-f172.google.com with SMTP id d9443c01a7336-201cd78c6a3so3558725ad.1 for ; Wed, 14 Aug 2024 17:34:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1723682067; x=1724286867; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=OxnfdKsnABkmxy+Awu1gzrCm5LBU5v/4gHba1EU76+4=; b=IqBJ1f5Yg5KdTUzS3GOZYUWs2lwEUA2BPNYAMU5rBNwtuVhNPFThDymkrmk6sorHTs Zu0lNB7w2DIhmb2iz06+kiSTMpsoI7UK3gRO33pOYwgnSeGv37PRNWd1Y2fwLwRICsc5 QvRBHP7yXlzYQ06y7SbO1IJdLrmV/oett2uk0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723682067; x=1724286867; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=OxnfdKsnABkmxy+Awu1gzrCm5LBU5v/4gHba1EU76+4=; b=J+YAGGVFxxL9AMtjCkrGSNXggmsuPf40D2nadwgukrJ24gXQtuvFqVGaL8NWAN5rIp QLy65FE6nReNlE3z62nEwMLGrsx/H7JcE3jeHAgp+la3CxoDqmglwpu1xZkP9smBnDRv 8/96ASWlM0Bha+riBHPLebwrgJCcDxy3boFkXsbLYi6unm6gRGisWRZ6GYfGZCTTpb1A PK66vtYyk3f4mfUCQjpE68yDpfeDWn94XaRlEU10sy5XmZoVizmRoOQ5LsSPRJxVt45s S86wze42tpTAwVGEuYu3gHBmdONLJ0cR3+mJoi5mnBStY6aiePcPdnBwrrXdPGfcQZNe n8lw== X-Gm-Message-State: AOJu0YwiOAitThfCAOxM3gNKRe+9emROa9zrHWB/9zgVnC6lZHf5uX4C eN7SnC7ejzfGf8ybkU6I/0aUyeWFQS5o7Ih49SyXEp+m7K31SiQaBsAey3o0sT61aO1aMRbZ/wU = X-Google-Smtp-Source: AGHT+IFOEYBYeh7yn8STFWbC43QluLLJJx9fWEole1fT2NjhKt+vfyJrK42tLqT8J/p9fFuXb0i9UA== X-Received: by 2002:a17:903:110d:b0:1fb:3ce5:122d with SMTP id d9443c01a7336-201d6487ed6mr55729075ad.41.1723682067050; Wed, 14 Aug 2024 17:34:27 -0700 (PDT) Received: from localhost (210.73.125.34.bc.googleusercontent.com. [34.125.73.210]) by smtp.gmail.com with UTF8SMTPSA id d9443c01a7336-201f03203efsm2036895ad.118.2024.08.14.17.34.25 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 14 Aug 2024 17:34:26 -0700 (PDT) From: Stephen Boyd To: chrome-platform@lists.linux.dev Cc: linux-kernel@vger.kernel.org, patches@lists.linux.dev, devicetree@vger.kernel.org, Douglas Anderson , Pin-yen Lin , Andrzej Hajda , Benson Leung , Conor Dooley , Daniel Vetter , David Airlie , Dmitry Baryshkov , dri-devel@lists.freedesktop.org, Guenter Roeck , Jernej Skrabec , Jonas Karlman , Krzysztof Kozlowski , Laurent Pinchart , Lee Jones , Maarten Lankhorst , Maxime Ripard , Neil Armstrong , Prashant Malani , Robert Foss , Rob Herring , Thomas Zimmermann , Tzung-Bi Shih Subject: [PATCH v2 03/11] drm/bridge: aux-hpd: Support USB Type-C DP altmodes via DRM lane assignment Date: Wed, 14 Aug 2024 17:34:08 -0700 Message-ID: <20240815003417.1175506-4-swboyd@chromium.org> X-Mailer: git-send-email 2.46.0.76.ge559c4bf1a-goog In-Reply-To: <20240815003417.1175506-1-swboyd@chromium.org> References: <20240815003417.1175506-1-swboyd@chromium.org> Precedence: bulk X-Mailing-List: chrome-platform@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Extend the aux-hpd bridge driver to support assigning DP lanes to USB Type-C pins. Existing users of this driver only need the HPD signaling support, so leave that in place and wrap the code with a variant that supports more features of USB Type-C DP altmode, i.e. pin configurations. Prefix that code with 'drm_dp_typec_bridge' to differentiate it from the existing 'drm_aux_hpd_bridge' code. Users allocate the bridge by passing a struct drm_dp_typec_bridge_desc to devm_drm_dp_typec_bridge_alloc() and then use the returned pointer for further operations like notifying HPD to the bridge chain or setting the DP altmode pin configuration. All these APIs take an opaque struct drm_dp_typec_bridge_dev pointer so that the wrong 'struct device' can't be mistakenly used. Note: The pin assignment function doesn't actively change the lane configuration. Instead it stashes the lane assignment and requests the assignment on the previous bridge in the chain during the atomic check phase. Assume the USB Type-C pins are in the normal orientation for now. A future patch will support type-c port orientation. Cc: Prashant Malani Cc: Benson Leung Cc: Tzung-Bi Shih Cc: Cc: Pin-yen Lin Cc: Dmitry Baryshkov Signed-off-by: Stephen Boyd --- drivers/gpu/drm/bridge/aux-hpd-bridge.c | 319 +++++++++++++++++++++++- include/drm/bridge/aux-bridge.h | 52 ++++ 2 files changed, 359 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/bridge/aux-hpd-bridge.c b/drivers/gpu/drm/bridge/aux-hpd-bridge.c index 6886db2d9e00..716b2220bdd5 100644 --- a/drivers/gpu/drm/bridge/aux-hpd-bridge.c +++ b/drivers/gpu/drm/bridge/aux-hpd-bridge.c @@ -7,8 +7,11 @@ #include #include #include +#include +#include #include +#include #include static DEFINE_IDA(drm_aux_hpd_bridge_ida); @@ -18,6 +21,48 @@ struct drm_aux_hpd_bridge_data { struct device *dev; }; +enum dp_lane { + DP_ML0 = 0, /* DP pins 1/3 */ + DP_ML1 = 1, /* DP pins 4/6 */ + DP_ML2 = 2, /* DP pins 7/9 */ + DP_ML3 = 3, /* DP pins 10/12 */ +}; + +struct drm_dp_typec_bridge_data { + u8 dp_lanes[DP_ML3 + 1]; + size_t num_lanes; + struct drm_aux_hpd_bridge_data hpd_bridge; +}; + +static inline struct drm_dp_typec_bridge_data * +hpd_bridge_to_typec_bridge_data(struct drm_aux_hpd_bridge_data *hpd_data) +{ + return container_of(hpd_data, struct drm_dp_typec_bridge_data, hpd_bridge); +} + +static inline struct drm_dp_typec_bridge_data * +to_drm_dp_typec_bridge_data(struct drm_bridge *bridge) +{ + struct drm_aux_hpd_bridge_data *hpd_data; + + hpd_data = container_of(bridge, struct drm_aux_hpd_bridge_data, bridge); + + return hpd_bridge_to_typec_bridge_data(hpd_data); +} + +struct drm_dp_typec_bridge_dev { + struct auxiliary_device adev; + size_t max_lanes; +}; + +static inline struct drm_dp_typec_bridge_dev * +to_drm_dp_typec_bridge_dev(struct device *dev) +{ + struct auxiliary_device *adev = to_auxiliary_dev(dev); + + return container_of(adev, struct drm_dp_typec_bridge_dev, adev); +} + static void drm_aux_hpd_bridge_release(struct device *dev) { struct auxiliary_device *adev = to_auxiliary_dev(dev); @@ -30,6 +75,22 @@ static void drm_aux_hpd_bridge_release(struct device *dev) kfree(adev); } +static void drm_dp_typec_bridge_release(struct device *dev) +{ + struct drm_dp_typec_bridge_dev *typec_bridge_dev; + struct auxiliary_device *adev; + + typec_bridge_dev = to_drm_dp_typec_bridge_dev(dev); + adev = &typec_bridge_dev->adev; + + ida_free(&drm_aux_hpd_bridge_ida, adev->id); + + of_node_put(adev->dev.platform_data); + of_node_put(adev->dev.of_node); + + kfree(typec_bridge_dev); +} + static void drm_aux_hpd_bridge_free_adev(void *_adev) { auxiliary_device_uninit(_adev); @@ -133,6 +194,72 @@ struct device *drm_dp_hpd_bridge_register(struct device *parent, struct device_n } EXPORT_SYMBOL_GPL(drm_dp_hpd_bridge_register); +/** + * devm_drm_dp_typec_bridge_alloc - Allocate a USB type-C DisplayPort bridge + * @parent: device instance providing this bridge + * @desc: device node pointer corresponding to this bridge instance + * + * Creates a DRM bridge with the type set to DRM_MODE_CONNECTOR_DisplayPort, + * which terminates the bridge chain and is able to send the HPD events along + * with remap DP lanes to match USB type-c DP altmode pin assignments. + * + * Return: device instance that will handle created bridge or an error code + * encoded into the pointer. + */ +struct drm_dp_typec_bridge_dev * +devm_drm_dp_typec_bridge_alloc(struct device *parent, const struct drm_dp_typec_bridge_desc *desc) +{ + struct drm_dp_typec_bridge_dev *typec_bridge_dev; + struct auxiliary_device *adev; + int ret; + + typec_bridge_dev = kzalloc(sizeof(*typec_bridge_dev), GFP_KERNEL); + if (!typec_bridge_dev) + return ERR_PTR(-ENOMEM); + adev = &typec_bridge_dev->adev; + + ret = ida_alloc(&drm_aux_hpd_bridge_ida, GFP_KERNEL); + if (ret < 0) { + kfree(adev); + return ERR_PTR(ret); + } + + adev->id = ret; + adev->name = "dp_typec_bridge"; + adev->dev.parent = parent; + adev->dev.of_node = of_node_get(parent->of_node); + adev->dev.release = drm_dp_typec_bridge_release; + adev->dev.platform_data = of_node_get(desc->of_node); + typec_bridge_dev->max_lanes = desc->num_dp_lanes; + + ret = auxiliary_device_init(adev); + if (ret) { + of_node_put(adev->dev.platform_data); + of_node_put(adev->dev.of_node); + ida_free(&drm_aux_hpd_bridge_ida, adev->id); + kfree(adev); + return ERR_PTR(ret); + } + + return typec_bridge_dev; +} +EXPORT_SYMBOL_GPL(devm_drm_dp_typec_bridge_alloc); + +/** + * devm_drm_dp_typec_bridge_add - register a USB type-C DisplayPort bridge + * @dev: struct device to tie registration lifetime to + * @typec_bridge_dev: USB type-c DisplayPort bridge to be registered + * + * Returns: zero on success or a negative errno + */ +int devm_drm_dp_typec_bridge_add(struct device *dev, struct drm_dp_typec_bridge_dev *typec_bridge_dev) +{ + struct auxiliary_device *adev = &typec_bridge_dev->adev; + + return devm_drm_dp_hpd_bridge_add(dev, adev); +} +EXPORT_SYMBOL_GPL(devm_drm_dp_typec_bridge_add); + /** * drm_aux_hpd_bridge_notify - notify hot plug detection events * @dev: device created for the HPD bridge @@ -155,38 +282,206 @@ void drm_aux_hpd_bridge_notify(struct device *dev, enum drm_connector_status sta } EXPORT_SYMBOL_GPL(drm_aux_hpd_bridge_notify); +/** + * drm_dp_typec_bridge_notify - notify hot plug detection events + * @typec_bridge_dev: device created for the type-C bridge + * @status: output connection status + * + * A wrapper around drm_bridge_hpd_notify() that is used to report hot plug + * detection events for bridges created via devm_drm_dp_typec_bridge_alloc(). + * + * This function shall be called in a context that can sleep. + */ +void drm_dp_typec_bridge_notify(struct drm_dp_typec_bridge_dev *typec_bridge_dev, + enum drm_connector_status status) +{ + drm_aux_hpd_bridge_notify(&typec_bridge_dev->adev.dev, status); +} +EXPORT_SYMBOL_GPL(drm_dp_typec_bridge_notify); + static int drm_aux_hpd_bridge_attach(struct drm_bridge *bridge, enum drm_bridge_attach_flags flags) { return flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR ? 0 : -EINVAL; } +static int dp_lane_to_typec_lane(enum dp_lane lane) +{ + switch (lane) { + case DP_ML0: + return USB_SSTX2; + case DP_ML1: + return USB_SSRX2; + case DP_ML2: + return USB_SSTX1; + case DP_ML3: + return USB_SSRX1; + } + + return -EINVAL; +} + +static int typec_to_dp_lane(enum usb_ss_lane lane) +{ + switch (lane) { + case USB_SSRX1: + return DP_ML3; + case USB_SSTX1: + return DP_ML2; + case USB_SSTX2: + return DP_ML0; + case USB_SSRX2: + return DP_ML1; + } + + return -EINVAL; +} + +/** + * drm_dp_typec_bridge_assign_pins - Assign DisplayPort (DP) lanes to USB type-C pins + * @typec_bridge_dev: Device created for the type-c bridge + * @conf: DisplayPort altmode configure command VDO content + * @lane_mapping: Physical (array index) to logical (array value) USB type-C lane mapping + * + * Assign DP lanes to the USB type-C pins for the DP altmode configuration + * @conf, while taking into account the USB type-C @lane_mapping. Future atomic + * checks on this bridge will request the lane assignment from the previous + * bridge so that the DP signal is sent to the proper USB type-C pins. + * + * Return: 0 on success, negative value for failure. + */ +int drm_dp_typec_bridge_assign_pins(struct drm_dp_typec_bridge_dev *typec_bridge_dev, + u32 conf, + enum usb_ss_lane lane_mapping[NUM_USB_SS]) +{ + struct auxiliary_device *adev = &typec_bridge_dev->adev; + struct drm_aux_hpd_bridge_data *hpd_data = auxiliary_get_drvdata(adev); + struct drm_dp_typec_bridge_data *data; + u8 *dp_lanes; + size_t num_lanes, max_lanes; + int i, typec_lane; + u8 pin_assign; + + if (!hpd_data) + return -EINVAL; + + data = hpd_bridge_to_typec_bridge_data(hpd_data); + dp_lanes = data->dp_lanes; + + pin_assign = DP_CONF_GET_PIN_ASSIGN(conf); + if (pin_assign == DP_PIN_ASSIGN_D) + num_lanes = 2; + else + num_lanes = 4; + max_lanes = typec_bridge_dev->max_lanes; + data->num_lanes = num_lanes = min(num_lanes, max_lanes); + + for (i = 0; i < num_lanes; i++) { + /* Get physical type-c lane for DP lane */ + typec_lane = dp_lane_to_typec_lane(i); + if (typec_lane < 0) { + dev_err(&adev->dev, "Invalid type-c lane configuration at DP_ML%d\n", i); + return -EINVAL; + } + + /* Map physical to logical type-c lane */ + typec_lane = lane_mapping[typec_lane]; + + /* Map logical type-c lane to logical DP lane */ + dp_lanes[i] = typec_to_dp_lane(typec_lane); + } + + return 0; +} +EXPORT_SYMBOL_GPL(drm_dp_typec_bridge_assign_pins); + +static int drm_dp_typec_bridge_atomic_check(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + struct drm_dp_typec_bridge_data *data; + struct drm_lane_cfg *in_lanes; + u8 *dp_lanes; + size_t num_lanes; + int i; + + data = to_drm_dp_typec_bridge_data(bridge); + num_lanes = data->num_lanes; + if (!num_lanes) + return 0; + dp_lanes = data->dp_lanes; + + in_lanes = kcalloc(num_lanes, sizeof(*in_lanes), GFP_KERNEL); + if (!in_lanes) + return -ENOMEM; + + bridge_state->input_bus_cfg.lanes = in_lanes; + bridge_state->input_bus_cfg.num_lanes = num_lanes; + + for (i = 0; i < num_lanes; i++) + in_lanes[i].logical = dp_lanes[i]; + + return 0; +} + static const struct drm_bridge_funcs drm_aux_hpd_bridge_funcs = { .attach = drm_aux_hpd_bridge_attach, }; +static const struct drm_bridge_funcs drm_dp_typec_bridge_funcs = { + .attach = drm_aux_hpd_bridge_attach, + .atomic_check = drm_dp_typec_bridge_atomic_check, + .atomic_reset = drm_atomic_helper_bridge_reset, + .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, +}; + +enum drm_aux_bridge_type { + DRM_AUX_HPD_BRIDGE, + DRM_AUX_TYPEC_BRIDGE, +}; + static int drm_aux_hpd_bridge_probe(struct auxiliary_device *auxdev, const struct auxiliary_device_id *id) { - struct drm_aux_hpd_bridge_data *data; + struct device *dev = &auxdev->dev; + struct drm_aux_hpd_bridge_data *hpd_data; + struct drm_dp_typec_bridge_data *typec_data; + struct drm_bridge *bridge; + u8 dp_lanes[] = { DP_ML0, DP_ML1, DP_ML2, DP_ML3 }; - data = devm_kzalloc(&auxdev->dev, sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; + if (id->driver_data == DRM_AUX_HPD_BRIDGE) { + hpd_data = devm_kzalloc(dev, sizeof(*hpd_data), GFP_KERNEL); + if (!hpd_data) + return -ENOMEM; + bridge = &hpd_data->bridge; + bridge->funcs = &drm_aux_hpd_bridge_funcs; + } else if (id->driver_data == DRM_AUX_TYPEC_BRIDGE) { + typec_data = devm_kzalloc(dev, sizeof(*typec_data), GFP_KERNEL); + if (!typec_data) + return -ENOMEM; + hpd_data = &typec_data->hpd_bridge; + bridge = &hpd_data->bridge; + bridge->funcs = &drm_dp_typec_bridge_funcs; + memcpy(typec_data->dp_lanes, dp_lanes, sizeof(typec_data->dp_lanes)); + } else { + return -ENODEV; + } - data->dev = &auxdev->dev; - data->bridge.funcs = &drm_aux_hpd_bridge_funcs; - data->bridge.of_node = dev_get_platdata(data->dev); - data->bridge.ops = DRM_BRIDGE_OP_HPD; - data->bridge.type = id->driver_data; + hpd_data->dev = dev; + bridge->of_node = dev_get_platdata(dev); + bridge->ops = DRM_BRIDGE_OP_HPD; + bridge->type = DRM_MODE_CONNECTOR_DisplayPort; - auxiliary_set_drvdata(auxdev, data); + auxiliary_set_drvdata(auxdev, hpd_data); - return devm_drm_bridge_add(data->dev, &data->bridge); + return devm_drm_bridge_add(dev, bridge); } static const struct auxiliary_device_id drm_aux_hpd_bridge_table[] = { - { .name = KBUILD_MODNAME ".dp_hpd_bridge", .driver_data = DRM_MODE_CONNECTOR_DisplayPort, }, + { .name = KBUILD_MODNAME ".dp_hpd_bridge", .driver_data = DRM_AUX_HPD_BRIDGE, }, + { .name = KBUILD_MODNAME ".dp_typec_bridge", .driver_data = DRM_AUX_TYPEC_BRIDGE, }, {}, }; MODULE_DEVICE_TABLE(auxiliary, drm_aux_hpd_bridge_table); diff --git a/include/drm/bridge/aux-bridge.h b/include/drm/bridge/aux-bridge.h index c2f5a855512f..aaace808772c 100644 --- a/include/drm/bridge/aux-bridge.h +++ b/include/drm/bridge/aux-bridge.h @@ -20,12 +20,40 @@ static inline int drm_aux_bridge_register(struct device *parent) } #endif +struct drm_dp_typec_bridge_dev; + +/** + * struct drm_dp_typec_bridge_desc - drm_dp_typec_bridge descriptor + * @of_node: device node pointer corresponding to this bridge instance + * @num_dp_lanes: number of input DP lanes possible (1, 2 or 4) + */ +struct drm_dp_typec_bridge_desc { + struct device_node *of_node; + size_t num_dp_lanes; +}; + +enum usb_ss_lane { + USB_SSRX1 = 0, /* Type-C pins B11/B10 */ + USB_SSTX1 = 1, /* Type-C pins A2/A3 */ + USB_SSTX2 = 2, /* Type-C pins A11/A10 */ + USB_SSRX2 = 3, /* Type-C pins B2/B3 */ +}; + +#define NUM_USB_SS (USB_SSRX2 + 1) + #if IS_ENABLED(CONFIG_DRM_AUX_HPD_BRIDGE) struct auxiliary_device *devm_drm_dp_hpd_bridge_alloc(struct device *parent, struct device_node *np); int devm_drm_dp_hpd_bridge_add(struct device *dev, struct auxiliary_device *adev); struct device *drm_dp_hpd_bridge_register(struct device *parent, struct device_node *np); void drm_aux_hpd_bridge_notify(struct device *dev, enum drm_connector_status status); +struct drm_dp_typec_bridge_dev *devm_drm_dp_typec_bridge_alloc(struct device *parent, + const struct drm_dp_typec_bridge_desc *desc); +int devm_drm_dp_typec_bridge_add(struct device *dev, struct drm_dp_typec_bridge_dev *typec_bridge_dev); +void drm_dp_typec_bridge_notify(struct drm_dp_typec_bridge_dev *typec_bridge_dev, + enum drm_connector_status status); +int drm_dp_typec_bridge_assign_pins(struct drm_dp_typec_bridge_dev *typec_bridge_dev, u32 conf, + enum usb_ss_lane lane_mapping[NUM_USB_SS]); #else static inline struct auxiliary_device *devm_drm_dp_hpd_bridge_alloc(struct device *parent, struct device_node *np) @@ -44,9 +72,33 @@ static inline struct device *drm_dp_hpd_bridge_register(struct device *parent, return NULL; } +static inline struct drm_dp_typec_bridge_dev * +devm_drm_dp_typec_bridge_alloc(struct device *parent, const struct drm_dp_typec_bridge_desc *desc) +{ + return NULL; +} + +static inline int devm_drm_dp_typec_bridge_add(struct device *dev, + struct drm_dp_typec_bridge_dev *typec_bridge_dev) +{ + return 0; +} + static inline void drm_aux_hpd_bridge_notify(struct device *dev, enum drm_connector_status status) { } + +static inline void drm_dp_typec_bridge_notify(struct drm_dp_typec_bridge_dev *typec_bridge_dev, + enum drm_connector_status status) +{ +} + +static inline int drm_dp_typec_bridge_assign_pins(struct drm_dp_typec_bridge_dev *typec_bridge_dev, + u32 conf, + enum usb_ss_lane lane_mapping[NUM_USB_SS]) +{ + return 0; +} #endif #endif From patchwork Thu Aug 15 00:34:09 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 13764317 Received: from mail-pl1-f175.google.com (mail-pl1-f175.google.com [209.85.214.175]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4525F171C9 for ; Thu, 15 Aug 2024 00:34:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.175 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723682071; cv=none; b=OjogG8sA96dJF/jguBYE2WE0PK7qFDTnEX4CJ9mwNbCdQMxKZZZM/EgjxeAFO5OA5AtlJHGqFu/fDG+ZgnyzdzC8qWF/lpqkX3h59WAMO9KYQQN7AhuAVHykKGwAiET/gRBL1miIrMVoBrC0hg8zK27au8neJHifh6UdkRh8AsU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723682071; c=relaxed/simple; bh=BBU1xkfoU7eurOrPvpMLLeunHugd7h5FgxT2uZgKilM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=C2/qbSz4mjbY0I6wU4G8LRI/wj67RPF2fIYWjPCcUIYzjXHyl6eitNMFC+Grw9btMxABVSa0xDspMtf2KbTya3EzBwvIlEdPjsjYXwaxk0dLsyOLOQco/+lKoEay+9MUeDfFIt89H/qaW9U4jTjNqApLyfTbfvg4UOWQ0Uy+x6c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=TR44jCAt; arc=none smtp.client-ip=209.85.214.175 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="TR44jCAt" Received: by mail-pl1-f175.google.com with SMTP id d9443c01a7336-201f2b7fe0dso28435ad.1 for ; Wed, 14 Aug 2024 17:34:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1723682069; x=1724286869; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Gq/ZMzuLbA1llqpSY1LjTmocM7fXF6nFIOTFbEevr4E=; b=TR44jCAtZW81uhUf2eSSPFKW9FyH1g400UqYBmORnPBNKBSGQSJ4+6F4oO2SeS7H2m e1rapIXBd+Alqmt1UDSNstN+r4o/aohAOjsbgik8nQ9H9ShoDdu0yrKx40yUKZOsiRj4 DP4hbEdRzyNFEe3lsn5WVyiXXRg3YTSrUbRgA= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723682069; x=1724286869; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Gq/ZMzuLbA1llqpSY1LjTmocM7fXF6nFIOTFbEevr4E=; b=hCUB5nbEGuwhXqna1y6gQutgURTFnIf6CvRnCPiQbRimEMsVDG3Oj6QcuARIZ6y0te Xq2673roskoWb9SOrjK1/GRfYGUMwW8/L7dtax8id37PrhiIK4MIdO2d12UE8/MADHwy 2ccBZ/Wtorh6IgV8nxLftVbHUBbfIFBkzWpHsVM8cuxaHFOZUMrzMaW17FGDFtgoLXvM iHvQxEhx/RaYp9BXfTdRgLA/8EzL8/z695KxottIa73tHxCyx0A1DMhL7YEpzqxurCgb +huRBH3hHmbB7DcLkmQMapqOW3/xunbvb/5ICNiEh+qkCuq3j7kdLg09lLsTBvzli9Ka bh5Q== X-Gm-Message-State: AOJu0Yzjwmi1AOyInUfJ12at4NUPW06xJqmXmt/o5wthN1DHTmF9PLki 1BnK/+fs1qTPgY4qZGZ5LEjDv49lGpIVKaHj+tK1/796EAqbzY44997AK4lKEMhaNvDNaixEHLA = X-Google-Smtp-Source: AGHT+IFq8j2VyEZ1BVNC68zp/NCCOurZ5Nog/t60mozUg9UPI/CSC7n9XcimPMI12CBkDG1lOi3FFw== X-Received: by 2002:a17:902:d507:b0:1fd:6598:613c with SMTP id d9443c01a7336-201d64b1531mr55994795ad.50.1723682069351; Wed, 14 Aug 2024 17:34:29 -0700 (PDT) Received: from localhost (210.73.125.34.bc.googleusercontent.com. [34.125.73.210]) by smtp.gmail.com with UTF8SMTPSA id d9443c01a7336-201f0394718sm1989155ad.226.2024.08.14.17.34.28 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 14 Aug 2024 17:34:28 -0700 (PDT) From: Stephen Boyd To: chrome-platform@lists.linux.dev Cc: linux-kernel@vger.kernel.org, patches@lists.linux.dev, devicetree@vger.kernel.org, Douglas Anderson , Pin-yen Lin , Andrzej Hajda , Benson Leung , Conor Dooley , Daniel Vetter , David Airlie , Dmitry Baryshkov , dri-devel@lists.freedesktop.org, Guenter Roeck , Jernej Skrabec , Jonas Karlman , Krzysztof Kozlowski , Laurent Pinchart , Lee Jones , Maarten Lankhorst , Maxime Ripard , Neil Armstrong , Prashant Malani , Robert Foss , Rob Herring , Thomas Zimmermann , Tzung-Bi Shih Subject: [PATCH v2 04/11] drm/bridge: dp_typec: Support USB Type-C orientation Date: Wed, 14 Aug 2024 17:34:09 -0700 Message-ID: <20240815003417.1175506-5-swboyd@chromium.org> X-Mailer: git-send-email 2.46.0.76.ge559c4bf1a-goog In-Reply-To: <20240815003417.1175506-1-swboyd@chromium.org> References: <20240815003417.1175506-1-swboyd@chromium.org> Precedence: bulk X-Mailing-List: chrome-platform@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add an orientation parameter to drm_dp_typec_bridge_assign_pins() so that the DP lanes can be directed to the proper USB type-c pins on the connector when the cable is flipped. This is mostly useful for the case where the DP lanes are directly connected to the usb-c-connector and the device doesn't have an orientation switch wired down on the board between the connector and the DP controller. Flip the lanes to match the physical pin locations on the connector when the orientation is reverse. Cc: Prashant Malani Cc: Benson Leung Cc: Tzung-Bi Shih Cc: Cc: Pin-yen Lin Cc: Dmitry Baryshkov Signed-off-by: Stephen Boyd --- drivers/gpu/drm/bridge/aux-hpd-bridge.c | 44 ++++++++++++++++++------- include/drm/bridge/aux-bridge.h | 7 ++-- 2 files changed, 37 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/bridge/aux-hpd-bridge.c b/drivers/gpu/drm/bridge/aux-hpd-bridge.c index 716b2220bdd5..79652d27db40 100644 --- a/drivers/gpu/drm/bridge/aux-hpd-bridge.c +++ b/drivers/gpu/drm/bridge/aux-hpd-bridge.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -321,17 +322,35 @@ static int dp_lane_to_typec_lane(enum dp_lane lane) return -EINVAL; } -static int typec_to_dp_lane(enum usb_ss_lane lane) +static int typec_to_dp_lane(enum usb_ss_lane lane, + enum typec_orientation orientation) { - switch (lane) { - case USB_SSRX1: - return DP_ML3; - case USB_SSTX1: - return DP_ML2; - case USB_SSTX2: - return DP_ML0; - case USB_SSRX2: - return DP_ML1; + switch (orientation) { + case TYPEC_ORIENTATION_NONE: + case TYPEC_ORIENTATION_NORMAL: + switch (lane) { + case USB_SSRX1: + return DP_ML3; + case USB_SSTX1: + return DP_ML2; + case USB_SSTX2: + return DP_ML0; + case USB_SSRX2: + return DP_ML1; + } + break; + case TYPEC_ORIENTATION_REVERSE: + switch (lane) { + case USB_SSRX1: + return DP_ML0; + case USB_SSTX1: + return DP_ML1; + case USB_SSTX2: + return DP_ML3; + case USB_SSRX2: + return DP_ML2; + } + break; } return -EINVAL; @@ -341,6 +360,7 @@ static int typec_to_dp_lane(enum usb_ss_lane lane) * drm_dp_typec_bridge_assign_pins - Assign DisplayPort (DP) lanes to USB type-C pins * @typec_bridge_dev: Device created for the type-c bridge * @conf: DisplayPort altmode configure command VDO content + * @orientation: Orientation of USB type-c port * @lane_mapping: Physical (array index) to logical (array value) USB type-C lane mapping * * Assign DP lanes to the USB type-C pins for the DP altmode configuration @@ -351,7 +371,7 @@ static int typec_to_dp_lane(enum usb_ss_lane lane) * Return: 0 on success, negative value for failure. */ int drm_dp_typec_bridge_assign_pins(struct drm_dp_typec_bridge_dev *typec_bridge_dev, - u32 conf, + u32 conf, enum typec_orientation orientation, enum usb_ss_lane lane_mapping[NUM_USB_SS]) { struct auxiliary_device *adev = &typec_bridge_dev->adev; @@ -388,7 +408,7 @@ int drm_dp_typec_bridge_assign_pins(struct drm_dp_typec_bridge_dev *typec_bridge typec_lane = lane_mapping[typec_lane]; /* Map logical type-c lane to logical DP lane */ - dp_lanes[i] = typec_to_dp_lane(typec_lane); + dp_lanes[i] = typec_to_dp_lane(typec_lane, orientation); } return 0; diff --git a/include/drm/bridge/aux-bridge.h b/include/drm/bridge/aux-bridge.h index aaace808772c..258b87c93623 100644 --- a/include/drm/bridge/aux-bridge.h +++ b/include/drm/bridge/aux-bridge.h @@ -7,6 +7,8 @@ #ifndef DRM_AUX_BRIDGE_H #define DRM_AUX_BRIDGE_H +#include + #include struct auxiliary_device; @@ -53,7 +55,8 @@ int devm_drm_dp_typec_bridge_add(struct device *dev, struct drm_dp_typec_bridge_ void drm_dp_typec_bridge_notify(struct drm_dp_typec_bridge_dev *typec_bridge_dev, enum drm_connector_status status); int drm_dp_typec_bridge_assign_pins(struct drm_dp_typec_bridge_dev *typec_bridge_dev, u32 conf, - enum usb_ss_lane lane_mapping[NUM_USB_SS]); + enum typec_orientation orientation, + enum usb_ss_lane lane_mapping[NUM_USB_SS]); #else static inline struct auxiliary_device *devm_drm_dp_hpd_bridge_alloc(struct device *parent, struct device_node *np) @@ -94,7 +97,7 @@ static inline void drm_dp_typec_bridge_notify(struct drm_dp_typec_bridge_dev *ty } static inline int drm_dp_typec_bridge_assign_pins(struct drm_dp_typec_bridge_dev *typec_bridge_dev, - u32 conf, + u32 conf, enum typec_orientation orientation, enum usb_ss_lane lane_mapping[NUM_USB_SS]) { return 0; From patchwork Thu Aug 15 00:34:10 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 13764318 Received: from mail-pf1-f170.google.com (mail-pf1-f170.google.com [209.85.210.170]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6A91836D for ; Thu, 15 Aug 2024 00:34:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.170 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723682075; cv=none; b=G38jQVxuw+deTmuNbMNftxVVCjCC08Fuckbfs3RaDyAv9W9svIzBpdvtOXfNPj38+BsecEkHotTjg2Yg6zJCQjk99vfKhjj2x2cNiALp+QDHXFcUmgykIKJsKCLLdBksFeTm83wklS0JFzh8m5SEqZSb8/I1lgwWBdLtI5wU+4I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723682075; c=relaxed/simple; bh=zTeIEewkb693isW8NOwvdmeLRQkQjPtBIKI0+HHAg2E=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=fBGGmiSDGYWetgqtFVdd1GhH9uhWk2Isbfz/9LjeqrA0WeIFJQ2D8G4WaGRJ5g2/8OxoQ0aBQeFuBcW405iNhfW5vJ8OcwpHyvKedWrL4KN6b4W4rK7q6wrWjGKZGyrPF/+ajeGYC2TMupOIYxsytMHyywSSLV/MfcgiRcLZB90= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=KuZGrxFL; arc=none smtp.client-ip=209.85.210.170 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="KuZGrxFL" Received: by mail-pf1-f170.google.com with SMTP id d2e1a72fcca58-712603f7ba5so311157b3a.3 for ; Wed, 14 Aug 2024 17:34:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1723682071; x=1724286871; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=LTAqmUB3C74WyCJMJxJLb1pif+r1V9bPB5gyO42OGKo=; b=KuZGrxFLnRRZRp6y6069S9ee/4Xk/j8Q/CFQwiIGPltoE28EX8UragvmrJxe+lah1K 1F1VJY8zZ0X7W/CIvocGDie0cRysGLFuxpXtbMf4iBuUWe/LO63XJBiJiAS4l0gw3ev1 JqIWS0Yl1Q/qMA6dsZztEaOfB5Qlc0iN18H4I= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723682071; x=1724286871; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=LTAqmUB3C74WyCJMJxJLb1pif+r1V9bPB5gyO42OGKo=; b=MJZ/dcWsyVSoZk/OwGEKn6BP4i1QwJKSet/kCEyym++gRj02VGT8SOETS2ZVnowm0E FPHRM74UqCkTUzcr07/06RT8GopEekOgQI6AidJA27gqC7sNWUmF+8aR3Wlyz4LJc/bj jI8CDb78CWwcu0hUtgqoBIP67Tp+BdpdyvsX1PpWUYtzqbNw+CEO+TJtSXLfatLZUO9R ZRCa7+yZokuCT0QRuAZUikHu7nblhE/LmLh5kgo/ciK5kGltnGCO5Cd8Ayu6LN6rwyif TgGLjwqOTFdYuy9mFnBZn6/6NCku8rOJm4jPDDcSfz+dq2zBZJYOy4b+DXMx2SQW5VPi fM0w== X-Gm-Message-State: AOJu0YywyPRIFVNX9uyZy6BfsyNqE697wmNwtMn8S6QWGZt6KQGbOFRl iksBICyDtp0Ms8DlmmRvZiJLV4AoYvzlpcYMKQQETq+E7WO9CjhP0/kRE6HCsrhnxU8R+pXg60M = X-Google-Smtp-Source: AGHT+IFi1sUOZeFN/sl/EmCy6pJtHVwtGc94+AhjMPhFgSZ7/Ovt9ABuwlS25ptPfHZRf5MNIAy+Kw== X-Received: by 2002:a05:6a21:2d0a:b0:1c6:fa3a:c798 with SMTP id adf61e73a8af0-1c8eaee91ecmr5582828637.32.1723682071315; Wed, 14 Aug 2024 17:34:31 -0700 (PDT) Received: from localhost (210.73.125.34.bc.googleusercontent.com. [34.125.73.210]) by smtp.gmail.com with UTF8SMTPSA id d2e1a72fcca58-7127af1999fsm151333b3a.169.2024.08.14.17.34.30 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 14 Aug 2024 17:34:30 -0700 (PDT) From: Stephen Boyd To: chrome-platform@lists.linux.dev Cc: linux-kernel@vger.kernel.org, patches@lists.linux.dev, devicetree@vger.kernel.org, Douglas Anderson , Pin-yen Lin , Andrzej Hajda , Benson Leung , Conor Dooley , Daniel Vetter , David Airlie , Dmitry Baryshkov , dri-devel@lists.freedesktop.org, Guenter Roeck , Jernej Skrabec , Jonas Karlman , Krzysztof Kozlowski , Laurent Pinchart , Lee Jones , Maarten Lankhorst , Maxime Ripard , Neil Armstrong , Prashant Malani , Robert Foss , Rob Herring , Thomas Zimmermann , Tzung-Bi Shih Subject: [PATCH v2 05/11] drm/bridge: dp_typec: Add "no-hpd" support Date: Wed, 14 Aug 2024 17:34:10 -0700 Message-ID: <20240815003417.1175506-6-swboyd@chromium.org> X-Mailer: git-send-email 2.46.0.76.ge559c4bf1a-goog In-Reply-To: <20240815003417.1175506-1-swboyd@chromium.org> References: <20240815003417.1175506-1-swboyd@chromium.org> Precedence: bulk X-Mailing-List: chrome-platform@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Some EC firmwares on Trogdor/Strongbad boards don't properly indicate the state of the DP HPD level on a type-c port. The EC only indicates that DP mode is entered or exited for a type-c port. The HPD state is expressed to the DP controller via a pin on the AP that the EC drives high or low when the type-c port partner (i.e. monitor) asserts or deasserts HPD. TL;DR: These devices don't support HPD signaling from the type-c code paths. Add support for HPD coming from somewhere else in the bridge chain. Callers can set the struct drm_dp_typec_bridge_desc::no_hpd member to indicate that HPD shouldn't be signaled from this bridge. Cc: Prashant Malani Cc: Benson Leung Cc: Tzung-Bi Shih Cc: Cc: Pin-yen Lin Cc: Dmitry Baryshkov Signed-off-by: Stephen Boyd --- drivers/gpu/drm/bridge/aux-hpd-bridge.c | 12 +++++++++++- include/drm/bridge/aux-bridge.h | 2 ++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/aux-hpd-bridge.c b/drivers/gpu/drm/bridge/aux-hpd-bridge.c index 79652d27db40..a5a434b7d5ec 100644 --- a/drivers/gpu/drm/bridge/aux-hpd-bridge.c +++ b/drivers/gpu/drm/bridge/aux-hpd-bridge.c @@ -20,6 +20,7 @@ static DEFINE_IDA(drm_aux_hpd_bridge_ida); struct drm_aux_hpd_bridge_data { struct drm_bridge bridge; struct device *dev; + bool no_hpd; }; enum dp_lane { @@ -54,6 +55,7 @@ to_drm_dp_typec_bridge_data(struct drm_bridge *bridge) struct drm_dp_typec_bridge_dev { struct auxiliary_device adev; size_t max_lanes; + bool no_hpd; }; static inline struct drm_dp_typec_bridge_dev * @@ -232,6 +234,7 @@ devm_drm_dp_typec_bridge_alloc(struct device *parent, const struct drm_dp_typec_ adev->dev.release = drm_dp_typec_bridge_release; adev->dev.platform_data = of_node_get(desc->of_node); typec_bridge_dev->max_lanes = desc->num_dp_lanes; + typec_bridge_dev->no_hpd = desc->no_hpd; ret = auxiliary_device_init(adev); if (ret) { @@ -278,6 +281,8 @@ void drm_aux_hpd_bridge_notify(struct device *dev, enum drm_connector_status sta if (!data) return; + if (data->no_hpd) + return; drm_bridge_hpd_notify(&data->bridge, status); } @@ -467,6 +472,7 @@ static int drm_aux_hpd_bridge_probe(struct auxiliary_device *auxdev, { struct device *dev = &auxdev->dev; struct drm_aux_hpd_bridge_data *hpd_data; + struct drm_dp_typec_bridge_dev *typec_bridge_dev; struct drm_dp_typec_bridge_data *typec_data; struct drm_bridge *bridge; u8 dp_lanes[] = { DP_ML0, DP_ML1, DP_ML2, DP_ML3 }; @@ -477,6 +483,7 @@ static int drm_aux_hpd_bridge_probe(struct auxiliary_device *auxdev, return -ENOMEM; bridge = &hpd_data->bridge; bridge->funcs = &drm_aux_hpd_bridge_funcs; + bridge->ops = DRM_BRIDGE_OP_HPD; } else if (id->driver_data == DRM_AUX_TYPEC_BRIDGE) { typec_data = devm_kzalloc(dev, sizeof(*typec_data), GFP_KERNEL); if (!typec_data) @@ -484,6 +491,10 @@ static int drm_aux_hpd_bridge_probe(struct auxiliary_device *auxdev, hpd_data = &typec_data->hpd_bridge; bridge = &hpd_data->bridge; bridge->funcs = &drm_dp_typec_bridge_funcs; + typec_bridge_dev = to_drm_dp_typec_bridge_dev(dev); + if (!typec_bridge_dev->no_hpd) + bridge->ops = DRM_BRIDGE_OP_HPD; + hpd_data->no_hpd = typec_bridge_dev->no_hpd; memcpy(typec_data->dp_lanes, dp_lanes, sizeof(typec_data->dp_lanes)); } else { return -ENODEV; @@ -491,7 +502,6 @@ static int drm_aux_hpd_bridge_probe(struct auxiliary_device *auxdev, hpd_data->dev = dev; bridge->of_node = dev_get_platdata(dev); - bridge->ops = DRM_BRIDGE_OP_HPD; bridge->type = DRM_MODE_CONNECTOR_DisplayPort; auxiliary_set_drvdata(auxdev, hpd_data); diff --git a/include/drm/bridge/aux-bridge.h b/include/drm/bridge/aux-bridge.h index 258b87c93623..13f5e98b4d31 100644 --- a/include/drm/bridge/aux-bridge.h +++ b/include/drm/bridge/aux-bridge.h @@ -28,10 +28,12 @@ struct drm_dp_typec_bridge_dev; * struct drm_dp_typec_bridge_desc - drm_dp_typec_bridge descriptor * @of_node: device node pointer corresponding to this bridge instance * @num_dp_lanes: number of input DP lanes possible (1, 2 or 4) + * @no_hpd: true if this bridge can't signal HPD state with drm_dp_typec_bridge_notify() */ struct drm_dp_typec_bridge_desc { struct device_node *of_node; size_t num_dp_lanes; + bool no_hpd; }; enum usb_ss_lane { From patchwork Thu Aug 15 00:34:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 13764319 Received: from mail-pl1-f175.google.com (mail-pl1-f175.google.com [209.85.214.175]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E90C229CE6 for ; Thu, 15 Aug 2024 00:34:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.175 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723682075; cv=none; b=Vy42orGXSLFZG/vejS7m5hSKQAw2SQNFJUlwiJVKt2H+bKwWj2CC7+EzCH5r+pl3i5VbThKJ4ZQO9oxTpDzEy83a6MUj70vVM0D9VXwD0qtalE1wBVMMoamS883Ee7Xy/+LSlE3k4Xy38JCM+iM+aQJ1b3Y2IBMJOl6FUu5pMh4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723682075; c=relaxed/simple; bh=/jcJ+rI0gKZr/IVP6XjS/Ak4IPjJQVitYadHxzTrZ4s=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=cHL1bhVD2f725nWKTllYwvbMx3TB8nh/7Rjm1de+0ju9NomYqaZHlEobTmHxt3I/dT07QRxleciVUTjuzOVymod+pnx/DTyBoQwmYTT8Em8Cn7GH8dtbQrg8lDdWZ+YQ0eiNQGa/kU5Q8kSIEceaYLwyILuwHkK2uz7YGEIVlYQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=A69DsFGd; arc=none smtp.client-ip=209.85.214.175 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="A69DsFGd" Received: by mail-pl1-f175.google.com with SMTP id d9443c01a7336-201d9fa899dso3632665ad.3 for ; Wed, 14 Aug 2024 17:34:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1723682073; x=1724286873; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=/yiv0xFPMhU7ZUs+XvuB/ZZA+l47REHWpzG575OPKPI=; b=A69DsFGdMednrGF3pFnSkOQHqKt66AlUBP8RpG7Bf8QF5hyrKqyQ7YNxajAtQanD6u pzdHBFTlQY8XVYgbqoMf+t2XOyXiIaWeux9pFU0wAx7DAnegBnP8Tc6hghS5uG6UpovE 6ALKrL7x0YMFhbGJazypRXx9/jAOQOiifqeSY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723682073; x=1724286873; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=/yiv0xFPMhU7ZUs+XvuB/ZZA+l47REHWpzG575OPKPI=; b=RsWObP7nwokiXHpgcTB1FmC5R8fKxyKttRfMxy4+aTBY4Mi3ldnb8gbT9e4uY2hBmQ CDyIzTehsfJGm7rwupKn/cjXwykDTH7SC95HxJrs2/qkpJ6SzR+klCOeIcdmwtfL0jgg NqDh2I5PC3K6IXvGmG4paJIzgSiR0HKKAS4W4NAPAVN8lWlIaL0O5cQZyvAPHhCrGOPb LiZLdOkhcCaveVfjZCHkJuXEtrQXsdtQP2yeqXqO+47ON71MPG0d6mKdY2NBMIt21OwA 7cXLRGatJPH4nRFTrJ1Ym139UPRp10B9UxdObC/E11dhrxV0URdi7Ty9v76nsq9ljWer ed1A== X-Gm-Message-State: AOJu0Yx1tTGT4Th4DeYtf3mrzYHkUVwanw4Z/r8HRM0LTOMOBlgptxwW LQ0rSP4393sYpJSqHtC6yl0D34w1v8K9PUKKL6qX6AkhLWXbP8VcXigJ1s11mAyK4e8ayJoYMfA = X-Google-Smtp-Source: AGHT+IHJN+4iBjtg5BFHkoM0j1LHWILoEX4QehkqxO/ua5YPwB+wrtI73F9/wcxBEBcJXyMVg84zJg== X-Received: by 2002:a17:902:7c92:b0:1fc:6b8b:4918 with SMTP id d9443c01a7336-201d64b09ddmr38089775ad.41.1723682072985; Wed, 14 Aug 2024 17:34:32 -0700 (PDT) Received: from localhost (210.73.125.34.bc.googleusercontent.com. [34.125.73.210]) by smtp.gmail.com with UTF8SMTPSA id d9443c01a7336-201f03a16b2sm1970445ad.268.2024.08.14.17.34.31 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 14 Aug 2024 17:34:32 -0700 (PDT) From: Stephen Boyd To: chrome-platform@lists.linux.dev Cc: linux-kernel@vger.kernel.org, patches@lists.linux.dev, devicetree@vger.kernel.org, Douglas Anderson , Pin-yen Lin , Andrzej Hajda , Benson Leung , Conor Dooley , Daniel Vetter , David Airlie , Dmitry Baryshkov , dri-devel@lists.freedesktop.org, Guenter Roeck , Jernej Skrabec , Jonas Karlman , Krzysztof Kozlowski , Laurent Pinchart , Lee Jones , Maarten Lankhorst , Maxime Ripard , Neil Armstrong , Prashant Malani , Robert Foss , Rob Herring , Thomas Zimmermann , Tzung-Bi Shih Subject: [PATCH v2 06/11] drm/bridge: dp_typec: Allow users to hook hpd notify path Date: Wed, 14 Aug 2024 17:34:11 -0700 Message-ID: <20240815003417.1175506-7-swboyd@chromium.org> X-Mailer: git-send-email 2.46.0.76.ge559c4bf1a-goog In-Reply-To: <20240815003417.1175506-1-swboyd@chromium.org> References: <20240815003417.1175506-1-swboyd@chromium.org> Precedence: bulk X-Mailing-List: chrome-platform@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The previous patch added support for no-hpd to drm_dp_typec_bridge code. Allow users of this bridge to hook the HPD notification path of the bridge chain so that they can be made aware of the connector status changing. This helps HPD-less users of the bridge inject the HPD state into their code by using the connector status as a proxy for HPD being asserted or deasserted. In particular, this will help Trogdor/Strongbad boards that need to read the EC's analog mux which steers the DP signal to one or the other USB type-c ports to figure out which type-c port has HPD asserted. Cc: Prashant Malani Cc: Benson Leung Cc: Tzung-Bi Shih Cc: Cc: Pin-yen Lin Cc: Dmitry Baryshkov Signed-off-by: Stephen Boyd --- drivers/gpu/drm/bridge/aux-hpd-bridge.c | 19 +++++++++++++++++++ include/drm/bridge/aux-bridge.h | 5 +++++ 2 files changed, 24 insertions(+) diff --git a/drivers/gpu/drm/bridge/aux-hpd-bridge.c b/drivers/gpu/drm/bridge/aux-hpd-bridge.c index a5a434b7d5ec..32c0171c512c 100644 --- a/drivers/gpu/drm/bridge/aux-hpd-bridge.c +++ b/drivers/gpu/drm/bridge/aux-hpd-bridge.c @@ -55,6 +55,9 @@ to_drm_dp_typec_bridge_data(struct drm_bridge *bridge) struct drm_dp_typec_bridge_dev { struct auxiliary_device adev; size_t max_lanes; + void (*hpd_notify)(struct drm_dp_typec_bridge_dev *dev, + void *data, enum drm_connector_status status); + void *hpd_data; bool no_hpd; }; @@ -235,6 +238,8 @@ devm_drm_dp_typec_bridge_alloc(struct device *parent, const struct drm_dp_typec_ adev->dev.platform_data = of_node_get(desc->of_node); typec_bridge_dev->max_lanes = desc->num_dp_lanes; typec_bridge_dev->no_hpd = desc->no_hpd; + typec_bridge_dev->hpd_notify = desc->hpd_notify; + typec_bridge_dev->hpd_data = desc->hpd_data; ret = auxiliary_device_init(adev); if (ret) { @@ -305,6 +310,19 @@ void drm_dp_typec_bridge_notify(struct drm_dp_typec_bridge_dev *typec_bridge_dev } EXPORT_SYMBOL_GPL(drm_dp_typec_bridge_notify); +static void drm_dp_typec_bridge_hpd_notify(struct drm_bridge *bridge, + enum drm_connector_status status) +{ + struct drm_dp_typec_bridge_data *data; + struct drm_dp_typec_bridge_dev *typec_bridge_dev; + + data = to_drm_dp_typec_bridge_data(bridge); + typec_bridge_dev = to_drm_dp_typec_bridge_dev(data->hpd_bridge.dev); + + if (typec_bridge_dev->hpd_notify) + typec_bridge_dev->hpd_notify(typec_bridge_dev, typec_bridge_dev->hpd_data, status); +} + static int drm_aux_hpd_bridge_attach(struct drm_bridge *bridge, enum drm_bridge_attach_flags flags) { @@ -460,6 +478,7 @@ static const struct drm_bridge_funcs drm_dp_typec_bridge_funcs = { .atomic_reset = drm_atomic_helper_bridge_reset, .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, + .hpd_notify = drm_dp_typec_bridge_hpd_notify, }; enum drm_aux_bridge_type { diff --git a/include/drm/bridge/aux-bridge.h b/include/drm/bridge/aux-bridge.h index 13f5e98b4d31..3229f200f0df 100644 --- a/include/drm/bridge/aux-bridge.h +++ b/include/drm/bridge/aux-bridge.h @@ -28,11 +28,16 @@ struct drm_dp_typec_bridge_dev; * struct drm_dp_typec_bridge_desc - drm_dp_typec_bridge descriptor * @of_node: device node pointer corresponding to this bridge instance * @num_dp_lanes: number of input DP lanes possible (1, 2 or 4) + * @hpd_notify: callback for bridge hot plug detect events + * @hpd_data: data passed to @hpd_notify callback * @no_hpd: true if this bridge can't signal HPD state with drm_dp_typec_bridge_notify() */ struct drm_dp_typec_bridge_desc { struct device_node *of_node; size_t num_dp_lanes; + void (*hpd_notify)(struct drm_dp_typec_bridge_dev *typec_bridge_dev, + void *data, enum drm_connector_status status); + void *hpd_data; bool no_hpd; }; From patchwork Thu Aug 15 00:34:12 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 13764320 Received: from mail-pl1-f178.google.com (mail-pl1-f178.google.com [209.85.214.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C511739AEB for ; Thu, 15 Aug 2024 00:34:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723682078; cv=none; b=pJlAsBqgguGmLYZMA8ZhWQQ/7V5L2CupGIQ6PNutv6X/z6j3EYa2I9y2iEG8L8WTqhFHAoM2+uZ1jlh4NYNGLvhVwabO3YWnr4qfAqFDYOZ2GbQ4LcqQPcwFE5RtRjeQOhwZYzDNE0XrsLATcPjYT0VmkrLqU/lqydyK+WfDmXc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723682078; c=relaxed/simple; bh=TumcHWw87aylU9A2iL70884Gdnzc7x4bQe8WzgEWOQ0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=bXl7O3qTLcblJGwLWjawNi3+YRx61ompGLftIqwlAwjjXUg9IhOIgur5p03Ooo8n1XqUGhyfCe0QySaiNLJkw1impK2Dpb2H/eFspWHFnoLWAGyzAQpTw17Sntsr7otnd5PhyyEVm4at/Mni9zdbiZFZ3XRvQQDjT37NS7jSwFM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=lbGTClEo; arc=none smtp.client-ip=209.85.214.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="lbGTClEo" Received: by mail-pl1-f178.google.com with SMTP id d9443c01a7336-1fd66cddd4dso4223905ad.2 for ; Wed, 14 Aug 2024 17:34:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1723682076; x=1724286876; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=1sRgulPJ1+mkqgVa6mf/3UC8LhJzrRLUVCX/M4EQ0c4=; b=lbGTClEofy+bIriVhE3zIDM3KVV+Fj7fVcjHw4F8sFqN7xJKQJd3lT0xHK5Ce2VThK f2K10qb8u+oz3QQ6q9mkI6qm3KIjqVf8BNP3yzZjhGQAAe2ZRJIsxftYUJm8Wne+CD7I EaUErK75mkep63kUcckJBYg0IL68Bxb+3UoG8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723682076; x=1724286876; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=1sRgulPJ1+mkqgVa6mf/3UC8LhJzrRLUVCX/M4EQ0c4=; b=hPEAmclSmGjMBzlT4B6SX9CE0VOiFI8fyv5m938WkB/3aIQ3fJODfz8yeaF+Ez4S5D e0VwiV9CsBQSj8A4OMbVGZGDVWayRTdCrU/ZARSdHXSNXHpruGXzAhQmGJpnxWPZBO+E Lddig+LZlTWxf4ct1NV2EiTr87uNbMteOvsW7BTsojxLv6oerX6Dbcbn+DMcv9XznYP7 TCJy9vLn5r5qtS9ka3BK+xh4+DlSfRX+QdeswI4wz0PUdgZ26qUL1wkq0tX7ppwdSdum 9Oc0Lzb5EU14rwYfwoj0Lj/UWsnAksdVKvPm+sqObHnUkP//kLzeeZJeqewbKTm+E5QP ARJg== X-Gm-Message-State: AOJu0YxJC2UTnYe3aFOhj0CWHb7lTJ7ceYZKT1Jl6+UCzbzREj7D+3Y2 VAgymn249OBje+l3foeF7gxvRbs/CiSyE8LcKBVpKYFNSoogmuBfUs3GkRR5UeIZvr2PNzgEv8c = X-Google-Smtp-Source: AGHT+IHbVzloJcEMHTMRWtdVRBjc1XqfslsElu4LQA8xI/W2vRG5qbpPTju2PgzgyOJIJKY/OqqVPg== X-Received: by 2002:a17:902:ced0:b0:1fd:91b1:7897 with SMTP id d9443c01a7336-201d64d0e79mr53482475ad.65.1723682075829; Wed, 14 Aug 2024 17:34:35 -0700 (PDT) Received: from localhost (210.73.125.34.bc.googleusercontent.com. [34.125.73.210]) by smtp.gmail.com with UTF8SMTPSA id d9443c01a7336-201f02faa5dsm2033485ad.2.2024.08.14.17.34.33 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 14 Aug 2024 17:34:34 -0700 (PDT) From: Stephen Boyd To: chrome-platform@lists.linux.dev Cc: linux-kernel@vger.kernel.org, patches@lists.linux.dev, devicetree@vger.kernel.org, Douglas Anderson , Pin-yen Lin , Andrzej Hajda , Benson Leung , Conor Dooley , Daniel Vetter , David Airlie , Dmitry Baryshkov , dri-devel@lists.freedesktop.org, Guenter Roeck , Jernej Skrabec , Jonas Karlman , Krzysztof Kozlowski , Laurent Pinchart , Lee Jones , Maarten Lankhorst , Maxime Ripard , Neil Armstrong , Prashant Malani , Robert Foss , Rob Herring , Thomas Zimmermann , Tzung-Bi Shih Subject: [PATCH v2 07/11] dt-bindings: chrome: Add ports to google,cros-ec-typec for DP altmode Date: Wed, 14 Aug 2024 17:34:12 -0700 Message-ID: <20240815003417.1175506-8-swboyd@chromium.org> X-Mailer: git-send-email 2.46.0.76.ge559c4bf1a-goog In-Reply-To: <20240815003417.1175506-1-swboyd@chromium.org> References: <20240815003417.1175506-1-swboyd@chromium.org> Precedence: bulk X-Mailing-List: chrome-platform@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add a DT graph binding to google,cros-ec-typec so that it can combine DisplayPort (DP) and USB SuperSpeed (SS) data into a USB type-c endpoint that is connected to the usb-c-connector node's SS endpoint. This also allows us to connect the DP and USB nodes in the graph to the USB type-c connectors, providing the full picture of the USB type-c data flows in the system. Allow there to be multiple typec nodes underneath the EC node so that one DT graph exists per DP bridge. The EC is actually controlling TCPCs and redrivers that combine the DP and USB signals together so this more accurately reflects the hardware design without introducing yet another DT node underneath the EC for USB type-c. If the type-c ports are being shared between a single DP controller then the ports need to know about each other and determine a policy to drive DP to one type-c port. If the type-c ports each have their own dedicated DP controller then they're able to operate independently and enter/exit DP altmode independently as well. We can't connect the DP controller's endpoint to one usb-c-connector port@1 endpoint and the USB controller's endpoint to another usb-c-connector port@1 endpoint either because the DP muxing case would have DP connected to two usb-c-connector endpoints which the graph binding doesn't support. Therefore, one typec node is required per the capabilities of the type-c port(s) being managed. This also lets us indicate which type-c ports the DP controller is wired to. For example, if DP was connected to ports 0 and 2, while port 1 was connected to another DP controller we wouldn't be able to implement that without having some other DT property to indicate which output ports are connected to the DP endpoint. Cc: Rob Herring Cc: Krzysztof Kozlowski Cc: Conor Dooley Cc: Lee Jones Cc: Benson Leung Cc: Guenter Roeck Cc: Prashant Malani Cc: Tzung-Bi Shih Cc: Cc: Cc: Pin-yen Lin Signed-off-by: Stephen Boyd Acked-by: Lee Jones --- .../bindings/chrome/google,cros-ec-typec.yaml | 260 ++++++++++++++++++ .../bindings/mfd/google,cros-ec.yaml | 7 +- 2 files changed, 264 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/chrome/google,cros-ec-typec.yaml b/Documentation/devicetree/bindings/chrome/google,cros-ec-typec.yaml index 9f9816fbecbc..1238adfbea21 100644 --- a/Documentation/devicetree/bindings/chrome/google,cros-ec-typec.yaml +++ b/Documentation/devicetree/bindings/chrome/google,cros-ec-typec.yaml @@ -26,6 +26,137 @@ properties: '#size-cells': const: 0 + mux-gpios: + description: GPIOs indicating which way the DP mux is steered + maxItems: 1 + + no-hpd: + description: Indicates this endpoint doesn't signal HPD for DisplayPort + type: boolean + + orientation: + description: + Indicates this endpoint assigns lanes based on altmode and + type-c port orientation + type: boolean + + ports: + $ref: /schemas/graph.yaml#/properties/ports + + properties: + port@0: + $ref: /schemas/graph.yaml#/$defs/port-base + description: + Input port to receive DisplayPort (DP) data + unevaluatedProperties: false + + properties: + endpoint@0: + $ref: /schemas/graph.yaml#/$defs/endpoint-base + description: DisplayPort data for the type-c port(s) + unevaluatedProperties: false + properties: + data-lanes: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: | + An array of physical DP data lane indexes + - 0 is DP ML0 lane + - 1 is DP ML1 lane + - 2 is DP ML2 lane + - 3 is DP ML3 lane + oneOf: + - items: + - const: 0 + - const: 1 + - items: + - const: 0 + - const: 1 + - const: 2 + - const: 3 + + required: + - endpoint@0 + + port@1: + $ref: /schemas/graph.yaml#/$defs/port-base + unevaluatedProperties: false + description: + Input port to receive USB SuperSpeed (SS) data + patternProperties: + "^endpoint@([0-8])$": + $ref: /schemas/graph.yaml#/properties/endpoint + + anyOf: + - required: + - endpoint@0 + - required: + - endpoint@1 + - required: + - endpoint@2 + - required: + - endpoint@3 + - required: + - endpoint@4 + - required: + - endpoint@5 + - required: + - endpoint@6 + - required: + - endpoint@7 + - required: + - endpoint@8 + + port@2: + $ref: /schemas/graph.yaml#/$defs/port-base + unevaluatedProperties: false + description: Output ports for combined DP and USB SS data + patternProperties: + "^endpoint@([0-8])$": + $ref: /schemas/graph.yaml#/$defs/endpoint-base + unevaluatedProperties: false + + properties: + data-lanes: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: | + An array of physical USB Type-C data lane indexes. + - 0 is SSRX1 lane + - 1 is SSTX1 lane + - 2 is SSTX2 lane + - 3 is SSRX2 lane + minItems: 4 + maxItems: 4 + items: + maximum: 3 + + anyOf: + - required: + - endpoint@0 + - required: + - endpoint@1 + - required: + - endpoint@2 + - required: + - endpoint@3 + - required: + - endpoint@4 + - required: + - endpoint@5 + - required: + - endpoint@6 + - required: + - endpoint@7 + - required: + - endpoint@8 + + required: + - port@2 + anyOf: + - required: + - port@0 + - required: + - port@1 + patternProperties: '^connector@[0-9a-f]+$': $ref: /schemas/connector/usb-connector.yaml# @@ -35,6 +166,38 @@ patternProperties: required: - compatible +allOf: + - if: + properties: + no-hpd: true + required: + - no-hpd + then: + properties: + ports: + required: + - port@0 + - if: + properties: + mux-gpios: true + required: + - mux-gpios + then: + properties: + ports: + required: + - port@0 + - if: + properties: + orientation: true + required: + - orientation + then: + properties: + ports: + required: + - port@0 + additionalProperties: false examples: @@ -60,6 +223,103 @@ examples: power-role = "dual"; data-role = "dual"; try-power-role = "source"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + usb_c0_hs: endpoint { + remote-endpoint = <&usb_hub_dfp3_hs>; + }; + }; + + port@1 { + reg = <1>; + usb_c0_ss: endpoint { + remote-endpoint = <&cros_typec_c0_ss>; + }; + }; + }; + }; + + connector@1 { + compatible = "usb-c-connector"; + reg = <1>; + power-role = "dual"; + data-role = "dual"; + try-power-role = "source"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + usb_c1_hs: endpoint { + remote-endpoint = <&usb_hub_dfp2_hs>; + }; + }; + + port@1 { + reg = <1>; + usb_c1_ss: endpoint { + remote-endpoint = <&cros_typec_c1_ss>; + }; + }; + }; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + dp_in: endpoint@0 { + reg = <0>; + remote-endpoint = <&dp_phy>; + data-lanes = <0 1>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + usb_in_0: endpoint@0 { + reg = <0>; + remote-endpoint = <&usb_ss_0_out>; + }; + + usb_in_1: endpoint@1 { + reg = <1>; + remote-endpoint = <&usb_ss_1_out>; + }; + }; + + port@2 { + reg = <2>; + #address-cells = <1>; + #size-cells = <0>; + + cros_typec_c0_ss: endpoint@0 { + reg = <0>; + remote-endpoint = <&usb_c0_ss>; + data-lanes = <0 1 2 3>; + }; + + cros_typec_c1_ss: endpoint@1 { + reg = <1>; + remote-endpoint = <&usb_c1_ss>; + data-lanes = <2 3 0 1>; + }; + }; }; }; }; diff --git a/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml b/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml index aac8819bd00b..c860eb7ed3f5 100644 --- a/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml +++ b/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml @@ -98,9 +98,6 @@ properties: gpio-controller: true - typec: - $ref: /schemas/chrome/google,cros-ec-typec.yaml# - ec-pwm: $ref: /schemas/pwm/google,cros-ec-pwm.yaml# deprecated: true @@ -166,6 +163,10 @@ patternProperties: type: object $ref: /schemas/extcon/extcon-usbc-cros-ec.yaml# + "^typec(-[0-9])*$": + type: object + $ref: /schemas/chrome/google,cros-ec-typec.yaml# + required: - compatible From patchwork Thu Aug 15 00:34:13 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 13764321 Received: from mail-pl1-f179.google.com (mail-pl1-f179.google.com [209.85.214.179]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C02515680 for ; Thu, 15 Aug 2024 00:34:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.179 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723682080; cv=none; b=mdOVmT6w7cLqtniPS/satW+osaT+ngaybfjDBNZCNwVTKXVWLtb/aGazMWp727Caq+M5/k0ME9EVT9r9hmyYh0YraOCdRv82TGoTG4LJUcLhW3BnWE5LTTzXMb/GcKZObt11a9CTB9DEan9hD2oiIIcetGgSoGrcR5b+NFmUAxA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723682080; c=relaxed/simple; bh=LeTPU6H6rCIzaxNzECUBVdQM4HVHJXSVMbMKRhsUJms=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mD/pRYTjuNkt12gHk6ueYgyHTfl0jcKdziUQ/p6O/A5WHgQRKOveiMDMEKAd2GwW6I5G11vKxRL4rj3k4x2jjBrLl+v0J4vwIS6bklE64PA1B6mf7p2c6AX+Oh1kXEoG3crExDd5RYQWWpeV4LIY0Ry/xUOoMo0vlzlw8kQzAPM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=kihKgM2a; arc=none smtp.client-ip=209.85.214.179 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="kihKgM2a" Received: by mail-pl1-f179.google.com with SMTP id d9443c01a7336-201d5af11a4so4125225ad.3 for ; Wed, 14 Aug 2024 17:34:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1723682078; x=1724286878; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=eay7JVeaRdUdJgh2AiNC6S0SBArgtOAmkTCpf0gbN4k=; b=kihKgM2ao21cyh5g1XtbXOLdkkI/5cqC4dhjyy5cvJUF096g0AkZV62n7QiQYwgjHO WC44SHbnDsItOifnJZS2NlW7Odzjr4On4387lxPDZL89JfQWk/+C/2CG2Hp/YIvirQ8p 23Y5sMBxd8LP6vMySn3c9xWAYvRRyhA4wRuPw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723682078; x=1724286878; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=eay7JVeaRdUdJgh2AiNC6S0SBArgtOAmkTCpf0gbN4k=; b=fZnV/xZFOZ6yEXarUw7igQSY2+1bSu4pQazKEOUlr+HdxBYzhNzc0+LXRfg53wPzkR H3HF2riD3jdEDIXrfljVwsqj1AbslK+7dJd8xZ8dBbhliu+bvAvUihXl5LPSFLFaXem8 2NDhP23sw8aJ3NiRc7j36qK1rJ03rJOWZjIbcA38YJzTgbyAyWyUw27J3JS+JxZj40wI a6QXyCFGMNl9KXlCGxikyF4OXeHIK1pcw6FJ+UdHRhTMeCcqEYqTQMsWjM1IY6i6VarV 6JDVtJ6qjVfR38Iq9Yr/OOf7fT7SuPDrQGP1x345I3EgjNHLcxNWOU6WD8HzPgdTlhBR M0eg== X-Gm-Message-State: AOJu0YzPNfK55QdKvmo0JWOPM6BviqQHptBXuvy/NZ1IQMFMyGHlxWvB ryqDAQVRybE96Eh4CmjBHpRtRy+9mmGSGrDYud7nW72aP+lRG3b5CDuC7kpNe6UgRwV9nXgE1kc = X-Google-Smtp-Source: AGHT+IHpwP//FMDrEpT41s5mxfmyYIk9kyHXUIvacsVcLLg/D2b+GUUjbBYfSj/U5sQTScK5NqQIqA== X-Received: by 2002:a17:902:cec2:b0:1fd:a360:447b with SMTP id d9443c01a7336-201d6487f50mr53664315ad.52.1723682077796; Wed, 14 Aug 2024 17:34:37 -0700 (PDT) Received: from localhost (210.73.125.34.bc.googleusercontent.com. [34.125.73.210]) by smtp.gmail.com with UTF8SMTPSA id d9443c01a7336-201f037aeadsm1985745ad.138.2024.08.14.17.34.36 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 14 Aug 2024 17:34:37 -0700 (PDT) From: Stephen Boyd To: chrome-platform@lists.linux.dev Cc: linux-kernel@vger.kernel.org, patches@lists.linux.dev, devicetree@vger.kernel.org, Douglas Anderson , Pin-yen Lin , Andrzej Hajda , Benson Leung , Conor Dooley , Daniel Vetter , David Airlie , Dmitry Baryshkov , dri-devel@lists.freedesktop.org, Guenter Roeck , Jernej Skrabec , Jonas Karlman , Krzysztof Kozlowski , Laurent Pinchart , Lee Jones , Maarten Lankhorst , Maxime Ripard , Neil Armstrong , Prashant Malani , Robert Foss , Rob Herring , Thomas Zimmermann , Tzung-Bi Shih Subject: [PATCH v2 08/11] platform/chrome: cros_ec_typec: Add support for signaling DP HPD via drm_bridge Date: Wed, 14 Aug 2024 17:34:13 -0700 Message-ID: <20240815003417.1175506-9-swboyd@chromium.org> X-Mailer: git-send-email 2.46.0.76.ge559c4bf1a-goog In-Reply-To: <20240815003417.1175506-1-swboyd@chromium.org> References: <20240815003417.1175506-1-swboyd@chromium.org> Precedence: bulk X-Mailing-List: chrome-platform@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 We can imagine that logically the EC is a device that has some number of DisplayPort (DP) connector inputs, some number of USB3 connector inputs, and some number of USB type-c connector outputs. If you squint enough it looks like a USB type-c dock. Logically there's a crossbar pin assignment capability within the EC that can assign USB and DP lanes to USB type-c lanes in the connector (i.e. USB type-c pin configurations). In reality, the EC is a microcontroller that has some TCPCs and redrivers connected to it over something like i2c and DP/USB from the AP is wired directly to those ICs, not the EC. This design allows the EC to abstract many possible USB and DP hardware configurations away from the AP (kernel) so that the AP can largely deal with USB and DP without thinking about USB Type-C much at all. The DP and USB data originate in the AP, not the EC, so it helps to think that the EC takes the DP and USB data as input to mux onto USB type-c ports even if it really doesn't do that. With this split design, the EC forwards the DP HPD state to the DP hardware via a GPIO that's connected to the DP phy. Having that HPD state signaled directly to the DP phy uses precious hardware resources, a pin or two and a wire, and it also forces the TCPM to live on the EC. If we want to save costs and move more control of USB type-c to the kernel it's in our interest to get rid of the HPD pin entirely and signal HPD to the DP phy some other way. Luckily, the EC already exposes information about the USB Type-C stack to the kernel via the host command interface in the "google,cros-ec-typec" compatible driver, which parses EC messages related to USB type-c and effectively "replays" those messages to the kernel's USB typec subsystem. This includes the state of HPD, which can be interrogated and acted upon by registering a 'struct typec_mux_dev' with the typec subsystem or by hooking directly into this cros_ec_typec driver. On DT based systems, the DP display pipeline is abstracted via a 'struct drm_bridge'. If we want to signal HPD state from within the kernel we need to hook into the drm_bridge framework somehow to call drm_bridge_hpd_notify() when HPD state changes in the typec framework. Use the newly added drm_dp_typec_bridge code to do this. When the EC notifies AP of a type-c event, look at the port state and set the connector state to connected or disconnected based on the HPD level when the port is in DP mode. To keep this patch minimal, only signal HPD state to the drm_bridge chain. Later patches will add more features. Eventually we'll be able to inform userspace about which usb-c-connector node is displaying DP and what USB devices are connected to a connector. Cc: Prashant Malani Cc: Benson Leung Cc: Tzung-Bi Shih Cc: Cc: Pin-yen Lin Signed-off-by: Stephen Boyd --- drivers/platform/chrome/Kconfig | 1 + drivers/platform/chrome/cros_ec_typec.c | 64 ++++++++++++++++++++++++- drivers/platform/chrome/cros_ec_typec.h | 4 +- 3 files changed, 67 insertions(+), 2 deletions(-) diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig index 7dbeb786352a..0aee8a77f1d6 100644 --- a/drivers/platform/chrome/Kconfig +++ b/drivers/platform/chrome/Kconfig @@ -231,6 +231,7 @@ config CROS_EC_TYPEC depends on MFD_CROS_EC_DEV && TYPEC depends on CROS_USBPD_NOTIFY depends on USB_ROLE_SWITCH + select DRM_AUX_HPD_BRIDGE if DRM_BRIDGE && OF default MFD_CROS_EC_DEV help If you say Y here, you get support for accessing Type C connector diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index 4d305876ec08..5cbc6b3df906 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -16,11 +17,18 @@ #include #include +#include + #include "cros_ec_typec.h" #include "cros_typec_vdm.h" #define DRV_NAME "cros-ec-typec" +struct cros_typec_dp_bridge { + struct cros_typec_data *typec_data; + struct drm_dp_typec_bridge_dev *dev; +}; + #define DP_PORT_VDO (DP_CONF_SET_PIN_ASSIGN(BIT(DP_PIN_ASSIGN_C) | BIT(DP_PIN_ASSIGN_D)) | \ DP_CAP_DFP_D | DP_CAP_RECEPTACLE) @@ -334,6 +342,9 @@ static int cros_typec_init_ports(struct cros_typec_data *typec) u32 port_num = 0; nports = device_get_child_node_count(dev); + /* Don't count any 'ports' child node */ + if (of_graph_is_present(dev->of_node)) + nports--; if (nports == 0) { dev_err(dev, "No port entries found.\n"); return -ENODEV; @@ -347,6 +358,10 @@ static int cros_typec_init_ports(struct cros_typec_data *typec) /* DT uses "reg" to specify port number. */ port_prop = dev->of_node ? "reg" : "port-number"; device_for_each_child_node(dev, fwnode) { + /* An OF graph isn't a connector */ + if (fwnode_name_eq(fwnode, "ports")) + continue; + if (fwnode_property_read_u32(fwnode, port_prop, &port_num)) { ret = -EINVAL; dev_err(dev, "No port-number for port, aborting.\n"); @@ -413,6 +428,36 @@ static int cros_typec_init_ports(struct cros_typec_data *typec) return ret; } +static int cros_typec_init_dp_bridge(struct cros_typec_data *typec) +{ + struct device *dev = typec->dev; + struct cros_typec_dp_bridge *dp_bridge; + struct fwnode_handle *ep __free(fwnode_handle); + struct drm_dp_typec_bridge_dev *dp_dev; + struct drm_dp_typec_bridge_desc desc = { + .of_node = dev->of_node, + }; + + ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), 0, 0, 0); + if (!ep) { + /* There isn't a DP input endpoint. Ignore. */ + return 0; + } + + dp_bridge = devm_kzalloc(dev, sizeof(*dp_bridge), GFP_KERNEL); + if (!dp_bridge) + return -ENOMEM; + typec->dp_bridge = dp_bridge; + dp_bridge->typec_data = typec; + + dp_dev = devm_drm_dp_typec_bridge_alloc(dev, &desc); + if (IS_ERR(dp_dev)) + return PTR_ERR(dp_dev); + dp_bridge->dev = dp_dev; + + return devm_drm_dp_typec_bridge_add(dev, dp_dev); +} + static int cros_typec_usb_safe_state(struct cros_typec_port *port) { int ret; @@ -612,6 +657,7 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num, struct ec_response_usb_pd_control_v2 *pd_ctrl) { struct cros_typec_port *port = typec->ports[port_num]; + struct cros_typec_dp_bridge *dp_bridge = typec->dp_bridge; struct ec_response_usb_pd_mux_info resp; struct ec_params_usb_pd_mux_info req = { .port = port_num, @@ -619,6 +665,7 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num, struct ec_params_usb_pd_mux_ack mux_ack; enum typec_orientation orientation; int ret; + bool dp_enabled; ret = cros_ec_cmd(typec->ec, 0, EC_CMD_USB_PD_MUX_INFO, &req, sizeof(req), &resp, sizeof(resp)); @@ -628,6 +675,8 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num, return ret; } + dp_enabled = resp.flags & USB_PD_MUX_DP_ENABLED; + /* No change needs to be made, let's exit early. */ if (port->mux_flags == resp.flags && port->role == pd_ctrl->role) return 0; @@ -659,8 +708,14 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num, ret = cros_typec_enable_usb4(typec, port_num, pd_ctrl); } else if (port->mux_flags & USB_PD_MUX_TBT_COMPAT_ENABLED) { ret = cros_typec_enable_tbt(typec, port_num, pd_ctrl); - } else if (port->mux_flags & USB_PD_MUX_DP_ENABLED) { + } else if (dp_enabled) { ret = cros_typec_enable_dp(typec, port_num, pd_ctrl); + if (dp_bridge) { + drm_dp_typec_bridge_notify(dp_bridge->dev, + port->mux_flags & USB_PD_MUX_HPD_LVL ? + connector_status_connected : + connector_status_disconnected); + } } else if (port->mux_flags & USB_PD_MUX_SAFE_MODE) { ret = cros_typec_usb_safe_state(port); } else if (port->mux_flags & USB_PD_MUX_USB_ENABLED) { @@ -677,6 +732,9 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num, } mux_ack: + if (dp_bridge && !dp_enabled) + drm_dp_typec_bridge_notify(dp_bridge->dev, connector_status_disconnected); + if (!typec->needs_mux_ack) return ret; @@ -1261,6 +1319,10 @@ static int cros_typec_probe(struct platform_device *pdev) if (ret < 0) return ret; + ret = cros_typec_init_dp_bridge(typec); + if (ret < 0) + return ret; + INIT_WORK(&typec->port_work, cros_typec_port_work); /* diff --git a/drivers/platform/chrome/cros_ec_typec.h b/drivers/platform/chrome/cros_ec_typec.h index deda180a646f..37c9a3ae3402 100644 --- a/drivers/platform/chrome/cros_ec_typec.h +++ b/drivers/platform/chrome/cros_ec_typec.h @@ -27,6 +27,8 @@ struct cros_typec_altmode_node { struct list_head list; }; +struct cros_typec_dp_bridge; + /* Platform-specific data for the Chrome OS EC Type C controller. */ struct cros_typec_data { struct device *dev; @@ -35,12 +37,12 @@ struct cros_typec_data { unsigned int pd_ctrl_ver; /* Array of ports, indexed by port number. */ struct cros_typec_port *ports[EC_USB_PD_MAX_PORTS]; + struct cros_typec_dp_bridge *dp_bridge; struct notifier_block nb; struct work_struct port_work; bool typec_cmd_supported; bool needs_mux_ack; }; - /* Per port data. */ struct cros_typec_port { struct typec_port *port; From patchwork Thu Aug 15 00:34:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 13764322 Received: from mail-oa1-f53.google.com (mail-oa1-f53.google.com [209.85.160.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D68593FB1B for ; Thu, 15 Aug 2024 00:34:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723682082; cv=none; b=YGCXecLpEr8Qr2UIl7i8nXXlgwvNvMmk656vfJ6aQvjUAxiZgY0ueQtwrAab9Pa/0kAcChlff/WtXJFZN63+K5VaErV+LS7ncUuCnF56l5vTBYIKh/sMVfuTBhJ9ifM867xz9GogUGngbKOGMu7DWFX1pB5oI1+5YWXMLvBrRoQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723682082; c=relaxed/simple; bh=Iyhcfdfc7GV4MbeX+RfzehRh0ODkIdvP4CjwxtvYzHA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=gSsMIakSFnowdz3p/1HliS6DxSGC7DktAq1LAxF8o7Y+9ZX+Oyww8X4Gbv+4TdzKrNW1BY77XcX8JfsvdzAKE1Z0kMjWlR8VJGAbFusJp7sBdmfFZBkNIGoFpdckcjLBAUjbw42F03CssjoJDB1kNjSq+sIRkow+Jb3hZ2X+3t0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=OpR+w3Iu; arc=none smtp.client-ip=209.85.160.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="OpR+w3Iu" Received: by mail-oa1-f53.google.com with SMTP id 586e51a60fabf-26ff21d82e4so289274fac.2 for ; Wed, 14 Aug 2024 17:34:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1723682079; x=1724286879; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=jDcmIdwmZg5Yjp+jQTQGuUvR4WKIJmLUFkwNG0Q1X0U=; b=OpR+w3IuC7X6wOo/M5/OA3TAK4KLSZ7LrCMscacxWgXUgOMTkkZah4pYsK/SP8+C9f 4wrGZ9HEIdriEeS8PlUk3hr3prXfEdpp95Jb98hDalyPIsHh8d7SW62jTnosiSNEx9GV 7s+rebCZE4hFfhhkp7UAfK/VZuh6B+K6oV1vs= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723682079; x=1724286879; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=jDcmIdwmZg5Yjp+jQTQGuUvR4WKIJmLUFkwNG0Q1X0U=; b=XyPCahAessz+twQy76AXtmM3KnuCV1ENKdE2j+eob2xQ+izSyYTgX7tO4fosWYMLRg WuEMGtFirpjwL2X8Dh+pskQZahsQQ/zzJ0nNmOXT6nReEfRwMaf8oW2ul4GsNiRJk2YF FZpsMaBpDxHxAg6ykFhOH4ZvCBJbVs27F4NTPwNGFL5zPKf+Dj/2aqxopAzwSMlyoeFU WhEsNShiAwvV3FQ5S3WWM88fiz3ddxDRaX1iH5af/Y9S76wod1ySaSlPoXUBwIg8iyTy jOpcgSczW/lZvs8F5DCEWet8N2JzMWZKu3UiALlSs7x5mnvqpPQ/ah5cHd7j5sY9OFPZ APVQ== X-Gm-Message-State: AOJu0Yze+gkhKdoSkjLTEClRZIos9EPeo+qYZ21JS2XGKvXDUMhwPwBW WQVxR1QrX+xlhDiZT8uKXkmfiihby86XVogHM9WOubZ4Eh8+dFlQwOvI6Qk+PAh8oZTPUKoSNNo = X-Google-Smtp-Source: AGHT+IEa5nlUzRlmODvLmYrrPm9ojtXH+NSdKM66EPsw+jd1PQ0hfX1+/ZLc0IjHpFllU8vz6fMt4Q== X-Received: by 2002:a05:6870:569e:b0:260:f058:48eb with SMTP id 586e51a60fabf-26fe5abd08bmr5594470fac.20.1723682079581; Wed, 14 Aug 2024 17:34:39 -0700 (PDT) Received: from localhost (210.73.125.34.bc.googleusercontent.com. [34.125.73.210]) by smtp.gmail.com with UTF8SMTPSA id d2e1a72fcca58-7127aef6ed0sm154177b3a.137.2024.08.14.17.34.38 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 14 Aug 2024 17:34:39 -0700 (PDT) From: Stephen Boyd To: chrome-platform@lists.linux.dev Cc: linux-kernel@vger.kernel.org, patches@lists.linux.dev, devicetree@vger.kernel.org, Douglas Anderson , Pin-yen Lin , Andrzej Hajda , Benson Leung , Conor Dooley , Daniel Vetter , David Airlie , Dmitry Baryshkov , dri-devel@lists.freedesktop.org, Guenter Roeck , Jernej Skrabec , Jonas Karlman , Krzysztof Kozlowski , Laurent Pinchart , Lee Jones , Maarten Lankhorst , Maxime Ripard , Neil Armstrong , Prashant Malani , Robert Foss , Rob Herring , Thomas Zimmermann , Tzung-Bi Shih Subject: [PATCH v2 09/11] platform/chrome: cros_ec_typec: Support DP muxing via DRM lane assignment Date: Wed, 14 Aug 2024 17:34:14 -0700 Message-ID: <20240815003417.1175506-10-swboyd@chromium.org> X-Mailer: git-send-email 2.46.0.76.ge559c4bf1a-goog In-Reply-To: <20240815003417.1175506-1-swboyd@chromium.org> References: <20240815003417.1175506-1-swboyd@chromium.org> Precedence: bulk X-Mailing-List: chrome-platform@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Most ARM based chromebooks with two usb-c-connector nodes and one DP controller are muxing the DP lanes between the two USB ports. This is done so that the type-c ports are at least equal in capability if not functionality. Either an analog mux is used to steer the DP signal to one or the other port, or a DP bridge chip has two lanes (DP ML0/ML1) wired to one type-c port while the other two (DP ML2/ML3) are wired to another type-c port. Use drm_dp_typec_bridge_assign_pins() to implement support for DP altmode configurations like pinconf D and DP muxing to different type-c ports. In the DP altmode spec, pinconf C assigns all 4 SuperSpeed lanes in the usb-c-connector node to DP, while pinconf D assigns 2 SuperSpeed lanes to DP and 2 SuperSpeed lanes to USB. Use the 'data-lanes' property from the input DP graph endpoint to calculate the maximum number of lanes coming from the DP source (either 2 or 4) and limit the lanes requested to the smaller of this or the pin configuration. Use the 'data-lanes' property from the active type-c output port to determine which logical DP lanes should be assigned to the output of the drm_bridge by passing the lane mapping to drm_dp_typec_bridge_assign_pins(). For now assume the type-c pins are in the normal orientation. The EC can mux the DP signal to any number of USB type-c ports. We only need to make sure that the drm_bridge is mapping the DP lanes to the appropriate type-c pins for the pin configuration. This means that having the same type-c port data-lanes property is valid and expected in cases where an analog mux is used to steer the DP signal to one of many TCPCs and eventually usb-c-connector nodes. Cc: Prashant Malani Cc: Benson Leung Cc: Tzung-Bi Shih Cc: Cc: Pin-yen Lin Signed-off-by: Stephen Boyd --- drivers/platform/chrome/cros_ec_typec.c | 49 +++++++++++++++++++++++-- drivers/platform/chrome/cros_ec_typec.h | 3 ++ 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index 5cbc6b3df906..fa7f7efb9d3f 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -27,6 +27,7 @@ struct cros_typec_dp_bridge { struct cros_typec_data *typec_data; struct drm_dp_typec_bridge_dev *dev; + struct cros_typec_port *active_port; }; #define DP_PORT_VDO (DP_CONF_SET_PIN_ASSIGN(BIT(DP_PIN_ASSIGN_C) | BIT(DP_PIN_ASSIGN_D)) | \ @@ -330,6 +331,20 @@ static int cros_typec_register_port_altmodes(struct cros_typec_data *typec, return 0; } +static void cros_typec_init_dp_usbc_lanes(struct cros_typec_port *typec_port) +{ + struct cros_typec_data *typec = typec_port->typec_data; + unsigned int port_num = typec_port->port_num; + struct device *dev = typec->dev; + struct fwnode_handle *ep __free(fwnode_handle); + const u32 default_lane_mapping[] = { 0, 1, 2, 3 }; + + ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), 2, port_num, 0); + if (fwnode_property_read_u32_array(ep, "data-lanes", typec_port->lane_mapping, + ARRAY_SIZE(typec_port->lane_mapping))) + memcpy(typec_port->lane_mapping, default_lane_mapping, sizeof(default_lane_mapping)); +} + static int cros_typec_init_ports(struct cros_typec_data *typec) { struct device *dev = typec->dev; @@ -387,6 +402,7 @@ static int cros_typec_init_ports(struct cros_typec_data *typec) typec->ports[port_num] = cros_port; cap = &cros_port->caps; + cros_typec_init_dp_usbc_lanes(cros_port); ret = cros_typec_parse_port_props(cap, fwnode, dev); if (ret < 0) goto unregister_ports; @@ -434,6 +450,7 @@ static int cros_typec_init_dp_bridge(struct cros_typec_data *typec) struct cros_typec_dp_bridge *dp_bridge; struct fwnode_handle *ep __free(fwnode_handle); struct drm_dp_typec_bridge_dev *dp_dev; + int num_lanes; struct drm_dp_typec_bridge_desc desc = { .of_node = dev->of_node, }; @@ -450,6 +467,11 @@ static int cros_typec_init_dp_bridge(struct cros_typec_data *typec) typec->dp_bridge = dp_bridge; dp_bridge->typec_data = typec; + num_lanes = fwnode_property_count_u32(ep, "data-lanes"); + if (num_lanes < 0) + num_lanes = 4; + desc.num_dp_lanes = num_lanes; + dp_dev = devm_drm_dp_typec_bridge_alloc(dev, &desc); if (IS_ERR(dp_dev)) return PTR_ERR(dp_dev); @@ -555,10 +577,12 @@ static int cros_typec_enable_dp(struct cros_typec_data *typec, struct ec_response_usb_pd_control_v2 *pd_ctrl) { struct cros_typec_port *port = typec->ports[port_num]; + struct cros_typec_dp_bridge *dp_bridge = typec->dp_bridge; struct typec_displayport_data dp_data; u32 cable_tbt_vdo; u32 cable_dp_vdo; int ret; + bool hpd_asserted = port->mux_flags & USB_PD_MUX_HPD_LVL; if (typec->pd_ctrl_ver < 2) { dev_err(typec->dev, @@ -566,6 +590,16 @@ static int cros_typec_enable_dp(struct cros_typec_data *typec, return -ENOTSUPP; } + /* + * Assume the first port to have HPD asserted is the one muxed to DP + * (i.e. active_port). When there's only one port this delays setting + * the active_port until HPD is asserted, but before that the + * drm_connector looks disconnected so active_port doesn't need to be + * set. + */ + if (dp_bridge && hpd_asserted && !dp_bridge->active_port) + dp_bridge->active_port = port; + if (!pd_ctrl->dp_mode) { dev_err(typec->dev, "No valid DP mode provided.\n"); return -EINVAL; @@ -575,7 +609,7 @@ static int cros_typec_enable_dp(struct cros_typec_data *typec, dp_data.status = DP_STATUS_ENABLED; if (port->mux_flags & USB_PD_MUX_HPD_IRQ) dp_data.status |= DP_STATUS_IRQ_HPD; - if (port->mux_flags & USB_PD_MUX_HPD_LVL) + if (hpd_asserted) dp_data.status |= DP_STATUS_HPD_STATE; /* Configuration VDO. */ @@ -587,6 +621,13 @@ static int cros_typec_enable_dp(struct cros_typec_data *typec, return ret; } + if (dp_bridge && dp_bridge->active_port == port) { + ret = drm_dp_typec_bridge_assign_pins(dp_bridge->dev, dp_data.conf, 0, + port->lane_mapping); + if (ret) + return ret; + } + port->state.data = &dp_data; port->state.mode = TYPEC_MODAL_STATE(ffs(pd_ctrl->dp_mode)); @@ -710,7 +751,7 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num, ret = cros_typec_enable_tbt(typec, port_num, pd_ctrl); } else if (dp_enabled) { ret = cros_typec_enable_dp(typec, port_num, pd_ctrl); - if (dp_bridge) { + if (dp_bridge && dp_bridge->active_port == port) { drm_dp_typec_bridge_notify(dp_bridge->dev, port->mux_flags & USB_PD_MUX_HPD_LVL ? connector_status_connected : @@ -732,8 +773,10 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num, } mux_ack: - if (dp_bridge && !dp_enabled) + if (dp_bridge && !dp_enabled && dp_bridge->active_port == port) { drm_dp_typec_bridge_notify(dp_bridge->dev, connector_status_disconnected); + dp_bridge->active_port = NULL; + } if (!typec->needs_mux_ack) return ret; diff --git a/drivers/platform/chrome/cros_ec_typec.h b/drivers/platform/chrome/cros_ec_typec.h index 37c9a3ae3402..74d062dc03b2 100644 --- a/drivers/platform/chrome/cros_ec_typec.h +++ b/drivers/platform/chrome/cros_ec_typec.h @@ -14,6 +14,8 @@ #include #include +#include + /* Supported alt modes. */ enum { CROS_EC_ALTMODE_DP = 0, @@ -67,6 +69,7 @@ struct cros_typec_port { uint8_t mux_flags; uint8_t role; + u32 lane_mapping[NUM_USB_SS]; struct typec_altmode *port_altmode[CROS_EC_ALTMODE_MAX]; /* Flag indicating that PD partner discovery data parsing is completed. */ From patchwork Thu Aug 15 00:34:15 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 13764323 Received: from mail-pf1-f174.google.com (mail-pf1-f174.google.com [209.85.210.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5EA013D0AD for ; Thu, 15 Aug 2024 00:34:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723682083; cv=none; b=bR8+eseegFqFqsy2CzikaF24ioq7Q3fIiZtuwYrJXdY+nbfw89x6lty8y9HuVkAer5ETHR81Qbp3q/O78RcCzpdIrtU81vzTgn7yT2jjYEO8f9t0BbdnmvW2vIZ0Z998yog4tVrVr6KzbCZLVBqo3QhtrZdF9ebi7GAd+MpJnPw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723682083; c=relaxed/simple; bh=zD9TsQUncAARnPnLMV9wmixLL+XTxWufmMdyanmITp8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=uAN4vLN2uvxfqrgWQtPqfpHd1RCgvtX4cMUyiBhE0S/FNllf/TIpqbEy5C1qpf+7WhiYWj4m+ir372+IIDa0EKib3/OVKaftCqz+851X34tHZYrBn+BNtzsDdef/bfshkbTS0SJIywRiw1hVdwja0ZNzCrruVM1thV8coFaLCIw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=XBOfqcyR; arc=none smtp.client-ip=209.85.210.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="XBOfqcyR" Received: by mail-pf1-f174.google.com with SMTP id d2e1a72fcca58-712603f7ba5so311234b3a.3 for ; Wed, 14 Aug 2024 17:34:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1723682081; x=1724286881; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=cBspZU3HeL7PY6QZuDg6iQx5V3y6UFV5ZGsLfhqF10c=; b=XBOfqcyRHet56786Lwdc86MRpOP3l/jiiW2DXbjyAAu9+cH/Xf8nT3L/PEPSF3dfqN bqnqHHpHdnd7yrEE1NPCt4/HGXHJaw9GhX1RaBXw963/BmpPSkqiGhsH8xFNcM3TkrhX zDsWIdXcRWlxCcgwF+nUxtW3H1A1zSLwcFZ1k= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723682081; x=1724286881; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=cBspZU3HeL7PY6QZuDg6iQx5V3y6UFV5ZGsLfhqF10c=; b=ORCu/OvSEN1ZiWH+7RJR7vW5vs3JKZpSiNCb9PqiCzkuM88nJr3/dhvnZMDagVI+BL v4usYgT+ZTb+su7A8eFk7AJOq7+95dDnx9wyaZGlxqmx78hyuIJ7x8mHEyWOmuGzkTNn h6moDBbJMAyjK9UAln8wQF6Ihp/ebEo4eIwcCNHLHNOuo+tXJpohanDrGhjzIZjAWbaW 4fHb4DP7tVeLZXcDAlRpcqfOh8miVYTPVl4V42k47ZaQA/3wHSgVejfgbOwroSTVj8Jz GZJK4kumA82Cc3mYClhr2W69YAgZzbOH51fmH8HxKNt9bXbNA3vMfpciyqvweogfvmn4 rn2A== X-Gm-Message-State: AOJu0YxiHoCcsikr95/DzkK3KTcRdBZ34iQtItY7QgE4rjf6iIrmmu8E XTMMa0q/t8UP4643n3D0MvWt1yt/9tdSu9WnNJRiKWPb0ZZ1YMbOmri/jk5Ap67LRKEklx3a/YA = X-Google-Smtp-Source: AGHT+IF3toalk+6TfBGNRbLO8JKuCUY5aMyE+LAw0Xw9EDSvJ2wZkjR8HAHNKQxh/Te6Kdy5uE3aKw== X-Received: by 2002:a05:6a00:3c84:b0:70d:1b17:3c5e with SMTP id d2e1a72fcca58-712670e8640mr6076731b3a.6.1723682081340; Wed, 14 Aug 2024 17:34:41 -0700 (PDT) Received: from localhost (210.73.125.34.bc.googleusercontent.com. [34.125.73.210]) by smtp.gmail.com with UTF8SMTPSA id d2e1a72fcca58-7127ae11b3csm157292b3a.71.2024.08.14.17.34.40 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 14 Aug 2024 17:34:40 -0700 (PDT) From: Stephen Boyd To: chrome-platform@lists.linux.dev Cc: linux-kernel@vger.kernel.org, patches@lists.linux.dev, devicetree@vger.kernel.org, Douglas Anderson , Pin-yen Lin , Andrzej Hajda , Benson Leung , Conor Dooley , Daniel Vetter , David Airlie , Dmitry Baryshkov , dri-devel@lists.freedesktop.org, Guenter Roeck , Jernej Skrabec , Jonas Karlman , Krzysztof Kozlowski , Laurent Pinchart , Lee Jones , Maarten Lankhorst , Maxime Ripard , Neil Armstrong , Prashant Malani , Robert Foss , Rob Herring , Thomas Zimmermann , Tzung-Bi Shih Subject: [PATCH v2 10/11] platform/chrome: cros_ec_typec: Support DP orientation Date: Wed, 14 Aug 2024 17:34:15 -0700 Message-ID: <20240815003417.1175506-11-swboyd@chromium.org> X-Mailer: git-send-email 2.46.0.76.ge559c4bf1a-goog In-Reply-To: <20240815003417.1175506-1-swboyd@chromium.org> References: <20240815003417.1175506-1-swboyd@chromium.org> Precedence: bulk X-Mailing-List: chrome-platform@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Handle orientation for the type-c port when the DT node has the 'orientation' property. The 'orientation' property is present when the DisplayPort lanes are directly wired to the usb-c-connector and the board design relies on the DP lanes to be remapped by software. The property wouldn't be present if, for example, the EC controls a port mapper part that flips the DP lanes for the port orientation. Pass the port orientation to drm_dp_typec_bridge_assign_pins() when the DT property is present so that the previous drm_bridge in the bridge chain can remap the DP lanes to the right usb-c-connector SuperSpeed pins for the orientation. Cc: Prashant Malani Cc: Benson Leung Cc: Tzung-Bi Shih Cc: Cc: Pin-yen Lin Signed-off-by: Stephen Boyd --- drivers/platform/chrome/cros_ec_typec.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index fa7f7efb9d3f..9b54b3288f5f 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -28,6 +28,7 @@ struct cros_typec_dp_bridge { struct cros_typec_data *typec_data; struct drm_dp_typec_bridge_dev *dev; struct cros_typec_port *active_port; + bool orientation; }; #define DP_PORT_VDO (DP_CONF_SET_PIN_ASSIGN(BIT(DP_PIN_ASSIGN_C) | BIT(DP_PIN_ASSIGN_D)) | \ @@ -449,13 +450,15 @@ static int cros_typec_init_dp_bridge(struct cros_typec_data *typec) struct device *dev = typec->dev; struct cros_typec_dp_bridge *dp_bridge; struct fwnode_handle *ep __free(fwnode_handle); + struct fwnode_handle *devnode; struct drm_dp_typec_bridge_dev *dp_dev; int num_lanes; struct drm_dp_typec_bridge_desc desc = { .of_node = dev->of_node, }; - ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), 0, 0, 0); + devnode = dev_fwnode(dev); + ep = fwnode_graph_get_endpoint_by_id(devnode, 0, 0, 0); if (!ep) { /* There isn't a DP input endpoint. Ignore. */ return 0; @@ -467,6 +470,8 @@ static int cros_typec_init_dp_bridge(struct cros_typec_data *typec) typec->dp_bridge = dp_bridge; dp_bridge->typec_data = typec; + dp_bridge->orientation = fwnode_property_read_bool(devnode, "orientation"); + num_lanes = fwnode_property_count_u32(ep, "data-lanes"); if (num_lanes < 0) num_lanes = 4; @@ -582,6 +587,7 @@ static int cros_typec_enable_dp(struct cros_typec_data *typec, u32 cable_tbt_vdo; u32 cable_dp_vdo; int ret; + enum typec_orientation orientation; bool hpd_asserted = port->mux_flags & USB_PD_MUX_HPD_LVL; if (typec->pd_ctrl_ver < 2) { @@ -622,7 +628,13 @@ static int cros_typec_enable_dp(struct cros_typec_data *typec, } if (dp_bridge && dp_bridge->active_port == port) { - ret = drm_dp_typec_bridge_assign_pins(dp_bridge->dev, dp_data.conf, 0, + orientation = TYPEC_ORIENTATION_NORMAL; + if (dp_bridge->orientation && + port->mux_flags & USB_PD_MUX_POLARITY_INVERTED) + orientation = TYPEC_ORIENTATION_REVERSE; + + ret = drm_dp_typec_bridge_assign_pins(dp_bridge->dev, dp_data.conf, + orientation, port->lane_mapping); if (ret) return ret; From patchwork Thu Aug 15 00:34:16 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 13764324 Received: from mail-pl1-f174.google.com (mail-pl1-f174.google.com [209.85.214.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1F48A3D0AD for ; Thu, 15 Aug 2024 00:34:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723682085; cv=none; b=kh5huHSjwrpFAqGzU1hX6Q+7pyhK/PwE2c1NxwpiubfQe2dn+0oN5XrZhlK9+rbK+rm9s9ciXNLyiKsAOOIEqmgbB+Dupbqpm5XyFFG/26+S8slk7s0r2SHYwXCIxrp242Ja7D9ZbGJmiqVEtmWVBvx53FBJMmmXTpUq1syXmE8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1723682085; c=relaxed/simple; bh=cnou3RaHYgs9uNVMimdkYBuUV/fum7WzcYAeoVvS/us=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Ag1jhtMK9amFCdUGdzKo8QhVEkjo0ifwDVLlGE0NbFrbfDBsH8p1X6IIG6fDu2am2WbFqm/rabpdKIanb/x5ti8NNRjmOUOxVlSVFRFi7vDF52LtV/6tvCIh1NWuXDA9rWvgaLzAVPYUUux8SwHFY8MyE4ZgiuInRimF2qdcb+U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=UMmGMJ6f; arc=none smtp.client-ip=209.85.214.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="UMmGMJ6f" Received: by mail-pl1-f174.google.com with SMTP id d9443c01a7336-201ee6b084bso4004535ad.2 for ; Wed, 14 Aug 2024 17:34:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1723682083; x=1724286883; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Llrpv/bhvM+ILeynT8xxMAhRB4gmjRWr+CKfaVkSb14=; b=UMmGMJ6fTEqaoVlDemggIt8jDuIwHmv6mVIF1RIpvRCgN7oMiSciy5tiUBIHeCCxXp Cd4D6WfPV8JGrIQv2gzIXolPmTACW8ozfqJGl3PrFnm6KMVo2aBds5B9EJ59sWTfpCUW ymeEjEImfaD/60/MDPPh820y3C7co72tZJdEI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723682083; x=1724286883; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Llrpv/bhvM+ILeynT8xxMAhRB4gmjRWr+CKfaVkSb14=; b=Vm8bAUe5C65kiKzWCoWsot94lseWFFW9wBShnwTYtM3yyNzrZoTgAMJ7629dHRyD2X H6FLgNUX1FZh5VvpAbs2LteDg7EGbr1ncm6MuqnkGPqtnroLYF94mkgMQeLyLjq4D2qw 8TEUxyn+kahJH8P8obESbl1/nm0JuiCr2aAlW+dXYXIfhZnhOrrB9SqSoO2DFs4gXiFB 9VSXFE9t3+0V0PpW4wCbWrPq7bDxi2TWyBoJL3GrxNV4EpuxA3A2JVDx4hzPC++tlFho BQZsx+rSjYM2QUQlbiqT5sCStOowOxjU26WVWkQ2BBJyvD+eGKL7sUHK7whz3Y3T7VIq vkrQ== X-Gm-Message-State: AOJu0Yw4jO/lKF+atP1NYmdJPjxv2oR5KSK1D32XLZt4J41PBrjyT8Ad zvSgx9VUuDou128hRJPKjgw06SNCVCt9A8fTaFw4ngT2Xdm0wfKRCAawQHDRNlU/vXy0Z7pYbow = X-Google-Smtp-Source: AGHT+IEVlM5ZgWwPjr8Cf8G8BgFV3d3kS53MUapqW/O1uSuFqkLJw8H1IVUD3jIv722S8xs6osc3hw== X-Received: by 2002:a17:903:18a:b0:1fa:2b89:f549 with SMTP id d9443c01a7336-201d638d77dmr64360645ad.10.1723682083238; Wed, 14 Aug 2024 17:34:43 -0700 (PDT) Received: from localhost (210.73.125.34.bc.googleusercontent.com. [34.125.73.210]) by smtp.gmail.com with UTF8SMTPSA id d9443c01a7336-201f03751e0sm1992385ad.177.2024.08.14.17.34.41 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 14 Aug 2024 17:34:42 -0700 (PDT) From: Stephen Boyd To: chrome-platform@lists.linux.dev Cc: linux-kernel@vger.kernel.org, patches@lists.linux.dev, devicetree@vger.kernel.org, Douglas Anderson , Pin-yen Lin , Andrzej Hajda , Benson Leung , Conor Dooley , Daniel Vetter , David Airlie , Dmitry Baryshkov , dri-devel@lists.freedesktop.org, Guenter Roeck , Jernej Skrabec , Jonas Karlman , Krzysztof Kozlowski , Laurent Pinchart , Lee Jones , Maarten Lankhorst , Maxime Ripard , Neil Armstrong , Prashant Malani , Robert Foss , Rob Herring , Thomas Zimmermann , Tzung-Bi Shih Subject: [PATCH v2 11/11] platform/chrome: cros_ec_typec: Handle lack of HPD information Date: Wed, 14 Aug 2024 17:34:16 -0700 Message-ID: <20240815003417.1175506-12-swboyd@chromium.org> X-Mailer: git-send-email 2.46.0.76.ge559c4bf1a-goog In-Reply-To: <20240815003417.1175506-1-swboyd@chromium.org> References: <20240815003417.1175506-1-swboyd@chromium.org> Precedence: bulk X-Mailing-List: chrome-platform@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Some EC firmwares on Trogdor/Strongbad boards don't properly indicate the state of DP HPD on a type-c port. Instead, the EC only indicates that a type-c port has entered or exited DP mode. To make matters worse, on these boards the DP signal is muxed between two USB type-c connectors, so we can't use the DP entry of a port to figure out which type-c port is actually displaying DP. Read the state of the EC's analog mux from the hpd notification callback to figure out which type-c port is displaying DP. This circumvents the entire host command/message interface, because it doesn't work all the time. Stash the hpd state into the port that's muxed, and then inject that hpd state into the struct we get from the EC. Only do this when we have the mux-gpios property in DT, indicating that we have to read the EC gpio state to figure this out. For now we only support a single gpio "bit", so there can only be two USB type-c ports. Cc: Prashant Malani Cc: Benson Leung Cc: Tzung-Bi Shih Cc: Cc: Pin-yen Lin Signed-off-by: Stephen Boyd --- drivers/platform/chrome/cros_ec_typec.c | 107 +++++++++++++++++++++--- drivers/platform/chrome/cros_ec_typec.h | 1 + 2 files changed, 98 insertions(+), 10 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index 9b54b3288f5f..e6e33b7bb543 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -28,6 +29,7 @@ struct cros_typec_dp_bridge { struct cros_typec_data *typec_data; struct drm_dp_typec_bridge_dev *dev; struct cros_typec_port *active_port; + struct gpio_desc *mux_gpio; bool orientation; }; @@ -445,6 +447,43 @@ static int cros_typec_init_ports(struct cros_typec_data *typec) return ret; } +static void cros_typec_dp_bridge_hpd_notify(struct drm_dp_typec_bridge_dev *typec_bridge_dev, + void *data, enum drm_connector_status status) +{ + struct cros_typec_dp_bridge *dp_bridge = data; + struct cros_typec_port *typec_port; + struct cros_typec_data *typec; + struct gpio_desc *mux_gpio; + struct device *dev; + int val; + + typec = dp_bridge->typec_data; + typec_port = typec->ports[0]; + dev = typec->dev; + + /* + * Some ECs don't notify AP when HPD goes high or low so we have to + * read the EC GPIO that controls the mux to figure out which type-c + * port is connected to DP by the EC. + */ + mux_gpio = dp_bridge->mux_gpio; + if (mux_gpio) { + val = gpiod_get_value_cansleep(mux_gpio); + if (val < 0) { + dev_err(dev, "Failed to read mux gpio for hpd notify\n"); + return; + } + + typec_port = typec->ports[val]; + } + + /* Proxy the connector status as the HPD state to replay later. */ + typec_port->hpd_asserted = status == connector_status_connected; + + /* Refresh port state. */ + schedule_work(&typec->port_work); +} + static int cros_typec_init_dp_bridge(struct cros_typec_data *typec) { struct device *dev = typec->dev; @@ -471,12 +510,21 @@ static int cros_typec_init_dp_bridge(struct cros_typec_data *typec) dp_bridge->typec_data = typec; dp_bridge->orientation = fwnode_property_read_bool(devnode, "orientation"); + dp_bridge->mux_gpio = devm_gpiod_get_optional(dev, "mux", GPIOD_ASIS); + if (IS_ERR(dp_bridge->mux_gpio)) + return dev_err_probe(dev, PTR_ERR(dp_bridge->mux_gpio), "failed to get mux gpio\n"); num_lanes = fwnode_property_count_u32(ep, "data-lanes"); if (num_lanes < 0) num_lanes = 4; desc.num_dp_lanes = num_lanes; + desc.no_hpd = fwnode_property_read_bool(devnode, "no-hpd"); + if (desc.no_hpd) { + desc.hpd_notify = cros_typec_dp_bridge_hpd_notify; + desc.hpd_data = dp_bridge; + } + dp_dev = devm_drm_dp_typec_bridge_alloc(dev, &desc); if (IS_ERR(dp_dev)) return PTR_ERR(dp_dev); @@ -582,6 +630,7 @@ static int cros_typec_enable_dp(struct cros_typec_data *typec, struct ec_response_usb_pd_control_v2 *pd_ctrl) { struct cros_typec_port *port = typec->ports[port_num]; + struct cros_typec_port *muxed_port; struct cros_typec_dp_bridge *dp_bridge = typec->dp_bridge; struct typec_displayport_data dp_data; u32 cable_tbt_vdo; @@ -589,6 +638,9 @@ static int cros_typec_enable_dp(struct cros_typec_data *typec, int ret; enum typec_orientation orientation; bool hpd_asserted = port->mux_flags & USB_PD_MUX_HPD_LVL; + bool is_active_port = false; + struct gpio_desc *mux_gpio; + int val; if (typec->pd_ctrl_ver < 2) { dev_err(typec->dev, @@ -596,15 +648,47 @@ static int cros_typec_enable_dp(struct cros_typec_data *typec, return -ENOTSUPP; } - /* - * Assume the first port to have HPD asserted is the one muxed to DP - * (i.e. active_port). When there's only one port this delays setting - * the active_port until HPD is asserted, but before that the - * drm_connector looks disconnected so active_port doesn't need to be - * set. - */ - if (dp_bridge && hpd_asserted && !dp_bridge->active_port) - dp_bridge->active_port = port; + if (dp_bridge) { + /* + * Some ECs don't notify AP when HPD goes high or low so we have to + * read the EC GPIO that controls the mux to figure out which type-c + * port is connected to DP by the EC. + */ + mux_gpio = dp_bridge->mux_gpio; + if (mux_gpio) { + /* + * Only read the mux GPIO setting if hpd is asserted + * and we need to change the active_port. Otherwise, an + * active_port is already set and HPD going high or low + * doesn't change the muxed port until DP mode is + * exited. + */ + if (hpd_asserted && !dp_bridge->active_port) { + val = gpiod_get_value_cansleep(mux_gpio); + if (val < 0) { + dev_err(typec->dev, "Failed to read mux gpio\n"); + return val; + } + + muxed_port = typec->ports[val]; + } + } else { + muxed_port = port; + } + + /* + * Assume the first port to have HPD asserted is the one muxed + * to DP (i.e. active_port). When there's only one port this + * delays setting the active_port until HPD is asserted, but + * before that the drm_connector looks disconnected so + * active_port doesn't need to be set. + */ + if (hpd_asserted && !dp_bridge->active_port && muxed_port == port) + dp_bridge->active_port = port; + + if (dp_bridge->active_port == port) + is_active_port = true; + } if (!pd_ctrl->dp_mode) { dev_err(typec->dev, "No valid DP mode provided.\n"); @@ -627,7 +711,7 @@ static int cros_typec_enable_dp(struct cros_typec_data *typec, return ret; } - if (dp_bridge && dp_bridge->active_port == port) { + if (is_active_port) { orientation = TYPEC_ORIENTATION_NORMAL; if (dp_bridge->orientation && port->mux_flags & USB_PD_MUX_POLARITY_INVERTED) @@ -729,6 +813,9 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num, } dp_enabled = resp.flags & USB_PD_MUX_DP_ENABLED; + /* Replay HPD from the GPIO state if EC firmware is broken */ + if (dp_enabled && port->hpd_asserted) + resp.flags |= USB_PD_MUX_HPD_LVL; /* No change needs to be made, let's exit early. */ if (port->mux_flags == resp.flags && port->role == pd_ctrl->role) diff --git a/drivers/platform/chrome/cros_ec_typec.h b/drivers/platform/chrome/cros_ec_typec.h index 74d062dc03b2..26565cd77d79 100644 --- a/drivers/platform/chrome/cros_ec_typec.h +++ b/drivers/platform/chrome/cros_ec_typec.h @@ -69,6 +69,7 @@ struct cros_typec_port { uint8_t mux_flags; uint8_t role; + bool hpd_asserted; u32 lane_mapping[NUM_USB_SS]; struct typec_altmode *port_altmode[CROS_EC_ALTMODE_MAX];