aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/pl111/pl111_drv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/pl111/pl111_drv.c')
-rw-r--r--drivers/gpu/drm/pl111/pl111_drv.c138
1 files changed, 88 insertions, 50 deletions
diff --git a/drivers/gpu/drm/pl111/pl111_drv.c b/drivers/gpu/drm/pl111/pl111_drv.c
index acb738c69873..1231905150d0 100644
--- a/drivers/gpu/drm/pl111/pl111_drv.c
+++ b/drivers/gpu/drm/pl111/pl111_drv.c
@@ -58,6 +58,8 @@
58#include <linux/dma-buf.h> 58#include <linux/dma-buf.h>
59#include <linux/module.h> 59#include <linux/module.h>
60#include <linux/slab.h> 60#include <linux/slab.h>
61#include <linux/of.h>
62#include <linux/of_graph.h>
61 63
62#include <drm/drmP.h> 64#include <drm/drmP.h>
63#include <drm/drm_atomic_helper.h> 65#include <drm/drm_atomic_helper.h>
@@ -85,9 +87,13 @@ static int pl111_modeset_init(struct drm_device *dev)
85{ 87{
86 struct drm_mode_config *mode_config; 88 struct drm_mode_config *mode_config;
87 struct pl111_drm_dev_private *priv = dev->dev_private; 89 struct pl111_drm_dev_private *priv = dev->dev_private;
88 struct drm_panel *panel; 90 struct device_node *np = dev->dev->of_node;
89 struct drm_bridge *bridge; 91 struct device_node *remote;
92 struct drm_panel *panel = NULL;
93 struct drm_bridge *bridge = NULL;
94 bool defer = false;
90 int ret = 0; 95 int ret = 0;
96 int i;
91 97
92 drm_mode_config_init(dev); 98 drm_mode_config_init(dev);
93 mode_config = &dev->mode_config; 99 mode_config = &dev->mode_config;
@@ -97,10 +103,54 @@ static int pl111_modeset_init(struct drm_device *dev)
97 mode_config->min_height = 1; 103 mode_config->min_height = 1;
98 mode_config->max_height = 768; 104 mode_config->max_height = 768;
99 105
100 ret = drm_of_find_panel_or_bridge(dev->dev->of_node, 106 i = 0;
101 0, 0, &panel, &bridge); 107 for_each_endpoint_of_node(np, remote) {
102 if (ret && ret != -ENODEV) 108 struct drm_panel *tmp_panel;
103 return ret; 109 struct drm_bridge *tmp_bridge;
110
111 dev_dbg(dev->dev, "checking endpoint %d\n", i);
112
113 ret = drm_of_find_panel_or_bridge(dev->dev->of_node,
114 0, i,
115 &tmp_panel,
116 &tmp_bridge);
117 if (ret) {
118 if (ret == -EPROBE_DEFER) {
119 /*
120 * Something deferred, but that is often just
121 * another way of saying -ENODEV, but let's
122 * cast a vote for later deferral.
123 */
124 defer = true;
125 } else if (ret != -ENODEV) {
126 /* Continue, maybe something else is working */
127 dev_err(dev->dev,
128 "endpoint %d returns %d\n", i, ret);
129 }
130 }
131
132 if (tmp_panel) {
133 dev_info(dev->dev,
134 "found panel on endpoint %d\n", i);
135 panel = tmp_panel;
136 }
137 if (tmp_bridge) {
138 dev_info(dev->dev,
139 "found bridge on endpoint %d\n", i);
140 bridge = tmp_bridge;
141 }
142
143 i++;
144 }
145
146 /*
147 * If we can't find neither panel nor bridge on any of the
148 * endpoints, and any of them retured -EPROBE_DEFER, then
149 * let's defer this driver too.
150 */
151 if ((!panel && !bridge) && defer)
152 return -EPROBE_DEFER;
153
104 if (panel) { 154 if (panel) {
105 bridge = drm_panel_bridge_add(panel, 155 bridge = drm_panel_bridge_add(panel,
106 DRM_MODE_CONNECTOR_Unknown); 156 DRM_MODE_CONNECTOR_Unknown);
@@ -108,11 +158,17 @@ static int pl111_modeset_init(struct drm_device *dev)
108 ret = PTR_ERR(bridge); 158 ret = PTR_ERR(bridge);
109 goto out_config; 159 goto out_config;
110 } 160 }
111 /* 161 } else if (bridge) {
112 * TODO: when we are using a different bridge than a panel 162 dev_info(dev->dev, "Using non-panel bridge\n");
113 * (such as a dumb VGA connector) we need to devise a different 163 } else {
114 * method to get the connector out of the bridge. 164 dev_err(dev->dev, "No bridge, exiting\n");
115 */ 165 return -ENODEV;
166 }
167
168 priv->bridge = bridge;
169 if (panel) {
170 priv->panel = panel;
171 priv->connector = panel->connector;
116 } 172 }
117 173
118 ret = pl111_display_init(dev); 174 ret = pl111_display_init(dev);
@@ -126,14 +182,12 @@ static int pl111_modeset_init(struct drm_device *dev)
126 if (ret) 182 if (ret)
127 return ret; 183 return ret;
128 184
129 priv->bridge = bridge; 185 if (!priv->variant->broken_vblank) {
130 priv->panel = panel; 186 ret = drm_vblank_init(dev, 1);
131 priv->connector = panel->connector; 187 if (ret != 0) {
132 188 dev_err(dev->dev, "Failed to init vblank\n");
133 ret = drm_vblank_init(dev, 1); 189 goto out_bridge;
134 if (ret != 0) { 190 }
135 dev_err(dev->dev, "Failed to init vblank\n");
136 goto out_bridge;
137 } 191 }
138 192
139 drm_mode_config_reset(dev); 193 drm_mode_config_reset(dev);
@@ -170,10 +224,6 @@ static struct drm_driver pl111_drm_driver = {
170 .dumb_create = drm_gem_cma_dumb_create, 224 .dumb_create = drm_gem_cma_dumb_create,
171 .gem_free_object_unlocked = drm_gem_cma_free_object, 225 .gem_free_object_unlocked = drm_gem_cma_free_object,
172 .gem_vm_ops = &drm_gem_cma_vm_ops, 226 .gem_vm_ops = &drm_gem_cma_vm_ops,
173
174 .enable_vblank = pl111_enable_vblank,
175 .disable_vblank = pl111_disable_vblank,
176
177 .prime_handle_to_fd = drm_gem_prime_handle_to_fd, 227 .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
178 .prime_fd_to_handle = drm_gem_prime_fd_to_handle, 228 .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
179 .gem_prime_import = drm_gem_prime_import, 229 .gem_prime_import = drm_gem_prime_import,
@@ -191,7 +241,7 @@ static int pl111_amba_probe(struct amba_device *amba_dev,
191{ 241{
192 struct device *dev = &amba_dev->dev; 242 struct device *dev = &amba_dev->dev;
193 struct pl111_drm_dev_private *priv; 243 struct pl111_drm_dev_private *priv;
194 struct pl111_variant_data *variant = id->data; 244 const struct pl111_variant_data *variant = id->data;
195 struct drm_device *drm; 245 struct drm_device *drm;
196 int ret; 246 int ret;
197 247
@@ -199,6 +249,11 @@ static int pl111_amba_probe(struct amba_device *amba_dev,
199 if (!priv) 249 if (!priv)
200 return -ENOMEM; 250 return -ENOMEM;
201 251
252 if (!variant->broken_vblank) {
253 pl111_drm_driver.enable_vblank = pl111_enable_vblank;
254 pl111_drm_driver.disable_vblank = pl111_disable_vblank;
255 }
256
202 drm = drm_dev_alloc(&pl111_drm_driver, dev); 257 drm = drm_dev_alloc(&pl111_drm_driver, dev);
203 if (IS_ERR(drm)) 258 if (IS_ERR(drm))
204 return PTR_ERR(drm); 259 return PTR_ERR(drm);
@@ -207,27 +262,10 @@ static int pl111_amba_probe(struct amba_device *amba_dev,
207 drm->dev_private = priv; 262 drm->dev_private = priv;
208 priv->variant = variant; 263 priv->variant = variant;
209 264
210 /* 265 /* The two variants swap this register */
211 * The PL110 and PL111 variants have two registers
212 * swapped: interrupt enable and control. For this reason
213 * we use offsets that we can change per variant.
214 */
215 if (variant->is_pl110) { 266 if (variant->is_pl110) {
216 /* 267 priv->ienb = CLCD_PL110_IENB;
217 * The ARM Versatile boards are even more special: 268 priv->ctrl = CLCD_PL110_CNTL;
218 * their PrimeCell ID say they are PL110 but the
219 * control and interrupt enable registers are anyway
220 * swapped to the PL111 order so they are not following
221 * the PL110 datasheet.
222 */
223 if (of_machine_is_compatible("arm,versatile-ab") ||
224 of_machine_is_compatible("arm,versatile-pb")) {
225 priv->ienb = CLCD_PL111_IENB;
226 priv->ctrl = CLCD_PL111_CNTL;
227 } else {
228 priv->ienb = CLCD_PL110_IENB;
229 priv->ctrl = CLCD_PL110_CNTL;
230 }
231 } else { 269 } else {
232 priv->ienb = CLCD_PL111_IENB; 270 priv->ienb = CLCD_PL111_IENB;
233 priv->ctrl = CLCD_PL111_CNTL; 271 priv->ctrl = CLCD_PL111_CNTL;
@@ -239,6 +277,11 @@ static int pl111_amba_probe(struct amba_device *amba_dev,
239 return PTR_ERR(priv->regs); 277 return PTR_ERR(priv->regs);
240 } 278 }
241 279
280 /* This may override some variant settings */
281 ret = pl111_versatile_init(dev, priv);
282 if (ret)
283 goto dev_unref;
284
242 /* turn off interrupts before requesting the irq */ 285 /* turn off interrupts before requesting the irq */
243 writel(0, priv->regs + priv->ienb); 286 writel(0, priv->regs + priv->ienb);
244 287
@@ -249,10 +292,6 @@ static int pl111_amba_probe(struct amba_device *amba_dev,
249 return ret; 292 return ret;
250 } 293 }
251 294
252 ret = pl111_versatile_init(dev, priv);
253 if (ret)
254 goto dev_unref;
255
256 ret = pl111_modeset_init(drm); 295 ret = pl111_modeset_init(drm);
257 if (ret != 0) 296 if (ret != 0)
258 goto dev_unref; 297 goto dev_unref;
@@ -284,8 +323,7 @@ static int pl111_amba_remove(struct amba_device *amba_dev)
284} 323}
285 324
286/* 325/*
287 * This variant exist in early versions like the ARM Integrator 326 * This early variant lacks the 565 and 444 pixel formats.
288 * and this version lacks the 565 and 444 pixel formats.
289 */ 327 */
290static const u32 pl110_pixel_formats[] = { 328static const u32 pl110_pixel_formats[] = {
291 DRM_FORMAT_ABGR8888, 329 DRM_FORMAT_ABGR8888,