Commit bf201127 authored by Hsin-Yi Wang's avatar Hsin-Yi Wang Committed by Douglas Anderson

drm/panel-edp: Match edp_panels with panel identity

It's found that some panels have variants that they share the same panel id
although their EDID and names are different. When matching generic edp
panels, we should first match with both panel identity, which contains both
panel id and panel name. If not found, match with panel id only.
Signed-off-by: default avatarHsin-Yi Wang <hsinyi@chromium.org>
Reviewed-by: default avatarDouglas Anderson <dianders@chromium.org>
Signed-off-by: default avatarDouglas Anderson <dianders@chromium.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20240307230653.1807557-5-hsinyi@chromium.org
parent 7ff53c2f
...@@ -210,15 +210,12 @@ struct panel_desc { ...@@ -210,15 +210,12 @@ struct panel_desc {
* struct edp_panel_entry - Maps panel ID to delay / panel name. * struct edp_panel_entry - Maps panel ID to delay / panel name.
*/ */
struct edp_panel_entry { struct edp_panel_entry {
/** @panel_id: 32-bit ID for panel, encoded with drm_edid_encode_panel_id(). */ /** @ident: edid identity used for panel matching. */
u32 panel_id; const struct drm_edid_ident ident;
/** @delay: The power sequencing delays needed for this panel. */ /** @delay: The power sequencing delays needed for this panel. */
const struct panel_delay *delay; const struct panel_delay *delay;
/** @name: Name of this panel (for printing to logs). */
const char *name;
/** @override_edid_mode: Override the mode obtained by edid. */ /** @override_edid_mode: Override the mode obtained by edid. */
const struct drm_display_mode *override_edid_mode; const struct drm_display_mode *override_edid_mode;
}; };
...@@ -691,7 +688,7 @@ static int detected_panel_show(struct seq_file *s, void *data) ...@@ -691,7 +688,7 @@ static int detected_panel_show(struct seq_file *s, void *data)
else if (!p->detected_panel) else if (!p->detected_panel)
seq_puts(s, "HARDCODED\n"); seq_puts(s, "HARDCODED\n");
else else
seq_printf(s, "%s\n", p->detected_panel->name); seq_printf(s, "%s\n", p->detected_panel->ident.name);
return 0; return 0;
} }
...@@ -761,7 +758,7 @@ static void panel_edp_parse_panel_timing_node(struct device *dev, ...@@ -761,7 +758,7 @@ static void panel_edp_parse_panel_timing_node(struct device *dev,
dev_err(dev, "Reject override mode: No display_timing found\n"); dev_err(dev, "Reject override mode: No display_timing found\n");
} }
static const struct edp_panel_entry *find_edp_panel(u32 panel_id); static const struct edp_panel_entry *find_edp_panel(u32 panel_id, const struct drm_edid *edid);
static int generic_edp_panel_probe(struct device *dev, struct panel_edp *panel) static int generic_edp_panel_probe(struct device *dev, struct panel_edp *panel)
{ {
...@@ -799,7 +796,6 @@ static int generic_edp_panel_probe(struct device *dev, struct panel_edp *panel) ...@@ -799,7 +796,6 @@ static int generic_edp_panel_probe(struct device *dev, struct panel_edp *panel)
base_block = drm_edid_read_base_block(panel->ddc); base_block = drm_edid_read_base_block(panel->ddc);
if (base_block) { if (base_block) {
panel_id = drm_edid_get_panel_id(base_block); panel_id = drm_edid_get_panel_id(base_block);
drm_edid_free(base_block);
} else { } else {
dev_err(dev, "Couldn't identify panel via EDID\n"); dev_err(dev, "Couldn't identify panel via EDID\n");
ret = -EIO; ret = -EIO;
...@@ -807,7 +803,9 @@ static int generic_edp_panel_probe(struct device *dev, struct panel_edp *panel) ...@@ -807,7 +803,9 @@ static int generic_edp_panel_probe(struct device *dev, struct panel_edp *panel)
} }
drm_edid_decode_panel_id(panel_id, vend, &product_id); drm_edid_decode_panel_id(panel_id, vend, &product_id);
panel->detected_panel = find_edp_panel(panel_id); panel->detected_panel = find_edp_panel(panel_id, base_block);
drm_edid_free(base_block);
/* /*
* We're using non-optimized timings and want it really obvious that * We're using non-optimized timings and want it really obvious that
...@@ -840,7 +838,7 @@ static int generic_edp_panel_probe(struct device *dev, struct panel_edp *panel) ...@@ -840,7 +838,7 @@ static int generic_edp_panel_probe(struct device *dev, struct panel_edp *panel)
panel->detected_panel = ERR_PTR(-EINVAL); panel->detected_panel = ERR_PTR(-EINVAL);
} else { } else {
dev_info(dev, "Detected %s %s (%#06x)\n", dev_info(dev, "Detected %s %s (%#06x)\n",
vend, panel->detected_panel->name, product_id); vend, panel->detected_panel->ident.name, product_id);
/* Update the delay; everything else comes from EDID */ /* Update the delay; everything else comes from EDID */
desc->delay = *panel->detected_panel->delay; desc->delay = *panel->detected_panel->delay;
...@@ -1930,17 +1928,21 @@ static const struct panel_delay delay_200_500_e50_po2e200 = { ...@@ -1930,17 +1928,21 @@ static const struct panel_delay delay_200_500_e50_po2e200 = {
#define EDP_PANEL_ENTRY(vend_chr_0, vend_chr_1, vend_chr_2, product_id, _delay, _name) \ #define EDP_PANEL_ENTRY(vend_chr_0, vend_chr_1, vend_chr_2, product_id, _delay, _name) \
{ \ { \
.name = _name, \ .ident = { \
.panel_id = drm_edid_encode_panel_id(vend_chr_0, vend_chr_1, vend_chr_2, \ .name = _name, \
product_id), \ .panel_id = drm_edid_encode_panel_id(vend_chr_0, vend_chr_1, vend_chr_2, \
product_id), \
}, \
.delay = _delay \ .delay = _delay \
} }
#define EDP_PANEL_ENTRY2(vend_chr_0, vend_chr_1, vend_chr_2, product_id, _delay, _name, _mode) \ #define EDP_PANEL_ENTRY2(vend_chr_0, vend_chr_1, vend_chr_2, product_id, _delay, _name, _mode) \
{ \ { \
.name = _name, \ .ident = { \
.panel_id = drm_edid_encode_panel_id(vend_chr_0, vend_chr_1, vend_chr_2, \ .name = _name, \
product_id), \ .panel_id = drm_edid_encode_panel_id(vend_chr_0, vend_chr_1, vend_chr_2, \
product_id), \
}, \
.delay = _delay, \ .delay = _delay, \
.override_edid_mode = _mode \ .override_edid_mode = _mode \
} }
...@@ -2089,15 +2091,25 @@ static const struct edp_panel_entry edp_panels[] = { ...@@ -2089,15 +2091,25 @@ static const struct edp_panel_entry edp_panels[] = {
{ /* sentinal */ } { /* sentinal */ }
}; };
static const struct edp_panel_entry *find_edp_panel(u32 panel_id) static const struct edp_panel_entry *find_edp_panel(u32 panel_id, const struct drm_edid *edid)
{ {
const struct edp_panel_entry *panel; const struct edp_panel_entry *panel;
if (!panel_id) if (!panel_id)
return NULL; return NULL;
for (panel = edp_panels; panel->panel_id; panel++) /*
if (panel->panel_id == panel_id) * Match with identity first. This allows handling the case where
* vendors incorrectly reused the same panel ID for multiple panels that
* need different settings. If there's no match, try again with panel
* ID, which should be unique.
*/
for (panel = edp_panels; panel->ident.panel_id; panel++)
if (drm_edid_match(edid, &panel->ident))
return panel;
for (panel = edp_panels; panel->ident.panel_id; panel++)
if (panel->ident.panel_id == panel_id)
return panel; return panel;
return NULL; return NULL;
......
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