From: Greg Kroah-Hartman Date: Fri, 21 Oct 2022 08:31:36 +0000 (+0200) Subject: drop unneeded ps8640 patches X-Git-Tag: v6.0.3~3 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3d753fbf4c5434ef53f07d34a8b59eccb76cea7c;p=thirdparty%2Fkernel%2Fstable-queue.git drop unneeded ps8640 patches The one bugfix still applied cleanly. stable-dep-bot went a bit wild... --- diff --git a/queue-5.10/drm-bridge-parade-ps8640-add-support-for-aux-channel.patch b/queue-5.10/drm-bridge-parade-ps8640-add-support-for-aux-channel.patch deleted file mode 100644 index 41812b47bce..00000000000 --- a/queue-5.10/drm-bridge-parade-ps8640-add-support-for-aux-channel.patch +++ /dev/null @@ -1,270 +0,0 @@ -From 029d0d60ff3e472d06508b3d763218ed517f9a93 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Tue, 21 Sep 2021 11:06:17 -0700 -Subject: drm/bridge: parade-ps8640: Add support for AUX channel - -From: Philip Chen - -[ Upstream commit 13afcdd7277eff9ab5c92dc0d8d21335d132ab2f ] - -Implement the first version of AUX support, which will be useful as -we expand the driver to support varied use cases. - -Signed-off-by: Philip Chen -Reviewed-by: Sam Ravnborg -Reviewed-by: Douglas Anderson -Reviewed-by: Stephen Boyd -[dianders: whitespace fixes reported by dim apply-branch] -Signed-off-by: Douglas Anderson -Link: https://patchwork.freedesktop.org/patch/msgid/20210921110556.v6.2.I1d6ea362dc76efa77cca2b46253d31b7651eaf17@changeid -Stable-dep-of: fc94224c2e0a ("drm/bridge: parade-ps8640: Fix regulator supply order") -Signed-off-by: Sasha Levin ---- - drivers/gpu/drm/bridge/parade-ps8640.c | 180 ++++++++++++++++++++++++- - 1 file changed, 179 insertions(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c -index 88c9f3404ac1..43afa848a36a 100644 ---- a/drivers/gpu/drm/bridge/parade-ps8640.c -+++ b/drivers/gpu/drm/bridge/parade-ps8640.c -@@ -13,11 +13,36 @@ - #include - - #include -+#include - #include - #include - #include - #include - -+#define PAGE0_AUXCH_CFG3 0x76 -+#define AUXCH_CFG3_RESET 0xff -+#define PAGE0_SWAUX_ADDR_7_0 0x7d -+#define PAGE0_SWAUX_ADDR_15_8 0x7e -+#define PAGE0_SWAUX_ADDR_23_16 0x7f -+#define SWAUX_ADDR_MASK GENMASK(19, 0) -+#define PAGE0_SWAUX_LENGTH 0x80 -+#define SWAUX_LENGTH_MASK GENMASK(3, 0) -+#define SWAUX_NO_PAYLOAD BIT(7) -+#define PAGE0_SWAUX_WDATA 0x81 -+#define PAGE0_SWAUX_RDATA 0x82 -+#define PAGE0_SWAUX_CTRL 0x83 -+#define SWAUX_SEND BIT(0) -+#define PAGE0_SWAUX_STATUS 0x84 -+#define SWAUX_M_MASK GENMASK(4, 0) -+#define SWAUX_STATUS_MASK GENMASK(7, 5) -+#define SWAUX_STATUS_NACK (0x1 << 5) -+#define SWAUX_STATUS_DEFER (0x2 << 5) -+#define SWAUX_STATUS_ACKM (0x3 << 5) -+#define SWAUX_STATUS_INVALID (0x4 << 5) -+#define SWAUX_STATUS_I2C_NACK (0x5 << 5) -+#define SWAUX_STATUS_I2C_DEFER (0x6 << 5) -+#define SWAUX_STATUS_TIMEOUT (0x7 << 5) -+ - #define PAGE2_GPIO_H 0xa7 - #define PS_GPIO9 BIT(1) - #define PAGE2_I2C_BYPASS 0xea -@@ -66,6 +91,7 @@ enum ps8640_vdo_control { - struct ps8640 { - struct drm_bridge bridge; - struct drm_bridge *panel_bridge; -+ struct drm_dp_aux aux; - struct mipi_dsi_device *dsi; - struct i2c_client *page[MAX_DEVS]; - struct regmap *regmap[MAX_DEVS]; -@@ -115,6 +141,137 @@ static inline struct ps8640 *bridge_to_ps8640(struct drm_bridge *e) - return container_of(e, struct ps8640, bridge); - } - -+static inline struct ps8640 *aux_to_ps8640(struct drm_dp_aux *aux) -+{ -+ return container_of(aux, struct ps8640, aux); -+} -+ -+static ssize_t ps8640_aux_transfer(struct drm_dp_aux *aux, -+ struct drm_dp_aux_msg *msg) -+{ -+ struct ps8640 *ps_bridge = aux_to_ps8640(aux); -+ struct regmap *map = ps_bridge->regmap[PAGE0_DP_CNTL]; -+ struct device *dev = &ps_bridge->page[PAGE0_DP_CNTL]->dev; -+ unsigned int len = msg->size; -+ unsigned int data; -+ unsigned int base; -+ int ret; -+ u8 request = msg->request & -+ ~(DP_AUX_I2C_MOT | DP_AUX_I2C_WRITE_STATUS_UPDATE); -+ u8 *buf = msg->buffer; -+ u8 addr_len[PAGE0_SWAUX_LENGTH + 1 - PAGE0_SWAUX_ADDR_7_0]; -+ u8 i; -+ bool is_native_aux = false; -+ -+ if (len > DP_AUX_MAX_PAYLOAD_BYTES) -+ return -EINVAL; -+ -+ if (msg->address & ~SWAUX_ADDR_MASK) -+ return -EINVAL; -+ -+ switch (request) { -+ case DP_AUX_NATIVE_WRITE: -+ case DP_AUX_NATIVE_READ: -+ is_native_aux = true; -+ fallthrough; -+ case DP_AUX_I2C_WRITE: -+ case DP_AUX_I2C_READ: -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ ret = regmap_write(map, PAGE0_AUXCH_CFG3, AUXCH_CFG3_RESET); -+ if (ret) { -+ DRM_DEV_ERROR(dev, "failed to write PAGE0_AUXCH_CFG3: %d\n", -+ ret); -+ return ret; -+ } -+ -+ /* Assume it's good */ -+ msg->reply = 0; -+ -+ base = PAGE0_SWAUX_ADDR_7_0; -+ addr_len[PAGE0_SWAUX_ADDR_7_0 - base] = msg->address; -+ addr_len[PAGE0_SWAUX_ADDR_15_8 - base] = msg->address >> 8; -+ addr_len[PAGE0_SWAUX_ADDR_23_16 - base] = (msg->address >> 16) | -+ (msg->request << 4); -+ addr_len[PAGE0_SWAUX_LENGTH - base] = (len == 0) ? SWAUX_NO_PAYLOAD : -+ ((len - 1) & SWAUX_LENGTH_MASK); -+ -+ regmap_bulk_write(map, PAGE0_SWAUX_ADDR_7_0, addr_len, -+ ARRAY_SIZE(addr_len)); -+ -+ if (len && (request == DP_AUX_NATIVE_WRITE || -+ request == DP_AUX_I2C_WRITE)) { -+ /* Write to the internal FIFO buffer */ -+ for (i = 0; i < len; i++) { -+ ret = regmap_write(map, PAGE0_SWAUX_WDATA, buf[i]); -+ if (ret) { -+ DRM_DEV_ERROR(dev, -+ "failed to write WDATA: %d\n", -+ ret); -+ return ret; -+ } -+ } -+ } -+ -+ regmap_write(map, PAGE0_SWAUX_CTRL, SWAUX_SEND); -+ -+ /* Zero delay loop because i2c transactions are slow already */ -+ regmap_read_poll_timeout(map, PAGE0_SWAUX_CTRL, data, -+ !(data & SWAUX_SEND), 0, 50 * 1000); -+ -+ regmap_read(map, PAGE0_SWAUX_STATUS, &data); -+ if (ret) { -+ DRM_DEV_ERROR(dev, "failed to read PAGE0_SWAUX_STATUS: %d\n", -+ ret); -+ return ret; -+ } -+ -+ switch (data & SWAUX_STATUS_MASK) { -+ /* Ignore the DEFER cases as they are already handled in hardware */ -+ case SWAUX_STATUS_NACK: -+ case SWAUX_STATUS_I2C_NACK: -+ /* -+ * The programming guide is not clear about whether a I2C NACK -+ * would trigger SWAUX_STATUS_NACK or SWAUX_STATUS_I2C_NACK. So -+ * we handle both cases together. -+ */ -+ if (is_native_aux) -+ msg->reply |= DP_AUX_NATIVE_REPLY_NACK; -+ else -+ msg->reply |= DP_AUX_I2C_REPLY_NACK; -+ -+ fallthrough; -+ case SWAUX_STATUS_ACKM: -+ len = data & SWAUX_M_MASK; -+ break; -+ case SWAUX_STATUS_INVALID: -+ return -EOPNOTSUPP; -+ case SWAUX_STATUS_TIMEOUT: -+ return -ETIMEDOUT; -+ } -+ -+ if (len && (request == DP_AUX_NATIVE_READ || -+ request == DP_AUX_I2C_READ)) { -+ /* Read from the internal FIFO buffer */ -+ for (i = 0; i < len; i++) { -+ ret = regmap_read(map, PAGE0_SWAUX_RDATA, &data); -+ if (ret) { -+ DRM_DEV_ERROR(dev, -+ "failed to read RDATA: %d\n", -+ ret); -+ return ret; -+ } -+ -+ buf[i] = data; -+ } -+ } -+ -+ return len; -+} -+ - static int ps8640_bridge_vdo_control(struct ps8640 *ps_bridge, - const enum ps8640_vdo_control ctrl) - { -@@ -284,18 +441,33 @@ static int ps8640_bridge_attach(struct drm_bridge *bridge, - dsi->format = MIPI_DSI_FMT_RGB888; - dsi->lanes = DP_NUM_LANES; - ret = mipi_dsi_attach(dsi); -- if (ret) -+ if (ret) { -+ dev_err(dev, "failed to attach dsi device: %d\n", ret); - goto err_dsi_attach; -+ } -+ -+ ret = drm_dp_aux_register(&ps_bridge->aux); -+ if (ret) { -+ dev_err(dev, "failed to register DP AUX channel: %d\n", ret); -+ goto err_aux_register; -+ } - - /* Attach the panel-bridge to the dsi bridge */ - return drm_bridge_attach(bridge->encoder, ps_bridge->panel_bridge, - &ps_bridge->bridge, flags); - -+err_aux_register: -+ mipi_dsi_detach(dsi); - err_dsi_attach: - mipi_dsi_device_unregister(dsi); - return ret; - } - -+static void ps8640_bridge_detach(struct drm_bridge *bridge) -+{ -+ drm_dp_aux_unregister(&bridge_to_ps8640(bridge)->aux); -+} -+ - static struct edid *ps8640_bridge_get_edid(struct drm_bridge *bridge, - struct drm_connector *connector) - { -@@ -332,6 +504,7 @@ static struct edid *ps8640_bridge_get_edid(struct drm_bridge *bridge, - - static const struct drm_bridge_funcs ps8640_bridge_funcs = { - .attach = ps8640_bridge_attach, -+ .detach = ps8640_bridge_detach, - .get_edid = ps8640_bridge_get_edid, - .post_disable = ps8640_post_disable, - .pre_enable = ps8640_pre_enable, -@@ -407,6 +580,11 @@ static int ps8640_probe(struct i2c_client *client) - - i2c_set_clientdata(client, ps_bridge); - -+ ps_bridge->aux.name = "parade-ps8640-aux"; -+ ps_bridge->aux.dev = dev; -+ ps_bridge->aux.transfer = ps8640_aux_transfer; -+ drm_dp_aux_init(&ps_bridge->aux); -+ - drm_bridge_add(&ps_bridge->bridge); - - return 0; --- -2.35.1 - diff --git a/queue-5.10/drm-bridge-parade-ps8640-enable-runtime-power-manage.patch b/queue-5.10/drm-bridge-parade-ps8640-enable-runtime-power-manage.patch deleted file mode 100644 index 2985065bbf2..00000000000 --- a/queue-5.10/drm-bridge-parade-ps8640-enable-runtime-power-manage.patch +++ /dev/null @@ -1,350 +0,0 @@ -From 6748190b8ca2e4190e17651940875380113e8cad Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Thu, 28 Oct 2021 10:58:10 -0700 -Subject: drm/bridge: parade-ps8640: Enable runtime power management - -From: Philip Chen - -[ Upstream commit 826cff3f7ebba460d3db61f135798ce76b0d26ed ] - -Fit ps8640 driver into runtime power management framework: - -First, break _poweron() to 3 parts: (1) turn on power and wait for -ps8640's internal MCU to finish init (2) check panel HPD (which is -proxied by GPIO9) (3) the other configs. As runtime_resume() can be -called before panel is powered, we only add (1) to _resume() and leave -(2)(3) to _pre_enable(). We also add (2) to _aux_transfer() as we want -to ensure panel HPD is asserted before we start AUX CH transactions. - -Second, the original driver has a mysterious delay of 50 ms between (2) -and (3). Since Parade's support can't explain what the delay is for, -and we don't see removing the delay break any boards at hand, remove -the delay to fit into this driver change. - -In addition, rename "powered" to "pre_enabled" and don't check for it -in the pm_runtime calls. The pm_runtime calls are already refcounted -so there's no reason to check there. The other user of "powered", -_get_edid(), only cares if pre_enable() has already been called. - -Lastly, change some existing DRM_...() logging to dev_...() along the -way, since DRM_...() seem to be deprecated in [1]. - -[1] https://patchwork.freedesktop.org/patch/454760/ - -Signed-off-by: Philip Chen -Reviewed-by: Douglas Anderson -Reviewed-by: Stephen Boyd -[dianders: fixed whitespace warning reported by dim tool] -Signed-off-by: Douglas Anderson -Link: https://patchwork.freedesktop.org/patch/msgid/20211028105754.v5.1.I828f5db745535fb7e36e8ffdd62d546f6d08b6d1@changeid -Stable-dep-of: fc94224c2e0a ("drm/bridge: parade-ps8640: Fix regulator supply order") -Signed-off-by: Sasha Levin ---- - drivers/gpu/drm/bridge/parade-ps8640.c | 190 ++++++++++++++++--------- - 1 file changed, 119 insertions(+), 71 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c -index 43afa848a36a..52f2ea6fcb26 100644 ---- a/drivers/gpu/drm/bridge/parade-ps8640.c -+++ b/drivers/gpu/drm/bridge/parade-ps8640.c -@@ -9,6 +9,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -98,7 +99,7 @@ struct ps8640 { - struct regulator_bulk_data supplies[2]; - struct gpio_desc *gpio_reset; - struct gpio_desc *gpio_powerdown; -- bool powered; -+ bool pre_enabled; - }; - - static const struct regmap_config ps8640_regmap_config[] = { -@@ -146,8 +147,29 @@ static inline struct ps8640 *aux_to_ps8640(struct drm_dp_aux *aux) - return container_of(aux, struct ps8640, aux); - } - --static ssize_t ps8640_aux_transfer(struct drm_dp_aux *aux, -- struct drm_dp_aux_msg *msg) -+static int ps8640_ensure_hpd(struct ps8640 *ps_bridge) -+{ -+ struct regmap *map = ps_bridge->regmap[PAGE2_TOP_CNTL]; -+ struct device *dev = &ps_bridge->page[PAGE2_TOP_CNTL]->dev; -+ int status; -+ int ret; -+ -+ /* -+ * Apparently something about the firmware in the chip signals that -+ * HPD goes high by reporting GPIO9 as high (even though HPD isn't -+ * actually connected to GPIO9). -+ */ -+ ret = regmap_read_poll_timeout(map, PAGE2_GPIO_H, status, -+ status & PS_GPIO9, 20 * 1000, 200 * 1000); -+ -+ if (ret < 0) -+ dev_warn(dev, "HPD didn't go high: %d\n", ret); -+ -+ return ret; -+} -+ -+static ssize_t ps8640_aux_transfer_msg(struct drm_dp_aux *aux, -+ struct drm_dp_aux_msg *msg) - { - struct ps8640 *ps_bridge = aux_to_ps8640(aux); - struct regmap *map = ps_bridge->regmap[PAGE0_DP_CNTL]; -@@ -272,38 +294,49 @@ static ssize_t ps8640_aux_transfer(struct drm_dp_aux *aux, - return len; - } - --static int ps8640_bridge_vdo_control(struct ps8640 *ps_bridge, -- const enum ps8640_vdo_control ctrl) -+static ssize_t ps8640_aux_transfer(struct drm_dp_aux *aux, -+ struct drm_dp_aux_msg *msg) -+{ -+ struct ps8640 *ps_bridge = aux_to_ps8640(aux); -+ struct device *dev = &ps_bridge->page[PAGE0_DP_CNTL]->dev; -+ int ret; -+ -+ pm_runtime_get_sync(dev); -+ ret = ps8640_ensure_hpd(ps_bridge); -+ if (!ret) -+ ret = ps8640_aux_transfer_msg(aux, msg); -+ pm_runtime_mark_last_busy(dev); -+ pm_runtime_put_autosuspend(dev); -+ -+ return ret; -+} -+ -+static void ps8640_bridge_vdo_control(struct ps8640 *ps_bridge, -+ const enum ps8640_vdo_control ctrl) - { - struct regmap *map = ps_bridge->regmap[PAGE3_DSI_CNTL1]; -+ struct device *dev = &ps_bridge->page[PAGE3_DSI_CNTL1]->dev; - u8 vdo_ctrl_buf[] = { VDO_CTL_ADD, ctrl }; - int ret; - - ret = regmap_bulk_write(map, PAGE3_SET_ADD, - vdo_ctrl_buf, sizeof(vdo_ctrl_buf)); - -- if (ret < 0) { -- DRM_ERROR("failed to %sable VDO: %d\n", -- ctrl == ENABLE ? "en" : "dis", ret); -- return ret; -- } -- -- return 0; -+ if (ret < 0) -+ dev_err(dev, "failed to %sable VDO: %d\n", -+ ctrl == ENABLE ? "en" : "dis", ret); - } - --static void ps8640_bridge_poweron(struct ps8640 *ps_bridge) -+static int __maybe_unused ps8640_resume(struct device *dev) - { -- struct regmap *map = ps_bridge->regmap[PAGE2_TOP_CNTL]; -- int ret, status; -- -- if (ps_bridge->powered) -- return; -+ struct ps8640 *ps_bridge = dev_get_drvdata(dev); -+ int ret; - - ret = regulator_bulk_enable(ARRAY_SIZE(ps_bridge->supplies), - ps_bridge->supplies); - if (ret < 0) { -- DRM_ERROR("cannot enable regulators %d\n", ret); -- return; -+ dev_err(dev, "cannot enable regulators %d\n", ret); -+ return ret; - } - - gpiod_set_value(ps_bridge->gpio_powerdown, 0); -@@ -312,86 +345,78 @@ static void ps8640_bridge_poweron(struct ps8640 *ps_bridge) - gpiod_set_value(ps_bridge->gpio_reset, 0); - - /* -- * Wait for the ps8640 embedded MCU to be ready -- * First wait 200ms and then check the MCU ready flag every 20ms -+ * Mystery 200 ms delay for the "MCU to be ready". It's unclear if -+ * this is truly necessary since the MCU will already signal that -+ * things are "good to go" by signaling HPD on "gpio 9". See -+ * ps8640_ensure_hpd(). For now we'll keep this mystery delay just in -+ * case. - */ - msleep(200); - -- ret = regmap_read_poll_timeout(map, PAGE2_GPIO_H, status, -- status & PS_GPIO9, 20 * 1000, 200 * 1000); -- -- if (ret < 0) { -- DRM_ERROR("failed read PAGE2_GPIO_H: %d\n", ret); -- goto err_regulators_disable; -- } -- -- msleep(50); -- -- /* -- * The Manufacturer Command Set (MCS) is a device dependent interface -- * intended for factory programming of the display module default -- * parameters. Once the display module is configured, the MCS shall be -- * disabled by the manufacturer. Once disabled, all MCS commands are -- * ignored by the display interface. -- */ -- -- ret = regmap_update_bits(map, PAGE2_MCS_EN, MCS_EN, 0); -- if (ret < 0) { -- DRM_ERROR("failed write PAGE2_MCS_EN: %d\n", ret); -- goto err_regulators_disable; -- } -- -- /* Switch access edp panel's edid through i2c */ -- ret = regmap_write(map, PAGE2_I2C_BYPASS, I2C_BYPASS_EN); -- if (ret < 0) { -- DRM_ERROR("failed write PAGE2_I2C_BYPASS: %d\n", ret); -- goto err_regulators_disable; -- } -- -- ps_bridge->powered = true; -- -- return; -- --err_regulators_disable: -- regulator_bulk_disable(ARRAY_SIZE(ps_bridge->supplies), -- ps_bridge->supplies); -+ return 0; - } - --static void ps8640_bridge_poweroff(struct ps8640 *ps_bridge) -+static int __maybe_unused ps8640_suspend(struct device *dev) - { -+ struct ps8640 *ps_bridge = dev_get_drvdata(dev); - int ret; - -- if (!ps_bridge->powered) -- return; -- - gpiod_set_value(ps_bridge->gpio_reset, 1); - gpiod_set_value(ps_bridge->gpio_powerdown, 1); - ret = regulator_bulk_disable(ARRAY_SIZE(ps_bridge->supplies), - ps_bridge->supplies); - if (ret < 0) -- DRM_ERROR("cannot disable regulators %d\n", ret); -+ dev_err(dev, "cannot disable regulators %d\n", ret); - -- ps_bridge->powered = false; -+ return ret; - } - -+static const struct dev_pm_ops ps8640_pm_ops = { -+ SET_RUNTIME_PM_OPS(ps8640_suspend, ps8640_resume, NULL) -+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, -+ pm_runtime_force_resume) -+}; -+ - static void ps8640_pre_enable(struct drm_bridge *bridge) - { - struct ps8640 *ps_bridge = bridge_to_ps8640(bridge); -+ struct regmap *map = ps_bridge->regmap[PAGE2_TOP_CNTL]; -+ struct device *dev = &ps_bridge->page[PAGE0_DP_CNTL]->dev; - int ret; - -- ps8640_bridge_poweron(ps_bridge); -+ pm_runtime_get_sync(dev); -+ ps8640_ensure_hpd(ps_bridge); - -- ret = ps8640_bridge_vdo_control(ps_bridge, ENABLE); -+ /* -+ * The Manufacturer Command Set (MCS) is a device dependent interface -+ * intended for factory programming of the display module default -+ * parameters. Once the display module is configured, the MCS shall be -+ * disabled by the manufacturer. Once disabled, all MCS commands are -+ * ignored by the display interface. -+ */ -+ -+ ret = regmap_update_bits(map, PAGE2_MCS_EN, MCS_EN, 0); -+ if (ret < 0) -+ dev_warn(dev, "failed write PAGE2_MCS_EN: %d\n", ret); -+ -+ /* Switch access edp panel's edid through i2c */ -+ ret = regmap_write(map, PAGE2_I2C_BYPASS, I2C_BYPASS_EN); - if (ret < 0) -- ps8640_bridge_poweroff(ps_bridge); -+ dev_warn(dev, "failed write PAGE2_MCS_EN: %d\n", ret); -+ -+ ps8640_bridge_vdo_control(ps_bridge, ENABLE); -+ -+ ps_bridge->pre_enabled = true; - } - - static void ps8640_post_disable(struct drm_bridge *bridge) - { - struct ps8640 *ps_bridge = bridge_to_ps8640(bridge); - -+ ps_bridge->pre_enabled = false; -+ - ps8640_bridge_vdo_control(ps_bridge, DISABLE); -- ps8640_bridge_poweroff(ps_bridge); -+ pm_runtime_put_sync_suspend(&ps_bridge->page[PAGE0_DP_CNTL]->dev); - } - - static int ps8640_bridge_attach(struct drm_bridge *bridge, -@@ -472,7 +497,7 @@ static struct edid *ps8640_bridge_get_edid(struct drm_bridge *bridge, - struct drm_connector *connector) - { - struct ps8640 *ps_bridge = bridge_to_ps8640(bridge); -- bool poweroff = !ps_bridge->powered; -+ bool poweroff = !ps_bridge->pre_enabled; - struct edid *edid; - - /* -@@ -502,6 +527,12 @@ static struct edid *ps8640_bridge_get_edid(struct drm_bridge *bridge, - return edid; - } - -+static void ps8640_runtime_disable(void *data) -+{ -+ pm_runtime_dont_use_autosuspend(data); -+ pm_runtime_disable(data); -+} -+ - static const struct drm_bridge_funcs ps8640_bridge_funcs = { - .attach = ps8640_bridge_attach, - .detach = ps8640_bridge_detach, -@@ -585,6 +616,22 @@ static int ps8640_probe(struct i2c_client *client) - ps_bridge->aux.transfer = ps8640_aux_transfer; - drm_dp_aux_init(&ps_bridge->aux); - -+ pm_runtime_enable(dev); -+ /* -+ * Powering on ps8640 takes ~300ms. To avoid wasting time on power -+ * cycling ps8640 too often, set autosuspend_delay to 500ms to ensure -+ * the bridge wouldn't suspend in between each _aux_transfer_msg() call -+ * during EDID read (~20ms in my experiment) and in between the last -+ * _aux_transfer_msg() call during EDID read and the _pre_enable() call -+ * (~100ms in my experiment). -+ */ -+ pm_runtime_set_autosuspend_delay(dev, 500); -+ pm_runtime_use_autosuspend(dev); -+ pm_suspend_ignore_children(dev, true); -+ ret = devm_add_action_or_reset(dev, ps8640_runtime_disable, dev); -+ if (ret) -+ return ret; -+ - drm_bridge_add(&ps_bridge->bridge); - - return 0; -@@ -611,6 +658,7 @@ static struct i2c_driver ps8640_driver = { - .driver = { - .name = "ps8640", - .of_match_table = ps8640_match, -+ .pm = &ps8640_pm_ops, - }, - }; - module_i2c_driver(ps8640_driver); --- -2.35.1 - diff --git a/queue-5.10/drm-bridge-parade-ps8640-fix-regulator-supply-order.patch b/queue-5.10/drm-bridge-parade-ps8640-fix-regulator-supply-order.patch index b46b0a3407c..401e9671510 100644 --- a/queue-5.10/drm-bridge-parade-ps8640-fix-regulator-supply-order.patch +++ b/queue-5.10/drm-bridge-parade-ps8640-fix-regulator-supply-order.patch @@ -20,15 +20,14 @@ Reviewed-by: Neil Armstrong Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20220721092258.3397461-1-wenst@chromium.org Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman --- - drivers/gpu/drm/bridge/parade-ps8640.c | 4 ++-- + drivers/gpu/drm/bridge/parade-ps8640.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) -diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c -index 52f2ea6fcb26..1367cc2d6fd7 100644 --- a/drivers/gpu/drm/bridge/parade-ps8640.c +++ b/drivers/gpu/drm/bridge/parade-ps8640.c -@@ -565,8 +565,8 @@ static int ps8640_probe(struct i2c_client *client) +@@ -333,8 +333,8 @@ static int ps8640_probe(struct i2c_clien if (IS_ERR(ps_bridge->panel_bridge)) return PTR_ERR(ps_bridge->panel_bridge); @@ -39,6 +38,3 @@ index 52f2ea6fcb26..1367cc2d6fd7 100644 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ps_bridge->supplies), ps_bridge->supplies); if (ret) --- -2.35.1 - diff --git a/queue-5.10/drm-bridge-parade-ps8640-use-regmap-apis.patch b/queue-5.10/drm-bridge-parade-ps8640-use-regmap-apis.patch deleted file mode 100644 index b82105e1dee..00000000000 --- a/queue-5.10/drm-bridge-parade-ps8640-use-regmap-apis.patch +++ /dev/null @@ -1,204 +0,0 @@ -From af54466e5b4eef355f8fee40de437401e6f8381a Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Tue, 21 Sep 2021 11:06:16 -0700 -Subject: drm/bridge: parade-ps8640: Use regmap APIs - -From: Philip Chen - -[ Upstream commit 692d8db0a5ca123017d7d4847856343512f87af9 ] - -Replace the direct i2c access (i2c_smbus_* functions) with regmap APIs, -which will simplify the future update on ps8640 driver. - -Signed-off-by: Philip Chen -Reviewed-by: Douglas Anderson -Acked-by: Sam Ravnborg -Reviewed-by: Stephen Boyd -[dianders: whitespace fixes reported by dim apply-branch] -Signed-off-by: Douglas Anderson -Link: https://patchwork.freedesktop.org/patch/msgid/20210921110556.v6.1.I2351df94f18d5d8debc22d4d100f36fac560409a@changeid -Stable-dep-of: fc94224c2e0a ("drm/bridge: parade-ps8640: Fix regulator supply order") -Signed-off-by: Sasha Levin ---- - drivers/gpu/drm/bridge/parade-ps8640.c | 94 ++++++++++++++++++-------- - 1 file changed, 64 insertions(+), 30 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c -index 7bd0affa057a..88c9f3404ac1 100644 ---- a/drivers/gpu/drm/bridge/parade-ps8640.c -+++ b/drivers/gpu/drm/bridge/parade-ps8640.c -@@ -9,6 +9,7 @@ - #include - #include - #include -+#include - #include - - #include -@@ -29,6 +30,11 @@ - #define VDO_EN 0x1c - #define DP_NUM_LANES 4 - -+#define COMMON_PS8640_REGMAP_CONFIG \ -+ .reg_bits = 8, \ -+ .val_bits = 8, \ -+ .cache_type = REGCACHE_NONE -+ - /* - * PS8640 uses multiple addresses: - * page[0]: for DP control -@@ -62,12 +68,48 @@ struct ps8640 { - struct drm_bridge *panel_bridge; - struct mipi_dsi_device *dsi; - struct i2c_client *page[MAX_DEVS]; -+ struct regmap *regmap[MAX_DEVS]; - struct regulator_bulk_data supplies[2]; - struct gpio_desc *gpio_reset; - struct gpio_desc *gpio_powerdown; - bool powered; - }; - -+static const struct regmap_config ps8640_regmap_config[] = { -+ [PAGE0_DP_CNTL] = { -+ COMMON_PS8640_REGMAP_CONFIG, -+ .max_register = 0xbf, -+ }, -+ [PAGE1_VDO_BDG] = { -+ COMMON_PS8640_REGMAP_CONFIG, -+ .max_register = 0xff, -+ }, -+ [PAGE2_TOP_CNTL] = { -+ COMMON_PS8640_REGMAP_CONFIG, -+ .max_register = 0xff, -+ }, -+ [PAGE3_DSI_CNTL1] = { -+ COMMON_PS8640_REGMAP_CONFIG, -+ .max_register = 0xff, -+ }, -+ [PAGE4_MIPI_PHY] = { -+ COMMON_PS8640_REGMAP_CONFIG, -+ .max_register = 0xff, -+ }, -+ [PAGE5_VPLL] = { -+ COMMON_PS8640_REGMAP_CONFIG, -+ .max_register = 0x7f, -+ }, -+ [PAGE6_DSI_CNTL2] = { -+ COMMON_PS8640_REGMAP_CONFIG, -+ .max_register = 0xff, -+ }, -+ [PAGE7_SPI_CNTL] = { -+ COMMON_PS8640_REGMAP_CONFIG, -+ .max_register = 0xff, -+ }, -+}; -+ - static inline struct ps8640 *bridge_to_ps8640(struct drm_bridge *e) - { - return container_of(e, struct ps8640, bridge); -@@ -76,13 +118,13 @@ static inline struct ps8640 *bridge_to_ps8640(struct drm_bridge *e) - static int ps8640_bridge_vdo_control(struct ps8640 *ps_bridge, - const enum ps8640_vdo_control ctrl) - { -- struct i2c_client *client = ps_bridge->page[PAGE3_DSI_CNTL1]; -+ struct regmap *map = ps_bridge->regmap[PAGE3_DSI_CNTL1]; - u8 vdo_ctrl_buf[] = { VDO_CTL_ADD, ctrl }; - int ret; - -- ret = i2c_smbus_write_i2c_block_data(client, PAGE3_SET_ADD, -- sizeof(vdo_ctrl_buf), -- vdo_ctrl_buf); -+ ret = regmap_bulk_write(map, PAGE3_SET_ADD, -+ vdo_ctrl_buf, sizeof(vdo_ctrl_buf)); -+ - if (ret < 0) { - DRM_ERROR("failed to %sable VDO: %d\n", - ctrl == ENABLE ? "en" : "dis", ret); -@@ -94,8 +136,7 @@ static int ps8640_bridge_vdo_control(struct ps8640 *ps_bridge, - - static void ps8640_bridge_poweron(struct ps8640 *ps_bridge) - { -- struct i2c_client *client = ps_bridge->page[PAGE2_TOP_CNTL]; -- unsigned long timeout; -+ struct regmap *map = ps_bridge->regmap[PAGE2_TOP_CNTL]; - int ret, status; - - if (ps_bridge->powered) -@@ -119,18 +160,12 @@ static void ps8640_bridge_poweron(struct ps8640 *ps_bridge) - */ - msleep(200); - -- timeout = jiffies + msecs_to_jiffies(200) + 1; -- -- while (time_is_after_jiffies(timeout)) { -- status = i2c_smbus_read_byte_data(client, PAGE2_GPIO_H); -- if (status < 0) { -- DRM_ERROR("failed read PAGE2_GPIO_H: %d\n", status); -- goto err_regulators_disable; -- } -- if ((status & PS_GPIO9) == PS_GPIO9) -- break; -+ ret = regmap_read_poll_timeout(map, PAGE2_GPIO_H, status, -+ status & PS_GPIO9, 20 * 1000, 200 * 1000); - -- msleep(20); -+ if (ret < 0) { -+ DRM_ERROR("failed read PAGE2_GPIO_H: %d\n", ret); -+ goto err_regulators_disable; - } - - msleep(50); -@@ -142,22 +177,15 @@ static void ps8640_bridge_poweron(struct ps8640 *ps_bridge) - * disabled by the manufacturer. Once disabled, all MCS commands are - * ignored by the display interface. - */ -- status = i2c_smbus_read_byte_data(client, PAGE2_MCS_EN); -- if (status < 0) { -- DRM_ERROR("failed read PAGE2_MCS_EN: %d\n", status); -- goto err_regulators_disable; -- } - -- ret = i2c_smbus_write_byte_data(client, PAGE2_MCS_EN, -- status & ~MCS_EN); -+ ret = regmap_update_bits(map, PAGE2_MCS_EN, MCS_EN, 0); - if (ret < 0) { - DRM_ERROR("failed write PAGE2_MCS_EN: %d\n", ret); - goto err_regulators_disable; - } - - /* Switch access edp panel's edid through i2c */ -- ret = i2c_smbus_write_byte_data(client, PAGE2_I2C_BYPASS, -- I2C_BYPASS_EN); -+ ret = regmap_write(map, PAGE2_I2C_BYPASS, I2C_BYPASS_EN); - if (ret < 0) { - DRM_ERROR("failed write PAGE2_I2C_BYPASS: %d\n", ret); - goto err_regulators_disable; -@@ -360,15 +388,21 @@ static int ps8640_probe(struct i2c_client *client) - - ps_bridge->page[PAGE0_DP_CNTL] = client; - -+ ps_bridge->regmap[PAGE0_DP_CNTL] = devm_regmap_init_i2c(client, ps8640_regmap_config); -+ if (IS_ERR(ps_bridge->regmap[PAGE0_DP_CNTL])) -+ return PTR_ERR(ps_bridge->regmap[PAGE0_DP_CNTL]); -+ - for (i = 1; i < ARRAY_SIZE(ps_bridge->page); i++) { - ps_bridge->page[i] = devm_i2c_new_dummy_device(&client->dev, - client->adapter, - client->addr + i); -- if (IS_ERR(ps_bridge->page[i])) { -- dev_err(dev, "failed i2c dummy device, address %02x\n", -- client->addr + i); -+ if (IS_ERR(ps_bridge->page[i])) - return PTR_ERR(ps_bridge->page[i]); -- } -+ -+ ps_bridge->regmap[i] = devm_regmap_init_i2c(ps_bridge->page[i], -+ ps8640_regmap_config + i); -+ if (IS_ERR(ps_bridge->regmap[i])) -+ return PTR_ERR(ps_bridge->regmap[i]); - } - - i2c_set_clientdata(client, ps_bridge); --- -2.35.1 - diff --git a/queue-5.10/series b/queue-5.10/series index 5a980afe10d..2c5f4279be3 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -141,9 +141,6 @@ net-mvpp2-fix-mvpp2-debugfs-leak.patch drm-bridge-adv7511-fix-cec-power-down-control-regist.patch drm-bridge-avoid-uninitialized-variable-warning.patch drm-mipi-dsi-detach-devices-when-removing-the-host.patch -drm-bridge-parade-ps8640-use-regmap-apis.patch -drm-bridge-parade-ps8640-add-support-for-aux-channel.patch -drm-bridge-parade-ps8640-enable-runtime-power-manage.patch drm-bridge-parade-ps8640-fix-regulator-supply-order.patch net-wwan-t7xx-add-control-dma-interface.patch drm-dp_mst-fix-drm_dp_dpcd_read-return-value-checks.patch diff --git a/queue-5.15/drm-bridge-parade-ps8640-add-support-for-aux-channel.patch b/queue-5.15/drm-bridge-parade-ps8640-add-support-for-aux-channel.patch deleted file mode 100644 index d4949a2f20a..00000000000 --- a/queue-5.15/drm-bridge-parade-ps8640-add-support-for-aux-channel.patch +++ /dev/null @@ -1,270 +0,0 @@ -From 2d9eb1483129ca84e2f02222ef920c57bf86b378 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Tue, 21 Sep 2021 11:06:17 -0700 -Subject: drm/bridge: parade-ps8640: Add support for AUX channel - -From: Philip Chen - -[ Upstream commit 13afcdd7277eff9ab5c92dc0d8d21335d132ab2f ] - -Implement the first version of AUX support, which will be useful as -we expand the driver to support varied use cases. - -Signed-off-by: Philip Chen -Reviewed-by: Sam Ravnborg -Reviewed-by: Douglas Anderson -Reviewed-by: Stephen Boyd -[dianders: whitespace fixes reported by dim apply-branch] -Signed-off-by: Douglas Anderson -Link: https://patchwork.freedesktop.org/patch/msgid/20210921110556.v6.2.I1d6ea362dc76efa77cca2b46253d31b7651eaf17@changeid -Stable-dep-of: fc94224c2e0a ("drm/bridge: parade-ps8640: Fix regulator supply order") -Signed-off-by: Sasha Levin ---- - drivers/gpu/drm/bridge/parade-ps8640.c | 180 ++++++++++++++++++++++++- - 1 file changed, 179 insertions(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c -index 88c9f3404ac1..43afa848a36a 100644 ---- a/drivers/gpu/drm/bridge/parade-ps8640.c -+++ b/drivers/gpu/drm/bridge/parade-ps8640.c -@@ -13,11 +13,36 @@ - #include - - #include -+#include - #include - #include - #include - #include - -+#define PAGE0_AUXCH_CFG3 0x76 -+#define AUXCH_CFG3_RESET 0xff -+#define PAGE0_SWAUX_ADDR_7_0 0x7d -+#define PAGE0_SWAUX_ADDR_15_8 0x7e -+#define PAGE0_SWAUX_ADDR_23_16 0x7f -+#define SWAUX_ADDR_MASK GENMASK(19, 0) -+#define PAGE0_SWAUX_LENGTH 0x80 -+#define SWAUX_LENGTH_MASK GENMASK(3, 0) -+#define SWAUX_NO_PAYLOAD BIT(7) -+#define PAGE0_SWAUX_WDATA 0x81 -+#define PAGE0_SWAUX_RDATA 0x82 -+#define PAGE0_SWAUX_CTRL 0x83 -+#define SWAUX_SEND BIT(0) -+#define PAGE0_SWAUX_STATUS 0x84 -+#define SWAUX_M_MASK GENMASK(4, 0) -+#define SWAUX_STATUS_MASK GENMASK(7, 5) -+#define SWAUX_STATUS_NACK (0x1 << 5) -+#define SWAUX_STATUS_DEFER (0x2 << 5) -+#define SWAUX_STATUS_ACKM (0x3 << 5) -+#define SWAUX_STATUS_INVALID (0x4 << 5) -+#define SWAUX_STATUS_I2C_NACK (0x5 << 5) -+#define SWAUX_STATUS_I2C_DEFER (0x6 << 5) -+#define SWAUX_STATUS_TIMEOUT (0x7 << 5) -+ - #define PAGE2_GPIO_H 0xa7 - #define PS_GPIO9 BIT(1) - #define PAGE2_I2C_BYPASS 0xea -@@ -66,6 +91,7 @@ enum ps8640_vdo_control { - struct ps8640 { - struct drm_bridge bridge; - struct drm_bridge *panel_bridge; -+ struct drm_dp_aux aux; - struct mipi_dsi_device *dsi; - struct i2c_client *page[MAX_DEVS]; - struct regmap *regmap[MAX_DEVS]; -@@ -115,6 +141,137 @@ static inline struct ps8640 *bridge_to_ps8640(struct drm_bridge *e) - return container_of(e, struct ps8640, bridge); - } - -+static inline struct ps8640 *aux_to_ps8640(struct drm_dp_aux *aux) -+{ -+ return container_of(aux, struct ps8640, aux); -+} -+ -+static ssize_t ps8640_aux_transfer(struct drm_dp_aux *aux, -+ struct drm_dp_aux_msg *msg) -+{ -+ struct ps8640 *ps_bridge = aux_to_ps8640(aux); -+ struct regmap *map = ps_bridge->regmap[PAGE0_DP_CNTL]; -+ struct device *dev = &ps_bridge->page[PAGE0_DP_CNTL]->dev; -+ unsigned int len = msg->size; -+ unsigned int data; -+ unsigned int base; -+ int ret; -+ u8 request = msg->request & -+ ~(DP_AUX_I2C_MOT | DP_AUX_I2C_WRITE_STATUS_UPDATE); -+ u8 *buf = msg->buffer; -+ u8 addr_len[PAGE0_SWAUX_LENGTH + 1 - PAGE0_SWAUX_ADDR_7_0]; -+ u8 i; -+ bool is_native_aux = false; -+ -+ if (len > DP_AUX_MAX_PAYLOAD_BYTES) -+ return -EINVAL; -+ -+ if (msg->address & ~SWAUX_ADDR_MASK) -+ return -EINVAL; -+ -+ switch (request) { -+ case DP_AUX_NATIVE_WRITE: -+ case DP_AUX_NATIVE_READ: -+ is_native_aux = true; -+ fallthrough; -+ case DP_AUX_I2C_WRITE: -+ case DP_AUX_I2C_READ: -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ ret = regmap_write(map, PAGE0_AUXCH_CFG3, AUXCH_CFG3_RESET); -+ if (ret) { -+ DRM_DEV_ERROR(dev, "failed to write PAGE0_AUXCH_CFG3: %d\n", -+ ret); -+ return ret; -+ } -+ -+ /* Assume it's good */ -+ msg->reply = 0; -+ -+ base = PAGE0_SWAUX_ADDR_7_0; -+ addr_len[PAGE0_SWAUX_ADDR_7_0 - base] = msg->address; -+ addr_len[PAGE0_SWAUX_ADDR_15_8 - base] = msg->address >> 8; -+ addr_len[PAGE0_SWAUX_ADDR_23_16 - base] = (msg->address >> 16) | -+ (msg->request << 4); -+ addr_len[PAGE0_SWAUX_LENGTH - base] = (len == 0) ? SWAUX_NO_PAYLOAD : -+ ((len - 1) & SWAUX_LENGTH_MASK); -+ -+ regmap_bulk_write(map, PAGE0_SWAUX_ADDR_7_0, addr_len, -+ ARRAY_SIZE(addr_len)); -+ -+ if (len && (request == DP_AUX_NATIVE_WRITE || -+ request == DP_AUX_I2C_WRITE)) { -+ /* Write to the internal FIFO buffer */ -+ for (i = 0; i < len; i++) { -+ ret = regmap_write(map, PAGE0_SWAUX_WDATA, buf[i]); -+ if (ret) { -+ DRM_DEV_ERROR(dev, -+ "failed to write WDATA: %d\n", -+ ret); -+ return ret; -+ } -+ } -+ } -+ -+ regmap_write(map, PAGE0_SWAUX_CTRL, SWAUX_SEND); -+ -+ /* Zero delay loop because i2c transactions are slow already */ -+ regmap_read_poll_timeout(map, PAGE0_SWAUX_CTRL, data, -+ !(data & SWAUX_SEND), 0, 50 * 1000); -+ -+ regmap_read(map, PAGE0_SWAUX_STATUS, &data); -+ if (ret) { -+ DRM_DEV_ERROR(dev, "failed to read PAGE0_SWAUX_STATUS: %d\n", -+ ret); -+ return ret; -+ } -+ -+ switch (data & SWAUX_STATUS_MASK) { -+ /* Ignore the DEFER cases as they are already handled in hardware */ -+ case SWAUX_STATUS_NACK: -+ case SWAUX_STATUS_I2C_NACK: -+ /* -+ * The programming guide is not clear about whether a I2C NACK -+ * would trigger SWAUX_STATUS_NACK or SWAUX_STATUS_I2C_NACK. So -+ * we handle both cases together. -+ */ -+ if (is_native_aux) -+ msg->reply |= DP_AUX_NATIVE_REPLY_NACK; -+ else -+ msg->reply |= DP_AUX_I2C_REPLY_NACK; -+ -+ fallthrough; -+ case SWAUX_STATUS_ACKM: -+ len = data & SWAUX_M_MASK; -+ break; -+ case SWAUX_STATUS_INVALID: -+ return -EOPNOTSUPP; -+ case SWAUX_STATUS_TIMEOUT: -+ return -ETIMEDOUT; -+ } -+ -+ if (len && (request == DP_AUX_NATIVE_READ || -+ request == DP_AUX_I2C_READ)) { -+ /* Read from the internal FIFO buffer */ -+ for (i = 0; i < len; i++) { -+ ret = regmap_read(map, PAGE0_SWAUX_RDATA, &data); -+ if (ret) { -+ DRM_DEV_ERROR(dev, -+ "failed to read RDATA: %d\n", -+ ret); -+ return ret; -+ } -+ -+ buf[i] = data; -+ } -+ } -+ -+ return len; -+} -+ - static int ps8640_bridge_vdo_control(struct ps8640 *ps_bridge, - const enum ps8640_vdo_control ctrl) - { -@@ -284,18 +441,33 @@ static int ps8640_bridge_attach(struct drm_bridge *bridge, - dsi->format = MIPI_DSI_FMT_RGB888; - dsi->lanes = DP_NUM_LANES; - ret = mipi_dsi_attach(dsi); -- if (ret) -+ if (ret) { -+ dev_err(dev, "failed to attach dsi device: %d\n", ret); - goto err_dsi_attach; -+ } -+ -+ ret = drm_dp_aux_register(&ps_bridge->aux); -+ if (ret) { -+ dev_err(dev, "failed to register DP AUX channel: %d\n", ret); -+ goto err_aux_register; -+ } - - /* Attach the panel-bridge to the dsi bridge */ - return drm_bridge_attach(bridge->encoder, ps_bridge->panel_bridge, - &ps_bridge->bridge, flags); - -+err_aux_register: -+ mipi_dsi_detach(dsi); - err_dsi_attach: - mipi_dsi_device_unregister(dsi); - return ret; - } - -+static void ps8640_bridge_detach(struct drm_bridge *bridge) -+{ -+ drm_dp_aux_unregister(&bridge_to_ps8640(bridge)->aux); -+} -+ - static struct edid *ps8640_bridge_get_edid(struct drm_bridge *bridge, - struct drm_connector *connector) - { -@@ -332,6 +504,7 @@ static struct edid *ps8640_bridge_get_edid(struct drm_bridge *bridge, - - static const struct drm_bridge_funcs ps8640_bridge_funcs = { - .attach = ps8640_bridge_attach, -+ .detach = ps8640_bridge_detach, - .get_edid = ps8640_bridge_get_edid, - .post_disable = ps8640_post_disable, - .pre_enable = ps8640_pre_enable, -@@ -407,6 +580,11 @@ static int ps8640_probe(struct i2c_client *client) - - i2c_set_clientdata(client, ps_bridge); - -+ ps_bridge->aux.name = "parade-ps8640-aux"; -+ ps_bridge->aux.dev = dev; -+ ps_bridge->aux.transfer = ps8640_aux_transfer; -+ drm_dp_aux_init(&ps_bridge->aux); -+ - drm_bridge_add(&ps_bridge->bridge); - - return 0; --- -2.35.1 - diff --git a/queue-5.15/drm-bridge-parade-ps8640-enable-runtime-power-manage.patch b/queue-5.15/drm-bridge-parade-ps8640-enable-runtime-power-manage.patch deleted file mode 100644 index 7bfb2952d07..00000000000 --- a/queue-5.15/drm-bridge-parade-ps8640-enable-runtime-power-manage.patch +++ /dev/null @@ -1,350 +0,0 @@ -From f911e7903705123552b722cc5f997dc674f91bfe Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Thu, 28 Oct 2021 10:58:10 -0700 -Subject: drm/bridge: parade-ps8640: Enable runtime power management - -From: Philip Chen - -[ Upstream commit 826cff3f7ebba460d3db61f135798ce76b0d26ed ] - -Fit ps8640 driver into runtime power management framework: - -First, break _poweron() to 3 parts: (1) turn on power and wait for -ps8640's internal MCU to finish init (2) check panel HPD (which is -proxied by GPIO9) (3) the other configs. As runtime_resume() can be -called before panel is powered, we only add (1) to _resume() and leave -(2)(3) to _pre_enable(). We also add (2) to _aux_transfer() as we want -to ensure panel HPD is asserted before we start AUX CH transactions. - -Second, the original driver has a mysterious delay of 50 ms between (2) -and (3). Since Parade's support can't explain what the delay is for, -and we don't see removing the delay break any boards at hand, remove -the delay to fit into this driver change. - -In addition, rename "powered" to "pre_enabled" and don't check for it -in the pm_runtime calls. The pm_runtime calls are already refcounted -so there's no reason to check there. The other user of "powered", -_get_edid(), only cares if pre_enable() has already been called. - -Lastly, change some existing DRM_...() logging to dev_...() along the -way, since DRM_...() seem to be deprecated in [1]. - -[1] https://patchwork.freedesktop.org/patch/454760/ - -Signed-off-by: Philip Chen -Reviewed-by: Douglas Anderson -Reviewed-by: Stephen Boyd -[dianders: fixed whitespace warning reported by dim tool] -Signed-off-by: Douglas Anderson -Link: https://patchwork.freedesktop.org/patch/msgid/20211028105754.v5.1.I828f5db745535fb7e36e8ffdd62d546f6d08b6d1@changeid -Stable-dep-of: fc94224c2e0a ("drm/bridge: parade-ps8640: Fix regulator supply order") -Signed-off-by: Sasha Levin ---- - drivers/gpu/drm/bridge/parade-ps8640.c | 190 ++++++++++++++++--------- - 1 file changed, 119 insertions(+), 71 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c -index 43afa848a36a..52f2ea6fcb26 100644 ---- a/drivers/gpu/drm/bridge/parade-ps8640.c -+++ b/drivers/gpu/drm/bridge/parade-ps8640.c -@@ -9,6 +9,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -98,7 +99,7 @@ struct ps8640 { - struct regulator_bulk_data supplies[2]; - struct gpio_desc *gpio_reset; - struct gpio_desc *gpio_powerdown; -- bool powered; -+ bool pre_enabled; - }; - - static const struct regmap_config ps8640_regmap_config[] = { -@@ -146,8 +147,29 @@ static inline struct ps8640 *aux_to_ps8640(struct drm_dp_aux *aux) - return container_of(aux, struct ps8640, aux); - } - --static ssize_t ps8640_aux_transfer(struct drm_dp_aux *aux, -- struct drm_dp_aux_msg *msg) -+static int ps8640_ensure_hpd(struct ps8640 *ps_bridge) -+{ -+ struct regmap *map = ps_bridge->regmap[PAGE2_TOP_CNTL]; -+ struct device *dev = &ps_bridge->page[PAGE2_TOP_CNTL]->dev; -+ int status; -+ int ret; -+ -+ /* -+ * Apparently something about the firmware in the chip signals that -+ * HPD goes high by reporting GPIO9 as high (even though HPD isn't -+ * actually connected to GPIO9). -+ */ -+ ret = regmap_read_poll_timeout(map, PAGE2_GPIO_H, status, -+ status & PS_GPIO9, 20 * 1000, 200 * 1000); -+ -+ if (ret < 0) -+ dev_warn(dev, "HPD didn't go high: %d\n", ret); -+ -+ return ret; -+} -+ -+static ssize_t ps8640_aux_transfer_msg(struct drm_dp_aux *aux, -+ struct drm_dp_aux_msg *msg) - { - struct ps8640 *ps_bridge = aux_to_ps8640(aux); - struct regmap *map = ps_bridge->regmap[PAGE0_DP_CNTL]; -@@ -272,38 +294,49 @@ static ssize_t ps8640_aux_transfer(struct drm_dp_aux *aux, - return len; - } - --static int ps8640_bridge_vdo_control(struct ps8640 *ps_bridge, -- const enum ps8640_vdo_control ctrl) -+static ssize_t ps8640_aux_transfer(struct drm_dp_aux *aux, -+ struct drm_dp_aux_msg *msg) -+{ -+ struct ps8640 *ps_bridge = aux_to_ps8640(aux); -+ struct device *dev = &ps_bridge->page[PAGE0_DP_CNTL]->dev; -+ int ret; -+ -+ pm_runtime_get_sync(dev); -+ ret = ps8640_ensure_hpd(ps_bridge); -+ if (!ret) -+ ret = ps8640_aux_transfer_msg(aux, msg); -+ pm_runtime_mark_last_busy(dev); -+ pm_runtime_put_autosuspend(dev); -+ -+ return ret; -+} -+ -+static void ps8640_bridge_vdo_control(struct ps8640 *ps_bridge, -+ const enum ps8640_vdo_control ctrl) - { - struct regmap *map = ps_bridge->regmap[PAGE3_DSI_CNTL1]; -+ struct device *dev = &ps_bridge->page[PAGE3_DSI_CNTL1]->dev; - u8 vdo_ctrl_buf[] = { VDO_CTL_ADD, ctrl }; - int ret; - - ret = regmap_bulk_write(map, PAGE3_SET_ADD, - vdo_ctrl_buf, sizeof(vdo_ctrl_buf)); - -- if (ret < 0) { -- DRM_ERROR("failed to %sable VDO: %d\n", -- ctrl == ENABLE ? "en" : "dis", ret); -- return ret; -- } -- -- return 0; -+ if (ret < 0) -+ dev_err(dev, "failed to %sable VDO: %d\n", -+ ctrl == ENABLE ? "en" : "dis", ret); - } - --static void ps8640_bridge_poweron(struct ps8640 *ps_bridge) -+static int __maybe_unused ps8640_resume(struct device *dev) - { -- struct regmap *map = ps_bridge->regmap[PAGE2_TOP_CNTL]; -- int ret, status; -- -- if (ps_bridge->powered) -- return; -+ struct ps8640 *ps_bridge = dev_get_drvdata(dev); -+ int ret; - - ret = regulator_bulk_enable(ARRAY_SIZE(ps_bridge->supplies), - ps_bridge->supplies); - if (ret < 0) { -- DRM_ERROR("cannot enable regulators %d\n", ret); -- return; -+ dev_err(dev, "cannot enable regulators %d\n", ret); -+ return ret; - } - - gpiod_set_value(ps_bridge->gpio_powerdown, 0); -@@ -312,86 +345,78 @@ static void ps8640_bridge_poweron(struct ps8640 *ps_bridge) - gpiod_set_value(ps_bridge->gpio_reset, 0); - - /* -- * Wait for the ps8640 embedded MCU to be ready -- * First wait 200ms and then check the MCU ready flag every 20ms -+ * Mystery 200 ms delay for the "MCU to be ready". It's unclear if -+ * this is truly necessary since the MCU will already signal that -+ * things are "good to go" by signaling HPD on "gpio 9". See -+ * ps8640_ensure_hpd(). For now we'll keep this mystery delay just in -+ * case. - */ - msleep(200); - -- ret = regmap_read_poll_timeout(map, PAGE2_GPIO_H, status, -- status & PS_GPIO9, 20 * 1000, 200 * 1000); -- -- if (ret < 0) { -- DRM_ERROR("failed read PAGE2_GPIO_H: %d\n", ret); -- goto err_regulators_disable; -- } -- -- msleep(50); -- -- /* -- * The Manufacturer Command Set (MCS) is a device dependent interface -- * intended for factory programming of the display module default -- * parameters. Once the display module is configured, the MCS shall be -- * disabled by the manufacturer. Once disabled, all MCS commands are -- * ignored by the display interface. -- */ -- -- ret = regmap_update_bits(map, PAGE2_MCS_EN, MCS_EN, 0); -- if (ret < 0) { -- DRM_ERROR("failed write PAGE2_MCS_EN: %d\n", ret); -- goto err_regulators_disable; -- } -- -- /* Switch access edp panel's edid through i2c */ -- ret = regmap_write(map, PAGE2_I2C_BYPASS, I2C_BYPASS_EN); -- if (ret < 0) { -- DRM_ERROR("failed write PAGE2_I2C_BYPASS: %d\n", ret); -- goto err_regulators_disable; -- } -- -- ps_bridge->powered = true; -- -- return; -- --err_regulators_disable: -- regulator_bulk_disable(ARRAY_SIZE(ps_bridge->supplies), -- ps_bridge->supplies); -+ return 0; - } - --static void ps8640_bridge_poweroff(struct ps8640 *ps_bridge) -+static int __maybe_unused ps8640_suspend(struct device *dev) - { -+ struct ps8640 *ps_bridge = dev_get_drvdata(dev); - int ret; - -- if (!ps_bridge->powered) -- return; -- - gpiod_set_value(ps_bridge->gpio_reset, 1); - gpiod_set_value(ps_bridge->gpio_powerdown, 1); - ret = regulator_bulk_disable(ARRAY_SIZE(ps_bridge->supplies), - ps_bridge->supplies); - if (ret < 0) -- DRM_ERROR("cannot disable regulators %d\n", ret); -+ dev_err(dev, "cannot disable regulators %d\n", ret); - -- ps_bridge->powered = false; -+ return ret; - } - -+static const struct dev_pm_ops ps8640_pm_ops = { -+ SET_RUNTIME_PM_OPS(ps8640_suspend, ps8640_resume, NULL) -+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, -+ pm_runtime_force_resume) -+}; -+ - static void ps8640_pre_enable(struct drm_bridge *bridge) - { - struct ps8640 *ps_bridge = bridge_to_ps8640(bridge); -+ struct regmap *map = ps_bridge->regmap[PAGE2_TOP_CNTL]; -+ struct device *dev = &ps_bridge->page[PAGE0_DP_CNTL]->dev; - int ret; - -- ps8640_bridge_poweron(ps_bridge); -+ pm_runtime_get_sync(dev); -+ ps8640_ensure_hpd(ps_bridge); - -- ret = ps8640_bridge_vdo_control(ps_bridge, ENABLE); -+ /* -+ * The Manufacturer Command Set (MCS) is a device dependent interface -+ * intended for factory programming of the display module default -+ * parameters. Once the display module is configured, the MCS shall be -+ * disabled by the manufacturer. Once disabled, all MCS commands are -+ * ignored by the display interface. -+ */ -+ -+ ret = regmap_update_bits(map, PAGE2_MCS_EN, MCS_EN, 0); -+ if (ret < 0) -+ dev_warn(dev, "failed write PAGE2_MCS_EN: %d\n", ret); -+ -+ /* Switch access edp panel's edid through i2c */ -+ ret = regmap_write(map, PAGE2_I2C_BYPASS, I2C_BYPASS_EN); - if (ret < 0) -- ps8640_bridge_poweroff(ps_bridge); -+ dev_warn(dev, "failed write PAGE2_MCS_EN: %d\n", ret); -+ -+ ps8640_bridge_vdo_control(ps_bridge, ENABLE); -+ -+ ps_bridge->pre_enabled = true; - } - - static void ps8640_post_disable(struct drm_bridge *bridge) - { - struct ps8640 *ps_bridge = bridge_to_ps8640(bridge); - -+ ps_bridge->pre_enabled = false; -+ - ps8640_bridge_vdo_control(ps_bridge, DISABLE); -- ps8640_bridge_poweroff(ps_bridge); -+ pm_runtime_put_sync_suspend(&ps_bridge->page[PAGE0_DP_CNTL]->dev); - } - - static int ps8640_bridge_attach(struct drm_bridge *bridge, -@@ -472,7 +497,7 @@ static struct edid *ps8640_bridge_get_edid(struct drm_bridge *bridge, - struct drm_connector *connector) - { - struct ps8640 *ps_bridge = bridge_to_ps8640(bridge); -- bool poweroff = !ps_bridge->powered; -+ bool poweroff = !ps_bridge->pre_enabled; - struct edid *edid; - - /* -@@ -502,6 +527,12 @@ static struct edid *ps8640_bridge_get_edid(struct drm_bridge *bridge, - return edid; - } - -+static void ps8640_runtime_disable(void *data) -+{ -+ pm_runtime_dont_use_autosuspend(data); -+ pm_runtime_disable(data); -+} -+ - static const struct drm_bridge_funcs ps8640_bridge_funcs = { - .attach = ps8640_bridge_attach, - .detach = ps8640_bridge_detach, -@@ -585,6 +616,22 @@ static int ps8640_probe(struct i2c_client *client) - ps_bridge->aux.transfer = ps8640_aux_transfer; - drm_dp_aux_init(&ps_bridge->aux); - -+ pm_runtime_enable(dev); -+ /* -+ * Powering on ps8640 takes ~300ms. To avoid wasting time on power -+ * cycling ps8640 too often, set autosuspend_delay to 500ms to ensure -+ * the bridge wouldn't suspend in between each _aux_transfer_msg() call -+ * during EDID read (~20ms in my experiment) and in between the last -+ * _aux_transfer_msg() call during EDID read and the _pre_enable() call -+ * (~100ms in my experiment). -+ */ -+ pm_runtime_set_autosuspend_delay(dev, 500); -+ pm_runtime_use_autosuspend(dev); -+ pm_suspend_ignore_children(dev, true); -+ ret = devm_add_action_or_reset(dev, ps8640_runtime_disable, dev); -+ if (ret) -+ return ret; -+ - drm_bridge_add(&ps_bridge->bridge); - - return 0; -@@ -611,6 +658,7 @@ static struct i2c_driver ps8640_driver = { - .driver = { - .name = "ps8640", - .of_match_table = ps8640_match, -+ .pm = &ps8640_pm_ops, - }, - }; - module_i2c_driver(ps8640_driver); --- -2.35.1 - diff --git a/queue-5.15/drm-bridge-parade-ps8640-fix-regulator-supply-order.patch b/queue-5.15/drm-bridge-parade-ps8640-fix-regulator-supply-order.patch index ae128d5fa4d..a4e5859bd30 100644 --- a/queue-5.15/drm-bridge-parade-ps8640-fix-regulator-supply-order.patch +++ b/queue-5.15/drm-bridge-parade-ps8640-fix-regulator-supply-order.patch @@ -20,17 +20,16 @@ Reviewed-by: Neil Armstrong Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20220721092258.3397461-1-wenst@chromium.org Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman --- - drivers/gpu/drm/bridge/parade-ps8640.c | 4 ++-- + drivers/gpu/drm/bridge/parade-ps8640.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) -diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c -index 3de796cf9328..f0ab75a5ea41 100644 --- a/drivers/gpu/drm/bridge/parade-ps8640.c +++ b/drivers/gpu/drm/bridge/parade-ps8640.c -@@ -572,8 +572,8 @@ static int ps8640_probe(struct i2c_client *client) - if (!ps_bridge) - return -ENOMEM; +@@ -333,8 +333,8 @@ static int ps8640_probe(struct i2c_clien + if (IS_ERR(ps_bridge->panel_bridge)) + return PTR_ERR(ps_bridge->panel_bridge); - ps_bridge->supplies[0].supply = "vdd33"; - ps_bridge->supplies[1].supply = "vdd12"; @@ -39,6 +38,3 @@ index 3de796cf9328..f0ab75a5ea41 100644 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ps_bridge->supplies), ps_bridge->supplies); if (ret) --- -2.35.1 - diff --git a/queue-5.15/drm-bridge-parade-ps8640-populate-devices-on-aux-bus.patch b/queue-5.15/drm-bridge-parade-ps8640-populate-devices-on-aux-bus.patch deleted file mode 100644 index e504869bc87..00000000000 --- a/queue-5.15/drm-bridge-parade-ps8640-populate-devices-on-aux-bus.patch +++ /dev/null @@ -1,141 +0,0 @@ -From 7c5fbace745bb2f2268545c25c495e0bea111cbb Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Thu, 28 Oct 2021 10:58:11 -0700 -Subject: drm/bridge: parade-ps8640: Populate devices on aux-bus - -From: Philip Chen - -[ Upstream commit e9d9f9582c3d90bced286a63d1f718d4aae60a03 ] - -Conventionally, panel is listed under the root of the device tree. -When userland asks for display mode, ps8640 bridge is responsible -for returning EDID when ps8640_bridge_get_edid() is called. - -Now enable a new option of listing panel under "aux-bus" of ps8640 -bridge node in the device tree. In this case, panel driver can retrieve -EDID by triggering AUX transactions, without ps8640_bridge_get_edid() -calls at all. - -To prevent the "old" and "new" options from interfering with each -other's logic flow, disable DRM_BRIDGE_OP_EDID when the new option -is taken. - -Signed-off-by: Philip Chen -Reviewed-by: Stephen Boyd -Reviewed-by: Douglas Anderson -Signed-off-by: Douglas Anderson -Link: https://patchwork.freedesktop.org/patch/msgid/20211028105754.v5.2.I09899dea340f11feab97d719cb4b62bef3179e4b@changeid -Stable-dep-of: fc94224c2e0a ("drm/bridge: parade-ps8640: Fix regulator supply order") -Signed-off-by: Sasha Levin ---- - drivers/gpu/drm/bridge/Kconfig | 1 + - drivers/gpu/drm/bridge/parade-ps8640.c | 51 ++++++++++++++++++++------ - 2 files changed, 40 insertions(+), 12 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig -index 68ec45abc1fb..44ad70939663 100644 ---- a/drivers/gpu/drm/bridge/Kconfig -+++ b/drivers/gpu/drm/bridge/Kconfig -@@ -182,6 +182,7 @@ config DRM_PARADE_PS8622 - config DRM_PARADE_PS8640 - tristate "Parade PS8640 MIPI DSI to eDP Converter" - depends on OF -+ select DRM_DP_AUX_BUS - select DRM_KMS_HELPER - select DRM_MIPI_DSI - select DRM_PANEL -diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c -index 52f2ea6fcb26..3de796cf9328 100644 ---- a/drivers/gpu/drm/bridge/parade-ps8640.c -+++ b/drivers/gpu/drm/bridge/parade-ps8640.c -@@ -14,6 +14,7 @@ - #include - - #include -+#include - #include - #include - #include -@@ -147,6 +148,23 @@ static inline struct ps8640 *aux_to_ps8640(struct drm_dp_aux *aux) - return container_of(aux, struct ps8640, aux); - } - -+static bool ps8640_of_panel_on_aux_bus(struct device *dev) -+{ -+ struct device_node *bus, *panel; -+ -+ bus = of_get_child_by_name(dev->of_node, "aux-bus"); -+ if (!bus) -+ return false; -+ -+ panel = of_get_child_by_name(bus, "panel"); -+ of_node_put(bus); -+ if (!panel) -+ return false; -+ of_node_put(panel); -+ -+ return true; -+} -+ - static int ps8640_ensure_hpd(struct ps8640 *ps_bridge) - { - struct regmap *map = ps_bridge->regmap[PAGE2_TOP_CNTL]; -@@ -554,17 +572,6 @@ static int ps8640_probe(struct i2c_client *client) - if (!ps_bridge) - return -ENOMEM; - -- /* port@1 is ps8640 output port */ -- ret = drm_of_find_panel_or_bridge(np, 1, 0, &panel, NULL); -- if (ret < 0) -- return ret; -- if (!panel) -- return -ENODEV; -- -- ps_bridge->panel_bridge = devm_drm_panel_bridge_add(dev, panel); -- if (IS_ERR(ps_bridge->panel_bridge)) -- return PTR_ERR(ps_bridge->panel_bridge); -- - ps_bridge->supplies[0].supply = "vdd33"; - ps_bridge->supplies[1].supply = "vdd12"; - ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ps_bridge->supplies), -@@ -587,9 +594,16 @@ static int ps8640_probe(struct i2c_client *client) - - ps_bridge->bridge.funcs = &ps8640_bridge_funcs; - ps_bridge->bridge.of_node = dev->of_node; -- ps_bridge->bridge.ops = DRM_BRIDGE_OP_EDID; - ps_bridge->bridge.type = DRM_MODE_CONNECTOR_eDP; - -+ /* -+ * In the device tree, if panel is listed under aux-bus of the bridge -+ * node, panel driver should be able to retrieve EDID by itself using -+ * aux-bus. So let's not set DRM_BRIDGE_OP_EDID here. -+ */ -+ if (!ps8640_of_panel_on_aux_bus(&client->dev)) -+ ps_bridge->bridge.ops = DRM_BRIDGE_OP_EDID; -+ - ps_bridge->page[PAGE0_DP_CNTL] = client; - - ps_bridge->regmap[PAGE0_DP_CNTL] = devm_regmap_init_i2c(client, ps8640_regmap_config); -@@ -632,6 +646,19 @@ static int ps8640_probe(struct i2c_client *client) - if (ret) - return ret; - -+ devm_of_dp_aux_populate_ep_devices(&ps_bridge->aux); -+ -+ /* port@1 is ps8640 output port */ -+ ret = drm_of_find_panel_or_bridge(np, 1, 0, &panel, NULL); -+ if (ret < 0) -+ return ret; -+ if (!panel) -+ return -ENODEV; -+ -+ ps_bridge->panel_bridge = devm_drm_panel_bridge_add(dev, panel); -+ if (IS_ERR(ps_bridge->panel_bridge)) -+ return PTR_ERR(ps_bridge->panel_bridge); -+ - drm_bridge_add(&ps_bridge->bridge); - - return 0; --- -2.35.1 - diff --git a/queue-5.15/drm-bridge-parade-ps8640-use-regmap-apis.patch b/queue-5.15/drm-bridge-parade-ps8640-use-regmap-apis.patch deleted file mode 100644 index fa3440ae504..00000000000 --- a/queue-5.15/drm-bridge-parade-ps8640-use-regmap-apis.patch +++ /dev/null @@ -1,204 +0,0 @@ -From 85a877c02788c394efcf8308482dabfa98117eb0 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Tue, 21 Sep 2021 11:06:16 -0700 -Subject: drm/bridge: parade-ps8640: Use regmap APIs - -From: Philip Chen - -[ Upstream commit 692d8db0a5ca123017d7d4847856343512f87af9 ] - -Replace the direct i2c access (i2c_smbus_* functions) with regmap APIs, -which will simplify the future update on ps8640 driver. - -Signed-off-by: Philip Chen -Reviewed-by: Douglas Anderson -Acked-by: Sam Ravnborg -Reviewed-by: Stephen Boyd -[dianders: whitespace fixes reported by dim apply-branch] -Signed-off-by: Douglas Anderson -Link: https://patchwork.freedesktop.org/patch/msgid/20210921110556.v6.1.I2351df94f18d5d8debc22d4d100f36fac560409a@changeid -Stable-dep-of: fc94224c2e0a ("drm/bridge: parade-ps8640: Fix regulator supply order") -Signed-off-by: Sasha Levin ---- - drivers/gpu/drm/bridge/parade-ps8640.c | 94 ++++++++++++++++++-------- - 1 file changed, 64 insertions(+), 30 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c -index 7bd0affa057a..88c9f3404ac1 100644 ---- a/drivers/gpu/drm/bridge/parade-ps8640.c -+++ b/drivers/gpu/drm/bridge/parade-ps8640.c -@@ -9,6 +9,7 @@ - #include - #include - #include -+#include - #include - - #include -@@ -29,6 +30,11 @@ - #define VDO_EN 0x1c - #define DP_NUM_LANES 4 - -+#define COMMON_PS8640_REGMAP_CONFIG \ -+ .reg_bits = 8, \ -+ .val_bits = 8, \ -+ .cache_type = REGCACHE_NONE -+ - /* - * PS8640 uses multiple addresses: - * page[0]: for DP control -@@ -62,12 +68,48 @@ struct ps8640 { - struct drm_bridge *panel_bridge; - struct mipi_dsi_device *dsi; - struct i2c_client *page[MAX_DEVS]; -+ struct regmap *regmap[MAX_DEVS]; - struct regulator_bulk_data supplies[2]; - struct gpio_desc *gpio_reset; - struct gpio_desc *gpio_powerdown; - bool powered; - }; - -+static const struct regmap_config ps8640_regmap_config[] = { -+ [PAGE0_DP_CNTL] = { -+ COMMON_PS8640_REGMAP_CONFIG, -+ .max_register = 0xbf, -+ }, -+ [PAGE1_VDO_BDG] = { -+ COMMON_PS8640_REGMAP_CONFIG, -+ .max_register = 0xff, -+ }, -+ [PAGE2_TOP_CNTL] = { -+ COMMON_PS8640_REGMAP_CONFIG, -+ .max_register = 0xff, -+ }, -+ [PAGE3_DSI_CNTL1] = { -+ COMMON_PS8640_REGMAP_CONFIG, -+ .max_register = 0xff, -+ }, -+ [PAGE4_MIPI_PHY] = { -+ COMMON_PS8640_REGMAP_CONFIG, -+ .max_register = 0xff, -+ }, -+ [PAGE5_VPLL] = { -+ COMMON_PS8640_REGMAP_CONFIG, -+ .max_register = 0x7f, -+ }, -+ [PAGE6_DSI_CNTL2] = { -+ COMMON_PS8640_REGMAP_CONFIG, -+ .max_register = 0xff, -+ }, -+ [PAGE7_SPI_CNTL] = { -+ COMMON_PS8640_REGMAP_CONFIG, -+ .max_register = 0xff, -+ }, -+}; -+ - static inline struct ps8640 *bridge_to_ps8640(struct drm_bridge *e) - { - return container_of(e, struct ps8640, bridge); -@@ -76,13 +118,13 @@ static inline struct ps8640 *bridge_to_ps8640(struct drm_bridge *e) - static int ps8640_bridge_vdo_control(struct ps8640 *ps_bridge, - const enum ps8640_vdo_control ctrl) - { -- struct i2c_client *client = ps_bridge->page[PAGE3_DSI_CNTL1]; -+ struct regmap *map = ps_bridge->regmap[PAGE3_DSI_CNTL1]; - u8 vdo_ctrl_buf[] = { VDO_CTL_ADD, ctrl }; - int ret; - -- ret = i2c_smbus_write_i2c_block_data(client, PAGE3_SET_ADD, -- sizeof(vdo_ctrl_buf), -- vdo_ctrl_buf); -+ ret = regmap_bulk_write(map, PAGE3_SET_ADD, -+ vdo_ctrl_buf, sizeof(vdo_ctrl_buf)); -+ - if (ret < 0) { - DRM_ERROR("failed to %sable VDO: %d\n", - ctrl == ENABLE ? "en" : "dis", ret); -@@ -94,8 +136,7 @@ static int ps8640_bridge_vdo_control(struct ps8640 *ps_bridge, - - static void ps8640_bridge_poweron(struct ps8640 *ps_bridge) - { -- struct i2c_client *client = ps_bridge->page[PAGE2_TOP_CNTL]; -- unsigned long timeout; -+ struct regmap *map = ps_bridge->regmap[PAGE2_TOP_CNTL]; - int ret, status; - - if (ps_bridge->powered) -@@ -119,18 +160,12 @@ static void ps8640_bridge_poweron(struct ps8640 *ps_bridge) - */ - msleep(200); - -- timeout = jiffies + msecs_to_jiffies(200) + 1; -- -- while (time_is_after_jiffies(timeout)) { -- status = i2c_smbus_read_byte_data(client, PAGE2_GPIO_H); -- if (status < 0) { -- DRM_ERROR("failed read PAGE2_GPIO_H: %d\n", status); -- goto err_regulators_disable; -- } -- if ((status & PS_GPIO9) == PS_GPIO9) -- break; -+ ret = regmap_read_poll_timeout(map, PAGE2_GPIO_H, status, -+ status & PS_GPIO9, 20 * 1000, 200 * 1000); - -- msleep(20); -+ if (ret < 0) { -+ DRM_ERROR("failed read PAGE2_GPIO_H: %d\n", ret); -+ goto err_regulators_disable; - } - - msleep(50); -@@ -142,22 +177,15 @@ static void ps8640_bridge_poweron(struct ps8640 *ps_bridge) - * disabled by the manufacturer. Once disabled, all MCS commands are - * ignored by the display interface. - */ -- status = i2c_smbus_read_byte_data(client, PAGE2_MCS_EN); -- if (status < 0) { -- DRM_ERROR("failed read PAGE2_MCS_EN: %d\n", status); -- goto err_regulators_disable; -- } - -- ret = i2c_smbus_write_byte_data(client, PAGE2_MCS_EN, -- status & ~MCS_EN); -+ ret = regmap_update_bits(map, PAGE2_MCS_EN, MCS_EN, 0); - if (ret < 0) { - DRM_ERROR("failed write PAGE2_MCS_EN: %d\n", ret); - goto err_regulators_disable; - } - - /* Switch access edp panel's edid through i2c */ -- ret = i2c_smbus_write_byte_data(client, PAGE2_I2C_BYPASS, -- I2C_BYPASS_EN); -+ ret = regmap_write(map, PAGE2_I2C_BYPASS, I2C_BYPASS_EN); - if (ret < 0) { - DRM_ERROR("failed write PAGE2_I2C_BYPASS: %d\n", ret); - goto err_regulators_disable; -@@ -360,15 +388,21 @@ static int ps8640_probe(struct i2c_client *client) - - ps_bridge->page[PAGE0_DP_CNTL] = client; - -+ ps_bridge->regmap[PAGE0_DP_CNTL] = devm_regmap_init_i2c(client, ps8640_regmap_config); -+ if (IS_ERR(ps_bridge->regmap[PAGE0_DP_CNTL])) -+ return PTR_ERR(ps_bridge->regmap[PAGE0_DP_CNTL]); -+ - for (i = 1; i < ARRAY_SIZE(ps_bridge->page); i++) { - ps_bridge->page[i] = devm_i2c_new_dummy_device(&client->dev, - client->adapter, - client->addr + i); -- if (IS_ERR(ps_bridge->page[i])) { -- dev_err(dev, "failed i2c dummy device, address %02x\n", -- client->addr + i); -+ if (IS_ERR(ps_bridge->page[i])) - return PTR_ERR(ps_bridge->page[i]); -- } -+ -+ ps_bridge->regmap[i] = devm_regmap_init_i2c(ps_bridge->page[i], -+ ps8640_regmap_config + i); -+ if (IS_ERR(ps_bridge->regmap[i])) -+ return PTR_ERR(ps_bridge->regmap[i]); - } - - i2c_set_clientdata(client, ps_bridge); --- -2.35.1 - diff --git a/queue-5.15/series b/queue-5.15/series index 2b7efabae5e..9e871e41080 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -215,10 +215,6 @@ drm-bridge-adv7511-unregister-cec-i2c-device-after-c.patch drm-bridge-avoid-uninitialized-variable-warning.patch drm-mipi-dsi-detach-devices-when-removing-the-host.patch drm-virtio-correct-drm_gem_shmem_get_sg_table-error-.patch -drm-bridge-parade-ps8640-use-regmap-apis.patch -drm-bridge-parade-ps8640-add-support-for-aux-channel.patch -drm-bridge-parade-ps8640-enable-runtime-power-manage.patch -drm-bridge-parade-ps8640-populate-devices-on-aux-bus.patch drm-bridge-parade-ps8640-fix-regulator-supply-order.patch net-wwan-t7xx-add-control-dma-interface.patch drm-dp_mst-fix-drm_dp_dpcd_read-return-value-checks.patch