#define ATMEL_HLCDC_RGB888_OUTPUT      BIT(3)
 #define ATMEL_HLCDC_OUTPUT_MODE_MASK   GENMASK(3, 0)
 
+static int atmel_hlcdc_connector_output_mode(struct drm_connector_state *state)
+{
+       struct drm_connector *connector = state->connector;
+       struct drm_display_info *info = &connector->display_info;
+       struct drm_encoder *encoder;
+       unsigned int supported_fmts = 0;
+       int j;
+
+       encoder = state->best_encoder;
+       if (!encoder)
+               encoder = connector->encoder;
+
+       switch (atmel_hlcdc_encoder_get_bus_fmt(encoder)) {
+       case 0:
+               break;
+       case MEDIA_BUS_FMT_RGB444_1X12:
+               return ATMEL_HLCDC_RGB444_OUTPUT;
+       case MEDIA_BUS_FMT_RGB565_1X16:
+               return ATMEL_HLCDC_RGB565_OUTPUT;
+       case MEDIA_BUS_FMT_RGB666_1X18:
+               return ATMEL_HLCDC_RGB666_OUTPUT;
+       case MEDIA_BUS_FMT_RGB888_1X24:
+               return ATMEL_HLCDC_RGB888_OUTPUT;
+       default:
+               return -EINVAL;
+       }
+
+       for (j = 0; j < info->num_bus_formats; j++) {
+               switch (info->bus_formats[j]) {
+               case MEDIA_BUS_FMT_RGB444_1X12:
+                       supported_fmts |= ATMEL_HLCDC_RGB444_OUTPUT;
+                       break;
+               case MEDIA_BUS_FMT_RGB565_1X16:
+                       supported_fmts |= ATMEL_HLCDC_RGB565_OUTPUT;
+                       break;
+               case MEDIA_BUS_FMT_RGB666_1X18:
+                       supported_fmts |= ATMEL_HLCDC_RGB666_OUTPUT;
+                       break;
+               case MEDIA_BUS_FMT_RGB888_1X24:
+                       supported_fmts |= ATMEL_HLCDC_RGB888_OUTPUT;
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       return supported_fmts;
+}
+
 static int atmel_hlcdc_crtc_select_output_mode(struct drm_crtc_state *state)
 {
        unsigned int output_fmts = ATMEL_HLCDC_OUTPUT_MODE_MASK;
        crtc = drm_crtc_to_atmel_hlcdc_crtc(state->crtc);
 
        for_each_new_connector_in_state(state->state, connector, cstate, i) {
-               struct drm_display_info *info = &connector->display_info;
                unsigned int supported_fmts = 0;
-               int j;
 
                if (!cstate->crtc)
                        continue;
 
-               for (j = 0; j < info->num_bus_formats; j++) {
-                       switch (info->bus_formats[j]) {
-                       case MEDIA_BUS_FMT_RGB444_1X12:
-                               supported_fmts |= ATMEL_HLCDC_RGB444_OUTPUT;
-                               break;
-                       case MEDIA_BUS_FMT_RGB565_1X16:
-                               supported_fmts |= ATMEL_HLCDC_RGB565_OUTPUT;
-                               break;
-                       case MEDIA_BUS_FMT_RGB666_1X18:
-                               supported_fmts |= ATMEL_HLCDC_RGB666_OUTPUT;
-                               break;
-                       case MEDIA_BUS_FMT_RGB888_1X24:
-                               supported_fmts |= ATMEL_HLCDC_RGB888_OUTPUT;
-                               break;
-                       default:
-                               break;
-                       }
-               }
+               supported_fmts = atmel_hlcdc_connector_output_mode(cstate);
 
                if (crtc->dc->desc->conflicting_output_formats)
                        output_fmts &= supported_fmts;
 
 
 #include "atmel_hlcdc_dc.h"
 
+struct atmel_hlcdc_rgb_output {
+       struct drm_encoder encoder;
+       int bus_fmt;
+};
+
 static const struct drm_encoder_funcs atmel_hlcdc_panel_encoder_funcs = {
        .destroy = drm_encoder_cleanup,
 };
 
+static struct atmel_hlcdc_rgb_output *
+atmel_hlcdc_encoder_to_rgb_output(struct drm_encoder *encoder)
+{
+       return container_of(encoder, struct atmel_hlcdc_rgb_output, encoder);
+}
+
+int atmel_hlcdc_encoder_get_bus_fmt(struct drm_encoder *encoder)
+{
+       struct atmel_hlcdc_rgb_output *output;
+
+       output = atmel_hlcdc_encoder_to_rgb_output(encoder);
+
+       return output->bus_fmt;
+}
+
+static int atmel_hlcdc_of_bus_fmt(const struct device_node *ep)
+{
+       u32 bus_width;
+       int ret;
+
+       ret = of_property_read_u32(ep, "bus-width", &bus_width);
+       if (ret == -EINVAL)
+               return 0;
+       if (ret)
+               return ret;
+
+       switch (bus_width) {
+       case 12:
+               return MEDIA_BUS_FMT_RGB444_1X12;
+       case 16:
+               return MEDIA_BUS_FMT_RGB565_1X16;
+       case 18:
+               return MEDIA_BUS_FMT_RGB666_1X18;
+       case 24:
+               return MEDIA_BUS_FMT_RGB888_1X24;
+       default:
+               return -EINVAL;
+       }
+}
+
 static int atmel_hlcdc_attach_endpoint(struct drm_device *dev, int endpoint)
 {
-       struct drm_encoder *encoder;
+       struct atmel_hlcdc_rgb_output *output;
+       struct device_node *ep;
        struct drm_panel *panel;
        struct drm_bridge *bridge;
        int ret;
 
+       ep = of_graph_get_endpoint_by_regs(dev->dev->of_node, 0, endpoint);
+       if (!ep)
+               return -ENODEV;
+
        ret = drm_of_find_panel_or_bridge(dev->dev->of_node, 0, endpoint,
                                          &panel, &bridge);
-       if (ret)
+       if (ret) {
+               of_node_put(ep);
                return ret;
+       }
 
-       encoder = devm_kzalloc(dev->dev, sizeof(*encoder), GFP_KERNEL);
-       if (!encoder)
+       output = devm_kzalloc(dev->dev, sizeof(*output), GFP_KERNEL);
+       if (!output) {
+               of_node_put(ep);
+               return -ENOMEM;
+       }
+
+       output->bus_fmt = atmel_hlcdc_of_bus_fmt(ep);
+       of_node_put(ep);
+       if (output->bus_fmt < 0) {
+               dev_err(dev->dev, "endpoint %d: invalid bus width\n", endpoint);
                return -EINVAL;
+       }
 
-       ret = drm_encoder_init(dev, encoder,
+       ret = drm_encoder_init(dev, &output->encoder,
                               &atmel_hlcdc_panel_encoder_funcs,
                               DRM_MODE_ENCODER_NONE, NULL);
        if (ret)
                return ret;
 
-       encoder->possible_crtcs = 0x1;
+       output->encoder.possible_crtcs = 0x1;
 
        if (panel) {
                bridge = drm_panel_bridge_add(panel, DRM_MODE_CONNECTOR_Unknown);
        }
 
        if (bridge) {
-               ret = drm_bridge_attach(encoder, bridge, NULL);
+               ret = drm_bridge_attach(&output->encoder, bridge, NULL);
                if (!ret)
                        return 0;
 
                        drm_panel_bridge_remove(bridge);
        }
 
-       drm_encoder_cleanup(encoder);
+       drm_encoder_cleanup(&output->encoder);
 
        return ret;
 }