Commit 11feaef6 authored by Pin-yen Lin's avatar Pin-yen Lin Committed by Robert Foss

drm/bridge: it6505: Add caching for EDID

Add caching when EDID is read, and invalidate the cache until the
bridge detects HPD low or sink count changes on HPD_IRQ.

It takes 1.2s for IT6505 bridge to read a 3-block EDID, and skipping
one EDID read would be a notable difference on user experience.
Signed-off-by: default avatarPin-yen Lin <treapking@chromium.org>
Reviewed-by: default avatarRobert Foss <robert.foss@linaro.org>
Signed-off-by: default avatarRobert Foss <robert.foss@linaro.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20221115112720.911158-1-treapking@chromium.org
parent 2a9df204
...@@ -456,6 +456,8 @@ struct it6505 { ...@@ -456,6 +456,8 @@ struct it6505 {
/* it6505 driver hold option */ /* it6505 driver hold option */
bool enable_drv_hold; bool enable_drv_hold;
struct edid *cached_edid;
}; };
struct it6505_step_train_para { struct it6505_step_train_para {
...@@ -2243,6 +2245,12 @@ static void it6505_plugged_status_to_codec(struct it6505 *it6505) ...@@ -2243,6 +2245,12 @@ static void it6505_plugged_status_to_codec(struct it6505 *it6505)
status == connector_status_connected); status == connector_status_connected);
} }
static void it6505_remove_edid(struct it6505 *it6505)
{
kfree(it6505->cached_edid);
it6505->cached_edid = NULL;
}
static int it6505_process_hpd_irq(struct it6505 *it6505) static int it6505_process_hpd_irq(struct it6505 *it6505)
{ {
struct device *dev = &it6505->client->dev; struct device *dev = &it6505->client->dev;
...@@ -2269,6 +2277,7 @@ static int it6505_process_hpd_irq(struct it6505 *it6505) ...@@ -2269,6 +2277,7 @@ static int it6505_process_hpd_irq(struct it6505 *it6505)
it6505_reset_logic(it6505); it6505_reset_logic(it6505);
it6505_int_mask_enable(it6505); it6505_int_mask_enable(it6505);
it6505_init(it6505); it6505_init(it6505);
it6505_remove_edid(it6505);
return 0; return 0;
} }
...@@ -2352,6 +2361,7 @@ static void it6505_irq_hpd(struct it6505 *it6505) ...@@ -2352,6 +2361,7 @@ static void it6505_irq_hpd(struct it6505 *it6505)
it6505_video_reset(it6505); it6505_video_reset(it6505);
} else { } else {
memset(it6505->dpcd, 0, sizeof(it6505->dpcd)); memset(it6505->dpcd, 0, sizeof(it6505->dpcd));
it6505_remove_edid(it6505);
if (it6505->hdcp_desired) if (it6505->hdcp_desired)
it6505_stop_hdcp(it6505); it6505_stop_hdcp(it6505);
...@@ -3011,16 +3021,18 @@ static struct edid *it6505_bridge_get_edid(struct drm_bridge *bridge, ...@@ -3011,16 +3021,18 @@ static struct edid *it6505_bridge_get_edid(struct drm_bridge *bridge,
{ {
struct it6505 *it6505 = bridge_to_it6505(bridge); struct it6505 *it6505 = bridge_to_it6505(bridge);
struct device *dev = &it6505->client->dev; struct device *dev = &it6505->client->dev;
struct edid *edid;
edid = drm_do_get_edid(connector, it6505_get_edid_block, it6505); if (!it6505->cached_edid) {
it6505->cached_edid = drm_do_get_edid(connector, it6505_get_edid_block,
it6505);
if (!edid) { if (!it6505->cached_edid) {
DRM_DEV_DEBUG_DRIVER(dev, "failed to get edid!"); DRM_DEV_DEBUG_DRIVER(dev, "failed to get edid!");
return NULL; return NULL;
}
} }
return edid; return drm_edid_duplicate(it6505->cached_edid);
} }
static const struct drm_bridge_funcs it6505_bridge_funcs = { static const struct drm_bridge_funcs it6505_bridge_funcs = {
...@@ -3360,6 +3372,7 @@ static void it6505_i2c_remove(struct i2c_client *client) ...@@ -3360,6 +3372,7 @@ static void it6505_i2c_remove(struct i2c_client *client)
drm_dp_aux_unregister(&it6505->aux); drm_dp_aux_unregister(&it6505->aux);
it6505_debugfs_remove(it6505); it6505_debugfs_remove(it6505);
it6505_poweroff(it6505); it6505_poweroff(it6505);
it6505_remove_edid(it6505);
} }
static const struct i2c_device_id it6505_id[] = { static const struct i2c_device_id it6505_id[] = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment