Hi, On Fri, Jan 11, 2019 at 05:51:17AM +0200, Laurent Pinchart wrote: > Hook up drm_panel support in the omapdrm driver. The change is > relatively simply as the way has been paved by drm_bridge support > already. In addition to looking up, attaching to and detaching from the > panel, we only need to add panel support in the connector .get_modes() > handler, take connector bus flags (set by the panel) into account, and > enable/disable the panel in the encoder enable/disable operations > handlers. > > Signed-off-by: Laurent Pinchart <laurent.pinchart@xxxxxxxxxxxxxxxx> > Reviewed-by: Sebastian Reichel <sebastian.reichel@xxxxxxxxxxxxx> > --- Tested-by: Sebastian Reichel <sebastian.reichel@xxxxxxxxxxxxx> -- Sebastian > drivers/gpu/drm/omapdrm/dss/base.c | 12 ++++--- > drivers/gpu/drm/omapdrm/dss/omapdss.h | 1 + > drivers/gpu/drm/omapdrm/dss/output.c | 7 +++- > drivers/gpu/drm/omapdrm/omap_connector.c | 9 ++++++ > drivers/gpu/drm/omapdrm/omap_drv.c | 15 ++++++++- > drivers/gpu/drm/omapdrm/omap_encoder.c | 41 ++++++++++++++++-------- > 6 files changed, 65 insertions(+), 20 deletions(-) > > diff --git a/drivers/gpu/drm/omapdrm/dss/base.c b/drivers/gpu/drm/omapdrm/dss/base.c > index 09c9f2971aa2..3c088cd2ceab 100644 > --- a/drivers/gpu/drm/omapdrm/dss/base.c > +++ b/drivers/gpu/drm/omapdrm/dss/base.c > @@ -157,7 +157,8 @@ struct omap_dss_device *omapdss_device_next_output(struct omap_dss_device *from) > goto done; > } > > - if (dssdev->id && (dssdev->next || dssdev->bridge)) > + if (dssdev->id && > + (dssdev->next || dssdev->bridge || dssdev->panel)) > goto done; > } > > @@ -192,10 +193,11 @@ int omapdss_device_connect(struct dss_device *dss, > if (!dst) { > /* > * The destination is NULL when the source is connected to a > - * bridge instead of a DSS device. Stop here, we will attach the > - * bridge later when we will have a DRM encoder. > + * bridge or panel instead of a DSS device. Stop here, we will > + * attach the bridge or panel later when we will have a DRM > + * encoder. > */ > - return src && src->bridge ? 0 : -EINVAL; > + return src && (src->bridge || src->panel) ? 0 : -EINVAL; > } > > if (omapdss_device_is_connected(dst)) > @@ -223,7 +225,7 @@ void omapdss_device_disconnect(struct omap_dss_device *src, > dst ? dev_name(dst->dev) : "NULL"); > > if (!dst) { > - WARN_ON(!src->bridge); > + WARN_ON(!src->bridge && !src->panel); > return; > } > > diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h > index f47e9b94288f..0c734d1f89e1 100644 > --- a/drivers/gpu/drm/omapdrm/dss/omapdss.h > +++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h > @@ -411,6 +411,7 @@ struct omap_dss_device { > struct dss_device *dss; > struct omap_dss_device *next; > struct drm_bridge *bridge; > + struct drm_panel *panel; > > struct list_head list; > > diff --git a/drivers/gpu/drm/omapdrm/dss/output.c b/drivers/gpu/drm/omapdrm/dss/output.c > index 2a53025c2fde..10a9ee5cdc61 100644 > --- a/drivers/gpu/drm/omapdrm/dss/output.c > +++ b/drivers/gpu/drm/omapdrm/dss/output.c > @@ -22,6 +22,8 @@ > #include <linux/of.h> > #include <linux/of_graph.h> > > +#include <drm/drm_panel.h> > + > #include "dss.h" > #include "omapdss.h" > > @@ -37,6 +39,9 @@ int omapdss_device_init_output(struct omap_dss_device *out) > > out->next = omapdss_find_device_by_node(remote_node); > out->bridge = of_drm_find_bridge(remote_node); > + out->panel = of_drm_find_panel(remote_node); > + if (IS_ERR(out->panel)) > + out->panel = NULL; > > of_node_put(remote_node); > > @@ -47,7 +52,7 @@ int omapdss_device_init_output(struct omap_dss_device *out) > return -EINVAL; > } > > - return out->next || out->bridge ? 0 : -EPROBE_DEFER; > + return out->next || out->bridge || out->panel ? 0 : -EPROBE_DEFER; > } > EXPORT_SYMBOL(omapdss_device_init_output); > > diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c > index f528baa80114..2da16f00cfae 100644 > --- a/drivers/gpu/drm/omapdrm/omap_connector.c > +++ b/drivers/gpu/drm/omapdrm/omap_connector.c > @@ -18,6 +18,7 @@ > #include <drm/drm_atomic_helper.h> > #include <drm/drm_crtc.h> > #include <drm/drm_crtc_helper.h> > +#include <drm/drm_panel.h> > > #include "omap_drv.h" > > @@ -211,6 +212,7 @@ static int omap_connector_get_modes_edid(struct drm_connector *connector, > > static int omap_connector_get_modes(struct drm_connector *connector) > { > + struct omap_connector *omap_connector = to_omap_connector(connector); > struct omap_dss_device *dssdev; > > DBG("%s", connector->name); > @@ -233,6 +235,13 @@ static int omap_connector_get_modes(struct drm_connector *connector) > if (dssdev) > return dssdev->ops->get_modes(dssdev, connector); > > + /* > + * Otherwise if the display pipeline uses a drm_panel, we delegate the > + * operation to the panel API. > + */ > + if (omap_connector->output->panel) > + return drm_panel_get_modes(omap_connector->output->panel); > + > /* > * We can't retrieve modes, which can happen for instance for a DVI or > * VGA output with the DDC bus unconnected. The KMS core will add the > diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c > index 35c4669dc69d..73a21ca3ae47 100644 > --- a/drivers/gpu/drm/omapdrm/omap_drv.c > +++ b/drivers/gpu/drm/omapdrm/omap_drv.c > @@ -23,6 +23,7 @@ > #include <drm/drm_atomic_helper.h> > #include <drm/drm_crtc_helper.h> > #include <drm/drm_fb_helper.h> > +#include <drm/drm_panel.h> > > #include "omap_dmm_tiler.h" > #include "omap_drv.h" > @@ -137,6 +138,9 @@ static void omap_disconnect_pipelines(struct drm_device *ddev) > for (i = 0; i < priv->num_pipes; i++) { > struct omap_drm_pipeline *pipe = &priv->pipes[i]; > > + if (pipe->output->panel) > + drm_panel_detach(pipe->output->panel); > + > omapdss_device_disconnect(NULL, pipe->output); > > omapdss_device_put(pipe->output); > @@ -214,13 +218,15 @@ static int omap_display_id(struct omap_dss_device *output) > display = omapdss_display_get(output); > node = display->dev->of_node; > omapdss_device_put(display); > - } else { > + } else if (output->bridge) { > struct drm_bridge *bridge = output->bridge; > > while (bridge->next) > bridge = bridge->next; > > node = bridge->of_node; > + } else if (output->panel) { > + node = output->panel->dev->of_node; > } > > return node ? of_alias_get_id(node, "display") : -ENODEV; > @@ -335,6 +341,13 @@ static int omap_modeset_init(struct drm_device *dev) > return -ENOMEM; > > drm_connector_attach_encoder(pipe->connector, encoder); > + > + if (pipe->output->panel) { > + ret = drm_panel_attach(pipe->output->panel, > + pipe->connector); > + if (ret < 0) > + return ret; > + } > } > > crtc = omap_crtc_init(dev, pipe, priv->planes[i]); > diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c b/drivers/gpu/drm/omapdrm/omap_encoder.c > index 76f94cc0c0cf..2b21e057b78b 100644 > --- a/drivers/gpu/drm/omapdrm/omap_encoder.c > +++ b/drivers/gpu/drm/omapdrm/omap_encoder.c > @@ -20,6 +20,7 @@ > #include <drm/drm_crtc.h> > #include <drm/drm_crtc_helper.h> > #include <drm/drm_edid.h> > +#include <drm/drm_panel.h> > > #include "omap_drv.h" > > @@ -79,22 +80,15 @@ static void omap_encoder_update_videomode_flags(struct videomode *vm, > } > } > > -static void omap_encoder_hdmi_mode_set(struct drm_encoder *encoder, > +static void omap_encoder_hdmi_mode_set(struct drm_connector *connector, > + struct drm_encoder *encoder, > struct drm_display_mode *adjusted_mode) > { > - struct drm_device *dev = encoder->dev; > struct omap_encoder *omap_encoder = to_omap_encoder(encoder); > struct omap_dss_device *dssdev = omap_encoder->output; > - struct drm_connector *connector; > bool hdmi_mode; > > - hdmi_mode = false; > - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { > - if (connector->encoder == encoder) { > - hdmi_mode = omap_connector_get_hdmi_mode(connector); > - break; > - } > - } > + hdmi_mode = omap_connector_get_hdmi_mode(connector); > > if (dssdev->ops->hdmi.set_hdmi_mode) > dssdev->ops->hdmi.set_hdmi_mode(dssdev, hdmi_mode); > @@ -117,8 +111,16 @@ static void omap_encoder_mode_set(struct drm_encoder *encoder, > struct omap_encoder *omap_encoder = to_omap_encoder(encoder); > struct omap_dss_device *output = omap_encoder->output; > struct omap_dss_device *dssdev; > + struct drm_device *dev = encoder->dev; > + struct drm_connector *connector; > struct drm_bridge *bridge; > struct videomode vm = { 0 }; > + u32 bus_flags; > + > + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { > + if (connector->encoder == encoder) > + break; > + } > > drm_display_mode_to_videomode(adjusted_mode, &vm); > > @@ -135,8 +137,6 @@ static void omap_encoder_mode_set(struct drm_encoder *encoder, > omap_encoder_update_videomode_flags(&vm, dssdev->bus_flags); > > for (bridge = output->bridge; bridge; bridge = bridge->next) { > - u32 bus_flags; > - > if (!bridge->timings) > continue; > > @@ -144,6 +144,9 @@ static void omap_encoder_mode_set(struct drm_encoder *encoder, > omap_encoder_update_videomode_flags(&vm, bus_flags); > } > > + bus_flags = connector->display_info.bus_flags; > + omap_encoder_update_videomode_flags(&vm, bus_flags); > + > /* Set timings for all devices in the display pipeline. */ > dss_mgr_set_timings(output, &vm); > > @@ -154,7 +157,7 @@ static void omap_encoder_mode_set(struct drm_encoder *encoder, > > /* Set the HDMI mode and HDMI infoframe if applicable. */ > if (output->type == OMAP_DISPLAY_TYPE_HDMI) > - omap_encoder_hdmi_mode_set(encoder, adjusted_mode); > + omap_encoder_hdmi_mode_set(connector, encoder, adjusted_mode); > } > > static void omap_encoder_disable(struct drm_encoder *encoder) > @@ -165,6 +168,12 @@ static void omap_encoder_disable(struct drm_encoder *encoder) > > dev_dbg(dev->dev, "disable(%s)\n", dssdev->name); > > + /* Disable the panel if present. */ > + if (dssdev->panel) { > + drm_panel_disable(dssdev->panel); > + drm_panel_unprepare(dssdev->panel); > + } > + > /* > * Disable the chain of external devices, starting at the one at the > * internal encoder's output. > @@ -214,6 +223,12 @@ static void omap_encoder_enable(struct drm_encoder *encoder) > * internal encoder's output. > */ > omapdss_device_enable(dssdev->next); > + > + /* Enable the panel if present. */ > + if (dssdev->panel) { > + drm_panel_prepare(dssdev->panel); > + drm_panel_enable(dssdev->panel); > + } > } > > static int omap_encoder_atomic_check(struct drm_encoder *encoder, > -- > Regards, > > Laurent Pinchart > > _______________________________________________ > dri-devel mailing list > dri-devel@xxxxxxxxxxxxxxxxxxxxx > https://lists.freedesktop.org/mailman/listinfo/dri-devel
Attachment:
signature.asc
Description: PGP signature
_______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel