diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2018-09-23 05:58:15 -0400 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2019-03-18 05:42:14 -0400 |
commit | 79107f274b2fc6bce13f687de33c8d0b70994558 (patch) | |
tree | c7aa23a717c4ecb622157370dffb4c9c40ff2951 /drivers/gpu/drm/omapdrm/omap_encoder.c | |
parent | 163f7a3578eca8f9bc550e0161b7d9b79e24e056 (diff) |
drm/omap: Add support for drm_bridge
Hook up drm_bridge support in the omapdrm driver. Despite the recent
extensive preparation work, this is a rather intrusive change, as the
management of outputs needs to be adapted through the driver to handle
both omap_dss_device and drm_bridge.
Connector creation is skipped when using a drm_bridge, as the bridge
creates the connector internally. This creates issues with systems that
split connector operations (such as modes retrieval and hot-plug
detection) across different bridges. These systems can't be supported
using drm_bridge for now (their support through the omap_dss_device
infrastructure is not affected), this will be fixed in subsequent
changes.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.com>
Tested-by: Sebastian Reichel <sebastian.reichel@collabora.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers/gpu/drm/omapdrm/omap_encoder.c')
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_encoder.c | 69 |
1 files changed, 42 insertions, 27 deletions
diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c b/drivers/gpu/drm/omapdrm/omap_encoder.c index b83a2ae64a03..9eb3db9ba23f 100644 --- a/drivers/gpu/drm/omapdrm/omap_encoder.c +++ b/drivers/gpu/drm/omapdrm/omap_encoder.c | |||
@@ -51,6 +51,34 @@ static const struct drm_encoder_funcs omap_encoder_funcs = { | |||
51 | .destroy = omap_encoder_destroy, | 51 | .destroy = omap_encoder_destroy, |
52 | }; | 52 | }; |
53 | 53 | ||
54 | static void omap_encoder_update_videomode_flags(struct videomode *vm, | ||
55 | u32 bus_flags) | ||
56 | { | ||
57 | if (!(vm->flags & (DISPLAY_FLAGS_DE_LOW | | ||
58 | DISPLAY_FLAGS_DE_HIGH))) { | ||
59 | if (bus_flags & DRM_BUS_FLAG_DE_LOW) | ||
60 | vm->flags |= DISPLAY_FLAGS_DE_LOW; | ||
61 | else if (bus_flags & DRM_BUS_FLAG_DE_HIGH) | ||
62 | vm->flags |= DISPLAY_FLAGS_DE_HIGH; | ||
63 | } | ||
64 | |||
65 | if (!(vm->flags & (DISPLAY_FLAGS_PIXDATA_POSEDGE | | ||
66 | DISPLAY_FLAGS_PIXDATA_NEGEDGE))) { | ||
67 | if (bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE) | ||
68 | vm->flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE; | ||
69 | else if (bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) | ||
70 | vm->flags |= DISPLAY_FLAGS_PIXDATA_NEGEDGE; | ||
71 | } | ||
72 | |||
73 | if (!(vm->flags & (DISPLAY_FLAGS_SYNC_POSEDGE | | ||
74 | DISPLAY_FLAGS_SYNC_NEGEDGE))) { | ||
75 | if (bus_flags & DRM_BUS_FLAG_SYNC_DRIVE_POSEDGE) | ||
76 | vm->flags |= DISPLAY_FLAGS_SYNC_POSEDGE; | ||
77 | else if (bus_flags & DRM_BUS_FLAG_SYNC_DRIVE_NEGEDGE) | ||
78 | vm->flags |= DISPLAY_FLAGS_SYNC_NEGEDGE; | ||
79 | } | ||
80 | } | ||
81 | |||
54 | static void omap_encoder_hdmi_mode_set(struct drm_encoder *encoder, | 82 | static void omap_encoder_hdmi_mode_set(struct drm_encoder *encoder, |
55 | struct drm_display_mode *adjusted_mode) | 83 | struct drm_display_mode *adjusted_mode) |
56 | { | 84 | { |
@@ -87,7 +115,9 @@ static void omap_encoder_mode_set(struct drm_encoder *encoder, | |||
87 | struct drm_display_mode *adjusted_mode) | 115 | struct drm_display_mode *adjusted_mode) |
88 | { | 116 | { |
89 | struct omap_encoder *omap_encoder = to_omap_encoder(encoder); | 117 | struct omap_encoder *omap_encoder = to_omap_encoder(encoder); |
118 | struct omap_dss_device *output = omap_encoder->output; | ||
90 | struct omap_dss_device *dssdev; | 119 | struct omap_dss_device *dssdev; |
120 | struct drm_bridge *bridge; | ||
91 | struct videomode vm = { 0 }; | 121 | struct videomode vm = { 0 }; |
92 | 122 | ||
93 | drm_display_mode_to_videomode(adjusted_mode, &vm); | 123 | drm_display_mode_to_videomode(adjusted_mode, &vm); |
@@ -101,44 +131,29 @@ static void omap_encoder_mode_set(struct drm_encoder *encoder, | |||
101 | * | 131 | * |
102 | * A better solution is to use DRM's bus-flags through the whole driver. | 132 | * A better solution is to use DRM's bus-flags through the whole driver. |
103 | */ | 133 | */ |
104 | for (dssdev = omap_encoder->output; dssdev; dssdev = dssdev->next) { | 134 | for (dssdev = output; dssdev; dssdev = dssdev->next) |
105 | unsigned long bus_flags = dssdev->bus_flags; | 135 | omap_encoder_update_videomode_flags(&vm, dssdev->bus_flags); |
106 | |||
107 | if (!(vm.flags & (DISPLAY_FLAGS_DE_LOW | | ||
108 | DISPLAY_FLAGS_DE_HIGH))) { | ||
109 | if (bus_flags & DRM_BUS_FLAG_DE_LOW) | ||
110 | vm.flags |= DISPLAY_FLAGS_DE_LOW; | ||
111 | else if (bus_flags & DRM_BUS_FLAG_DE_HIGH) | ||
112 | vm.flags |= DISPLAY_FLAGS_DE_HIGH; | ||
113 | } | ||
114 | 136 | ||
115 | if (!(vm.flags & (DISPLAY_FLAGS_PIXDATA_POSEDGE | | 137 | for (bridge = output->bridge; bridge; bridge = bridge->next) { |
116 | DISPLAY_FLAGS_PIXDATA_NEGEDGE))) { | 138 | u32 bus_flags; |
117 | if (bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE) | ||
118 | vm.flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE; | ||
119 | else if (bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) | ||
120 | vm.flags |= DISPLAY_FLAGS_PIXDATA_NEGEDGE; | ||
121 | } | ||
122 | 139 | ||
123 | if (!(vm.flags & (DISPLAY_FLAGS_SYNC_POSEDGE | | 140 | if (!bridge->timings) |
124 | DISPLAY_FLAGS_SYNC_NEGEDGE))) { | 141 | continue; |
125 | if (bus_flags & DRM_BUS_FLAG_SYNC_DRIVE_POSEDGE) | 142 | |
126 | vm.flags |= DISPLAY_FLAGS_SYNC_POSEDGE; | 143 | bus_flags = bridge->timings->input_bus_flags; |
127 | else if (bus_flags & DRM_BUS_FLAG_SYNC_DRIVE_NEGEDGE) | 144 | omap_encoder_update_videomode_flags(&vm, bus_flags); |
128 | vm.flags |= DISPLAY_FLAGS_SYNC_NEGEDGE; | ||
129 | } | ||
130 | } | 145 | } |
131 | 146 | ||
132 | /* Set timings for all devices in the display pipeline. */ | 147 | /* Set timings for all devices in the display pipeline. */ |
133 | dss_mgr_set_timings(omap_encoder->output, &vm); | 148 | dss_mgr_set_timings(output, &vm); |
134 | 149 | ||
135 | for (dssdev = omap_encoder->output; dssdev; dssdev = dssdev->next) { | 150 | for (dssdev = output; dssdev; dssdev = dssdev->next) { |
136 | if (dssdev->ops->set_timings) | 151 | if (dssdev->ops->set_timings) |
137 | dssdev->ops->set_timings(dssdev, adjusted_mode); | 152 | dssdev->ops->set_timings(dssdev, adjusted_mode); |
138 | } | 153 | } |
139 | 154 | ||
140 | /* Set the HDMI mode and HDMI infoframe if applicable. */ | 155 | /* Set the HDMI mode and HDMI infoframe if applicable. */ |
141 | if (omap_encoder->output->type == OMAP_DISPLAY_TYPE_HDMI) | 156 | if (output->type == OMAP_DISPLAY_TYPE_HDMI) |
142 | omap_encoder_hdmi_mode_set(encoder, adjusted_mode); | 157 | omap_encoder_hdmi_mode_set(encoder, adjusted_mode); |
143 | } | 158 | } |
144 | 159 | ||