2023-03-03 14:34:11

by Pin-yen Lin

[permalink] [raw]
Subject: [PATCH v13 00/10] Register Type-C mode-switch in DP bridge endpoints


This series introduces bindings for anx7625/it6505 to register Type-C
mode-switch in their output endpoints, and use data-lanes property to
describe the pin connections.

This series is not directly related to the built-in mux in anx7625,
which automatically switches between the two orientations of a single
Type-C connector. This series adds support of registering mode switches
for two downstream devices, while we use orientation switches for two
orientations of the Type-C connector.

The first two patch modifies fwnode_graph_devcon_matches and
cros_typec_init_ports to enable the registration of the switches.

Patch 4~6 introduce the bindings for anx7625 and the corresponding driver
modifications.

Patch 7~9 add similar bindings and driver changes for it6505.

v12: https://lore.kernel.org/all/[email protected]/
v11: https://lore.kernel.org/all/[email protected]/
v10: https://lore.kernel.org/all/[email protected]/
v9: https://lore.kernel.org/all/[email protected]/
v8: https://lore.kernel.org/all/[email protected]/
v7: https://lore.kernel.org/all/[email protected]/
v6: https://lore.kernel.org/all/[email protected]/
v5: https://lore.kernel.org/linux-usb/[email protected]/

Changes in v13:
- Update the kernel doc of fwnode_connection_find_match
- Add typec_mode_switch_node_count helper
- Fix style issues
- Update a typo in the commit message
- Collect Reviewed-by tag

Changes in v12:
- Check the availability of the device node in fwnode_graph_devcon_matches
- Ensured valid access to "matches" in fwnode_graph_devcon_matches
- Updated the documentation in fwnode_connection_find_match(es)
- Add fwnode_for_each_typec_mode_switch macro
- Remove a duplicated dmesg in the helper
- Used IS_REACHABLE instead to guard the function signatures
- Removed the 4-lane binding in analogix,anx7625.yaml
- Reworded the description for the mode-switch property
- Fixed style issues in anx7625 driver
- Fixed the inverted orientation setting in anx7625 driver
- Changed "&ctx->client->dev" to "ctx->dev"
- Fixed the schema of "data-lanes" property for it6505
- Fixes style issues in it6505 driver
- Replaced &it6505->client->dev with it6505->dev
- Updated the error logs when parsing data-lanes property

Changes in v11:
- Added missing fwnode_handle_put in drivers/base/property.c
- Collected Acked-by tag
- Use fwnode helpers instead of DT
- Moved the helpers to a new file
- Use "reg" instead of "data-lanes" to determine the port number
- Updated the description of the endpoints in the bindings
- Referenced video-interfaces.yaml instead for the endpoints binding
- Removed duplicated definitions from inherited schema
- Moved the "data-lanes" parsing logics to bridge drivers
- Removed Kconfig dependencies for the bridge drivers
- Updated the usage of the private bridge driver data
- Added a clarification on the anx7625 built-in mux in the cover letter

Changes in v10:
- Collected Reviewed-by and Tested-by tags
- Replaced "void *" with "typec_mux_set_fn_t" for mux_set callbacks
- Print out the node name when errors on parsing DT
- Use dev_dbg instead of dev_warn when no Type-C switch nodes available
- Made the return path of drm_dp_register_mode_switch clearer
- Added a TODO for implementing orientation switch for anx7625
- Updated the commit message for the absence of orientation switch
- Fixed typo in the commit message

Changes in v9:
- Collected Reviewed-by tag
- Fixed subject prefix again
- Changed the naming of the example node for it6505

Changes in v8:
- Fixed the build issue when CONFIG_TYPEC=m
- Fixed some style issues
- Fixed the subject prefixes for the bindings patch
- Fixed the bindings for data-lanes properties

Changes in v7:
- Fix the long comment lines
- Extracted the common codes to a helper function
- Fixed style issues in anx7625 driver
- Removed DT property validation in anx7625 driver.
- Fixed style issues in it6505 driver
- Removed the redundant sleep in it6505 driver
- Removed DT property validation in it6505 driver
- Rebased to drm-misc-next
- Fixed indentations in bindings patches
- Added a new patch to fix indentations in Kconfig

Changes in v6:
- Changed it6505_typec_mux_set callback function to accommodate with
the latest drm-misc patches
- Changed the driver implementation to accommodate with the new binding
- Dropped typec-switch binding and use endpoints and data-lanes properties
to describe the pin connections
- Added new patches (patch 1,2,4) to fix probing issues
- Changed the bindings of it6505/anx7625 and modified the drivers
accordingly
- Merged it6505/anx7625 driver changes into a single patch

Pin-yen Lin (8):
drm/display: Add Type-C switch helpers
dt-bindings: display: bridge: anx7625: Add mode-switch support
drm/bridge: anx7625: Check for Type-C during panel registration
drm/bridge: Remove redundant i2c_client in anx7625/it6505
drm/bridge: anx7625: Register Type C mode switches
dt-bindings: display: bridge: it6505: Add mode-switch support
drm/bridge: it6505: Fix Kconfig indentation
drm/bridge: it6505: Register Type C mode switches

Prashant Malani (2):
device property: Add remote endpoint to devcon matcher
platform/chrome: cros_ec_typec: Purge blocking switch devlinks

.../display/bridge/analogix,anx7625.yaml | 88 ++++-
.../bindings/display/bridge/ite,it6505.yaml | 101 +++++-
drivers/base/property.c | 31 +-
drivers/gpu/drm/bridge/Kconfig | 20 +-
drivers/gpu/drm/bridge/analogix/anx7625.c | 257 +++++++++++---
drivers/gpu/drm/bridge/analogix/anx7625.h | 22 +-
drivers/gpu/drm/bridge/ite-it6505.c | 313 ++++++++++++++----
drivers/gpu/drm/display/Makefile | 1 +
drivers/gpu/drm/display/drm_dp_typec_helper.c | 105 ++++++
drivers/platform/chrome/cros_ec_typec.c | 10 +
include/drm/display/drm_dp_helper.h | 46 +++
11 files changed, 845 insertions(+), 149 deletions(-)
create mode 100644 drivers/gpu/drm/display/drm_dp_typec_helper.c

--
2.40.0.rc0.216.gc4246ad0f0-goog



2023-03-03 14:34:29

by Pin-yen Lin

[permalink] [raw]
Subject: [PATCH v13 01/10] device property: Add remote endpoint to devcon matcher

From: Prashant Malani <[email protected]>

When searching the device graph for device matches, check the
remote-endpoint itself for a match.

Some drivers register devices for individual endpoints. This allows
the matcher code to evaluate those for a match too, instead
of only looking at the remote parent devices. This is required when a
device supports two mode switches in its endpoints, so we can't simply
register the mode switch with the parent node.

Signed-off-by: Prashant Malani <[email protected]>
Signed-off-by: Pin-yen Lin <[email protected]>

---

Changes in v13:
- Update the kernel doc of fwnode_connection_find_match

Changes in v12:
- Check the availability of the device node in fwnode_graph_devcon_matches
- Ensured valid access to "matches" in fwnode_graph_devcon_matches
- Updated the documentation in fwnode_connection_find_match(es)
- Dropped collected tags due to the new changes

Changes in v11:
- Added missing fwnode_handle_put in drivers/base/property.c

Changes in v10:
- Collected Reviewed-by and Tested-by tags

Changes in v6:
- New in v6

drivers/base/property.c | 31 ++++++++++++++++++++++++++-----
1 file changed, 26 insertions(+), 5 deletions(-)

diff --git a/drivers/base/property.c b/drivers/base/property.c
index 083a95791d3b..4426ac2b16ca 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -1243,6 +1243,23 @@ static unsigned int fwnode_graph_devcon_matches(const struct fwnode_handle *fwno
continue;
}

+ ret = match(node, con_id, data);
+ fwnode_handle_put(node);
+ if (ret) {
+ if (matches)
+ matches[count] = ret;
+ count++;
+
+ if (matches && count >= matches_len)
+ break;
+ }
+
+ /*
+ * Some drivers may register devices for endpoints. Check
+ * the remote-endpoints for matches in addition to the remote
+ * port parent.
+ */
+ node = fwnode_graph_get_remote_endpoint(ep);
ret = match(node, con_id, data);
fwnode_handle_put(node);
if (ret) {
@@ -1293,8 +1310,11 @@ static unsigned int fwnode_devcon_matches(const struct fwnode_handle *fwnode,
* @match: Function to check and convert the connection description
*
* Find a connection with unique identifier @con_id between @fwnode and another
- * device node. @match will be used to convert the connection description to
- * data the caller is expecting to be returned.
+ * device node. For fwnode graph connections, the graph endpoints are also
+ * checked. @match will be used to convert the connection description to data
+ * the caller is expecting to be returned.
+ *
+ * Return: The pointer to the matched node, or NULL on error.
*/
void *fwnode_connection_find_match(const struct fwnode_handle *fwnode,
const char *con_id, void *data,
@@ -1325,9 +1345,10 @@ EXPORT_SYMBOL_GPL(fwnode_connection_find_match);
* @matches_len: Length of @matches
*
* Find up to @matches_len connections with unique identifier @con_id between
- * @fwnode and other device nodes. @match will be used to convert the
- * connection description to data the caller is expecting to be returned
- * through the @matches array.
+ * @fwnode and other device nodes. For fwnode graph connections, the graph
+ * endpoints are also checked. @match will be used to convert the connection
+ * description to data the caller is expecting to be returned through the
+ * @matches array.
* If @matches is NULL @matches_len is ignored and the total number of resolved
* matches is returned.
*
--
2.40.0.rc0.216.gc4246ad0f0-goog


2023-03-03 14:34:32

by Pin-yen Lin

[permalink] [raw]
Subject: [PATCH v13 02/10] platform/chrome: cros_ec_typec: Purge blocking switch devlinks

From: Prashant Malani <[email protected]>

When using OF graph, the fw_devlink code will create links between the
individual port driver (cros-ec-typec here) and the parent device for
a Type-C switch (like mode-switch). Since the mode-switch will in turn
have the usb-c-connector (i.e the child of the port driver) as a
supplier, fw_devlink will not be able to resolve the cyclic dependency
correctly.

As a result, the mode-switch driver probe() never runs, so mode-switches
are never registered. Because of that, the port driver probe constantly
fails with -EPROBE_DEFER, because the Type-C connector class requires all
switch devices to be registered prior to port registration.

To break this deadlock and allow the mode-switch registration to occur,
purge all the usb-c-connector nodes' absent suppliers. This eliminates
the connector as a supplier for a switch and allows it to be probed.

Signed-off-by: Prashant Malani <[email protected]>
Signed-off-by: Pin-yen Lin <[email protected]>
Reviewed-by: Chen-Yu Tsai <[email protected]>
Tested-by: Chen-Yu Tsai <[email protected]>
Acked-by: Heikki Krogerus <[email protected]>

---

(no changes since v11)

Changes in v11:
- Collected Acked-by tag

Changes in v10:
- Collected Reviewed-by and Tested-by tags

Changes in v7:
- Fix the long comment lines

Changes in v6:
- New in v6

drivers/platform/chrome/cros_ec_typec.c | 10 ++++++++++
1 file changed, 10 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c
index 001b0de95a46..bbc95a3ba5a7 100644
--- a/drivers/platform/chrome/cros_ec_typec.c
+++ b/drivers/platform/chrome/cros_ec_typec.c
@@ -385,6 +385,16 @@ static int cros_typec_init_ports(struct cros_typec_data *typec)
return -EINVAL;
}

+ /*
+ * OF graph may have set up some device links with switches,
+ * since connectors have their own compatible. Purge these
+ * to avoid a deadlock in switch probe (the switch mistakenly
+ * assumes the connector is a supplier).
+ */
+ if (dev_of_node(dev))
+ device_for_each_child_node(dev, fwnode)
+ fw_devlink_purge_absent_suppliers(fwnode);
+
/* DT uses "reg" to specify port number. */
port_prop = dev->of_node ? "reg" : "port-number";
device_for_each_child_node(dev, fwnode) {
--
2.40.0.rc0.216.gc4246ad0f0-goog


2023-03-03 14:34:53

by Pin-yen Lin

[permalink] [raw]
Subject: [PATCH v13 03/10] drm/display: Add Type-C switch helpers

Add helpers to register and unregister Type-C "switches" for bridges
capable of switching their output between two downstream devices.

The helper registers USB Type-C mode switches when the "mode-switch"
and the "reg" properties are available in Device Tree.

Signed-off-by: Pin-yen Lin <[email protected]>

---

Changes in v13:
- Add typec_mode_switch_node_count helper
- Fix style issues

Changes in v12:
- Add fwnode_for_each_typec_mode_switch macro
- Remove a duplicated dmesg in the helper
- Used IS_REACHABLE instead to guard the function signatures

Changes in v11:
- Use fwnode helpers instead of DT
- Moved the helpers to a new file
- Use "reg" instead of "data-lanes" to determine the port number
- Dropped collected tags due to new changes

Changes in v10:
- Collected Reviewed-by and Tested-by tags
- Replaced "void *" with "typec_mux_set_fn_t" for mux_set callbacks
- Print out the node name when errors on parsing DT
- Use dev_dbg instead of dev_warn when no Type-C switch nodes available
- Made the return path of drm_dp_register_mode_switch clearer

Changes in v8:
- Fixed the build issue when CONFIG_TYPEC=m
- Fixed some style issues

Changes in v7:
- Extracted the common codes to a helper function
- New in v7

drivers/gpu/drm/display/Makefile | 1 +
drivers/gpu/drm/display/drm_dp_typec_helper.c | 105 ++++++++++++++++++
include/drm/display/drm_dp_helper.h | 46 ++++++++
3 files changed, 152 insertions(+)
create mode 100644 drivers/gpu/drm/display/drm_dp_typec_helper.c

diff --git a/drivers/gpu/drm/display/Makefile b/drivers/gpu/drm/display/Makefile
index 17ac4a1006a8..ef80b9fde615 100644
--- a/drivers/gpu/drm/display/Makefile
+++ b/drivers/gpu/drm/display/Makefile
@@ -14,5 +14,6 @@ drm_display_helper-$(CONFIG_DRM_DISPLAY_HDMI_HELPER) += \
drm_scdc_helper.o
drm_display_helper-$(CONFIG_DRM_DP_AUX_CHARDEV) += drm_dp_aux_dev.o
drm_display_helper-$(CONFIG_DRM_DP_CEC) += drm_dp_cec.o
+drm_display_helper-$(CONFIG_TYPEC) += drm_dp_typec_helper.o

obj-$(CONFIG_DRM_DISPLAY_HELPER) += drm_display_helper.o
diff --git a/drivers/gpu/drm/display/drm_dp_typec_helper.c b/drivers/gpu/drm/display/drm_dp_typec_helper.c
new file mode 100644
index 000000000000..0c705a4bca24
--- /dev/null
+++ b/drivers/gpu/drm/display/drm_dp_typec_helper.c
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/usb/typec_mux.h>
+#include <drm/display/drm_dp_helper.h>
+
+static int drm_dp_register_mode_switch(struct device *dev,
+ struct fwnode_handle *fwnode,
+ struct drm_dp_typec_switch_desc *switch_desc,
+ void *data, typec_mux_set_fn_t mux_set)
+{
+ struct drm_dp_typec_port_data *port_data;
+ struct typec_mux_desc mux_desc = {};
+ char name[32];
+ u32 port_num;
+ int ret;
+
+ ret = fwnode_property_read_u32(fwnode, "reg", &port_num);
+ if (ret) {
+ dev_err(dev, "Failed to read reg property: %d\n", ret);
+ return ret;
+ }
+
+ port_data = &switch_desc->typec_ports[port_num];
+ port_data->data = data;
+ port_data->port_num = port_num;
+ port_data->fwnode = fwnode;
+ mux_desc.fwnode = fwnode;
+ mux_desc.drvdata = port_data;
+ snprintf(name, sizeof(name), "%pfwP-%u", fwnode, port_num);
+ mux_desc.name = name;
+ mux_desc.set = mux_set;
+
+ port_data->typec_mux = typec_mux_register(dev, &mux_desc);
+ if (IS_ERR(port_data->typec_mux)) {
+ ret = PTR_ERR(port_data->typec_mux);
+ dev_err(dev, "Mode switch register for port %d failed: %d\n",
+ port_num, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * drm_dp_register_typec_switches() - register Type-C switches
+ * @dev: Device that registers Type-C switches
+ * @port: Device node for the switch
+ * @switch_desc: A Type-C switch descriptor
+ * @data: Private data for the switches
+ * @mux_set: Callback function for typec_mux_set
+ *
+ * This function registers USB Type-C switches for DP bridges that can switch
+ * the output signal between their output pins.
+ *
+ * Currently only mode switches are implemented, and the function assumes the
+ * given @port device node has endpoints with "mode-switch" property.
+ * The port number is determined by the "reg" property of the endpoint.
+ */
+int drm_dp_register_typec_switches(struct device *dev, struct fwnode_handle *port,
+ struct drm_dp_typec_switch_desc *switch_desc,
+ void *data, typec_mux_set_fn_t mux_set)
+{
+ struct fwnode_handle *sw;
+ int ret;
+
+ switch_desc->num_typec_switches = typec_mode_switch_node_count(port);
+ if (!switch_desc->num_typec_switches) {
+ dev_dbg(dev, "No Type-C switches node found\n");
+ return 0;
+ }
+
+ switch_desc->typec_ports = devm_kcalloc(dev, switch_desc->num_typec_switches,
+ sizeof(struct drm_dp_typec_port_data),
+ GFP_KERNEL);
+ if (!switch_desc->typec_ports)
+ return -ENOMEM;
+
+ /* Register switches for each connector. */
+ for_each_typec_mode_switch_node(port, sw) {
+ ret = drm_dp_register_mode_switch(dev, sw, switch_desc, data, mux_set);
+ if (ret)
+ goto err_unregister_typec_switches;
+ }
+
+ return 0;
+
+err_unregister_typec_switches:
+ fwnode_handle_put(sw);
+ drm_dp_unregister_typec_switches(switch_desc);
+ return ret;
+}
+EXPORT_SYMBOL(drm_dp_register_typec_switches);
+
+/**
+ * drm_dp_unregister_typec_switches() - unregister Type-C switches
+ * @switch_desc: A Type-C switch descriptor
+ */
+void drm_dp_unregister_typec_switches(struct drm_dp_typec_switch_desc *switch_desc)
+{
+ unsigned int i;
+
+ for (i = 0; i < switch_desc->num_typec_switches; i++)
+ typec_mux_unregister(switch_desc->typec_ports[i].typec_mux);
+}
+EXPORT_SYMBOL(drm_dp_unregister_typec_switches);
diff --git a/include/drm/display/drm_dp_helper.h b/include/drm/display/drm_dp_helper.h
index ab55453f2d2c..fb359b0cc8e8 100644
--- a/include/drm/display/drm_dp_helper.h
+++ b/include/drm/display/drm_dp_helper.h
@@ -25,6 +25,7 @@

#include <linux/delay.h>
#include <linux/i2c.h>
+#include <linux/usb/typec_mux.h>

#include <drm/display/drm_dp.h>
#include <drm/drm_connector.h>
@@ -763,4 +764,49 @@ bool drm_dp_downstream_rgb_to_ycbcr_conversion(const u8 dpcd[DP_RECEIVER_CAP_SIZ
const u8 port_cap[4], u8 color_spc);
int drm_dp_pcon_convert_rgb_to_ycbcr(struct drm_dp_aux *aux, u8 color_spc);

+struct drm_dp_typec_port_data {
+ struct typec_mux_dev *typec_mux;
+ int port_num;
+ struct fwnode_handle *fwnode;
+ void *data;
+};
+
+struct drm_dp_typec_switch_desc {
+ int num_typec_switches;
+ struct drm_dp_typec_port_data *typec_ports;
+};
+
+#define for_each_typec_mode_switch_node(port, sw) \
+ fwnode_for_each_child_node((port), (sw)) \
+ for_each_if(fwnode_property_present((sw), "mode-switch"))
+
+static inline unsigned int typec_mode_switch_node_count(struct fwnode_handle *port)
+{
+ struct fwnode_handle *sw;
+ unsigned int count = 0;
+
+ for_each_typec_mode_switch_node(port, sw)
+ count++;
+
+ return count;
+}
+
+#if IS_REACHABLE(CONFIG_TYPEC)
+void drm_dp_unregister_typec_switches(struct drm_dp_typec_switch_desc *switch_desc);
+int drm_dp_register_typec_switches(struct device *dev, struct fwnode_handle *port,
+ struct drm_dp_typec_switch_desc *switch_desc,
+ void *data, typec_mux_set_fn_t mux_set);
+#else
+static inline void drm_dp_unregister_typec_switches(struct drm_dp_typec_switch_desc *switch_desc)
+{
+}
+static inline int drm_dp_register_typec_switches(
+ struct device *dev, struct fwnode_handle *port,
+ struct drm_dp_typec_switch_desc *switch_desc, void *data,
+ typec_mux_set_fn_t mux_set)
+{
+ return -EOPNOTSUPP;
+}
+#endif
+
#endif /* _DRM_DP_HELPER_H_ */
--
2.40.0.rc0.216.gc4246ad0f0-goog


2023-03-03 14:34:57

by Pin-yen Lin

[permalink] [raw]
Subject: [PATCH v13 04/10] dt-bindings: display: bridge: anx7625: Add mode-switch support

Analogix 7625 can be used in systems to switch the DP traffic between
two downstreams, which can be USB Type-C DisplayPort alternate mode
lane or regular DisplayPort output ports.

Update the binding to accommodate this usage by introducing a
data-lanes and a mode-switch property on endpoints.

Also include the link to the product brief in the bindings.

Signed-off-by: Pin-yen Lin <[email protected]>
Reviewed-by: Krzysztof Kozlowski <[email protected]>
Reviewed-by: Chen-Yu Tsai <[email protected]>
Tested-by: Chen-Yu Tsai <[email protected]>
Reviewed-by: AngeloGioacchino Del Regno <[email protected]>

---

(no changes since v12)

Changes in v12:
- Removed the 4-lane binding in analogix,anx7625.yaml
- Reworded the description for the mode-switch property

Changes in v11:
- Updated the description of the endpoints
- Referenced video-interfaces.yaml instead for the endpoints

Changes in v10:
- Collected Reviewed-by and Tested-by tags

Changes in v9:
- Collected Reviewed-by tag

Changes in v8:
- Updated anx7625 bindings for data-lane property
- Fixed the subject prefix

Changes in v7:
- Fixed issues reported by dt_binding_check
- Updated the schema and the example dts for data-lanes.
- Changed to generic naming for the example dts node.

Changes in v6:
- Remove switches node and use endpoints and data-lanes property to
describe the connections.

.../display/bridge/analogix,anx7625.yaml | 88 ++++++++++++++++++-
1 file changed, 85 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml b/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
index 4590186c4a0b..a50de536cffd 100644
--- a/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
+++ b/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
@@ -12,7 +12,8 @@ maintainers:

description: |
The ANX7625 is an ultra-low power 4K Mobile HD Transmitter
- designed for portable devices.
+ designed for portable devices. Product brief is available at
+ https://www.analogix.com/en/system/files/AA-002291-PB-6-ANX7625_ProductBrief.pdf

properties:
compatible:
@@ -112,9 +113,40 @@ properties:
data-lanes: true

port@1:
- $ref: /schemas/graph.yaml#/properties/port
+ $ref: /schemas/graph.yaml#/$defs/port-base
description:
- Video port for panel or connector.
+ Video port for panel or connector. Each endpoint connects to a video
+ output downstream, and the "data-lanes" property is used to describe
+ the pin connections. 0, 1, 2, 3 in "data-lanes" maps to SSRX1, SSTX1,
+ SSRX2, SSTX2, respectively.
+
+ patternProperties:
+ "^endpoint@[01]$":
+ $ref: /schemas/media/video-interfaces.yaml#
+ properties:
+ reg: true
+
+ remote-endpoint: true
+
+ data-lanes:
+ oneOf:
+ - items:
+ - enum: [0, 1, 2, 3]
+
+ - items:
+ - const: 0
+ - const: 1
+
+ - items:
+ - const: 2
+ - const: 3
+
+ mode-switch:
+ type: boolean
+ description: Serves as Type-C mode switch if present.
+
+ required:
+ - remote-endpoint

required:
- port@0
@@ -186,3 +218,53 @@ examples:
};
};
};
+ - |
+ i2c3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ encoder@58 {
+ compatible = "analogix,anx7625";
+ reg = <0x58>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&anx7625_dp_pins>;
+ enable-gpios = <&pio 176 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&pio 177 GPIO_ACTIVE_HIGH>;
+ vdd10-supply = <&pp1100_dpbrdg>;
+ vdd18-supply = <&pp1800_dpbrdg_dx>;
+ vdd33-supply = <&pp3300_dpbrdg_dx>;
+ analogix,audio-enable;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ anx7625_dp_in: endpoint {
+ bus-type = <7>;
+ remote-endpoint = <&dpi_out>;
+ };
+ };
+
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <1>;
+ anx_typec0: endpoint@0 {
+ reg = <0>;
+ mode-switch;
+ data-lanes = <0 1>;
+ remote-endpoint = <&typec_port0>;
+ };
+ anx_typec1: endpoint@1 {
+ reg = <1>;
+ mode-switch;
+ data-lanes = <2 3>;
+ remote-endpoint = <&typec_port1>;
+ };
+ };
+ };
+ };
+ };
--
2.40.0.rc0.216.gc4246ad0f0-goog


2023-03-03 14:35:01

by Pin-yen Lin

[permalink] [raw]
Subject: [PATCH v13 05/10] drm/bridge: anx7625: Check for Type-C during panel registration

The output port endpoints can be connected to USB-C connectors.
Running drm_of_find_panel_or_bridge() with such endpoints leads to
a continuous return value of -EPROBE_DEFER, even though there is
no panel present.

To avoid this, check for the existence of a "mode-switch" property in
the port endpoint, and skip panel registration completely if so.

Signed-off-by: Pin-yen Lin <[email protected]>

---

Changes in v13:
- Use the new typec_mode_switch_node_count helper

Changes in v12:
- Updated to use fwnode_for_each_typec_mode_switch macro
- Dropped collected tags

Changes in v10:
- Collected Reviewed-by and Tested-by tags

Changes in v6:
- New in v6

drivers/gpu/drm/bridge/analogix/anx7625.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
index 6846199a2ee1..3f6bf7674d32 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.c
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
@@ -1648,7 +1648,8 @@ static int anx7625_get_swing_setting(struct device *dev,
static int anx7625_parse_dt(struct device *dev,
struct anx7625_platform_data *pdata)
{
- struct device_node *np = dev->of_node, *ep0;
+ struct device_node *np = dev->of_node, *ep0, *port_node;
+ unsigned int count;
int bus_type, mipi_lanes;

anx7625_get_swing_setting(dev, pdata);
@@ -1687,6 +1688,15 @@ static int anx7625_parse_dt(struct device *dev,
if (of_property_read_bool(np, "analogix,audio-enable"))
pdata->audio_en = 1;

+ /*
+ * Don't bother finding a panel if a Type-C `mode-switch` property is
+ * present in one of the endpoints in the output port.
+ */
+ port_node = of_graph_get_port_by_id(np, 1);
+ count = typec_mode_switch_node_count(&port_node->fwnode);
+ if (count)
+ return 0;
+
pdata->panel_bridge = devm_drm_of_get_bridge(dev, np, 1, 0);
if (IS_ERR(pdata->panel_bridge)) {
if (PTR_ERR(pdata->panel_bridge) == -ENODEV) {
--
2.40.0.rc0.216.gc4246ad0f0-goog


2023-03-03 14:35:21

by Pin-yen Lin

[permalink] [raw]
Subject: [PATCH v13 06/10] drm/bridge: Remove redundant i2c_client in anx7625/it6505

These two drivers embed a i2c_client in their private driver data, but
only strict device is actually needed. Replace the i2c_client reference
with a struct device one.

Signed-off-by: Pin-yen Lin <[email protected]>
Reviewed-by: Andy Shevchenko <[email protected]>
---

Changes in v13:
- Update a typo in the commit message
- Collect Reviewed-by tag

Changes in v12:
- New in v12

drivers/gpu/drm/bridge/analogix/anx7625.c | 96 ++++++++--------
drivers/gpu/drm/bridge/analogix/anx7625.h | 2 +-
drivers/gpu/drm/bridge/ite-it6505.c | 128 +++++++++++-----------
3 files changed, 113 insertions(+), 113 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
index 3f6bf7674d32..76d46db3f8dc 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.c
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
@@ -207,7 +207,7 @@ static int anx7625_read_ctrl_status_p0(struct anx7625_data *ctx)

static int wait_aux_op_finish(struct anx7625_data *ctx)
{
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
int val;
int ret;

@@ -234,7 +234,7 @@ static int wait_aux_op_finish(struct anx7625_data *ctx)
static int anx7625_aux_trans(struct anx7625_data *ctx, u8 op, u32 address,
u8 len, u8 *buf)
{
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
int ret;
u8 addrh, addrm, addrl;
u8 cmd;
@@ -427,7 +427,7 @@ static int anx7625_odfc_config(struct anx7625_data *ctx,
u8 post_divider)
{
int ret;
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;

/* Config input reference clock frequency 27MHz/19.2MHz */
ret = anx7625_write_and(ctx, ctx->i2c.rx_p1_client, MIPI_DIGITAL_PLL_16,
@@ -477,7 +477,7 @@ static int anx7625_set_k_value(struct anx7625_data *ctx)

static int anx7625_dsi_video_timing_config(struct anx7625_data *ctx)
{
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
unsigned long m, n;
u16 htotal;
int ret;
@@ -575,7 +575,7 @@ static int anx7625_dsi_video_timing_config(struct anx7625_data *ctx)
static int anx7625_swap_dsi_lane3(struct anx7625_data *ctx)
{
int val;
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;

/* Swap MIPI-DSI data lane 3 P and N */
val = anx7625_reg_read(ctx, ctx->i2c.rx_p1_client, MIPI_SWAP);
@@ -592,7 +592,7 @@ static int anx7625_api_dsi_config(struct anx7625_data *ctx)

{
int val, ret;
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;

/* Swap MIPI-DSI data lane 3 P and N */
ret = anx7625_swap_dsi_lane3(ctx);
@@ -657,7 +657,7 @@ static int anx7625_api_dsi_config(struct anx7625_data *ctx)

static int anx7625_dsi_config(struct anx7625_data *ctx)
{
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
int ret;

DRM_DEV_DEBUG_DRIVER(dev, "config dsi.\n");
@@ -689,7 +689,7 @@ static int anx7625_dsi_config(struct anx7625_data *ctx)

static int anx7625_api_dpi_config(struct anx7625_data *ctx)
{
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
u16 freq = ctx->dt.pixelclock.min / 1000;
int ret;

@@ -720,7 +720,7 @@ static int anx7625_api_dpi_config(struct anx7625_data *ctx)

static int anx7625_dpi_config(struct anx7625_data *ctx)
{
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
int ret;

DRM_DEV_DEBUG_DRIVER(dev, "config dpi\n");
@@ -765,7 +765,7 @@ static int anx7625_read_flash_status(struct anx7625_data *ctx)
static int anx7625_hdcp_key_probe(struct anx7625_data *ctx)
{
int ret, val;
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
u8 ident[FLASH_BUF_LEN];

ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
@@ -815,7 +815,7 @@ static int anx7625_hdcp_key_probe(struct anx7625_data *ctx)
static int anx7625_hdcp_key_load(struct anx7625_data *ctx)
{
int ret;
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;

/* Select HDCP 1.4 KEY */
ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
@@ -843,7 +843,7 @@ static int anx7625_hdcp_key_load(struct anx7625_data *ctx)
static int anx7625_hdcp_disable(struct anx7625_data *ctx)
{
int ret;
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;

dev_dbg(dev, "disable HDCP 1.4\n");

@@ -864,7 +864,7 @@ static int anx7625_hdcp_enable(struct anx7625_data *ctx)
{
u8 bcap;
int ret;
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;

ret = anx7625_hdcp_key_probe(ctx);
if (ret) {
@@ -922,7 +922,7 @@ static int anx7625_hdcp_enable(struct anx7625_data *ctx)
static void anx7625_dp_start(struct anx7625_data *ctx)
{
int ret;
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
u8 data;

if (!ctx->display_timing_valid) {
@@ -955,7 +955,7 @@ static void anx7625_dp_start(struct anx7625_data *ctx)

static void anx7625_dp_stop(struct anx7625_data *ctx)
{
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
int ret;
u8 data;

@@ -1020,7 +1020,7 @@ static int sp_tx_aux_rd(struct anx7625_data *ctx, u8 len_cmd)
static int sp_tx_get_edid_block(struct anx7625_data *ctx)
{
int c = 0;
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;

sp_tx_aux_wr(ctx, 0x7e);
sp_tx_aux_rd(ctx, 0x01);
@@ -1042,7 +1042,7 @@ static int edid_read(struct anx7625_data *ctx,
u8 offset, u8 *pblock_buf)
{
int ret, cnt;
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;

for (cnt = 0; cnt <= EDID_TRY_CNT; cnt++) {
sp_tx_aux_wr(ctx, offset);
@@ -1073,7 +1073,7 @@ static int segments_edid_read(struct anx7625_data *ctx,
{
u8 cnt;
int ret;
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;

/* Write address only */
ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
@@ -1128,7 +1128,7 @@ static int sp_tx_edid_read(struct anx7625_data *ctx,
u8 i, j;
int g_edid_break = 0;
int ret;
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;

/* Address initial */
ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
@@ -1235,7 +1235,7 @@ static int sp_tx_edid_read(struct anx7625_data *ctx,

static void anx7625_power_on(struct anx7625_data *ctx)
{
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
int ret, i;

if (!ctx->pdata.low_power_mode) {
@@ -1271,7 +1271,7 @@ static void anx7625_power_on(struct anx7625_data *ctx)

static void anx7625_power_standby(struct anx7625_data *ctx)
{
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
int ret;

if (!ctx->pdata.low_power_mode) {
@@ -1301,7 +1301,7 @@ static void anx7625_config(struct anx7625_data *ctx)

static void anx7625_disable_pd_protocol(struct anx7625_data *ctx)
{
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
int ret;

/* Reset main ocm */
@@ -1321,7 +1321,7 @@ static void anx7625_disable_pd_protocol(struct anx7625_data *ctx)
static int anx7625_ocm_loading_check(struct anx7625_data *ctx)
{
int ret;
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;

/* Check interface workable */
ret = anx7625_reg_read(ctx, ctx->i2c.rx_p0_client,
@@ -1367,7 +1367,7 @@ static void anx7625_power_on_init(struct anx7625_data *ctx)

static void anx7625_init_gpio(struct anx7625_data *platform)
{
- struct device *dev = &platform->client->dev;
+ struct device *dev = platform->dev;

DRM_DEV_DEBUG_DRIVER(dev, "init gpio\n");

@@ -1407,7 +1407,7 @@ static void anx7625_stop_dp_work(struct anx7625_data *ctx)
static void anx7625_start_dp_work(struct anx7625_data *ctx)
{
int ret;
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;

if (ctx->hpd_high_cnt >= 2) {
DRM_DEV_DEBUG_DRIVER(dev, "filter useless HPD\n");
@@ -1459,7 +1459,7 @@ static int _anx7625_hpd_polling(struct anx7625_data *ctx,
unsigned long wait_us)
{
int ret, val;
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;

/* Interrupt mode, no need poll HPD status, just return */
if (ctx->pdata.intp_irq)
@@ -1493,7 +1493,7 @@ static int anx7625_wait_hpd_asserted(struct drm_dp_aux *aux,
unsigned long wait_us)
{
struct anx7625_data *ctx = container_of(aux, struct anx7625_data, aux);
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
int ret;

pm_runtime_get_sync(dev);
@@ -1526,7 +1526,7 @@ static void anx7625_dp_adjust_swing(struct anx7625_data *ctx)

static void dp_hpd_change_handler(struct anx7625_data *ctx, bool on)
{
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;

/* HPD changed */
DRM_DEV_DEBUG_DRIVER(dev, "dp_hpd_change_default_func: %d\n",
@@ -1546,7 +1546,7 @@ static void dp_hpd_change_handler(struct anx7625_data *ctx, bool on)
static int anx7625_hpd_change_detect(struct anx7625_data *ctx)
{
int intr_vector, status;
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;

status = anx7625_reg_write(ctx, ctx->i2c.tcpc_client,
INTR_ALERT_1, 0xFF);
@@ -1594,7 +1594,7 @@ static void anx7625_work_func(struct work_struct *work)

mutex_lock(&ctx->lock);

- if (pm_runtime_suspended(&ctx->client->dev))
+ if (pm_runtime_suspended(ctx->dev))
goto unlock;

event = anx7625_hpd_change_detect(ctx);
@@ -1738,7 +1738,7 @@ static ssize_t anx7625_aux_transfer(struct drm_dp_aux *aux,
struct drm_dp_aux_msg *msg)
{
struct anx7625_data *ctx = container_of(aux, struct anx7625_data, aux);
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
u8 request = msg->request & ~DP_AUX_I2C_MOT;
int ret = 0;

@@ -1764,7 +1764,7 @@ static ssize_t anx7625_aux_transfer(struct drm_dp_aux *aux,

static struct edid *anx7625_get_edid(struct anx7625_data *ctx)
{
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
struct s_edid_data *p_edid = &ctx->slimport_edid_p;
int edid_num;
u8 *edid;
@@ -1800,7 +1800,7 @@ static struct edid *anx7625_get_edid(struct anx7625_data *ctx)

static enum drm_connector_status anx7625_sink_detect(struct anx7625_data *ctx)
{
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;

DRM_DEV_DEBUG_DRIVER(dev, "sink detect\n");

@@ -2009,7 +2009,7 @@ static const struct hdmi_codec_ops anx7625_codec_ops = {

static void anx7625_unregister_audio(struct anx7625_data *ctx)
{
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;

if (ctx->audio_pdev) {
platform_device_unregister(ctx->audio_pdev);
@@ -2045,7 +2045,7 @@ static int anx7625_register_audio(struct device *dev, struct anx7625_data *ctx)
static int anx7625_attach_dsi(struct anx7625_data *ctx)
{
struct mipi_dsi_device *dsi;
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
struct mipi_dsi_host *host;
const struct mipi_dsi_device_info info = {
.type = "anx7625",
@@ -2098,7 +2098,7 @@ static void hdcp_check_work_func(struct work_struct *work)

dwork = to_delayed_work(work);
ctx = container_of(dwork, struct anx7625_data, hdcp_work);
- dev = &ctx->client->dev;
+ dev = ctx->dev;

if (!ctx->connector) {
dev_err(dev, "HDCP connector is null!");
@@ -2125,7 +2125,7 @@ static void hdcp_check_work_func(struct work_struct *work)
static int anx7625_connector_atomic_check(struct anx7625_data *ctx,
struct drm_connector_state *state)
{
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
int cp;

dev_dbg(dev, "hdcp state check\n");
@@ -2170,7 +2170,7 @@ static int anx7625_bridge_attach(struct drm_bridge *bridge,
{
struct anx7625_data *ctx = bridge_to_anx7625(bridge);
int err;
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;

DRM_DEV_DEBUG_DRIVER(dev, "drm attach\n");
if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR))
@@ -2214,7 +2214,7 @@ anx7625_bridge_mode_valid(struct drm_bridge *bridge,
const struct drm_display_mode *mode)
{
struct anx7625_data *ctx = bridge_to_anx7625(bridge);
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;

DRM_DEV_DEBUG_DRIVER(dev, "drm mode checking\n");

@@ -2235,7 +2235,7 @@ static void anx7625_bridge_mode_set(struct drm_bridge *bridge,
const struct drm_display_mode *mode)
{
struct anx7625_data *ctx = bridge_to_anx7625(bridge);
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;

DRM_DEV_DEBUG_DRIVER(dev, "drm mode set\n");

@@ -2281,7 +2281,7 @@ static bool anx7625_bridge_mode_fixup(struct drm_bridge *bridge,
struct drm_display_mode *adj)
{
struct anx7625_data *ctx = bridge_to_anx7625(bridge);
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
u32 hsync, hfp, hbp, hblanking;
u32 adj_hsync, adj_hfp, adj_hbp, adj_hblanking, delta_adj;
u32 vref, adj_clock;
@@ -2399,7 +2399,7 @@ static int anx7625_bridge_atomic_check(struct drm_bridge *bridge,
struct drm_connector_state *conn_state)
{
struct anx7625_data *ctx = bridge_to_anx7625(bridge);
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;

dev_dbg(dev, "drm bridge atomic check\n");

@@ -2413,7 +2413,7 @@ static void anx7625_bridge_atomic_enable(struct drm_bridge *bridge,
struct drm_bridge_state *state)
{
struct anx7625_data *ctx = bridge_to_anx7625(bridge);
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
struct drm_connector *connector;

dev_dbg(dev, "drm atomic enable\n");
@@ -2440,7 +2440,7 @@ static void anx7625_bridge_atomic_disable(struct drm_bridge *bridge,
struct drm_bridge_state *old)
{
struct anx7625_data *ctx = bridge_to_anx7625(bridge);
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;

dev_dbg(dev, "drm atomic disable\n");

@@ -2454,7 +2454,7 @@ static enum drm_connector_status
anx7625_bridge_detect(struct drm_bridge *bridge)
{
struct anx7625_data *ctx = bridge_to_anx7625(bridge);
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;

DRM_DEV_DEBUG_DRIVER(dev, "drm bridge detect\n");

@@ -2465,7 +2465,7 @@ static struct edid *anx7625_bridge_get_edid(struct drm_bridge *bridge,
struct drm_connector *connector)
{
struct anx7625_data *ctx = bridge_to_anx7625(bridge);
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;

DRM_DEV_DEBUG_DRIVER(dev, "drm bridge get edid\n");

@@ -2490,7 +2490,7 @@ static const struct drm_bridge_funcs anx7625_bridge_funcs = {
static int anx7625_register_i2c_dummy_clients(struct anx7625_data *ctx,
struct i2c_client *client)
{
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;

ctx->i2c.tx_p0_client = devm_i2c_new_dummy_device(dev, client->adapter,
TX_P0_ADDR >> 1);
@@ -2591,7 +2591,7 @@ static int anx7625_i2c_probe(struct i2c_client *client)

pdata = &platform->pdata;

- platform->client = client;
+ platform->dev = &client->dev;
i2c_set_clientdata(client, platform);

pdata->supplies[0].supply = "vdd10";
diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h
index 14f33d6be289..5af819611ebc 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.h
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
@@ -458,7 +458,7 @@ struct anx7625_data {
int hdcp_cp;
/* Lock for work queue */
struct mutex lock;
- struct i2c_client *client;
+ struct device *dev;
struct anx7625_i2c_client i2c;
struct i2c_client *last_client;
struct timer_list hdcp_timer;
diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c
index bc451b2a77c2..d4bc388b68ac 100644
--- a/drivers/gpu/drm/bridge/ite-it6505.c
+++ b/drivers/gpu/drm/bridge/ite-it6505.c
@@ -404,7 +404,7 @@ struct debugfs_entries {
struct it6505 {
struct drm_dp_aux aux;
struct drm_bridge bridge;
- struct i2c_client *client;
+ struct device *dev;
struct it6505_drm_dp_link link;
struct it6505_platform_data pdata;
/*
@@ -508,7 +508,7 @@ static int it6505_read(struct it6505 *it6505, unsigned int reg_addr)
{
unsigned int value;
int err;
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;

if (!it6505->powered)
return -ENODEV;
@@ -526,7 +526,7 @@ static int it6505_write(struct it6505 *it6505, unsigned int reg_addr,
unsigned int reg_val)
{
int err;
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;

if (!it6505->powered)
return -ENODEV;
@@ -546,7 +546,7 @@ static int it6505_set_bits(struct it6505 *it6505, unsigned int reg,
unsigned int mask, unsigned int value)
{
int err;
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;

if (!it6505->powered)
return -ENODEV;
@@ -564,7 +564,7 @@ static int it6505_set_bits(struct it6505 *it6505, unsigned int reg,
static void it6505_debug_print(struct it6505 *it6505, unsigned int reg,
const char *prefix)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
int val;

if (!drm_debug_enabled(DRM_UT_DRIVER))
@@ -583,7 +583,7 @@ static int it6505_dpcd_read(struct it6505 *it6505, unsigned long offset)
{
u8 value;
int ret;
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;

ret = drm_dp_dpcd_readb(&it6505->aux, offset, &value);
if (ret < 0) {
@@ -597,7 +597,7 @@ static int it6505_dpcd_write(struct it6505 *it6505, unsigned long offset,
u8 datain)
{
int ret;
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;

ret = drm_dp_dpcd_writeb(&it6505->aux, offset, datain);
if (ret < 0) {
@@ -610,7 +610,7 @@ static int it6505_dpcd_write(struct it6505 *it6505, unsigned long offset,
static int it6505_get_dpcd(struct it6505 *it6505, int offset, u8 *dpcd, int num)
{
int ret;
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;

ret = drm_dp_dpcd_read(&it6505->aux, offset, dpcd, num);

@@ -627,7 +627,7 @@ static void it6505_dump(struct it6505 *it6505)
{
unsigned int i, j;
u8 regs[16];
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;

for (i = 0; i <= 0xff; i += 16) {
for (j = 0; j < 16; j++)
@@ -666,7 +666,7 @@ static int it6505_read_word(struct it6505 *it6505, unsigned int reg)

static void it6505_calc_video_info(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
int hsync_pol, vsync_pol, interlaced;
int htotal, hdes, hdew, hfph, hsyncw;
int vtotal, vdes, vdew, vfph, vsyncw;
@@ -910,7 +910,7 @@ static int it6505_aux_wait(struct it6505 *it6505)
{
int status;
unsigned long timeout;
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;

timeout = jiffies + msecs_to_jiffies(AUX_WAIT_TIMEOUT_MS) + 1;

@@ -1125,7 +1125,7 @@ static int it6505_get_edid_block(void *data, u8 *buf, unsigned int block,
size_t len)
{
struct it6505 *it6505 = data;
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
enum aux_cmd_reply reply;
int offset, ret, aux_retry = 100;

@@ -1185,7 +1185,7 @@ static int it6505_send_video_infoframe(struct it6505 *it6505,
{
u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE];
int err;
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;

err = hdmi_avi_infoframe_pack(frame, buffer, sizeof(buffer));
if (err < 0) {
@@ -1215,7 +1215,7 @@ static void it6505_get_extcon_property(struct it6505 *it6505)
{
int err;
union extcon_property_value property;
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;

if (it6505->extcon && !it6505->lane_swap_disabled) {
err = extcon_get_property(it6505->extcon, EXTCON_DISP_DP,
@@ -1368,7 +1368,7 @@ static void it6505_enable_audio_source(struct it6505 *it6505)

static void it6505_enable_audio_infoframe(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
u8 audio_info_ca[] = { 0x00, 0x00, 0x01, 0x03, 0x07, 0x0B, 0x0F, 0x1F };

DRM_DEV_DEBUG_DRIVER(dev, "infoframe channel_allocation:0x%02x",
@@ -1397,7 +1397,7 @@ static void it6505_disable_audio(struct it6505 *it6505)

static void it6505_enable_audio(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
int regbe;

DRM_DEV_DEBUG_DRIVER(dev, "start");
@@ -1432,7 +1432,7 @@ static bool it6505_use_step_train_check(struct it6505 *it6505)

static void it6505_parse_link_capabilities(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
struct it6505_drm_dp_link *link = &it6505->link;
int bcaps;

@@ -1545,7 +1545,7 @@ static void it6505_lane_count_setup(struct it6505 *it6505)

static void it6505_link_training_setup(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;

if (it6505->enable_enhanced_frame)
it6505_set_bits(it6505, REG_DATA_MUTE_CTRL,
@@ -1696,7 +1696,7 @@ it6505_step_cr_train(struct it6505 *it6505,
FORCE_CR_DONE);
return true;
}
- DRM_DEV_DEBUG_DRIVER(&it6505->client->dev, "cr not done");
+ DRM_DEV_DEBUG_DRIVER(it6505->dev, "cr not done");

if (it6505_check_max_voltage_swing_reached(lane_level_config,
it6505->lane_count))
@@ -1773,7 +1773,7 @@ it6505_step_eq_train(struct it6505 *it6505,
FORCE_EQ_DONE);
return true;
}
- DRM_DEV_DEBUG_DRIVER(&it6505->client->dev, "eq not done");
+ DRM_DEV_DEBUG_DRIVER(it6505->dev, "eq not done");

for (i = 0; i < it6505->lane_count; i++) {
lane_voltage_pre_emphasis->voltage_swing[i] =
@@ -1808,7 +1808,7 @@ static bool it6505_link_start_step_train(struct it6505 *it6505)
.pre_emphasis = { 0 },
};

- DRM_DEV_DEBUG_DRIVER(&it6505->client->dev, "start");
+ DRM_DEV_DEBUG_DRIVER(it6505->dev, "start");
err = it6505_drm_dp_link_configure(it6505);

if (err < 0)
@@ -1842,7 +1842,7 @@ static void it6505_reset_hdcp(struct it6505 *it6505)

static void it6505_start_hdcp(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;

DRM_DEV_DEBUG_DRIVER(dev, "start");
it6505_reset_hdcp(it6505);
@@ -1870,7 +1870,7 @@ static bool it6505_hdcp_is_ksv_valid(u8 *ksv)

static void it6505_hdcp_part1_auth(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
u8 hdcp_bcaps;

it6505_set_bits(it6505, REG_RESET_CTRL, HDCP_RESET, 0x00);
@@ -1911,7 +1911,7 @@ static int it6505_sha1_digest(struct it6505 *it6505, u8 *sha1_input,
struct shash_desc *desc;
struct crypto_shash *tfm;
int err;
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;

tfm = crypto_alloc_shash("sha1", 0, 0);
if (IS_ERR(tfm)) {
@@ -1936,7 +1936,7 @@ static int it6505_sha1_digest(struct it6505 *it6505, u8 *sha1_input,

static int it6505_setup_sha1_input(struct it6505 *it6505, u8 *sha1_input)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
u8 binfo[2];
int down_stream_count, i, err, msg_count = 0;

@@ -2000,7 +2000,7 @@ static int it6505_setup_sha1_input(struct it6505 *it6505, u8 *sha1_input)

static bool it6505_hdcp_part2_ksvlist_check(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
u8 av[5][4], bv[5][4];
int i, err;

@@ -2033,7 +2033,7 @@ static void it6505_hdcp_wait_ksv_list(struct work_struct *work)
{
struct it6505 *it6505 = container_of(work, struct it6505,
hdcp_wait_ksv_list);
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
unsigned int timeout = 5000;
u8 bstatus = 0;
bool ksv_list_check;
@@ -2075,7 +2075,7 @@ static void it6505_hdcp_work(struct work_struct *work)
{
struct it6505 *it6505 = container_of(work, struct it6505,
hdcp_work.work);
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
int ret;
u8 link_status[DP_LINK_STATUS_SIZE] = { 0 };

@@ -2116,7 +2116,7 @@ static void it6505_hdcp_work(struct work_struct *work)

static void it6505_show_hdcp_info(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
int i;
u8 *sha1 = it6505->sha1_input;

@@ -2150,7 +2150,7 @@ static void it6505_stop_link_train(struct it6505 *it6505)

static void it6505_link_train_ok(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;

it6505->link_state = LINK_OK;
/* disalbe mute enable avi info frame */
@@ -2169,7 +2169,7 @@ static void it6505_link_train_ok(struct it6505 *it6505)

static void it6505_link_step_train_process(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
int ret, i, step_retry = 3;

DRM_DEV_DEBUG_DRIVER(dev, "Start step train");
@@ -2207,7 +2207,7 @@ static void it6505_link_step_train_process(struct it6505 *it6505)
static void it6505_link_training_work(struct work_struct *work)
{
struct it6505 *it6505 = container_of(work, struct it6505, link_works);
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
int ret;

DRM_DEV_DEBUG_DRIVER(dev, "it6505->sink_count: %d",
@@ -2255,7 +2255,7 @@ static void it6505_remove_edid(struct it6505 *it6505)

static int it6505_process_hpd_irq(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
int ret, dpcd_sink_count, dp_irq_vector, bstatus;
u8 link_status[DP_LINK_STATUS_SIZE];

@@ -2319,7 +2319,7 @@ static int it6505_process_hpd_irq(struct it6505 *it6505)

static void it6505_irq_hpd(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
int dp_sink_count;

it6505->hpd_state = it6505_get_sink_hpd_status(it6505);
@@ -2381,7 +2381,7 @@ static void it6505_irq_hpd(struct it6505 *it6505)

static void it6505_irq_hpd_irq(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;

DRM_DEV_DEBUG_DRIVER(dev, "hpd_irq interrupt");

@@ -2391,7 +2391,7 @@ static void it6505_irq_hpd_irq(struct it6505 *it6505)

static void it6505_irq_scdt(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
bool data;

data = it6505_get_video_status(it6505);
@@ -2406,7 +2406,7 @@ static void it6505_irq_scdt(struct it6505 *it6505)

static void it6505_irq_hdcp_done(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;

DRM_DEV_DEBUG_DRIVER(dev, "hdcp done interrupt");
it6505->hdcp_status = HDCP_AUTH_DONE;
@@ -2415,7 +2415,7 @@ static void it6505_irq_hdcp_done(struct it6505 *it6505)

static void it6505_irq_hdcp_fail(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;

DRM_DEV_DEBUG_DRIVER(dev, "hdcp fail interrupt");
it6505->hdcp_status = HDCP_AUTH_IDLE;
@@ -2425,14 +2425,14 @@ static void it6505_irq_hdcp_fail(struct it6505 *it6505)

static void it6505_irq_aux_cmd_fail(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;

DRM_DEV_DEBUG_DRIVER(dev, "AUX PC Request Fail Interrupt");
}

static void it6505_irq_hdcp_ksv_check(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;

DRM_DEV_DEBUG_DRIVER(dev, "HDCP event Interrupt");
schedule_work(&it6505->hdcp_wait_ksv_list);
@@ -2440,7 +2440,7 @@ static void it6505_irq_hdcp_ksv_check(struct it6505 *it6505)

static void it6505_irq_audio_fifo_error(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;

DRM_DEV_DEBUG_DRIVER(dev, "audio fifo error Interrupt");

@@ -2450,7 +2450,7 @@ static void it6505_irq_audio_fifo_error(struct it6505 *it6505)

static void it6505_irq_link_train_fail(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;

DRM_DEV_DEBUG_DRIVER(dev, "link training fail interrupt");
schedule_work(&it6505->link_works);
@@ -2458,7 +2458,7 @@ static void it6505_irq_link_train_fail(struct it6505 *it6505)

static void it6505_irq_video_fifo_error(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;

DRM_DEV_DEBUG_DRIVER(dev, "video fifo overflow interrupt");
it6505->auto_train_retry = AUTO_TRAIN_RETRY;
@@ -2469,7 +2469,7 @@ static void it6505_irq_video_fifo_error(struct it6505 *it6505)

static void it6505_irq_io_latch_fifo_overflow(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;

DRM_DEV_DEBUG_DRIVER(dev, "IO latch fifo overflow interrupt");
it6505->auto_train_retry = AUTO_TRAIN_RETRY;
@@ -2486,7 +2486,7 @@ static bool it6505_test_bit(unsigned int bit, const unsigned int *addr)
static irqreturn_t it6505_int_threaded_handler(int unused, void *data)
{
struct it6505 *it6505 = data;
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
static const struct {
int bit;
void (*handler)(struct it6505 *it6505);
@@ -2538,7 +2538,7 @@ static irqreturn_t it6505_int_threaded_handler(int unused, void *data)

static int it6505_poweron(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
struct it6505_platform_data *pdata = &it6505->pdata;
int err;

@@ -2587,7 +2587,7 @@ static int it6505_poweron(struct it6505 *it6505)

static int it6505_poweroff(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
struct it6505_platform_data *pdata = &it6505->pdata;
int err;

@@ -2621,7 +2621,7 @@ static int it6505_poweroff(struct it6505 *it6505)

static enum drm_connector_status it6505_detect(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
enum drm_connector_status status = connector_status_disconnected;
int dp_sink_count;

@@ -2682,7 +2682,7 @@ static int it6505_extcon_notifier(struct notifier_block *self,
static void it6505_extcon_work(struct work_struct *work)
{
struct it6505 *it6505 = container_of(work, struct it6505, extcon_wq);
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
int state, ret;

if (it6505->enable_drv_hold)
@@ -2727,11 +2727,11 @@ static void it6505_extcon_work(struct work_struct *work)
static int it6505_use_notifier_module(struct it6505 *it6505)
{
int ret;
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;

it6505->event_nb.notifier_call = it6505_extcon_notifier;
INIT_WORK(&it6505->extcon_wq, it6505_extcon_work);
- ret = devm_extcon_register_notifier(&it6505->client->dev,
+ ret = devm_extcon_register_notifier(it6505->dev,
it6505->extcon, EXTCON_DISP_DP,
&it6505->event_nb);
if (ret) {
@@ -2747,7 +2747,7 @@ static int it6505_use_notifier_module(struct it6505 *it6505)
static void it6505_remove_notifier_module(struct it6505 *it6505)
{
if (it6505->extcon) {
- devm_extcon_unregister_notifier(&it6505->client->dev,
+ devm_extcon_unregister_notifier(it6505->dev,
it6505->extcon, EXTCON_DISP_DP,
&it6505->event_nb);

@@ -2760,7 +2760,7 @@ static void __maybe_unused it6505_delayed_audio(struct work_struct *work)
struct it6505 *it6505 = container_of(work, struct it6505,
delayed_audio.work);

- DRM_DEV_DEBUG_DRIVER(&it6505->client->dev, "start");
+ DRM_DEV_DEBUG_DRIVER(it6505->dev, "start");

if (!it6505->powered)
return;
@@ -2773,7 +2773,7 @@ static int __maybe_unused it6505_audio_setup_hw_params(struct it6505 *it6505,
struct hdmi_codec_params
*params)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
int i = 0;

DRM_DEV_DEBUG_DRIVER(dev, "%s %d Hz, %d bit, %d channels\n", __func__,
@@ -2857,7 +2857,7 @@ static int it6505_bridge_attach(struct drm_bridge *bridge,
enum drm_bridge_attach_flags flags)
{
struct it6505 *it6505 = bridge_to_it6505(bridge);
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
int ret;

if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) {
@@ -2921,7 +2921,7 @@ static void it6505_bridge_atomic_enable(struct drm_bridge *bridge,
struct drm_bridge_state *old_state)
{
struct it6505 *it6505 = bridge_to_it6505(bridge);
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
struct drm_atomic_state *state = old_state->base.state;
struct hdmi_avi_infoframe frame;
struct drm_crtc_state *crtc_state;
@@ -2977,7 +2977,7 @@ static void it6505_bridge_atomic_disable(struct drm_bridge *bridge,
struct drm_bridge_state *old_state)
{
struct it6505 *it6505 = bridge_to_it6505(bridge);
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;

DRM_DEV_DEBUG_DRIVER(dev, "start");

@@ -2992,7 +2992,7 @@ static void it6505_bridge_atomic_pre_enable(struct drm_bridge *bridge,
struct drm_bridge_state *old_state)
{
struct it6505 *it6505 = bridge_to_it6505(bridge);
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;

DRM_DEV_DEBUG_DRIVER(dev, "start");

@@ -3003,7 +3003,7 @@ static void it6505_bridge_atomic_post_disable(struct drm_bridge *bridge,
struct drm_bridge_state *old_state)
{
struct it6505 *it6505 = bridge_to_it6505(bridge);
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;

DRM_DEV_DEBUG_DRIVER(dev, "start");

@@ -3022,7 +3022,7 @@ static struct edid *it6505_bridge_get_edid(struct drm_bridge *bridge,
struct drm_connector *connector)
{
struct it6505 *it6505 = bridge_to_it6505(bridge);
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;

if (!it6505->cached_edid) {
it6505->cached_edid = drm_do_get_edid(connector, it6505_get_edid_block,
@@ -3074,7 +3074,7 @@ static const struct dev_pm_ops it6505_bridge_pm_ops = {
static int it6505_init_pdata(struct it6505 *it6505)
{
struct it6505_platform_data *pdata = &it6505->pdata;
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;

/* 1.0V digital core power regulator */
pdata->pwr18 = devm_regulator_get(dev, "pwr18");
@@ -3116,7 +3116,7 @@ static int it6505_get_data_lanes_count(const struct device_node *endpoint,

static void it6505_parse_dt(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
struct device_node *np = dev->of_node, *ep = NULL;
int len;
u64 link_frequencies;
@@ -3320,7 +3320,7 @@ static void debugfs_create_files(struct it6505 *it6505)

static void debugfs_init(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;

it6505->debugfs = debugfs_create_dir(DEBUGFS_DIR_NAME, NULL);

@@ -3362,7 +3362,7 @@ static int it6505_i2c_probe(struct i2c_client *client)

it6505->bridge.of_node = client->dev.of_node;
it6505->connector_status = connector_status_disconnected;
- it6505->client = client;
+ it6505->dev = &client->dev;
i2c_set_clientdata(client, it6505);

/* get extcon device from DTS */
--
2.40.0.rc0.216.gc4246ad0f0-goog


2023-03-03 14:35:36

by Pin-yen Lin

[permalink] [raw]
Subject: [PATCH v13 07/10] drm/bridge: anx7625: Register Type C mode switches

Register USB Type-C mode switches when the "mode-switch" property and
relevant ports are available in Device Tree. Configure the crosspoint
switch based on the entered alternate mode for a specific Type-C
connector.

Crosspoint switch can also be used for switching the output signal for
different orientations of a single USB Type-C connector, but the
orientation switch is not implemented yet. A TODO is added for this.

Signed-off-by: Pin-yen Lin <[email protected]>

---

(no changes since v12)

Changes in v12:
- Fixed style issues in anx7625 driver
- Fixed the inverted orientation setting in anx7625 driver
- Changed "&ctx->client->dev" to "ctx->dev"
- Fix style issues
- Updated the error logs when parsing data-lanes property

Changes in v11:
- Added back "data-lanes" parsing logics
- Removed Kconfig dependency
- Updated the usage of the private data
- Dropped Tested-by tag because of the new changes

Changes in v10:
- Added a TODO for implementing orientation switch for anx7625
- Updated the commit message for the absence of orientation switch
- Fixed typo in the commit message
- Collected Tested-by tag

Changes in v7:
- Fixed style issues in anx7625 driver
- Removed DT property validation in anx7625 driver.
- Extracted common codes to another commit.

Changes in v6:
- Squashed to a single patch

drivers/gpu/drm/bridge/analogix/anx7625.c | 149 ++++++++++++++++++++++
drivers/gpu/drm/bridge/analogix/anx7625.h | 20 +++
2 files changed, 169 insertions(+)

diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
index 76d46db3f8dc..4361a1b52a67 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.c
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
@@ -15,6 +15,8 @@
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/types.h>
+#include <linux/usb/typec_dp.h>
+#include <linux/usb/typec_mux.h>
#include <linux/workqueue.h>

#include <linux/of_gpio.h>
@@ -2570,6 +2572,146 @@ static void anx7625_runtime_disable(void *data)
pm_runtime_disable(data);
}

+static void anx7625_set_crosspoint_switch(struct anx7625_data *ctx,
+ enum typec_orientation orientation)
+{
+ if (orientation == TYPEC_ORIENTATION_NORMAL) {
+ anx7625_reg_write(ctx, ctx->i2c.tcpc_client, TCPC_SWITCH_0,
+ SW_SEL1_SSRX_RX1 | SW_SEL1_DPTX0_RX2);
+ anx7625_reg_write(ctx, ctx->i2c.tcpc_client, TCPC_SWITCH_1,
+ SW_SEL2_SSTX_TX1 | SW_SEL2_DPTX1_TX2);
+ } else if (orientation == TYPEC_ORIENTATION_REVERSE) {
+ anx7625_reg_write(ctx, ctx->i2c.tcpc_client, TCPC_SWITCH_0,
+ SW_SEL1_SSRX_RX2 | SW_SEL1_DPTX0_RX1);
+ anx7625_reg_write(ctx, ctx->i2c.tcpc_client, TCPC_SWITCH_1,
+ SW_SEL2_SSTX_TX2 | SW_SEL2_DPTX1_TX1);
+ }
+}
+
+static void anx7625_typec_two_ports_update(struct anx7625_data *ctx)
+{
+ unsigned int i;
+
+ /* Check if both ports available and do nothing to retain the current one */
+ if (ctx->port_data[0].dp_connected && ctx->port_data[1].dp_connected)
+ return;
+
+ for (i = 0; i < 2; i++) {
+ if (ctx->port_data[i].dp_connected)
+ anx7625_set_crosspoint_switch(ctx,
+ ctx->port_data[i].orientation);
+ }
+}
+
+static int anx7625_typec_mux_set(struct typec_mux_dev *mux,
+ struct typec_mux_state *state)
+{
+ struct drm_dp_typec_port_data *port = typec_mux_get_drvdata(mux);
+ struct anx7625_data *ctx = port->data;
+ struct device *dev = ctx->dev;
+ struct drm_dp_typec_switch_desc switch_desc = ctx->switch_desc;
+ bool new_dp_connected, old_dp_connected;
+
+ if (switch_desc.num_typec_switches == 1)
+ return 0;
+
+ wait_for_completion(&ctx->mux_register);
+
+ old_dp_connected = ctx->port_data[0].dp_connected ||
+ ctx->port_data[1].dp_connected;
+
+ ctx->port_data[port->port_num].dp_connected =
+ state->alt &&
+ state->alt->svid == USB_TYPEC_DP_SID &&
+ state->alt->mode == USB_TYPEC_DP_MODE;
+
+ dev_dbg(dev, "mux_set dp_connected: c0=%d, c1=%d\n",
+ ctx->port_data[0].dp_connected, ctx->port_data[1].dp_connected);
+
+ new_dp_connected = ctx->port_data[0].dp_connected ||
+ ctx->port_data[1].dp_connected;
+
+ /* DP on, power on first */
+ if (!old_dp_connected && new_dp_connected)
+ pm_runtime_get_sync(dev);
+
+ anx7625_typec_two_ports_update(ctx);
+
+ /* DP off, power off last */
+ if (old_dp_connected && !new_dp_connected)
+ pm_runtime_put_sync(dev);
+
+ return 0;
+}
+
+static void anx7625_unregister_typec_switches(struct anx7625_data *ctx)
+{
+ drm_dp_unregister_typec_switches(&ctx->switch_desc);
+}
+
+static int anx7625_register_typec_switches(struct device *dev, struct anx7625_data *ctx)
+{
+ struct device_node *port_node = of_graph_get_port_by_id(dev->of_node, 1);
+ struct drm_dp_typec_switch_desc *switch_desc = &ctx->switch_desc;
+ int ret;
+ u32 dp_lanes[4];
+ unsigned int i, num_lanes;
+
+ /*
+ * Currently, only mode switch is implemented.
+ * TODO: Implement Type-C orientation switch for anx7625.
+ */
+ ret = drm_dp_register_typec_switches(dev, &port_node->fwnode,
+ &ctx->switch_desc, ctx,
+ anx7625_typec_mux_set);
+ if (ret)
+ return ret;
+
+ ctx->port_data = devm_kcalloc(
+ dev, switch_desc->num_typec_switches,
+ sizeof(struct anx7625_typec_port_data), GFP_KERNEL);
+
+ if (!ctx->port_data) {
+ ret = -ENOMEM;
+ goto unregister_mux;
+ }
+
+ for (i = 0; i < switch_desc->num_typec_switches; i++) {
+ struct drm_dp_typec_port_data *port = &switch_desc->typec_ports[i];
+ struct fwnode_handle *fwnode = port->fwnode;
+
+ ret = fwnode_property_count_u32(fwnode, "data-lanes");
+ if (ret < 0) {
+ dev_err(dev,
+ "Error on getting data lanes count from %pfwP: %d\n",
+ fwnode, ret);
+ goto unregister_mux;
+ }
+ num_lanes = ret;
+
+ ret = fwnode_property_read_u32_array(fwnode, "data-lanes",
+ dp_lanes, num_lanes);
+ if (ret) {
+ dev_err(dev,
+ "Failed to read the data-lanes variable: %d\n",
+ ret);
+ goto unregister_mux;
+ }
+
+ ctx->port_data[i].orientation = (dp_lanes[0] / 2 == 0) ?
+ TYPEC_ORIENTATION_REVERSE : TYPEC_ORIENTATION_NORMAL;
+ ctx->port_data[i].dp_connected = false;
+ }
+ complete_all(&ctx->mux_register);
+
+ return 0;
+
+unregister_mux:
+ complete_all(&ctx->mux_register);
+ anx7625_unregister_typec_switches(ctx);
+ return ret;
+}
+
static int anx7625_i2c_probe(struct i2c_client *client)
{
struct anx7625_data *platform;
@@ -2607,6 +2749,7 @@ static int anx7625_i2c_probe(struct i2c_client *client)

mutex_init(&platform->lock);
mutex_init(&platform->hdcp_wq_lock);
+ init_completion(&platform->mux_register);

INIT_DELAYED_WORK(&platform->hdcp_work, hdcp_check_work_func);
platform->hdcp_workqueue = create_workqueue("hdcp workqueue");
@@ -2677,6 +2820,10 @@ static int anx7625_i2c_probe(struct i2c_client *client)
if (platform->pdata.intp_irq)
queue_work(platform->workqueue, &platform->work);

+ ret = anx7625_register_typec_switches(dev, platform);
+ if (ret && ret != -ENODEV)
+ dev_warn(dev, "Didn't register Type-C switches, err: %d\n", ret);
+
platform->bridge.funcs = &anx7625_bridge_funcs;
platform->bridge.of_node = client->dev.of_node;
if (!anx7625_of_panel_on_aux_bus(&client->dev))
@@ -2728,6 +2875,8 @@ static void anx7625_i2c_remove(struct i2c_client *client)

drm_bridge_remove(&platform->bridge);

+ anx7625_unregister_typec_switches(platform);
+
if (platform->pdata.intp_irq)
destroy_workqueue(platform->workqueue);

diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h
index 5af819611ebc..5a200da34800 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.h
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
@@ -55,6 +55,18 @@
#define HPD_STATUS_CHANGE 0x80
#define HPD_STATUS 0x80

+#define TCPC_SWITCH_0 0xB4
+#define SW_SEL1_DPTX0_RX2 BIT(0)
+#define SW_SEL1_DPTX0_RX1 BIT(1)
+#define SW_SEL1_SSRX_RX2 BIT(4)
+#define SW_SEL1_SSRX_RX1 BIT(5)
+
+#define TCPC_SWITCH_1 0xB5
+#define SW_SEL2_DPTX1_TX2 BIT(0)
+#define SW_SEL2_DPTX1_TX1 BIT(1)
+#define SW_SEL2_SSTX_TX2 BIT(4)
+#define SW_SEL2_SSTX_TX1 BIT(5)
+
/******** END of I2C Address 0x58 ********/

/***************************************************************/
@@ -449,6 +461,11 @@ struct anx7625_i2c_client {
struct i2c_client *tcpc_client;
};

+struct anx7625_typec_port_data {
+ bool dp_connected;
+ enum typec_orientation orientation;
+};
+
struct anx7625_data {
struct anx7625_platform_data pdata;
struct platform_device *audio_pdev;
@@ -479,6 +496,9 @@ struct anx7625_data {
struct drm_connector *connector;
struct mipi_dsi_device *dsi;
struct drm_dp_aux aux;
+ struct completion mux_register;
+ struct drm_dp_typec_switch_desc switch_desc;
+ struct anx7625_typec_port_data *port_data;
};

#endif /* __ANX7625_H__ */
--
2.40.0.rc0.216.gc4246ad0f0-goog


2023-03-03 14:35:53

by Pin-yen Lin

[permalink] [raw]
Subject: [PATCH v13 08/10] dt-bindings: display: bridge: it6505: Add mode-switch support

ITE IT6505 can be used in systems to switch the DP traffic between
two downstreams, which can be USB Type-C DisplayPort alternate mode
lane or regular DisplayPort output ports.

Update the binding to accommodate this usage by introducing a
data-lanes and a mode-switch property on endpoints.

Signed-off-by: Pin-yen Lin <[email protected]>

---

(no changes since v12)

Changes in v12:
- Fixed the schema of "data-lanes" property for it6505
- Reworded the description of the mode-switch property

Changes in v11:
- Updated the description of the endpoints in the bindings
- Referenced video-interfaces.yaml instead for the endpoints binding
- Removed duplicated definitions from inherited schema

Changes in v9:
- Fixed subject prefix again
- Changed the naming of the example node for it6505

Changes in v8:
- Updated bindings for data-lanes property
- Fixed subject prefix

Changes in v7:
- Fixed issues reported by dt_binding_check.
- Updated the schema and the example dts for data-lanes.
- Changed to generic naming for the example dts node.

Changes in v6:
- Remove switches node and use endpoints and data-lanes property to
describe the connections.

.../bindings/display/bridge/ite,it6505.yaml | 101 +++++++++++++++---
1 file changed, 88 insertions(+), 13 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/bridge/ite,it6505.yaml b/Documentation/devicetree/bindings/display/bridge/ite,it6505.yaml
index c9a882ee6d98..348b02f26041 100644
--- a/Documentation/devicetree/bindings/display/bridge/ite,it6505.yaml
+++ b/Documentation/devicetree/bindings/display/bridge/ite,it6505.yaml
@@ -75,22 +75,49 @@ properties:
port@1:
$ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false
- description: Video port for DP output
+ description:
+ Video port for DP output. Each endpoint connects to a video output
+ downstream, and the "data-lanes" property is used to describe the pin
+ connections. 0, 1, 2, 3 in "data-lanes" maps to TX0, TX1, TX2, TX3,
+ respectively.

- properties:
- endpoint:
- $ref: /schemas/graph.yaml#/$defs/endpoint-base
+
+ patternProperties:
+ "^endpoint@[01]$":
+ $ref: /schemas/media/video-interfaces.yaml#
unevaluatedProperties: false

properties:
+ reg: true
+
+ remote-endpoint: true
+
data-lanes:
- minItems: 1
- uniqueItems: true
- items:
- - enum: [ 0, 1 ]
- - const: 1
- - const: 2
- - const: 3
+ oneOf:
+ - items:
+ - enum: [0, 3]
+
+ - items:
+ - const: 0
+ - const: 1
+
+ - items:
+ - const: 3
+ - const: 2
+
+ - items:
+ - const: 0
+ - const: 1
+ - const: 2
+ - const: 3
+
+ mode-switch:
+ type: boolean
+ description: Serves as Type-C mode switch if present.
+
+ required:
+ - reg
+ - remote-endpoint

required:
- port@0
@@ -102,7 +129,6 @@ required:
- pwr18-supply
- interrupts
- reset-gpios
- - extcon
- ports

additionalProperties: false
@@ -139,8 +165,11 @@ examples:
};

port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
reg = <1>;
- it6505_out: endpoint {
+ it6505_out: endpoint@0 {
+ reg = <0>;
remote-endpoint = <&dp_in>;
data-lanes = <0 1>;
};
@@ -148,3 +177,49 @@ examples:
};
};
};
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ dp-bridge@5c {
+ compatible = "ite,it6505";
+ interrupts = <8 IRQ_TYPE_LEVEL_LOW 8 0>;
+ reg = <0x5c>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&it6505_pins>;
+ ovdd-supply = <&mt6366_vsim2_reg>;
+ pwr18-supply = <&pp1800_dpbrdg_dx>;
+ reset-gpios = <&pio 177 0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ it6505_dpi_in: endpoint {
+ remote-endpoint = <&dpi_out>;
+ };
+ };
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ ite_typec0: endpoint@0 {
+ reg = <0>;
+ mode-switch;
+ data-lanes = <0 1>;
+ remote-endpoint = <&typec_port0>;
+ };
+ ite_typec1: endpoint@1 {
+ reg = <1>;
+ mode-switch;
+ data-lanes = <3 2>;
+ remote-endpoint = <&typec_port1>;
+ };
+ };
+ };
+ };
+ };
--
2.40.0.rc0.216.gc4246ad0f0-goog


2023-03-03 14:35:57

by Pin-yen Lin

[permalink] [raw]
Subject: [PATCH v13 09/10] drm/bridge: it6505: Fix Kconfig indentation

Replace the spaces with tab characters in the Kconfig file.

Signed-off-by: Pin-yen Lin <[email protected]>
Reviewed-by: AngeloGioacchino Del Regno <[email protected]>

---

(no changes since v10)

Changes in v10:
- Collected Reviewed-by tag

Changes in v7:
- New in v7

drivers/gpu/drm/bridge/Kconfig | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 12e8f30c65f7..28dc7711bf5f 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -74,19 +74,19 @@ config DRM_FSL_LDB
Support for i.MX8MP DPI-to-LVDS on-SoC encoder.

config DRM_ITE_IT6505
- tristate "ITE IT6505 DisplayPort bridge"
- depends on OF
+ tristate "ITE IT6505 DisplayPort bridge"
+ depends on OF
select DRM_DISPLAY_DP_HELPER
select DRM_DISPLAY_HDCP_HELPER
select DRM_DISPLAY_HELPER
- select DRM_DP_AUX_BUS
- select DRM_KMS_HELPER
- select DRM_DP_HELPER
- select EXTCON
- select CRYPTO
- select CRYPTO_HASH
- help
- ITE IT6505 DisplayPort bridge chip driver.
+ select DRM_DP_AUX_BUS
+ select DRM_KMS_HELPER
+ select DRM_DP_HELPER
+ select EXTCON
+ select CRYPTO
+ select CRYPTO_HASH
+ help
+ ITE IT6505 DisplayPort bridge chip driver.

config DRM_LONTIUM_LT8912B
tristate "Lontium LT8912B DSI/HDMI bridge"
--
2.40.0.rc0.216.gc4246ad0f0-goog


2023-03-03 14:36:01

by Pin-yen Lin

[permalink] [raw]
Subject: [PATCH v13 10/10] drm/bridge: it6505: Register Type C mode switches

Register USB Type-C mode switches when the "mode-switch" property and
relevant port are available in Device Tree. Configure the "lane_swap"
state based on the entered alternate mode for a specific Type-C
connector, which ends up updating the lane swap registers of the it6505
chip.

Signed-off-by: Pin-yen Lin <[email protected]>

---

Changes in v13:
- Fix style issues

Changes in v12:
- Fixes style issues in it6505 driver
- Replaced &it6505->client->dev with it6505->dev
- Updated the error logs when parsing data-lanes property

Changes in v11:
- Added back "data-lanes" parsing logics
- Removed Kconfig dependency
- Updated the usage of the private data

Changes in v7:
- Fixed style issues in it6505 driver
- Removed the redundant sleep in it6505 driver
- Removed DT property validation in it6505 driver
- Rebased to drm-misc-next
- Extracted common codes to another commit

Changes in v6:
- Changed it6505_typec_mux_set callback function to accommodate with
the latest drm-misc patches
- Changed the driver implementation to accommodate with the new binding
- Squashed to a single patch

drivers/gpu/drm/bridge/ite-it6505.c | 185 +++++++++++++++++++++++++++-
1 file changed, 181 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c
index d4bc388b68ac..988fe28619ab 100644
--- a/drivers/gpu/drm/bridge/ite-it6505.c
+++ b/drivers/gpu/drm/bridge/ite-it6505.c
@@ -17,6 +17,8 @@
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/types.h>
+#include <linux/usb/typec_dp.h>
+#include <linux/usb/typec_mux.h>
#include <linux/wait.h>

#include <crypto/hash.h>
@@ -27,6 +29,7 @@
#include <drm/drm_bridge.h>
#include <drm/drm_crtc.h>
#include <drm/drm_edid.h>
+#include <drm/drm_of.h>
#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>

@@ -401,6 +404,11 @@ struct debugfs_entries {
const struct file_operations *fops;
};

+struct it6505_typec_port_data {
+ bool dp_connected;
+ bool lane_swap;
+};
+
struct it6505 {
struct drm_dp_aux aux;
struct drm_bridge bridge;
@@ -454,6 +462,9 @@ struct it6505 {
struct delayed_work delayed_audio;
struct it6505_audio_data audio;
struct dentry *debugfs;
+ struct completion mux_register;
+ struct drm_dp_typec_switch_desc switch_desc;
+ struct it6505_typec_port_data *port_data;

/* it6505 driver hold option */
bool enable_drv_hold;
@@ -3345,12 +3356,163 @@ static void it6505_shutdown(struct i2c_client *client)
it6505_lane_off(it6505);
}

+static void it6505_typec_ports_update(struct it6505 *it6505)
+{
+ unsigned int i;
+
+ /* Check if both ports available and do nothing to retain the current one */
+ if (it6505->port_data[0].dp_connected && it6505->port_data[1].dp_connected)
+ return;
+
+ for (i = 0; i < 2; i++) {
+ if (it6505->port_data[i].dp_connected)
+ it6505->lane_swap = it6505->port_data[i].lane_swap;
+ }
+}
+
+static int it6505_typec_mux_set(struct typec_mux_dev *mux,
+ struct typec_mux_state *state)
+{
+ struct drm_dp_typec_port_data *port = typec_mux_get_drvdata(mux);
+ struct it6505 *it6505 = port->data;
+ struct device *dev = it6505->dev;
+ struct drm_dp_typec_switch_desc switch_desc = it6505->switch_desc;
+ bool old_dp_connected, new_dp_connected;
+
+ if (switch_desc.num_typec_switches == 1)
+ return 0;
+
+ mutex_lock(&it6505->extcon_lock);
+ wait_for_completion(&it6505->mux_register);
+
+ old_dp_connected = it6505->port_data[0].dp_connected ||
+ it6505->port_data[1].dp_connected;
+
+ it6505->port_data[port->port_num].dp_connected =
+ state->alt &&
+ state->alt->svid == USB_TYPEC_DP_SID &&
+ state->alt->mode == USB_TYPEC_DP_MODE;
+
+ dev_dbg(dev, "mux_set dp_connected: c0=%d, c1=%d\n",
+ it6505->port_data[0].dp_connected, it6505->port_data[1].dp_connected);
+
+ new_dp_connected = it6505->port_data[0].dp_connected ||
+ it6505->port_data[1].dp_connected;
+
+ if (it6505->enable_drv_hold) {
+ dev_dbg(dev, "enable driver hold\n");
+ goto unlock;
+ }
+
+ it6505_typec_ports_update(it6505);
+
+ if (!old_dp_connected && new_dp_connected) {
+ int ret = pm_runtime_get_sync(dev);
+
+ /*
+ * pm_runtime_force_suspend() disables runtime PM when the
+ * system enters suspend state. But on system resume, mux_set
+ * can be triggered before pm_runtime_force_resume() re-enables
+ * runtime PM. This makes the bridge stay powered off if the
+ * downstream display is connected when the system is suspended.
+ * Handling the error here to make sure the bridge is powered
+ * on, and leave the PM runtime usage count incremented so
+ * the future runtime PM calls is balanced.
+ */
+ if (ret < 0)
+ it6505_poweron(it6505);
+
+ complete_all(&it6505->extcon_completion);
+ }
+
+ if (old_dp_connected && !new_dp_connected) {
+ reinit_completion(&it6505->extcon_completion);
+ pm_runtime_put_sync(dev);
+ if (it6505->bridge.dev)
+ drm_helper_hpd_irq_event(it6505->bridge.dev);
+ memset(it6505->dpcd, 0, sizeof(it6505->dpcd));
+ }
+
+unlock:
+ mutex_unlock(&it6505->extcon_lock);
+ return 0;
+}
+
+static void it6505_unregister_typec_switches(struct it6505 *it6505)
+{
+ drm_dp_unregister_typec_switches(&it6505->switch_desc);
+}
+
+static int it6505_register_typec_switches(struct device *dev, struct it6505 *it6505)
+{
+ struct device_node *port_node = of_graph_get_port_by_id(dev->of_node, 1);
+ struct drm_dp_typec_switch_desc *switch_desc = &it6505->switch_desc;
+ int ret;
+ u32 dp_lanes[4];
+ unsigned int i, num_lanes;
+
+ ret = drm_dp_register_typec_switches(dev, &port_node->fwnode,
+ &it6505->switch_desc, it6505,
+ it6505_typec_mux_set);
+ if (ret)
+ return ret;
+
+ it6505->port_data = devm_kcalloc(dev, switch_desc->num_typec_switches,
+ sizeof(struct it6505_typec_port_data),
+ GFP_KERNEL);
+
+ if (!it6505->port_data) {
+ ret = -ENOMEM;
+ goto unregister_mux;
+ }
+
+ for (i = 0; i < switch_desc->num_typec_switches; i++) {
+ struct drm_dp_typec_port_data *port = &switch_desc->typec_ports[i];
+ struct fwnode_handle *fwnode = port->fwnode;
+
+ ret = fwnode_property_count_u32(fwnode, "data-lanes");
+ if (ret < 0) {
+ dev_err(dev,
+ "Error on getting data lanes count from %pfwP: %d\n",
+ fwnode, ret);
+ goto unregister_mux;
+ }
+ if (ret > 2) {
+ dev_err(dev,
+ "Invalid data lanes count for mode switches from %pfwP: %d\n",
+ fwnode, ret);
+ ret = -EINVAL;
+ goto unregister_mux;
+ }
+ num_lanes = ret;
+
+ ret = fwnode_property_read_u32_array(fwnode, "data-lanes",
+ dp_lanes, num_lanes);
+ if (ret) {
+ dev_err(dev,
+ "Failed to read the data-lanes variable: %d\n",
+ ret);
+ goto unregister_mux;
+ }
+
+ it6505->port_data[i].lane_swap = (dp_lanes[0] / 2 == 1);
+ }
+ complete_all(&it6505->mux_register);
+
+ return 0;
+
+unregister_mux:
+ complete_all(&it6505->mux_register);
+ it6505_unregister_typec_switches(it6505);
+ return ret;
+}
+
static int it6505_i2c_probe(struct i2c_client *client)
{
struct it6505 *it6505;
struct device *dev = &client->dev;
struct extcon_dev *extcon;
- int err, intp_irq;
+ int err, intp_irq, ret;

it6505 = devm_kzalloc(&client->dev, sizeof(*it6505), GFP_KERNEL);
if (!it6505)
@@ -3370,11 +3532,25 @@ static int it6505_i2c_probe(struct i2c_client *client)
if (PTR_ERR(extcon) == -EPROBE_DEFER)
return -EPROBE_DEFER;
if (IS_ERR(extcon)) {
- dev_err(dev, "can not get extcon device!");
- return PTR_ERR(extcon);
+ if (PTR_ERR(extcon) != -ENODEV)
+ dev_warn(dev, "Cannot get extcon device: %ld\n",
+ PTR_ERR(extcon));
+ it6505->extcon = NULL;
+ } else {
+ it6505->extcon = extcon;
}

- it6505->extcon = extcon;
+ init_completion(&it6505->mux_register);
+ ret = it6505_register_typec_switches(dev, it6505);
+ if (ret) {
+ if (ret != -ENODEV)
+ dev_warn(dev, "Didn't register Type-C switches, err: %d\n",
+ ret);
+ if (!it6505->extcon) {
+ dev_err(dev, "Both extcon and typec-switch are not registered.\n");
+ return -EINVAL;
+ }
+ }

it6505->regmap = devm_regmap_init_i2c(client, &it6505_regmap_config);
if (IS_ERR(it6505->regmap)) {
@@ -3446,6 +3622,7 @@ static void it6505_i2c_remove(struct i2c_client *client)
it6505_debugfs_remove(it6505);
it6505_poweroff(it6505);
it6505_remove_edid(it6505);
+ it6505_unregister_typec_switches(it6505);
}

static const struct i2c_device_id it6505_id[] = {
--
2.40.0.rc0.216.gc4246ad0f0-goog


2023-03-06 11:44:08

by Andy Shevchenko

[permalink] [raw]
Subject: Re: [PATCH v13 01/10] device property: Add remote endpoint to devcon matcher

On Fri, Mar 03, 2023 at 10:33:41PM +0800, Pin-yen Lin wrote:
> From: Prashant Malani <[email protected]>
>
> When searching the device graph for device matches, check the
> remote-endpoint itself for a match.
>
> Some drivers register devices for individual endpoints. This allows
> the matcher code to evaluate those for a match too, instead
> of only looking at the remote parent devices. This is required when a
> device supports two mode switches in its endpoints, so we can't simply
> register the mode switch with the parent node.

OK!
Reviewed-by: Andy Shevchenko <[email protected]>

> Signed-off-by: Prashant Malani <[email protected]>
> Signed-off-by: Pin-yen Lin <[email protected]>
>
> ---
>
> Changes in v13:
> - Update the kernel doc of fwnode_connection_find_match
>
> Changes in v12:
> - Check the availability of the device node in fwnode_graph_devcon_matches
> - Ensured valid access to "matches" in fwnode_graph_devcon_matches
> - Updated the documentation in fwnode_connection_find_match(es)
> - Dropped collected tags due to the new changes
>
> Changes in v11:
> - Added missing fwnode_handle_put in drivers/base/property.c
>
> Changes in v10:
> - Collected Reviewed-by and Tested-by tags
>
> Changes in v6:
> - New in v6
>
> drivers/base/property.c | 31 ++++++++++++++++++++++++++-----
> 1 file changed, 26 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/base/property.c b/drivers/base/property.c
> index 083a95791d3b..4426ac2b16ca 100644
> --- a/drivers/base/property.c
> +++ b/drivers/base/property.c
> @@ -1243,6 +1243,23 @@ static unsigned int fwnode_graph_devcon_matches(const struct fwnode_handle *fwno
> continue;
> }
>
> + ret = match(node, con_id, data);
> + fwnode_handle_put(node);
> + if (ret) {
> + if (matches)
> + matches[count] = ret;
> + count++;
> +
> + if (matches && count >= matches_len)
> + break;
> + }
> +
> + /*
> + * Some drivers may register devices for endpoints. Check
> + * the remote-endpoints for matches in addition to the remote
> + * port parent.
> + */
> + node = fwnode_graph_get_remote_endpoint(ep);
> ret = match(node, con_id, data);
> fwnode_handle_put(node);
> if (ret) {
> @@ -1293,8 +1310,11 @@ static unsigned int fwnode_devcon_matches(const struct fwnode_handle *fwnode,
> * @match: Function to check and convert the connection description
> *
> * Find a connection with unique identifier @con_id between @fwnode and another
> - * device node. @match will be used to convert the connection description to
> - * data the caller is expecting to be returned.
> + * device node. For fwnode graph connections, the graph endpoints are also
> + * checked. @match will be used to convert the connection description to data
> + * the caller is expecting to be returned.
> + *
> + * Return: The pointer to the matched node, or NULL on error.
> */
> void *fwnode_connection_find_match(const struct fwnode_handle *fwnode,
> const char *con_id, void *data,
> @@ -1325,9 +1345,10 @@ EXPORT_SYMBOL_GPL(fwnode_connection_find_match);
> * @matches_len: Length of @matches
> *
> * Find up to @matches_len connections with unique identifier @con_id between
> - * @fwnode and other device nodes. @match will be used to convert the
> - * connection description to data the caller is expecting to be returned
> - * through the @matches array.
> + * @fwnode and other device nodes. For fwnode graph connections, the graph
> + * endpoints are also checked. @match will be used to convert the connection
> + * description to data the caller is expecting to be returned through the
> + * @matches array.
> * If @matches is NULL @matches_len is ignored and the total number of resolved
> * matches is returned.
> *
> --
> 2.40.0.rc0.216.gc4246ad0f0-goog
>

--
With Best Regards,
Andy Shevchenko



2023-03-06 11:49:58

by Andy Shevchenko

[permalink] [raw]
Subject: Re: [PATCH v13 03/10] drm/display: Add Type-C switch helpers

On Fri, Mar 03, 2023 at 10:33:43PM +0800, Pin-yen Lin wrote:
> Add helpers to register and unregister Type-C "switches" for bridges
> capable of switching their output between two downstream devices.
>
> The helper registers USB Type-C mode switches when the "mode-switch"
> and the "reg" properties are available in Device Tree.

...

> + port_data->typec_mux = typec_mux_register(dev, &mux_desc);
> + if (IS_ERR(port_data->typec_mux)) {
> + ret = PTR_ERR(port_data->typec_mux);
> + dev_err(dev, "Mode switch register for port %d failed: %d\n",
> + port_num, ret);

> + return ret;
> + }
> +
> + return 0;

Can be simply

port_data->typec_mux = typec_mux_register(dev, &mux_desc);
ret = PTR_ERR_OR_ZERO(port_data->typec_mux);
if (ret)
dev_err(dev, "Mode switch register for port %d failed: %d\n",
port_num, ret);

return ret;

...

> + switch_desc->typec_ports = devm_kcalloc(dev, switch_desc->num_typec_switches,
> + sizeof(struct drm_dp_typec_port_data),
> + GFP_KERNEL);
> + if (!switch_desc->typec_ports)
> + return -ENOMEM;

How often this function _can_ be called during the runtime?
If it's _possible_ to call it infinite times, consider *not* using devm.

--
With Best Regards,
Andy Shevchenko



2023-03-06 11:52:05

by Andy Shevchenko

[permalink] [raw]
Subject: Re: [PATCH v13 05/10] drm/bridge: anx7625: Check for Type-C during panel registration

On Fri, Mar 03, 2023 at 10:33:45PM +0800, Pin-yen Lin wrote:
> The output port endpoints can be connected to USB-C connectors.
> Running drm_of_find_panel_or_bridge() with such endpoints leads to
> a continuous return value of -EPROBE_DEFER, even though there is
> no panel present.
>
> To avoid this, check for the existence of a "mode-switch" property in
> the port endpoint, and skip panel registration completely if so.

...

> + port_node = of_graph_get_port_by_id(np, 1);
> + count = typec_mode_switch_node_count(&port_node->fwnode);

Do you need to drop reference count here?
(I don't know myself, so, please check this)

If no, patch LGTM.

> + if (count)
> + return 0;

--
With Best Regards,
Andy Shevchenko



2023-03-06 11:55:08

by Sakari Ailus

[permalink] [raw]
Subject: Re: [PATCH v13 01/10] device property: Add remote endpoint to devcon matcher

Hi Pin-yen,

Thanks for the update.

On Fri, Mar 03, 2023 at 10:33:41PM +0800, Pin-yen Lin wrote:
> From: Prashant Malani <[email protected]>
>
> When searching the device graph for device matches, check the
> remote-endpoint itself for a match.
>
> Some drivers register devices for individual endpoints. This allows
> the matcher code to evaluate those for a match too, instead
> of only looking at the remote parent devices. This is required when a
> device supports two mode switches in its endpoints, so we can't simply
> register the mode switch with the parent node.
>
> Signed-off-by: Prashant Malani <[email protected]>
> Signed-off-by: Pin-yen Lin <[email protected]>

Reviewed-by: Sakari Ailus <[email protected]>

--
Sakari Ailus

2023-03-06 11:55:43

by Andy Shevchenko

[permalink] [raw]
Subject: Re: [PATCH v13 07/10] drm/bridge: anx7625: Register Type C mode switches

On Fri, Mar 03, 2023 at 10:33:47PM +0800, Pin-yen Lin wrote:
> Register USB Type-C mode switches when the "mode-switch" property and
> relevant ports are available in Device Tree. Configure the crosspoint
> switch based on the entered alternate mode for a specific Type-C
> connector.
>
> Crosspoint switch can also be used for switching the output signal for
> different orientations of a single USB Type-C connector, but the
> orientation switch is not implemented yet. A TODO is added for this.

...

> + ctx->port_data = devm_kcalloc(
> + dev, switch_desc->num_typec_switches,
> + sizeof(struct anx7625_typec_port_data), GFP_KERNEL);

I believe I have commented on this (indentation)...

> +

...and this (blank line).

> + if (!ctx->port_data) {
> + ret = -ENOMEM;
> + goto unregister_mux;
> + }

...

> + ctx->port_data[i].orientation = (dp_lanes[0] / 2 == 0) ?
> + TYPEC_ORIENTATION_REVERSE : TYPEC_ORIENTATION_NORMAL;

I believe that this is an error prone check, you should rather do the opposite,
i.e. ' % 2 == 0'.

--
With Best Regards,
Andy Shevchenko



2023-03-06 12:03:14

by Andy Shevchenko

[permalink] [raw]
Subject: Re: [PATCH v13 10/10] drm/bridge: it6505: Register Type C mode switches

On Fri, Mar 03, 2023 at 10:33:50PM +0800, Pin-yen Lin wrote:
> Register USB Type-C mode switches when the "mode-switch" property and
> relevant port are available in Device Tree. Configure the "lane_swap"
> state based on the entered alternate mode for a specific Type-C
> connector, which ends up updating the lane swap registers of the it6505
> chip.

...

> + it6505->port_data = devm_kcalloc(dev, switch_desc->num_typec_switches,
> + sizeof(struct it6505_typec_port_data),
> + GFP_KERNEL);

> +

Same, no need for a blank line here.

> + if (!it6505->port_data) {
> + ret = -ENOMEM;
> + goto unregister_mux;
> + }

...

> + it6505->port_data[i].lane_swap = (dp_lanes[0] / 2 == 1);

' % 2 == 0' ?

...

Wouldn't be better to have

ret = PTR_ERR_OR_ZERO(extcon);

here and amend the following accordingly?

> if (PTR_ERR(extcon) == -EPROBE_DEFER)
> return -EPROBE_DEFER;
> if (IS_ERR(extcon)) {
> - dev_err(dev, "can not get extcon device!");
> - return PTR_ERR(extcon);
> + if (PTR_ERR(extcon) != -ENODEV)
> + dev_warn(dev, "Cannot get extcon device: %ld\n",
> + PTR_ERR(extcon));
> + it6505->extcon = NULL;
> + } else {
> + it6505->extcon = extcon;
> }
>
> - it6505->extcon = extcon;
> + init_completion(&it6505->mux_register);
> + ret = it6505_register_typec_switches(dev, it6505);
> + if (ret) {
> + if (ret != -ENODEV)
> + dev_warn(dev, "Didn't register Type-C switches, err: %d\n",
> + ret);
> + if (!it6505->extcon) {
> + dev_err(dev, "Both extcon and typec-switch are not registered.\n");
> + return -EINVAL;
> + }
> + }


Perhaps

if (ret != -ENODEV)
dev_warn(dev, "Didn't register Type-C switches, err: %d\n", ret);

if (ret && !it6505->extcon) {
dev_err(dev, "Both extcon and typec-switch are not registered.\n");
return ret;
}

?

--
With Best Regards,
Andy Shevchenko



2023-03-08 07:30:42

by Heikki Krogerus

[permalink] [raw]
Subject: Re: [PATCH v13 01/10] device property: Add remote endpoint to devcon matcher

On Fri, Mar 03, 2023 at 10:33:41PM +0800, Pin-yen Lin wrote:
> From: Prashant Malani <[email protected]>
>
> When searching the device graph for device matches, check the
> remote-endpoint itself for a match.
>
> Some drivers register devices for individual endpoints. This allows
> the matcher code to evaluate those for a match too, instead
> of only looking at the remote parent devices. This is required when a
> device supports two mode switches in its endpoints, so we can't simply
> register the mode switch with the parent node.
>
> Signed-off-by: Prashant Malani <[email protected]>
> Signed-off-by: Pin-yen Lin <[email protected]>

Reviewed-by: Heikki Krogerus <[email protected]>

> ---
>
> Changes in v13:
> - Update the kernel doc of fwnode_connection_find_match
>
> Changes in v12:
> - Check the availability of the device node in fwnode_graph_devcon_matches
> - Ensured valid access to "matches" in fwnode_graph_devcon_matches
> - Updated the documentation in fwnode_connection_find_match(es)
> - Dropped collected tags due to the new changes
>
> Changes in v11:
> - Added missing fwnode_handle_put in drivers/base/property.c
>
> Changes in v10:
> - Collected Reviewed-by and Tested-by tags
>
> Changes in v6:
> - New in v6
>
> drivers/base/property.c | 31 ++++++++++++++++++++++++++-----
> 1 file changed, 26 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/base/property.c b/drivers/base/property.c
> index 083a95791d3b..4426ac2b16ca 100644
> --- a/drivers/base/property.c
> +++ b/drivers/base/property.c
> @@ -1243,6 +1243,23 @@ static unsigned int fwnode_graph_devcon_matches(const struct fwnode_handle *fwno
> continue;
> }
>
> + ret = match(node, con_id, data);
> + fwnode_handle_put(node);
> + if (ret) {
> + if (matches)
> + matches[count] = ret;
> + count++;
> +
> + if (matches && count >= matches_len)
> + break;
> + }
> +
> + /*
> + * Some drivers may register devices for endpoints. Check
> + * the remote-endpoints for matches in addition to the remote
> + * port parent.
> + */
> + node = fwnode_graph_get_remote_endpoint(ep);
> ret = match(node, con_id, data);
> fwnode_handle_put(node);
> if (ret) {
> @@ -1293,8 +1310,11 @@ static unsigned int fwnode_devcon_matches(const struct fwnode_handle *fwnode,
> * @match: Function to check and convert the connection description
> *
> * Find a connection with unique identifier @con_id between @fwnode and another
> - * device node. @match will be used to convert the connection description to
> - * data the caller is expecting to be returned.
> + * device node. For fwnode graph connections, the graph endpoints are also
> + * checked. @match will be used to convert the connection description to data
> + * the caller is expecting to be returned.
> + *
> + * Return: The pointer to the matched node, or NULL on error.
> */
> void *fwnode_connection_find_match(const struct fwnode_handle *fwnode,
> const char *con_id, void *data,
> @@ -1325,9 +1345,10 @@ EXPORT_SYMBOL_GPL(fwnode_connection_find_match);
> * @matches_len: Length of @matches
> *
> * Find up to @matches_len connections with unique identifier @con_id between
> - * @fwnode and other device nodes. @match will be used to convert the
> - * connection description to data the caller is expecting to be returned
> - * through the @matches array.
> + * @fwnode and other device nodes. For fwnode graph connections, the graph
> + * endpoints are also checked. @match will be used to convert the connection
> + * description to data the caller is expecting to be returned through the
> + * @matches array.
> * If @matches is NULL @matches_len is ignored and the total number of resolved
> * matches is returned.
> *
> --
> 2.40.0.rc0.216.gc4246ad0f0-goog

--
heikki

2023-03-08 10:20:51

by Pin-yen Lin

[permalink] [raw]
Subject: Re: [PATCH v13 03/10] drm/display: Add Type-C switch helpers

Hi Andy,

Thanks for the review.

On Mon, Mar 6, 2023 at 7:49 PM Andy Shevchenko
<[email protected]> wrote:
>
> On Fri, Mar 03, 2023 at 10:33:43PM +0800, Pin-yen Lin wrote:
> > Add helpers to register and unregister Type-C "switches" for bridges
> > capable of switching their output between two downstream devices.
> >
> > The helper registers USB Type-C mode switches when the "mode-switch"
> > and the "reg" properties are available in Device Tree.
>
> ...
>
> > + port_data->typec_mux = typec_mux_register(dev, &mux_desc);
> > + if (IS_ERR(port_data->typec_mux)) {
> > + ret = PTR_ERR(port_data->typec_mux);
> > + dev_err(dev, "Mode switch register for port %d failed: %d\n",
> > + port_num, ret);
>
> > + return ret;
> > + }
> > +
> > + return 0;
>
> Can be simply
>
> port_data->typec_mux = typec_mux_register(dev, &mux_desc);
> ret = PTR_ERR_OR_ZERO(port_data->typec_mux);
> if (ret)
> dev_err(dev, "Mode switch register for port %d failed: %d\n",
> port_num, ret);
>
> return ret;
>
This was suggested by Angelo in [1], but you are not the first
reviewer that finds this weird... I'll update this in the next
version.

[1]: https://lore.kernel.org/all/[email protected]/

> ...
>
> > + switch_desc->typec_ports = devm_kcalloc(dev, switch_desc->num_typec_switches,
> > + sizeof(struct drm_dp_typec_port_data),
> > + GFP_KERNEL);
> > + if (!switch_desc->typec_ports)
> > + return -ENOMEM;
>
> How often this function _can_ be called during the runtime?
> If it's _possible_ to call it infinite times, consider *not* using devm.

I would expect this function to be only called during driver probing,
and this is the case for the current users in this series. So I think
this is only called once if EPROBDE_DEFER doesn't count.
>
> --
> With Best Regards,
> Andy Shevchenko
>
>
Best regards,
Pin-yen

2023-03-08 10:25:25

by Pin-yen Lin

[permalink] [raw]
Subject: Re: [PATCH v13 05/10] drm/bridge: anx7625: Check for Type-C during panel registration

HI Andy,

On Mon, Mar 6, 2023 at 7:52 PM Andy Shevchenko
<[email protected]> wrote:
>
> On Fri, Mar 03, 2023 at 10:33:45PM +0800, Pin-yen Lin wrote:
> > The output port endpoints can be connected to USB-C connectors.
> > Running drm_of_find_panel_or_bridge() with such endpoints leads to
> > a continuous return value of -EPROBE_DEFER, even though there is
> > no panel present.
> >
> > To avoid this, check for the existence of a "mode-switch" property in
> > the port endpoint, and skip panel registration completely if so.
>
> ...
>
> > + port_node = of_graph_get_port_by_id(np, 1);
> > + count = typec_mode_switch_node_count(&port_node->fwnode);
>
> Do you need to drop reference count here?
> (I don't know myself, so, please check this)
>
> If no, patch LGTM.

The helper completes the for-loop of fwnode_for_each_child_node, which
drops the reference count whenever the next node is get. So we don't
need drop the reference count here.
>
> > + if (count)
> > + return 0;
>
> --
> With Best Regards,
> Andy Shevchenko
>
>
Best regards,
Pin-yen

2023-03-08 13:46:12

by Pin-yen Lin

[permalink] [raw]
Subject: Re: [PATCH v13 07/10] drm/bridge: anx7625: Register Type C mode switches

Hi Andy,

Thanks for the review.

On Mon, Mar 6, 2023 at 7:55 PM Andy Shevchenko
<[email protected]> wrote:
>
> On Fri, Mar 03, 2023 at 10:33:47PM +0800, Pin-yen Lin wrote:
> > Register USB Type-C mode switches when the "mode-switch" property and
> > relevant ports are available in Device Tree. Configure the crosspoint
> > switch based on the entered alternate mode for a specific Type-C
> > connector.
> >
> > Crosspoint switch can also be used for switching the output signal for
> > different orientations of a single USB Type-C connector, but the
> > orientation switch is not implemented yet. A TODO is added for this.
>
> ...
>
> > + ctx->port_data = devm_kcalloc(
> > + dev, switch_desc->num_typec_switches,
> > + sizeof(struct anx7625_typec_port_data), GFP_KERNEL);
>
> I believe I have commented on this (indentation)...
>
> > +
>
> ...and this (blank line).

Sorry for missing this one. I'll fix this in v14.
>
> > + if (!ctx->port_data) {
> > + ret = -ENOMEM;
> > + goto unregister_mux;
> > + }
>
> ...
>
> > + ctx->port_data[i].orientation = (dp_lanes[0] / 2 == 0) ?
> > + TYPEC_ORIENTATION_REVERSE : TYPEC_ORIENTATION_NORMAL;
>
> I believe that this is an error prone check, you should rather do the opposite,
> i.e. ' % 2 == 0'.
>
The orientation should be TYPEC_ORIENTATION_REVERSE when the
data-lanes value is 0/1, so ` / 2` is what I meant here.

Though, after second thought, I think it would be clearer if I use
`dp_lanes[0] < 2`. I'll update this in v14 as well.
> --
> With Best Regards,
> Andy Shevchenko
>
>
Best regards,
Pin-yen

2023-03-08 13:51:55

by Pin-yen Lin

[permalink] [raw]
Subject: Re: [PATCH v13 10/10] drm/bridge: it6505: Register Type C mode switches

Hi Andy,

Thanks for the review.

On Mon, Mar 6, 2023 at 8:03 PM Andy Shevchenko
<[email protected]> wrote:
>
> On Fri, Mar 03, 2023 at 10:33:50PM +0800, Pin-yen Lin wrote:
> > Register USB Type-C mode switches when the "mode-switch" property and
> > relevant port are available in Device Tree. Configure the "lane_swap"
> > state based on the entered alternate mode for a specific Type-C
> > connector, which ends up updating the lane swap registers of the it6505
> > chip.
>
> ...
>
> > + it6505->port_data = devm_kcalloc(dev, switch_desc->num_typec_switches,
> > + sizeof(struct it6505_typec_port_data),
> > + GFP_KERNEL);
>
> > +
>
> Same, no need for a blank line here.
>
I'll fix this in the next version.
> > + if (!it6505->port_data) {
> > + ret = -ENOMEM;
> > + goto unregister_mux;
> > + }
>
> ...
>
> > + it6505->port_data[i].lane_swap = (dp_lanes[0] / 2 == 1);
>
> ' % 2 == 0' ?
>
Per another patch, I'll update this into `< 2`
> ...
>
> Wouldn't be better to have
>
> ret = PTR_ERR_OR_ZERO(extcon);
>
> here and amend the following accordingly?
>
> > if (PTR_ERR(extcon) == -EPROBE_DEFER)
> > return -EPROBE_DEFER;
> > if (IS_ERR(extcon)) {
> > - dev_err(dev, "can not get extcon device!");
> > - return PTR_ERR(extcon);
> > + if (PTR_ERR(extcon) != -ENODEV)
> > + dev_warn(dev, "Cannot get extcon device: %ld\n",
> > + PTR_ERR(extcon));
> > + it6505->extcon = NULL;
> > + } else {
> > + it6505->extcon = extcon;
> > }
> >
> > - it6505->extcon = extcon;
> > + init_completion(&it6505->mux_register);
> > + ret = it6505_register_typec_switches(dev, it6505);
> > + if (ret) {
> > + if (ret != -ENODEV)
> > + dev_warn(dev, "Didn't register Type-C switches, err: %d\n",
> > + ret);
> > + if (!it6505->extcon) {
> > + dev_err(dev, "Both extcon and typec-switch are not registered.\n");
> > + return -EINVAL;
> > + }
> > + }
>
>
> Perhaps
>
> if (ret != -ENODEV)
> dev_warn(dev, "Didn't register Type-C switches, err: %d\n", ret);
>
> if (ret && !it6505->extcon) {
> dev_err(dev, "Both extcon and typec-switch are not registered.\n");
> return ret;
> }
>
> ?


Thanks for the suggestion! I'll update this in v14.
>
> --
> With Best Regards,
> Andy Shevchenko
>
>
Best regards,
Pin-yen

2023-03-08 15:29:41

by Andy Shevchenko

[permalink] [raw]
Subject: Re: [PATCH v13 03/10] drm/display: Add Type-C switch helpers

On Wed, Mar 08, 2023 at 06:20:14PM +0800, Pin-yen Lin wrote:
> On Mon, Mar 6, 2023 at 7:49 PM Andy Shevchenko
> > On Fri, Mar 03, 2023 at 10:33:43PM +0800, Pin-yen Lin wrote:

...

> > > + switch_desc->typec_ports = devm_kcalloc(dev, switch_desc->num_typec_switches,
> > > + sizeof(struct drm_dp_typec_port_data),
> > > + GFP_KERNEL);
> > > + if (!switch_desc->typec_ports)
> > > + return -ENOMEM;
> >
> > How often this function _can_ be called during the runtime?
> > If it's _possible_ to call it infinite times, consider *not* using devm.
>
> I would expect this function to be only called during driver probing,
> and this is the case for the current users in this series. So I think
> this is only called once if EPROBDE_DEFER doesn't count.

No, deferred probe is not counted.

Can you add a word somewhere in the comment(?) to make this clear?

--
With Best Regards,
Andy Shevchenko



2023-03-08 15:31:43

by Andy Shevchenko

[permalink] [raw]
Subject: Re: [PATCH v13 10/10] drm/bridge: it6505: Register Type C mode switches

On Wed, Mar 08, 2023 at 09:51:19PM +0800, Pin-yen Lin wrote:
> On Mon, Mar 6, 2023 at 8:03 PM Andy Shevchenko
> <[email protected]> wrote:
> > On Fri, Mar 03, 2023 at 10:33:50PM +0800, Pin-yen Lin wrote:

...

> > > + it6505->port_data[i].lane_swap = (dp_lanes[0] / 2 == 1);
> >
> > ' % 2 == 0' ?
> >
> Per another patch, I'll update this into `< 2`

But here it should be >= 2 then, no?

--
With Best Regards,
Andy Shevchenko



2023-03-09 10:21:54

by Pin-yen Lin

[permalink] [raw]
Subject: Re: [PATCH v13 03/10] drm/display: Add Type-C switch helpers

Hi Andy,

On Wed, Mar 8, 2023 at 11:29 PM Andy Shevchenko
<[email protected]> wrote:
>
> On Wed, Mar 08, 2023 at 06:20:14PM +0800, Pin-yen Lin wrote:
> > On Mon, Mar 6, 2023 at 7:49 PM Andy Shevchenko
> > > On Fri, Mar 03, 2023 at 10:33:43PM +0800, Pin-yen Lin wrote:
>
> ...
>
> > > > + switch_desc->typec_ports = devm_kcalloc(dev, switch_desc->num_typec_switches,
> > > > + sizeof(struct drm_dp_typec_port_data),
> > > > + GFP_KERNEL);
> > > > + if (!switch_desc->typec_ports)
> > > > + return -ENOMEM;
> > >
> > > How often this function _can_ be called during the runtime?
> > > If it's _possible_ to call it infinite times, consider *not* using devm.
> >
> > I would expect this function to be only called during driver probing,
> > and this is the case for the current users in this series. So I think
> > this is only called once if EPROBDE_DEFER doesn't count.
>
> No, deferred probe is not counted.
>
> Can you add a word somewhere in the comment(?) to make this clear?

Sure. I'll add some note in the comments about this.
>
> --
> With Best Regards,
> Andy Shevchenko
>
>
Thanks and regards,
Pin-yen

2023-03-09 10:22:18

by Pin-yen Lin

[permalink] [raw]
Subject: Re: [PATCH v13 10/10] drm/bridge: it6505: Register Type C mode switches

Hi Andy,

On Wed, Mar 8, 2023 at 11:31 PM Andy Shevchenko
<[email protected]> wrote:
>
> On Wed, Mar 08, 2023 at 09:51:19PM +0800, Pin-yen Lin wrote:
> > On Mon, Mar 6, 2023 at 8:03 PM Andy Shevchenko
> > <[email protected]> wrote:
> > > On Fri, Mar 03, 2023 at 10:33:50PM +0800, Pin-yen Lin wrote:
>
> ...
>
> > > > + it6505->port_data[i].lane_swap = (dp_lanes[0] / 2 == 1);
> > >
> > > ' % 2 == 0' ?
> > >
> > Per another patch, I'll update this into `< 2`
>
> But here it should be >= 2 then, no?
>
Yes it should be >= 2 here. I wasn't really using my brain when I
replied to the mail....
> --
> With Best Regards,
> Andy Shevchenko
>
>
Best regards,
Pin-yen