Hi Boris! Dne ponedeljek, 26. avgust 2019 ob 17:26:46 CEST je Boris Brezillon napisal(a): > Some LVDS encoder might support several input/output bus formats. Add > a way to describe the one used on a specific design by adding optional > 'data-mapping' properties to the input/output ports. > > Signed-off-by: Boris Brezillon <boris.brezillon@xxxxxxxxxxxxx> > --- > Changes in v2: > * Make the bus-format negotiation logic more generic > --- > .../display/bridge/lvds-transmitter.txt | 12 ++ > drivers/gpu/drm/bridge/lvds-encoder.c | 105 ++++++++++++++++++ > 2 files changed, 117 insertions(+) > > diff --git > a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt > b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt > index 60091db5dfa5..db51eab216f7 100644 > --- a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt > +++ b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt > @@ -36,6 +36,18 @@ graph bindings specified in > Documentation/devicetree/bindings/graph.txt. - Video port 0 for parallel > input > - Video port 1 for LVDS output > > +Optional port 0 node properties: > + > +- data-mapping: can be one of the following values > + "rgb-24" > + "rgb-18" > + > +Optional port 0 node properties: You probably mean port 1 ^^^ ? Anyway, devicetree doc changes should be separate patch and be send to DT ML (I can't see it in CC). Best regards, Jernej > + > +- data-mapping: can be one of the following values > + "jeida-18" > + "jeida-24" > + "vesa-24" > > Example > ------- > diff --git a/drivers/gpu/drm/bridge/lvds-encoder.c > b/drivers/gpu/drm/bridge/lvds-encoder.c index 2ab2c234f26c..38cad7a7d828 > 100644 > --- a/drivers/gpu/drm/bridge/lvds-encoder.c > +++ b/drivers/gpu/drm/bridge/lvds-encoder.c > @@ -6,6 +6,7 @@ > #include <linux/gpio/consumer.h> > #include <linux/module.h> > #include <linux/of.h> > +#include <linux/of_device.h> > #include <linux/of_graph.h> > #include <linux/platform_device.h> > > @@ -16,6 +17,8 @@ struct lvds_encoder { > struct drm_bridge bridge; > struct drm_bridge *panel_bridge; > struct gpio_desc *powerdown_gpio; > + u32 output_fmt; > + u32 input_fmt; > }; > > static int lvds_encoder_attach(struct drm_bridge *bridge) > @@ -48,12 +51,86 @@ static void lvds_encoder_disable(struct drm_bridge > *bridge) gpiod_set_value_cansleep(lvds_encoder->powerdown_gpio, 1); > } > > +static void lvds_atomic_get_input_bus_fmts(struct drm_bridge *bridge, > + struct drm_bridge_state *bridge_state, > + struct drm_crtc_state *crtc_state, > + struct drm_connector_state *conn_state, > + u32 output_fmt, > + unsigned int *num_input_fmts, > + u32 *input_fmts) > +{ > + struct lvds_encoder *lvds_encoder = container_of(bridge, > + struct lvds_encoder, > + bridge); > + > + if (output_fmt == MEDIA_BUS_FMT_FIXED || > + output_fmt == lvds_encoder->output_fmt) > + *num_input_fmts = 1; > + else > + *num_input_fmts = 0; > + > + if (*num_input_fmts && input_fmts) > + input_fmts[0] = lvds_encoder->input_fmt; > +} > + > +static int lvds_encoder_atomic_check(struct drm_bridge *bridge, > + struct drm_bridge_state *bridge_state, > + struct drm_crtc_state *crtc_state, > + struct drm_connector_state *conn_state) > +{ > + /* Propagate the bus_flags. */ > + bridge_state->input_bus_cfg.flags = bridge_state- >output_bus_cfg.flags; > + return 0; > +} > + > static struct drm_bridge_funcs funcs = { > .attach = lvds_encoder_attach, > .enable = lvds_encoder_enable, > .disable = lvds_encoder_disable, > + .atomic_get_input_bus_fmts = lvds_atomic_get_input_bus_fmts, > + .atomic_check = lvds_encoder_atomic_check, > }; > > +struct of_data_mapping { > + const char *name; > + u32 id; > +}; > + > +static const struct of_data_mapping output_data_mappings[] = { > + { "jeida-18", MEDIA_BUS_FMT_RGB666_1X7X3_SPWG }, > + { "jeida-24", MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA }, > + { "vesa-24", MEDIA_BUS_FMT_RGB888_1X7X4_SPWG }, > +}; > + > +static const struct of_data_mapping input_data_mappings[] = { > + { "rgb-24", MEDIA_BUS_FMT_RGB888_1X24 }, > + { "rgb-18", MEDIA_BUS_FMT_RGB666_1X18 }, > +}; > + > +static int of_get_data_mapping(struct device_node *port, > + const struct of_data_mapping *mappings, > + unsigned int num_mappings, > + u32 *fmt) > +{ > + const char *name = NULL; > + unsigned int i; > + > + of_property_read_string(port, "data-mapping", &name); > + if (!name) { > + *fmt = MEDIA_BUS_FMT_FIXED; > + return 0; > + } > + > + for (i = 0; i < num_mappings; i++) { > + if (!strcmp(mappings[i].name, name)) { > + *fmt = mappings[i].id; > + return 0; > + } > + } > + > + return -ENOTSUPP; > +} > + > static int lvds_encoder_probe(struct platform_device *pdev) > { > struct device *dev = &pdev->dev; > @@ -62,11 +139,15 @@ static int lvds_encoder_probe(struct platform_device > *pdev) struct device_node *panel_node; > struct drm_panel *panel; > struct lvds_encoder *lvds_encoder; > + int ret; > > lvds_encoder = devm_kzalloc(dev, sizeof(*lvds_encoder), GFP_KERNEL); > if (!lvds_encoder) > return -ENOMEM; > > + lvds_encoder->input_fmt = MEDIA_BUS_FMT_FIXED; > + lvds_encoder->output_fmt = MEDIA_BUS_FMT_FIXED; > + > lvds_encoder->powerdown_gpio = devm_gpiod_get_optional(dev, "powerdown", > GPIOD_OUT_HIGH); > if (IS_ERR(lvds_encoder->powerdown_gpio)) { > @@ -77,6 +158,21 @@ static int lvds_encoder_probe(struct platform_device > *pdev) return err; > } > > + port = of_graph_get_port_by_id(dev->of_node, 0); > + if (!port) { > + dev_dbg(dev, "port 0 not found\n"); > + return -ENXIO; > + } > + > + ret = of_get_data_mapping(port, input_data_mappings, > + ARRAY_SIZE(input_data_mappings), > + &lvds_encoder->input_fmt); > + of_node_put(port); > + if (ret) { > + dev_dbg(dev, "unsupported input data-mapping\n"); > + return ret; > + } > + > /* Locate the panel DT node. */ > port = of_graph_get_port_by_id(dev->of_node, 1); > if (!port) { > @@ -84,6 +180,15 @@ static int lvds_encoder_probe(struct platform_device > *pdev) return -ENXIO; > } > > + ret = of_get_data_mapping(port, output_data_mappings, > + ARRAY_SIZE(output_data_mappings), > + &lvds_encoder->output_fmt); > + if (ret) { > + of_node_put(port); > + dev_dbg(dev, "unsupported output data-mapping\n"); > + return ret; > + } > + > endpoint = of_get_child_by_name(port, "endpoint"); > of_node_put(port); > if (!endpoint) { _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel