Message ID | 1468565618-27124-1-git-send-email-meng.yi@nxp.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On 2016-07-14 23:53, Meng Yi wrote: > This patch rework the output code to add of_graph dt binding support > for panel device and also keeps the backward compatibility > > Signed-off-by: Meng Yi <meng.yi@nxp.com> Applied, with Rob's Ack from the earlier documentation only patch for the Documentation part. -- Stefan > --- > Changes in V5: > -remove unused variable 'ret' > Changes in V4: > -simplify return value statements > -merge corresponding documentation to this patch > Changes in V3: > -simplify return value statements > Changes in V2: > -fix some coding style issue > -add fsl_dev->connector.panel check > -use fsl_dev->np and drop fsl_dev->dev->of_node > -return 'ret' when fsl_dcu_attach_panel failed > --- > .../devicetree/bindings/display/fsl,dcu.txt | 9 ++- > drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_kms.c | 2 +- > drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_output.h | 3 +- > drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c | 68 +++++++++++++++------- > 4 files changed, 57 insertions(+), 25 deletions(-) > > diff --git a/Documentation/devicetree/bindings/display/fsl,dcu.txt > b/Documentation/devicetree/bindings/display/fsl,dcu.txt > index ae55cde..63ec2a6 100644 > --- a/Documentation/devicetree/bindings/display/fsl,dcu.txt > +++ b/Documentation/devicetree/bindings/display/fsl,dcu.txt > @@ -12,7 +12,7 @@ Required properties: > - clock-names: Should be "dcu" and "pix" > See ../clocks/clock-bindings.txt for details. > - big-endian Boolean property, LS1021A DCU registers are big-endian. > -- fsl,panel: The phandle to panel node. > +- port Video port for the panel output > > Optional properties: > - fsl,tcon: The phandle to the timing controller node. > @@ -24,6 +24,11 @@ dcu: dcu@2ce0000 { > clocks = <&platform_clk 0>, <&platform_clk 0>; > clock-names = "dcu", "pix"; > big-endian; > - fsl,panel = <&panel>; > fsl,tcon = <&tcon>; > + > + port { > + dcu_out: endpoint { > + remote-endpoint = <&panel_out>; > + }; > + }; > }; > diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_kms.c > b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_kms.c > index a6e4cd5..d9d6cc1 100644 > --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_kms.c > +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_kms.c > @@ -43,7 +43,7 @@ int fsl_dcu_drm_modeset_init(struct > fsl_dcu_drm_device *fsl_dev) > if (ret) > goto err; > > - ret = fsl_dcu_drm_connector_create(fsl_dev, &fsl_dev->encoder); > + ret = fsl_dcu_create_outputs(fsl_dev); > if (ret) > goto err; > > diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_output.h > b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_output.h > index 7093109..5a7b88e 100644 > --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_output.h > +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_output.h > @@ -25,9 +25,8 @@ to_fsl_dcu_connector(struct drm_connector *con) > : NULL; > } > > -int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev, > - struct drm_encoder *encoder); > int fsl_dcu_drm_encoder_create(struct fsl_dcu_drm_device *fsl_dev, > struct drm_crtc *crtc); > +int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev); > > #endif /* __FSL_DCU_DRM_CONNECTOR_H__ */ > diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c > b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c > index 0b0989e..ba1edb1 100644 > --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c > +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c > @@ -10,6 +10,7 @@ > */ > > #include <linux/backlight.h> > +#include <linux/of_graph.h> > > #include <drm/drmP.h> > #include <drm/drm_atomic_helper.h> > @@ -132,12 +133,12 @@ static const struct drm_connector_helper_funcs > connector_helper_funcs = { > .mode_valid = fsl_dcu_drm_connector_mode_valid, > }; > > -int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev, > - struct drm_encoder *encoder) > +static int fsl_dcu_attach_panel(struct fsl_dcu_drm_device *fsl_dev, > + struct drm_panel *panel) > { > + struct drm_encoder *encoder = &fsl_dev->encoder; > struct drm_connector *connector = &fsl_dev->connector.base; > struct drm_mode_config *mode_config = &fsl_dev->drm->mode_config; > - struct device_node *panel_node; > int ret; > > fsl_dev->connector.encoder = encoder; > @@ -161,21 +162,7 @@ int fsl_dcu_drm_connector_create(struct > fsl_dcu_drm_device *fsl_dev, > mode_config->dpms_property, > DRM_MODE_DPMS_OFF); > > - panel_node = of_parse_phandle(fsl_dev->np, "fsl,panel", 0); > - if (!panel_node) { > - dev_err(fsl_dev->dev, "fsl,panel property not found\n"); > - ret = -ENODEV; > - goto err_sysfs; > - } > - > - fsl_dev->connector.panel = of_drm_find_panel(panel_node); > - if (!fsl_dev->connector.panel) { > - ret = -EPROBE_DEFER; > - goto err_panel; > - } > - of_node_put(panel_node); > - > - ret = drm_panel_attach(fsl_dev->connector.panel, connector); > + ret = drm_panel_attach(panel, connector); > if (ret) { > dev_err(fsl_dev->dev, "failed to attach panel\n"); > goto err_sysfs; > @@ -183,11 +170,52 @@ int fsl_dcu_drm_connector_create(struct > fsl_dcu_drm_device *fsl_dev, > > return 0; > > -err_panel: > - of_node_put(panel_node); > err_sysfs: > drm_connector_unregister(connector); > err_cleanup: > drm_connector_cleanup(connector); > return ret; > } > + > +static int fsl_dcu_attach_endpoint(struct fsl_dcu_drm_device *fsl_dev, > + const struct of_endpoint *ep) > +{ > + struct device_node *np; > + > + np = of_graph_get_remote_port_parent(ep->local_node); > + > + fsl_dev->connector.panel = of_drm_find_panel(np); > + of_node_put(np); > + if (fsl_dev->connector.panel) > + return fsl_dcu_attach_panel(fsl_dev, fsl_dev->connector.panel); > + > + return -ENODEV; > +} > + > +int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev) > +{ > + struct of_endpoint ep; > + struct device_node *ep_node, *panel_node; > + int ret; > + > + /* This is for backward compatibility */ > + panel_node = of_parse_phandle(fsl_dev->np, "fsl,panel", 0); > + if (panel_node) { > + fsl_dev->connector.panel = of_drm_find_panel(panel_node); > + of_node_put(panel_node); > + if (!fsl_dev->connector.panel) > + return -EPROBE_DEFER; > + return fsl_dcu_attach_panel(fsl_dev, fsl_dev->connector.panel); > + } > + > + ep_node = of_graph_get_next_endpoint(fsl_dev->np, NULL); > + if (!ep_node) > + return -ENODEV; > + > + ret = of_graph_parse_endpoint(ep_node, &ep); > + of_node_put(ep_node); > + if (ret) > + return -ENODEV; > + > + return fsl_dcu_attach_endpoint(fsl_dev, &ep); > +}
diff --git a/Documentation/devicetree/bindings/display/fsl,dcu.txt b/Documentation/devicetree/bindings/display/fsl,dcu.txt index ae55cde..63ec2a6 100644 --- a/Documentation/devicetree/bindings/display/fsl,dcu.txt +++ b/Documentation/devicetree/bindings/display/fsl,dcu.txt @@ -12,7 +12,7 @@ Required properties: - clock-names: Should be "dcu" and "pix" See ../clocks/clock-bindings.txt for details. - big-endian Boolean property, LS1021A DCU registers are big-endian. -- fsl,panel: The phandle to panel node. +- port Video port for the panel output Optional properties: - fsl,tcon: The phandle to the timing controller node. @@ -24,6 +24,11 @@ dcu: dcu@2ce0000 { clocks = <&platform_clk 0>, <&platform_clk 0>; clock-names = "dcu", "pix"; big-endian; - fsl,panel = <&panel>; fsl,tcon = <&tcon>; + + port { + dcu_out: endpoint { + remote-endpoint = <&panel_out>; + }; + }; }; diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_kms.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_kms.c index a6e4cd5..d9d6cc1 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_kms.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_kms.c @@ -43,7 +43,7 @@ int fsl_dcu_drm_modeset_init(struct fsl_dcu_drm_device *fsl_dev) if (ret) goto err; - ret = fsl_dcu_drm_connector_create(fsl_dev, &fsl_dev->encoder); + ret = fsl_dcu_create_outputs(fsl_dev); if (ret) goto err; diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_output.h b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_output.h index 7093109..5a7b88e 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_output.h +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_output.h @@ -25,9 +25,8 @@ to_fsl_dcu_connector(struct drm_connector *con) : NULL; } -int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev, - struct drm_encoder *encoder); int fsl_dcu_drm_encoder_create(struct fsl_dcu_drm_device *fsl_dev, struct drm_crtc *crtc); +int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev); #endif /* __FSL_DCU_DRM_CONNECTOR_H__ */ diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c index 0b0989e..ba1edb1 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c @@ -10,6 +10,7 @@ */ #include <linux/backlight.h> +#include <linux/of_graph.h> #include <drm/drmP.h> #include <drm/drm_atomic_helper.h> @@ -132,12 +133,12 @@ static const struct drm_connector_helper_funcs connector_helper_funcs = { .mode_valid = fsl_dcu_drm_connector_mode_valid, }; -int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev, - struct drm_encoder *encoder) +static int fsl_dcu_attach_panel(struct fsl_dcu_drm_device *fsl_dev, + struct drm_panel *panel) { + struct drm_encoder *encoder = &fsl_dev->encoder; struct drm_connector *connector = &fsl_dev->connector.base; struct drm_mode_config *mode_config = &fsl_dev->drm->mode_config; - struct device_node *panel_node; int ret; fsl_dev->connector.encoder = encoder; @@ -161,21 +162,7 @@ int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev, mode_config->dpms_property, DRM_MODE_DPMS_OFF); - panel_node = of_parse_phandle(fsl_dev->np, "fsl,panel", 0); - if (!panel_node) { - dev_err(fsl_dev->dev, "fsl,panel property not found\n"); - ret = -ENODEV; - goto err_sysfs; - } - - fsl_dev->connector.panel = of_drm_find_panel(panel_node); - if (!fsl_dev->connector.panel) { - ret = -EPROBE_DEFER; - goto err_panel; - } - of_node_put(panel_node); - - ret = drm_panel_attach(fsl_dev->connector.panel, connector); + ret = drm_panel_attach(panel, connector); if (ret) { dev_err(fsl_dev->dev, "failed to attach panel\n"); goto err_sysfs; @@ -183,11 +170,52 @@ int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev, return 0; -err_panel: - of_node_put(panel_node); err_sysfs: drm_connector_unregister(connector); err_cleanup: drm_connector_cleanup(connector); return ret; } + +static int fsl_dcu_attach_endpoint(struct fsl_dcu_drm_device *fsl_dev, + const struct of_endpoint *ep) +{ + struct device_node *np; + + np = of_graph_get_remote_port_parent(ep->local_node); + + fsl_dev->connector.panel = of_drm_find_panel(np); + of_node_put(np); + if (fsl_dev->connector.panel) + return fsl_dcu_attach_panel(fsl_dev, fsl_dev->connector.panel); + + return -ENODEV; +} + +int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev) +{ + struct of_endpoint ep; + struct device_node *ep_node, *panel_node; + int ret; + + /* This is for backward compatibility */ + panel_node = of_parse_phandle(fsl_dev->np, "fsl,panel", 0); + if (panel_node) { + fsl_dev->connector.panel = of_drm_find_panel(panel_node); + of_node_put(panel_node); + if (!fsl_dev->connector.panel) + return -EPROBE_DEFER; + return fsl_dcu_attach_panel(fsl_dev, fsl_dev->connector.panel); + } + + ep_node = of_graph_get_next_endpoint(fsl_dev->np, NULL); + if (!ep_node) + return -ENODEV; + + ret = of_graph_parse_endpoint(ep_node, &ep); + of_node_put(ep_node); + if (ret) + return -ENODEV; + + return fsl_dcu_attach_endpoint(fsl_dev, &ep); +}
This patch rework the output code to add of_graph dt binding support for panel device and also keeps the backward compatibility Signed-off-by: Meng Yi <meng.yi@nxp.com> --- Changes in V5: -remove unused variable 'ret' Changes in V4: -simplify return value statements -merge corresponding documentation to this patch Changes in V3: -simplify return value statements Changes in V2: -fix some coding style issue -add fsl_dev->connector.panel check -use fsl_dev->np and drop fsl_dev->dev->of_node -return 'ret' when fsl_dcu_attach_panel failed --- .../devicetree/bindings/display/fsl,dcu.txt | 9 ++- drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_kms.c | 2 +- drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_output.h | 3 +- drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c | 68 +++++++++++++++------- 4 files changed, 57 insertions(+), 25 deletions(-)