aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/imx
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/imx')
-rw-r--r--drivers/gpu/drm/imx/dw_hdmi-imx.c13
-rw-r--r--drivers/gpu/drm/imx/imx-drm-core.c10
-rw-r--r--drivers/gpu/drm/imx/ipuv3-plane.c123
-rw-r--r--drivers/gpu/drm/imx/ipuv3-plane.h4
4 files changed, 119 insertions, 31 deletions
diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c
index 2a95d10e9d92..a24631fdf4ad 100644
--- a/drivers/gpu/drm/imx/dw_hdmi-imx.c
+++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c
@@ -225,8 +225,6 @@ static int dw_hdmi_imx_bind(struct device *dev, struct device *master,
225 if (!iores) 225 if (!iores)
226 return -ENXIO; 226 return -ENXIO;
227 227
228 platform_set_drvdata(pdev, hdmi);
229
230 encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node); 228 encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
231 /* 229 /*
232 * If we failed to find the CRTC(s) which this encoder is 230 * If we failed to find the CRTC(s) which this encoder is
@@ -245,7 +243,16 @@ static int dw_hdmi_imx_bind(struct device *dev, struct device *master,
245 drm_encoder_init(drm, encoder, &dw_hdmi_imx_encoder_funcs, 243 drm_encoder_init(drm, encoder, &dw_hdmi_imx_encoder_funcs,
246 DRM_MODE_ENCODER_TMDS, NULL); 244 DRM_MODE_ENCODER_TMDS, NULL);
247 245
248 return dw_hdmi_bind(dev, master, data, encoder, iores, irq, plat_data); 246 ret = dw_hdmi_bind(dev, master, data, encoder, iores, irq, plat_data);
247
248 /*
249 * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(),
250 * which would have called the encoder cleanup. Do it manually.
251 */
252 if (ret)
253 drm_encoder_cleanup(encoder);
254
255 return ret;
249} 256}
250 257
251static void dw_hdmi_imx_unbind(struct device *dev, struct device *master, 258static void dw_hdmi_imx_unbind(struct device *dev, struct device *master,
diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c
index 9876e0f0c3e1..e26dcdec2aba 100644
--- a/drivers/gpu/drm/imx/imx-drm-core.c
+++ b/drivers/gpu/drm/imx/imx-drm-core.c
@@ -326,7 +326,6 @@ int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc,
326{ 326{
327 struct imx_drm_device *imxdrm = drm->dev_private; 327 struct imx_drm_device *imxdrm = drm->dev_private;
328 struct imx_drm_crtc *imx_drm_crtc; 328 struct imx_drm_crtc *imx_drm_crtc;
329 int ret;
330 329
331 /* 330 /*
332 * The vblank arrays are dimensioned by MAX_CRTC - we can't 331 * The vblank arrays are dimensioned by MAX_CRTC - we can't
@@ -351,10 +350,6 @@ int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc,
351 350
352 *new_crtc = imx_drm_crtc; 351 *new_crtc = imx_drm_crtc;
353 352
354 ret = drm_mode_crtc_set_gamma_size(imx_drm_crtc->crtc, 256);
355 if (ret)
356 goto err_register;
357
358 drm_crtc_helper_add(crtc, 353 drm_crtc_helper_add(crtc,
359 imx_drm_crtc->imx_drm_helper_funcs.crtc_helper_funcs); 354 imx_drm_crtc->imx_drm_helper_funcs.crtc_helper_funcs);
360 355
@@ -362,11 +357,6 @@ int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc,
362 imx_drm_crtc->imx_drm_helper_funcs.crtc_funcs, NULL); 357 imx_drm_crtc->imx_drm_helper_funcs.crtc_funcs, NULL);
363 358
364 return 0; 359 return 0;
365
366err_register:
367 imxdrm->crtc[--imxdrm->pipes] = NULL;
368 kfree(imx_drm_crtc);
369 return ret;
370} 360}
371EXPORT_SYMBOL_GPL(imx_drm_add_crtc); 361EXPORT_SYMBOL_GPL(imx_drm_add_crtc);
372 362
diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c
index 588827844f30..681ec6eb77d9 100644
--- a/drivers/gpu/drm/imx/ipuv3-plane.c
+++ b/drivers/gpu/drm/imx/ipuv3-plane.c
@@ -72,22 +72,101 @@ static inline int calc_bandwidth(int width, int height, unsigned int vref)
72int ipu_plane_set_base(struct ipu_plane *ipu_plane, struct drm_framebuffer *fb, 72int ipu_plane_set_base(struct ipu_plane *ipu_plane, struct drm_framebuffer *fb,
73 int x, int y) 73 int x, int y)
74{ 74{
75 struct drm_gem_cma_object *cma_obj; 75 struct drm_gem_cma_object *cma_obj[3];
76 unsigned long eba; 76 unsigned long eba, ubo, vbo;
77 int active; 77 int active, i;
78 78
79 cma_obj = drm_fb_cma_get_gem_obj(fb, 0); 79 for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) {
80 if (!cma_obj) { 80 cma_obj[i] = drm_fb_cma_get_gem_obj(fb, i);
81 DRM_DEBUG_KMS("entry is null.\n"); 81 if (!cma_obj[i]) {
82 return -EFAULT; 82 DRM_DEBUG_KMS("plane %d entry is null.\n", i);
83 return -EFAULT;
84 }
83 } 85 }
84 86
85 dev_dbg(ipu_plane->base.dev->dev, "phys = %pad, x = %d, y = %d", 87 eba = cma_obj[0]->paddr + fb->offsets[0] +
86 &cma_obj->paddr, x, y);
87
88 eba = cma_obj->paddr + fb->offsets[0] +
89 fb->pitches[0] * y + (fb->bits_per_pixel >> 3) * x; 88 fb->pitches[0] * y + (fb->bits_per_pixel >> 3) * x;
90 89
90 if (eba & 0x7) {
91 DRM_DEBUG_KMS("base address must be a multiple of 8.\n");
92 return -EINVAL;
93 }
94
95 if (fb->pitches[0] < 1 || fb->pitches[0] > 16384) {
96 DRM_DEBUG_KMS("pitches out of range.\n");
97 return -EINVAL;
98 }
99
100 if (ipu_plane->enabled && fb->pitches[0] != ipu_plane->stride[0]) {
101 DRM_DEBUG_KMS("pitches must not change while plane is enabled.\n");
102 return -EINVAL;
103 }
104
105 ipu_plane->stride[0] = fb->pitches[0];
106
107 switch (fb->pixel_format) {
108 case DRM_FORMAT_YUV420:
109 case DRM_FORMAT_YVU420:
110 /*
111 * Multiplanar formats have to meet the following restrictions:
112 * - The (up to) three plane addresses are EBA, EBA+UBO, EBA+VBO
113 * - EBA, UBO and VBO are a multiple of 8
114 * - UBO and VBO are unsigned and not larger than 0xfffff8
115 * - Only EBA may be changed while scanout is active
116 * - The strides of U and V planes must be identical.
117 */
118 ubo = cma_obj[1]->paddr + fb->offsets[1] +
119 fb->pitches[1] * y / 2 + x / 2 - eba;
120 vbo = cma_obj[2]->paddr + fb->offsets[2] +
121 fb->pitches[2] * y / 2 + x / 2 - eba;
122
123 if ((ubo & 0x7) || (vbo & 0x7)) {
124 DRM_DEBUG_KMS("U/V buffer offsets must be a multiple of 8.\n");
125 return -EINVAL;
126 }
127
128 if ((ubo > 0xfffff8) || (vbo > 0xfffff8)) {
129 DRM_DEBUG_KMS("U/V buffer offsets must be positive and not larger than 0xfffff8.\n");
130 return -EINVAL;
131 }
132
133 if (ipu_plane->enabled && ((ipu_plane->u_offset != ubo) ||
134 (ipu_plane->v_offset != vbo))) {
135 DRM_DEBUG_KMS("U/V buffer offsets must not change while plane is enabled.\n");
136 return -EINVAL;
137 }
138
139 if (fb->pitches[1] != fb->pitches[2]) {
140 DRM_DEBUG_KMS("U/V pitches must be identical.\n");
141 return -EINVAL;
142 }
143
144 if (fb->pitches[1] < 1 || fb->pitches[1] > 16384) {
145 DRM_DEBUG_KMS("U/V pitches out of range.\n");
146 return -EINVAL;
147 }
148
149 if (ipu_plane->enabled &&
150 (ipu_plane->stride[1] != fb->pitches[1])) {
151 DRM_DEBUG_KMS("U/V pitches must not change while plane is enabled.\n");
152 return -EINVAL;
153 }
154
155 ipu_plane->u_offset = ubo;
156 ipu_plane->v_offset = vbo;
157 ipu_plane->stride[1] = fb->pitches[1];
158
159 dev_dbg(ipu_plane->base.dev->dev,
160 "phys = %pad %pad %pad, x = %d, y = %d",
161 &cma_obj[0]->paddr, &cma_obj[1]->paddr,
162 &cma_obj[2]->paddr, x, y);
163 break;
164 default:
165 dev_dbg(ipu_plane->base.dev->dev, "phys = %pad, x = %d, y = %d",
166 &cma_obj[0]->paddr, x, y);
167 break;
168 }
169
91 if (ipu_plane->enabled) { 170 if (ipu_plane->enabled) {
92 active = ipu_idmac_get_current_buffer(ipu_plane->ipu_ch); 171 active = ipu_idmac_get_current_buffer(ipu_plane->ipu_ch);
93 ipu_cpmem_set_buffer(ipu_plane->ipu_ch, !active, eba); 172 ipu_cpmem_set_buffer(ipu_plane->ipu_ch, !active, eba);
@@ -201,12 +280,6 @@ int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct drm_crtc *crtc,
201 } 280 }
202 } 281 }
203 282
204 ret = ipu_dmfc_init_channel(ipu_plane->dmfc, crtc_w);
205 if (ret) {
206 dev_err(dev, "initializing dmfc channel failed with %d\n", ret);
207 return ret;
208 }
209
210 ret = ipu_dmfc_alloc_bandwidth(ipu_plane->dmfc, 283 ret = ipu_dmfc_alloc_bandwidth(ipu_plane->dmfc,
211 calc_bandwidth(crtc_w, crtc_h, 284 calc_bandwidth(crtc_w, crtc_h,
212 calc_vref(mode)), 64); 285 calc_vref(mode)), 64);
@@ -215,6 +288,8 @@ int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct drm_crtc *crtc,
215 return ret; 288 return ret;
216 } 289 }
217 290
291 ipu_dmfc_config_wait4eot(ipu_plane->dmfc, crtc_w);
292
218 ipu_cpmem_zero(ipu_plane->ipu_ch); 293 ipu_cpmem_zero(ipu_plane->ipu_ch);
219 ipu_cpmem_set_resolution(ipu_plane->ipu_ch, src_w, src_h); 294 ipu_cpmem_set_resolution(ipu_plane->ipu_ch, src_w, src_h);
220 ret = ipu_cpmem_set_fmt(ipu_plane->ipu_ch, fb->pixel_format); 295 ret = ipu_cpmem_set_fmt(ipu_plane->ipu_ch, fb->pixel_format);
@@ -233,6 +308,18 @@ int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct drm_crtc *crtc,
233 if (interlaced) 308 if (interlaced)
234 ipu_cpmem_interlaced_scan(ipu_plane->ipu_ch, fb->pitches[0]); 309 ipu_cpmem_interlaced_scan(ipu_plane->ipu_ch, fb->pitches[0]);
235 310
311 if (fb->pixel_format == DRM_FORMAT_YUV420) {
312 ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch,
313 ipu_plane->stride[1],
314 ipu_plane->u_offset,
315 ipu_plane->v_offset);
316 } else if (fb->pixel_format == DRM_FORMAT_YVU420) {
317 ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch,
318 ipu_plane->stride[1],
319 ipu_plane->v_offset,
320 ipu_plane->u_offset);
321 }
322
236 ipu_plane->w = src_w; 323 ipu_plane->w = src_w;
237 ipu_plane->h = src_h; 324 ipu_plane->h = src_h;
238 325
diff --git a/drivers/gpu/drm/imx/ipuv3-plane.h b/drivers/gpu/drm/imx/ipuv3-plane.h
index 3a443b413c60..4448fd4ad4eb 100644
--- a/drivers/gpu/drm/imx/ipuv3-plane.h
+++ b/drivers/gpu/drm/imx/ipuv3-plane.h
@@ -29,6 +29,10 @@ struct ipu_plane {
29 int w; 29 int w;
30 int h; 30 int h;
31 31
32 unsigned int u_offset;
33 unsigned int v_offset;
34 unsigned int stride[2];
35
32 bool enabled; 36 bool enabled;
33}; 37};
34 38