@@ -168,23 +168,35 @@ static bool ps8640_of_panel_on_aux_bus(struct device *dev)
return true;
}
-static int ps8640_ensure_hpd(struct ps8640 *ps_bridge)
+static int _ps8640_wait_hpd_asserted(struct ps8640 *ps_bridge, unsigned long wait_us)
{
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);
+ return regmap_read_poll_timeout(map, PAGE2_GPIO_H, status,
+ status & PS_GPIO9, wait_us / 10, wait_us);
+}
- if (ret < 0)
- dev_warn(dev, "HPD didn't go high: %d\n", ret);
+static int ps8640_wait_hpd_asserted(struct drm_dp_aux *aux, unsigned long wait_us)
+{
+ struct ps8640 *ps_bridge = aux_to_ps8640(aux);
+ struct device *dev = &ps_bridge->page[PAGE0_DP_CNTL]->dev;
+ int ret;
+
+ /*
+ * Note that this function is called by code that has already powered
+ * the panel. We have to power ourselves up but we don't need to worry
+ * about powering the panel.
+ */
+ pm_runtime_get_sync(dev);
+ ret = _ps8640_wait_hpd_asserted(ps_bridge, wait_us);
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
return ret;
}
@@ -323,9 +335,7 @@ static ssize_t ps8640_aux_transfer(struct drm_dp_aux *aux,
int ret;
pm_runtime_get_sync(dev);
- ret = ps8640_ensure_hpd(ps_bridge);
- if (!ret)
- ret = ps8640_aux_transfer_msg(aux, msg);
+ ret = ps8640_aux_transfer_msg(aux, msg);
pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
@@ -369,8 +379,8 @@ static int __maybe_unused ps8640_resume(struct device *dev)
* 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.
+ * _ps8640_wait_hpd_asserted(). For now we'll keep this mystery delay
+ * just in case.
*/
msleep(200);
@@ -406,7 +416,9 @@ static void ps8640_pre_enable(struct drm_bridge *bridge)
int ret;
pm_runtime_get_sync(dev);
- ps8640_ensure_hpd(ps_bridge);
+ ret = _ps8640_wait_hpd_asserted(ps_bridge, 200 * 1000);
+ if (ret < 0)
+ dev_warn(dev, "HPD didn't go high: %d\n", ret);
/*
* The Manufacturer Command Set (MCS) is a device dependent interface
@@ -682,6 +694,7 @@ static int ps8640_probe(struct i2c_client *client)
ps_bridge->aux.name = "parade-ps8640-aux";
ps_bridge->aux.dev = dev;
ps_bridge->aux.transfer = ps8640_aux_transfer;
+ ps_bridge->aux.wait_hpd_asserted = ps8640_wait_hpd_asserted;
drm_dp_aux_init(&ps_bridge->aux);
pm_runtime_enable(dev);