Many panel data sheets additionally to typical values list allowed ranges for timings such as hsync/vsync lengths, porches, and the pixel clock rate. This patch allows simple panels to store a struct display_timing in place of the struct drm_display_mode used before. The get_modes panel_ops callback calculates the drm_display_mode list from the typical timings and the get_timings callback returns the timings to the connected encoder for mode fixup and validation. Signed-off-by: Philipp Zabel <p.zabel@xxxxxxxxxxxxxx> --- drivers/gpu/drm/panel/panel-simple.c | 40 ++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index c4b6167..895af09 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -33,9 +33,14 @@ #include <drm/drm_mipi_dsi.h> #include <drm/drm_panel.h> +#include <video/display_timing.h> +#include <video/videomode.h> + struct panel_desc { const struct drm_display_mode *modes; unsigned int num_modes; + const struct display_timing *timings; + unsigned int num_timings; unsigned int bpc; @@ -92,6 +97,25 @@ static int panel_simple_get_fixed_modes(struct panel_simple *panel) if (!panel->desc) return 0; + for (i = 0; i < panel->desc->num_timings; i++) { + const struct display_timing *dt = &panel->desc->timings[i]; + struct videomode vm; + + videomode_from_timing(dt, &vm); + mode = drm_mode_create(drm); + if (!mode) { + dev_err(drm->dev, "failed to add mode %ux%u\n", + dt->hactive.typ, dt->vactive.typ); + continue; + } + + drm_display_mode_from_videomode(&vm, mode); + drm_mode_set_name(mode); + + drm_mode_probed_add(connector, mode); + num++; + } + for (i = 0; i < panel->desc->num_modes; i++) { const struct drm_display_mode *m = &panel->desc->modes[i]; @@ -221,12 +245,28 @@ static int panel_simple_get_modes(struct drm_panel *panel) return num; } +static int panel_simple_get_timings(struct drm_panel *panel, + unsigned int num_timings, + struct display_timing *timings) +{ + struct panel_simple *p = to_panel_simple(panel); + int i; + + if (timings) { + for (i = 0; i < min(num_timings, p->desc->num_timings); i++) + timings[i] = p->desc->timings[i]; + } + + return p->desc->num_timings; +} + static const struct drm_panel_funcs panel_simple_funcs = { .disable = panel_simple_disable, .unprepare = panel_simple_unprepare, .prepare = panel_simple_prepare, .enable = panel_simple_enable, .get_modes = panel_simple_get_modes, + .get_timings = panel_simple_get_timings, }; static int panel_simple_probe(struct device *dev, const struct panel_desc *desc) -- 2.1.3 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel