diff options
author | Dave Airlie <airlied@redhat.com> | 2015-08-17 01:33:23 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2015-08-17 01:33:23 -0400 |
commit | 3ff8e5090c337a4eb26952d68587f450e012bd72 (patch) | |
tree | 5e21297fd91d72be8f65636b8d2e85cabdc522d4 | |
parent | 3be66711b6adefad2a95c108161607d79729ea05 (diff) | |
parent | 2a8cb48945408984cd04c850b293f467b32ec5af (diff) |
Merge branch 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos into drm-next
Summary:
- Clean up HDMI and MIXER parts
- Clean up legacy structures specific to Exynos DRM
. This patch series removes existing exyons_drm_display and
exynos_drm_encoder structures specific to Exynos DRM, and
makes them to replace with common drm_encoder structure.
With cleanup patch, we removes exynos_drm_encoder module.
- Clean up gem, dmabuf and buffer modules
. This patch series replaces existing Exynos DRM dmabuf codes
with common drm prime ones, and embeds all codes of exynos_drm_buf
into exynos_drm_gem module.
With cleanup patch, we removes exynos_drm_buf and exynos_drm_dmabuf
modules.
- And some fixups.
* 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos: (53 commits)
drm/exynos: merge exynos_drm_buf.c to exynos_drm_gem.c
drm/exynos: use prime helpers
drm/exynos: remove function roundup_gem_size
drm/exynos: remove function update_vm_cache_attr
drm/exynos: remove function check_gem_flags
drm/exynos: use ERR_PTR instead of NULL in exynos_drm_gem_init
drm/exynos: remove unused fields of struct exynos_drm_gem_buf
drm/exynos: stop copying sg table
drm/exynos: remove function exynos_drm_gem_map_buf
drm/exynos: remove mutex locking in pagefault handler
drm/exynos: remove function convert_to_vm_err_msg
drm/exynos: stop using sgtable in page fault handler
drm/exynos: remove struct exynos_drm_encoder layer
drm/exynos: fold encoder setup into exynos_drm_load()
drm/exynos: remove exynos_drm_create_enc_conn()
drm/exynos: remove exynos_encoder's .commit() op
drm/exynos: remove extra call to exynos_dp_commit()
drm/exynos: remove extra call to hdmi_commit()
drm/exynos: remove struct exynos_drm_display
drm/exynos: simplify calculation of possible CRTCs
...
33 files changed, 1139 insertions, 2301 deletions
diff --git a/drivers/gpu/drm/exynos/Makefile b/drivers/gpu/drm/exynos/Makefile index 7de0b1084fcd..02aecfed6354 100644 --- a/drivers/gpu/drm/exynos/Makefile +++ b/drivers/gpu/drm/exynos/Makefile | |||
@@ -3,10 +3,9 @@ | |||
3 | # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. | 3 | # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. |
4 | 4 | ||
5 | ccflags-y := -Iinclude/drm -Idrivers/gpu/drm/exynos | 5 | ccflags-y := -Iinclude/drm -Idrivers/gpu/drm/exynos |
6 | exynosdrm-y := exynos_drm_drv.o exynos_drm_encoder.o \ | 6 | exynosdrm-y := exynos_drm_drv.o exynos_drm_crtc.o exynos_drm_fbdev.o \ |
7 | exynos_drm_crtc.o exynos_drm_fbdev.o exynos_drm_fb.o \ | 7 | exynos_drm_fb.o exynos_drm_gem.o exynos_drm_core.o \ |
8 | exynos_drm_buf.o exynos_drm_gem.o exynos_drm_core.o \ | 8 | exynos_drm_plane.o |
9 | exynos_drm_plane.o exynos_drm_dmabuf.o | ||
10 | 9 | ||
11 | exynosdrm-$(CONFIG_DRM_EXYNOS_IOMMU) += exynos_drm_iommu.o | 10 | exynosdrm-$(CONFIG_DRM_EXYNOS_IOMMU) += exynos_drm_iommu.o |
12 | exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD) += exynos_drm_fimd.o | 11 | exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD) += exynos_drm_fimd.o |
diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c index 8b1225f245fc..484e312e0a22 100644 --- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c | |||
@@ -152,15 +152,15 @@ static void decon_commit(struct exynos_drm_crtc *crtc) | |||
152 | #define OFFSIZE(x) (((x) & 0x3fff) << 14) | 152 | #define OFFSIZE(x) (((x) & 0x3fff) << 14) |
153 | #define PAGEWIDTH(x) ((x) & 0x3fff) | 153 | #define PAGEWIDTH(x) ((x) & 0x3fff) |
154 | 154 | ||
155 | static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win) | 155 | static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win, |
156 | struct drm_framebuffer *fb) | ||
156 | { | 157 | { |
157 | struct exynos_drm_plane *plane = &ctx->planes[win]; | ||
158 | unsigned long val; | 158 | unsigned long val; |
159 | 159 | ||
160 | val = readl(ctx->addr + DECON_WINCONx(win)); | 160 | val = readl(ctx->addr + DECON_WINCONx(win)); |
161 | val &= ~WINCONx_BPPMODE_MASK; | 161 | val &= ~WINCONx_BPPMODE_MASK; |
162 | 162 | ||
163 | switch (plane->pixel_format) { | 163 | switch (fb->pixel_format) { |
164 | case DRM_FORMAT_XRGB1555: | 164 | case DRM_FORMAT_XRGB1555: |
165 | val |= WINCONx_BPPMODE_16BPP_I1555; | 165 | val |= WINCONx_BPPMODE_16BPP_I1555; |
166 | val |= WINCONx_HAWSWP_F; | 166 | val |= WINCONx_HAWSWP_F; |
@@ -186,7 +186,7 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win) | |||
186 | return; | 186 | return; |
187 | } | 187 | } |
188 | 188 | ||
189 | DRM_DEBUG_KMS("bpp = %u\n", plane->bpp); | 189 | DRM_DEBUG_KMS("bpp = %u\n", fb->bits_per_pixel); |
190 | 190 | ||
191 | /* | 191 | /* |
192 | * In case of exynos, setting dma-burst to 16Word causes permanent | 192 | * In case of exynos, setting dma-burst to 16Word causes permanent |
@@ -196,7 +196,7 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win) | |||
196 | * movement causes unstable DMA which results into iommu crash/tear. | 196 | * movement causes unstable DMA which results into iommu crash/tear. |
197 | */ | 197 | */ |
198 | 198 | ||
199 | if (plane->fb_width < MIN_FB_WIDTH_FOR_16WORD_BURST) { | 199 | if (fb->width < MIN_FB_WIDTH_FOR_16WORD_BURST) { |
200 | val &= ~WINCONx_BURSTLEN_MASK; | 200 | val &= ~WINCONx_BURSTLEN_MASK; |
201 | val |= WINCONx_BURSTLEN_8WORD; | 201 | val |= WINCONx_BURSTLEN_8WORD; |
202 | } | 202 | } |
@@ -219,17 +219,16 @@ static void decon_shadow_protect_win(struct decon_context *ctx, int win, | |||
219 | writel(val, ctx->addr + DECON_SHADOWCON); | 219 | writel(val, ctx->addr + DECON_SHADOWCON); |
220 | } | 220 | } |
221 | 221 | ||
222 | static void decon_win_commit(struct exynos_drm_crtc *crtc, unsigned int win) | 222 | static void decon_update_plane(struct exynos_drm_crtc *crtc, |
223 | struct exynos_drm_plane *plane) | ||
223 | { | 224 | { |
224 | struct decon_context *ctx = crtc->ctx; | 225 | struct decon_context *ctx = crtc->ctx; |
225 | struct exynos_drm_plane *plane; | 226 | struct drm_plane_state *state = plane->base.state; |
227 | unsigned int win = plane->zpos; | ||
228 | unsigned int bpp = state->fb->bits_per_pixel >> 3; | ||
229 | unsigned int pitch = state->fb->pitches[0]; | ||
226 | u32 val; | 230 | u32 val; |
227 | 231 | ||
228 | if (win < 0 || win >= WINDOWS_NR) | ||
229 | return; | ||
230 | |||
231 | plane = &ctx->planes[win]; | ||
232 | |||
233 | if (ctx->suspended) | 232 | if (ctx->suspended) |
234 | return; | 233 | return; |
235 | 234 | ||
@@ -238,8 +237,8 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, unsigned int win) | |||
238 | val = COORDINATE_X(plane->crtc_x) | COORDINATE_Y(plane->crtc_y); | 237 | val = COORDINATE_X(plane->crtc_x) | COORDINATE_Y(plane->crtc_y); |
239 | writel(val, ctx->addr + DECON_VIDOSDxA(win)); | 238 | writel(val, ctx->addr + DECON_VIDOSDxA(win)); |
240 | 239 | ||
241 | val = COORDINATE_X(plane->crtc_x + plane->crtc_width - 1) | | 240 | val = COORDINATE_X(plane->crtc_x + plane->crtc_w - 1) | |
242 | COORDINATE_Y(plane->crtc_y + plane->crtc_height - 1); | 241 | COORDINATE_Y(plane->crtc_y + plane->crtc_h - 1); |
243 | writel(val, ctx->addr + DECON_VIDOSDxB(win)); | 242 | writel(val, ctx->addr + DECON_VIDOSDxB(win)); |
244 | 243 | ||
245 | val = VIDOSD_Wx_ALPHA_R_F(0x0) | VIDOSD_Wx_ALPHA_G_F(0x0) | | 244 | val = VIDOSD_Wx_ALPHA_R_F(0x0) | VIDOSD_Wx_ALPHA_G_F(0x0) | |
@@ -252,14 +251,14 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, unsigned int win) | |||
252 | 251 | ||
253 | writel(plane->dma_addr[0], ctx->addr + DECON_VIDW0xADD0B0(win)); | 252 | writel(plane->dma_addr[0], ctx->addr + DECON_VIDW0xADD0B0(win)); |
254 | 253 | ||
255 | val = plane->dma_addr[0] + plane->pitch * plane->crtc_height; | 254 | val = plane->dma_addr[0] + pitch * plane->crtc_h; |
256 | writel(val, ctx->addr + DECON_VIDW0xADD1B0(win)); | 255 | writel(val, ctx->addr + DECON_VIDW0xADD1B0(win)); |
257 | 256 | ||
258 | val = OFFSIZE(plane->pitch - plane->crtc_width * (plane->bpp >> 3)) | 257 | val = OFFSIZE(pitch - plane->crtc_w * bpp) |
259 | | PAGEWIDTH(plane->crtc_width * (plane->bpp >> 3)); | 258 | | PAGEWIDTH(plane->crtc_w * bpp); |
260 | writel(val, ctx->addr + DECON_VIDW0xADD2(win)); | 259 | writel(val, ctx->addr + DECON_VIDW0xADD2(win)); |
261 | 260 | ||
262 | decon_win_set_pixfmt(ctx, win); | 261 | decon_win_set_pixfmt(ctx, win, state->fb); |
263 | 262 | ||
264 | /* window enable */ | 263 | /* window enable */ |
265 | val = readl(ctx->addr + DECON_WINCONx(win)); | 264 | val = readl(ctx->addr + DECON_WINCONx(win)); |
@@ -277,17 +276,13 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, unsigned int win) | |||
277 | atomic_set(&ctx->win_updated, 1); | 276 | atomic_set(&ctx->win_updated, 1); |
278 | } | 277 | } |
279 | 278 | ||
280 | static void decon_win_disable(struct exynos_drm_crtc *crtc, unsigned int win) | 279 | static void decon_disable_plane(struct exynos_drm_crtc *crtc, |
280 | struct exynos_drm_plane *plane) | ||
281 | { | 281 | { |
282 | struct decon_context *ctx = crtc->ctx; | 282 | struct decon_context *ctx = crtc->ctx; |
283 | struct exynos_drm_plane *plane; | 283 | unsigned int win = plane->zpos; |
284 | u32 val; | 284 | u32 val; |
285 | 285 | ||
286 | if (win < 0 || win >= WINDOWS_NR) | ||
287 | return; | ||
288 | |||
289 | plane = &ctx->planes[win]; | ||
290 | |||
291 | if (ctx->suspended) | 286 | if (ctx->suspended) |
292 | return; | 287 | return; |
293 | 288 | ||
@@ -378,7 +373,7 @@ static void decon_disable(struct exynos_drm_crtc *crtc) | |||
378 | * a destroyed buffer later. | 373 | * a destroyed buffer later. |
379 | */ | 374 | */ |
380 | for (i = 0; i < WINDOWS_NR; i++) | 375 | for (i = 0; i < WINDOWS_NR; i++) |
381 | decon_win_disable(crtc, i); | 376 | decon_disable_plane(crtc, &ctx->planes[i]); |
382 | 377 | ||
383 | decon_swreset(ctx); | 378 | decon_swreset(ctx); |
384 | 379 | ||
@@ -407,7 +402,7 @@ void decon_te_irq_handler(struct exynos_drm_crtc *crtc) | |||
407 | writel(val, ctx->addr + DECON_TRIGCON); | 402 | writel(val, ctx->addr + DECON_TRIGCON); |
408 | } | 403 | } |
409 | 404 | ||
410 | drm_handle_vblank(ctx->drm_dev, ctx->pipe); | 405 | drm_crtc_handle_vblank(&ctx->crtc->base); |
411 | } | 406 | } |
412 | 407 | ||
413 | static void decon_clear_channels(struct exynos_drm_crtc *crtc) | 408 | static void decon_clear_channels(struct exynos_drm_crtc *crtc) |
@@ -460,10 +455,9 @@ static struct exynos_drm_crtc_ops decon_crtc_ops = { | |||
460 | .enable_vblank = decon_enable_vblank, | 455 | .enable_vblank = decon_enable_vblank, |
461 | .disable_vblank = decon_disable_vblank, | 456 | .disable_vblank = decon_disable_vblank, |
462 | .commit = decon_commit, | 457 | .commit = decon_commit, |
463 | .win_commit = decon_win_commit, | 458 | .update_plane = decon_update_plane, |
464 | .win_disable = decon_win_disable, | 459 | .disable_plane = decon_disable_plane, |
465 | .te_handler = decon_te_irq_handler, | 460 | .te_handler = decon_te_irq_handler, |
466 | .clear_channels = decon_clear_channels, | ||
467 | }; | 461 | }; |
468 | 462 | ||
469 | static int decon_bind(struct device *dev, struct device *master, void *data) | 463 | static int decon_bind(struct device *dev, struct device *master, void *data) |
@@ -497,7 +491,9 @@ static int decon_bind(struct device *dev, struct device *master, void *data) | |||
497 | goto err; | 491 | goto err; |
498 | } | 492 | } |
499 | 493 | ||
500 | ret = drm_iommu_attach_device_if_possible(ctx->crtc, drm_dev, dev); | 494 | decon_clear_channels(ctx->crtc); |
495 | |||
496 | ret = drm_iommu_attach_device(drm_dev, dev); | ||
501 | if (ret) | 497 | if (ret) |
502 | goto err; | 498 | goto err; |
503 | 499 | ||
@@ -514,8 +510,7 @@ static void decon_unbind(struct device *dev, struct device *master, void *data) | |||
514 | decon_disable(ctx->crtc); | 510 | decon_disable(ctx->crtc); |
515 | 511 | ||
516 | /* detach this sub driver from iommu mapping if supported. */ | 512 | /* detach this sub driver from iommu mapping if supported. */ |
517 | if (is_drm_iommu_supported(ctx->drm_dev)) | 513 | drm_iommu_detach_device(ctx->drm_dev, ctx->dev); |
518 | drm_iommu_detach_device(ctx->drm_dev, ctx->dev); | ||
519 | } | 514 | } |
520 | 515 | ||
521 | static const struct component_ops decon_component_ops = { | 516 | static const struct component_ops decon_component_ops = { |
@@ -533,7 +528,7 @@ static irqreturn_t decon_vsync_irq_handler(int irq, void *dev_id) | |||
533 | 528 | ||
534 | val = readl(ctx->addr + DECON_VIDINTCON1); | 529 | val = readl(ctx->addr + DECON_VIDINTCON1); |
535 | if (val & VIDINTCON1_INTFRMPEND) { | 530 | if (val & VIDINTCON1_INTFRMPEND) { |
536 | drm_handle_vblank(ctx->drm_dev, ctx->pipe); | 531 | drm_crtc_handle_vblank(&ctx->crtc->base); |
537 | 532 | ||
538 | /* clear */ | 533 | /* clear */ |
539 | writel(VIDINTCON1_INTFRMPEND, ctx->addr + DECON_VIDINTCON1); | 534 | writel(VIDINTCON1_INTFRMPEND, ctx->addr + DECON_VIDINTCON1); |
@@ -553,7 +548,7 @@ static irqreturn_t decon_lcd_sys_irq_handler(int irq, void *dev_id) | |||
553 | 548 | ||
554 | val = readl(ctx->addr + DECON_VIDINTCON1); | 549 | val = readl(ctx->addr + DECON_VIDINTCON1); |
555 | if (val & VIDINTCON1_INTFRMDONEPEND) { | 550 | if (val & VIDINTCON1_INTFRMDONEPEND) { |
556 | exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe); | 551 | exynos_drm_crtc_finish_pageflip(ctx->crtc); |
557 | 552 | ||
558 | /* clear */ | 553 | /* clear */ |
559 | writel(VIDINTCON1_INTFRMDONEPEND, | 554 | writel(VIDINTCON1_INTFRMDONEPEND, |
diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c index 362532afd1a5..07926547c94f 100644 --- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c | |||
@@ -61,7 +61,7 @@ struct decon_context { | |||
61 | atomic_t wait_vsync_event; | 61 | atomic_t wait_vsync_event; |
62 | 62 | ||
63 | struct exynos_drm_panel_info panel; | 63 | struct exynos_drm_panel_info panel; |
64 | struct exynos_drm_display *display; | 64 | struct drm_encoder *encoder; |
65 | }; | 65 | }; |
66 | 66 | ||
67 | static const struct of_device_id decon_driver_dt_match[] = { | 67 | static const struct of_device_id decon_driver_dt_match[] = { |
@@ -126,7 +126,9 @@ static int decon_ctx_initialize(struct decon_context *ctx, | |||
126 | ctx->drm_dev = drm_dev; | 126 | ctx->drm_dev = drm_dev; |
127 | ctx->pipe = priv->pipe++; | 127 | ctx->pipe = priv->pipe++; |
128 | 128 | ||
129 | ret = drm_iommu_attach_device_if_possible(ctx->crtc, drm_dev, ctx->dev); | 129 | decon_clear_channels(ctx->crtc); |
130 | |||
131 | ret = drm_iommu_attach_device(drm_dev, ctx->dev); | ||
130 | if (ret) | 132 | if (ret) |
131 | priv->pipe--; | 133 | priv->pipe--; |
132 | 134 | ||
@@ -136,8 +138,7 @@ static int decon_ctx_initialize(struct decon_context *ctx, | |||
136 | static void decon_ctx_remove(struct decon_context *ctx) | 138 | static void decon_ctx_remove(struct decon_context *ctx) |
137 | { | 139 | { |
138 | /* detach this sub driver from iommu mapping if supported. */ | 140 | /* detach this sub driver from iommu mapping if supported. */ |
139 | if (is_drm_iommu_supported(ctx->drm_dev)) | 141 | drm_iommu_detach_device(ctx->drm_dev, ctx->dev); |
140 | drm_iommu_detach_device(ctx->drm_dev, ctx->dev); | ||
141 | } | 142 | } |
142 | 143 | ||
143 | static u32 decon_calc_clkdiv(struct decon_context *ctx, | 144 | static u32 decon_calc_clkdiv(struct decon_context *ctx, |
@@ -271,16 +272,16 @@ static void decon_disable_vblank(struct exynos_drm_crtc *crtc) | |||
271 | } | 272 | } |
272 | } | 273 | } |
273 | 274 | ||
274 | static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win) | 275 | static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win, |
276 | struct drm_framebuffer *fb) | ||
275 | { | 277 | { |
276 | struct exynos_drm_plane *plane = &ctx->planes[win]; | ||
277 | unsigned long val; | 278 | unsigned long val; |
278 | int padding; | 279 | int padding; |
279 | 280 | ||
280 | val = readl(ctx->regs + WINCON(win)); | 281 | val = readl(ctx->regs + WINCON(win)); |
281 | val &= ~WINCONx_BPPMODE_MASK; | 282 | val &= ~WINCONx_BPPMODE_MASK; |
282 | 283 | ||
283 | switch (plane->pixel_format) { | 284 | switch (fb->pixel_format) { |
284 | case DRM_FORMAT_RGB565: | 285 | case DRM_FORMAT_RGB565: |
285 | val |= WINCONx_BPPMODE_16BPP_565; | 286 | val |= WINCONx_BPPMODE_16BPP_565; |
286 | val |= WINCONx_BURSTLEN_16WORD; | 287 | val |= WINCONx_BURSTLEN_16WORD; |
@@ -329,7 +330,7 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win) | |||
329 | break; | 330 | break; |
330 | } | 331 | } |
331 | 332 | ||
332 | DRM_DEBUG_KMS("bpp = %d\n", plane->bpp); | 333 | DRM_DEBUG_KMS("bpp = %d\n", fb->bits_per_pixel); |
333 | 334 | ||
334 | /* | 335 | /* |
335 | * In case of exynos, setting dma-burst to 16Word causes permanent | 336 | * In case of exynos, setting dma-burst to 16Word causes permanent |
@@ -339,8 +340,8 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win) | |||
339 | * movement causes unstable DMA which results into iommu crash/tear. | 340 | * movement causes unstable DMA which results into iommu crash/tear. |
340 | */ | 341 | */ |
341 | 342 | ||
342 | padding = (plane->pitch / (plane->bpp >> 3)) - plane->fb_width; | 343 | padding = (fb->pitches[0] / (fb->bits_per_pixel >> 3)) - fb->width; |
343 | if (plane->fb_width + padding < MIN_FB_WIDTH_FOR_16WORD_BURST) { | 344 | if (fb->width + padding < MIN_FB_WIDTH_FOR_16WORD_BURST) { |
344 | val &= ~WINCONx_BURSTLEN_MASK; | 345 | val &= ~WINCONx_BURSTLEN_MASK; |
345 | val |= WINCONx_BURSTLEN_8WORD; | 346 | val |= WINCONx_BURSTLEN_8WORD; |
346 | } | 347 | } |
@@ -382,23 +383,19 @@ static void decon_shadow_protect_win(struct decon_context *ctx, | |||
382 | writel(val, ctx->regs + SHADOWCON); | 383 | writel(val, ctx->regs + SHADOWCON); |
383 | } | 384 | } |
384 | 385 | ||
385 | static void decon_win_commit(struct exynos_drm_crtc *crtc, unsigned int win) | 386 | static void decon_update_plane(struct exynos_drm_crtc *crtc, |
387 | struct exynos_drm_plane *plane) | ||
386 | { | 388 | { |
387 | struct decon_context *ctx = crtc->ctx; | 389 | struct decon_context *ctx = crtc->ctx; |
388 | struct drm_display_mode *mode = &crtc->base.state->adjusted_mode; | 390 | struct drm_display_mode *mode = &crtc->base.state->adjusted_mode; |
389 | struct exynos_drm_plane *plane; | 391 | struct drm_plane_state *state = plane->base.state; |
390 | int padding; | 392 | int padding; |
391 | unsigned long val, alpha; | 393 | unsigned long val, alpha; |
392 | unsigned int last_x; | 394 | unsigned int last_x; |
393 | unsigned int last_y; | 395 | unsigned int last_y; |
394 | 396 | unsigned int win = plane->zpos; | |
395 | if (ctx->suspended) | 397 | unsigned int bpp = state->fb->bits_per_pixel >> 3; |
396 | return; | 398 | unsigned int pitch = state->fb->pitches[0]; |
397 | |||
398 | if (win < 0 || win >= WINDOWS_NR) | ||
399 | return; | ||
400 | |||
401 | plane = &ctx->planes[win]; | ||
402 | 399 | ||
403 | if (ctx->suspended) | 400 | if (ctx->suspended) |
404 | return; | 401 | return; |
@@ -420,11 +417,11 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, unsigned int win) | |||
420 | val = (unsigned long)plane->dma_addr[0]; | 417 | val = (unsigned long)plane->dma_addr[0]; |
421 | writel(val, ctx->regs + VIDW_BUF_START(win)); | 418 | writel(val, ctx->regs + VIDW_BUF_START(win)); |
422 | 419 | ||
423 | padding = (plane->pitch / (plane->bpp >> 3)) - plane->fb_width; | 420 | padding = (pitch / bpp) - state->fb->width; |
424 | 421 | ||
425 | /* buffer size */ | 422 | /* buffer size */ |
426 | writel(plane->fb_width + padding, ctx->regs + VIDW_WHOLE_X(win)); | 423 | writel(state->fb->width + padding, ctx->regs + VIDW_WHOLE_X(win)); |
427 | writel(plane->fb_height, ctx->regs + VIDW_WHOLE_Y(win)); | 424 | writel(state->fb->height, ctx->regs + VIDW_WHOLE_Y(win)); |
428 | 425 | ||
429 | /* offset from the start of the buffer to read */ | 426 | /* offset from the start of the buffer to read */ |
430 | writel(plane->src_x, ctx->regs + VIDW_OFFSET_X(win)); | 427 | writel(plane->src_x, ctx->regs + VIDW_OFFSET_X(win)); |
@@ -433,25 +430,25 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, unsigned int win) | |||
433 | DRM_DEBUG_KMS("start addr = 0x%lx\n", | 430 | DRM_DEBUG_KMS("start addr = 0x%lx\n", |
434 | (unsigned long)val); | 431 | (unsigned long)val); |
435 | DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n", | 432 | DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n", |
436 | plane->crtc_width, plane->crtc_height); | 433 | plane->crtc_w, plane->crtc_h); |
437 | 434 | ||
438 | /* | 435 | /* |
439 | * OSD position. | 436 | * OSD position. |
440 | * In case the window layout goes of LCD layout, DECON fails. | 437 | * In case the window layout goes of LCD layout, DECON fails. |
441 | */ | 438 | */ |
442 | if ((plane->crtc_x + plane->crtc_width) > mode->hdisplay) | 439 | if ((plane->crtc_x + plane->crtc_w) > mode->hdisplay) |
443 | plane->crtc_x = mode->hdisplay - plane->crtc_width; | 440 | plane->crtc_x = mode->hdisplay - plane->crtc_w; |
444 | if ((plane->crtc_y + plane->crtc_height) > mode->vdisplay) | 441 | if ((plane->crtc_y + plane->crtc_h) > mode->vdisplay) |
445 | plane->crtc_y = mode->vdisplay - plane->crtc_height; | 442 | plane->crtc_y = mode->vdisplay - plane->crtc_h; |
446 | 443 | ||
447 | val = VIDOSDxA_TOPLEFT_X(plane->crtc_x) | | 444 | val = VIDOSDxA_TOPLEFT_X(plane->crtc_x) | |
448 | VIDOSDxA_TOPLEFT_Y(plane->crtc_y); | 445 | VIDOSDxA_TOPLEFT_Y(plane->crtc_y); |
449 | writel(val, ctx->regs + VIDOSD_A(win)); | 446 | writel(val, ctx->regs + VIDOSD_A(win)); |
450 | 447 | ||
451 | last_x = plane->crtc_x + plane->crtc_width; | 448 | last_x = plane->crtc_x + plane->crtc_w; |
452 | if (last_x) | 449 | if (last_x) |
453 | last_x--; | 450 | last_x--; |
454 | last_y = plane->crtc_y + plane->crtc_height; | 451 | last_y = plane->crtc_y + plane->crtc_h; |
455 | if (last_y) | 452 | if (last_y) |
456 | last_y--; | 453 | last_y--; |
457 | 454 | ||
@@ -475,7 +472,7 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, unsigned int win) | |||
475 | 472 | ||
476 | writel(alpha, ctx->regs + VIDOSD_D(win)); | 473 | writel(alpha, ctx->regs + VIDOSD_D(win)); |
477 | 474 | ||
478 | decon_win_set_pixfmt(ctx, win); | 475 | decon_win_set_pixfmt(ctx, win, state->fb); |
479 | 476 | ||
480 | /* hardware window 0 doesn't support color key. */ | 477 | /* hardware window 0 doesn't support color key. */ |
481 | if (win != 0) | 478 | if (win != 0) |
@@ -495,17 +492,13 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, unsigned int win) | |||
495 | writel(val, ctx->regs + DECON_UPDATE); | 492 | writel(val, ctx->regs + DECON_UPDATE); |
496 | } | 493 | } |
497 | 494 | ||
498 | static void decon_win_disable(struct exynos_drm_crtc *crtc, unsigned int win) | 495 | static void decon_disable_plane(struct exynos_drm_crtc *crtc, |
496 | struct exynos_drm_plane *plane) | ||
499 | { | 497 | { |
500 | struct decon_context *ctx = crtc->ctx; | 498 | struct decon_context *ctx = crtc->ctx; |
501 | struct exynos_drm_plane *plane; | 499 | unsigned int win = plane->zpos; |
502 | u32 val; | 500 | u32 val; |
503 | 501 | ||
504 | if (win < 0 || win >= WINDOWS_NR) | ||
505 | return; | ||
506 | |||
507 | plane = &ctx->planes[win]; | ||
508 | |||
509 | if (ctx->suspended) | 502 | if (ctx->suspended) |
510 | return; | 503 | return; |
511 | 504 | ||
@@ -601,7 +594,7 @@ static void decon_disable(struct exynos_drm_crtc *crtc) | |||
601 | * a destroyed buffer later. | 594 | * a destroyed buffer later. |
602 | */ | 595 | */ |
603 | for (i = 0; i < WINDOWS_NR; i++) | 596 | for (i = 0; i < WINDOWS_NR; i++) |
604 | decon_win_disable(crtc, i); | 597 | decon_disable_plane(crtc, &ctx->planes[i]); |
605 | 598 | ||
606 | clk_disable_unprepare(ctx->vclk); | 599 | clk_disable_unprepare(ctx->vclk); |
607 | clk_disable_unprepare(ctx->eclk); | 600 | clk_disable_unprepare(ctx->eclk); |
@@ -621,9 +614,8 @@ static const struct exynos_drm_crtc_ops decon_crtc_ops = { | |||
621 | .enable_vblank = decon_enable_vblank, | 614 | .enable_vblank = decon_enable_vblank, |
622 | .disable_vblank = decon_disable_vblank, | 615 | .disable_vblank = decon_disable_vblank, |
623 | .wait_for_vblank = decon_wait_for_vblank, | 616 | .wait_for_vblank = decon_wait_for_vblank, |
624 | .win_commit = decon_win_commit, | 617 | .update_plane = decon_update_plane, |
625 | .win_disable = decon_win_disable, | 618 | .disable_plane = decon_disable_plane, |
626 | .clear_channels = decon_clear_channels, | ||
627 | }; | 619 | }; |
628 | 620 | ||
629 | 621 | ||
@@ -643,8 +635,8 @@ static irqreturn_t decon_irq_handler(int irq, void *dev_id) | |||
643 | goto out; | 635 | goto out; |
644 | 636 | ||
645 | if (!ctx->i80_if) { | 637 | if (!ctx->i80_if) { |
646 | drm_handle_vblank(ctx->drm_dev, ctx->pipe); | 638 | drm_crtc_handle_vblank(&ctx->crtc->base); |
647 | exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe); | 639 | exynos_drm_crtc_finish_pageflip(ctx->crtc); |
648 | 640 | ||
649 | /* set wait vsync event to zero and wake up queue. */ | 641 | /* set wait vsync event to zero and wake up queue. */ |
650 | if (atomic_read(&ctx->wait_vsync_event)) { | 642 | if (atomic_read(&ctx->wait_vsync_event)) { |
@@ -689,8 +681,8 @@ static int decon_bind(struct device *dev, struct device *master, void *data) | |||
689 | return PTR_ERR(ctx->crtc); | 681 | return PTR_ERR(ctx->crtc); |
690 | } | 682 | } |
691 | 683 | ||
692 | if (ctx->display) | 684 | if (ctx->encoder) |
693 | exynos_drm_create_enc_conn(drm_dev, ctx->display); | 685 | exynos_dpi_bind(drm_dev, ctx->encoder); |
694 | 686 | ||
695 | return 0; | 687 | return 0; |
696 | 688 | ||
@@ -703,8 +695,8 @@ static void decon_unbind(struct device *dev, struct device *master, | |||
703 | 695 | ||
704 | decon_disable(ctx->crtc); | 696 | decon_disable(ctx->crtc); |
705 | 697 | ||
706 | if (ctx->display) | 698 | if (ctx->encoder) |
707 | exynos_dpi_remove(ctx->display); | 699 | exynos_dpi_remove(ctx->encoder); |
708 | 700 | ||
709 | decon_ctx_remove(ctx); | 701 | decon_ctx_remove(ctx); |
710 | } | 702 | } |
@@ -789,9 +781,9 @@ static int decon_probe(struct platform_device *pdev) | |||
789 | 781 | ||
790 | platform_set_drvdata(pdev, ctx); | 782 | platform_set_drvdata(pdev, ctx); |
791 | 783 | ||
792 | ctx->display = exynos_dpi_probe(dev); | 784 | ctx->encoder = exynos_dpi_probe(dev); |
793 | if (IS_ERR(ctx->display)) { | 785 | if (IS_ERR(ctx->encoder)) { |
794 | ret = PTR_ERR(ctx->display); | 786 | ret = PTR_ERR(ctx->encoder); |
795 | goto err_iounmap; | 787 | goto err_iounmap; |
796 | } | 788 | } |
797 | 789 | ||
diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c index 172b8002a2c8..d66ade0efac8 100644 --- a/drivers/gpu/drm/exynos/exynos_dp_core.c +++ b/drivers/gpu/drm/exynos/exynos_dp_core.c | |||
@@ -32,19 +32,20 @@ | |||
32 | #include <drm/drm_panel.h> | 32 | #include <drm/drm_panel.h> |
33 | 33 | ||
34 | #include "exynos_dp_core.h" | 34 | #include "exynos_dp_core.h" |
35 | #include "exynos_drm_crtc.h" | ||
35 | 36 | ||
36 | #define ctx_from_connector(c) container_of(c, struct exynos_dp_device, \ | 37 | #define ctx_from_connector(c) container_of(c, struct exynos_dp_device, \ |
37 | connector) | 38 | connector) |
38 | 39 | ||
39 | static inline struct exynos_drm_crtc *dp_to_crtc(struct exynos_dp_device *dp) | 40 | static inline struct exynos_drm_crtc *dp_to_crtc(struct exynos_dp_device *dp) |
40 | { | 41 | { |
41 | return to_exynos_crtc(dp->encoder->crtc); | 42 | return to_exynos_crtc(dp->encoder.crtc); |
42 | } | 43 | } |
43 | 44 | ||
44 | static inline struct exynos_dp_device * | 45 | static inline struct exynos_dp_device *encoder_to_dp( |
45 | display_to_dp(struct exynos_drm_display *d) | 46 | struct drm_encoder *e) |
46 | { | 47 | { |
47 | return container_of(d, struct exynos_dp_device, display); | 48 | return container_of(e, struct exynos_dp_device, encoder); |
48 | } | 49 | } |
49 | 50 | ||
50 | struct bridge_init { | 51 | struct bridge_init { |
@@ -795,9 +796,6 @@ static int exynos_dp_config_video(struct exynos_dp_device *dp) | |||
795 | /* Configure video slave mode */ | 796 | /* Configure video slave mode */ |
796 | exynos_dp_enable_video_master(dp, 0); | 797 | exynos_dp_enable_video_master(dp, 0); |
797 | 798 | ||
798 | /* Enable video */ | ||
799 | exynos_dp_start_video(dp); | ||
800 | |||
801 | timeout_loop = 0; | 799 | timeout_loop = 0; |
802 | 800 | ||
803 | for (;;) { | 801 | for (;;) { |
@@ -891,9 +889,9 @@ static void exynos_dp_hotplug(struct work_struct *work) | |||
891 | drm_helper_hpd_irq_event(dp->drm_dev); | 889 | drm_helper_hpd_irq_event(dp->drm_dev); |
892 | } | 890 | } |
893 | 891 | ||
894 | static void exynos_dp_commit(struct exynos_drm_display *display) | 892 | static void exynos_dp_commit(struct drm_encoder *encoder) |
895 | { | 893 | { |
896 | struct exynos_dp_device *dp = display_to_dp(display); | 894 | struct exynos_dp_device *dp = encoder_to_dp(encoder); |
897 | int ret; | 895 | int ret; |
898 | 896 | ||
899 | /* Keep the panel disabled while we configure video */ | 897 | /* Keep the panel disabled while we configure video */ |
@@ -938,6 +936,9 @@ static void exynos_dp_commit(struct exynos_drm_display *display) | |||
938 | if (drm_panel_enable(dp->panel)) | 936 | if (drm_panel_enable(dp->panel)) |
939 | DRM_ERROR("failed to enable the panel\n"); | 937 | DRM_ERROR("failed to enable the panel\n"); |
940 | } | 938 | } |
939 | |||
940 | /* Enable video */ | ||
941 | exynos_dp_start_video(dp); | ||
941 | } | 942 | } |
942 | 943 | ||
943 | static enum drm_connector_status exynos_dp_detect( | 944 | static enum drm_connector_status exynos_dp_detect( |
@@ -994,7 +995,7 @@ static struct drm_encoder *exynos_dp_best_encoder( | |||
994 | { | 995 | { |
995 | struct exynos_dp_device *dp = ctx_from_connector(connector); | 996 | struct exynos_dp_device *dp = ctx_from_connector(connector); |
996 | 997 | ||
997 | return dp->encoder; | 998 | return &dp->encoder; |
998 | } | 999 | } |
999 | 1000 | ||
1000 | static struct drm_connector_helper_funcs exynos_dp_connector_helper_funcs = { | 1001 | static struct drm_connector_helper_funcs exynos_dp_connector_helper_funcs = { |
@@ -1019,15 +1020,12 @@ static int exynos_drm_attach_lcd_bridge(struct exynos_dp_device *dp, | |||
1019 | return 0; | 1020 | return 0; |
1020 | } | 1021 | } |
1021 | 1022 | ||
1022 | static int exynos_dp_create_connector(struct exynos_drm_display *display, | 1023 | static int exynos_dp_create_connector(struct drm_encoder *encoder) |
1023 | struct drm_encoder *encoder) | ||
1024 | { | 1024 | { |
1025 | struct exynos_dp_device *dp = display_to_dp(display); | 1025 | struct exynos_dp_device *dp = encoder_to_dp(encoder); |
1026 | struct drm_connector *connector = &dp->connector; | 1026 | struct drm_connector *connector = &dp->connector; |
1027 | int ret; | 1027 | int ret; |
1028 | 1028 | ||
1029 | dp->encoder = encoder; | ||
1030 | |||
1031 | /* Pre-empt DP connector creation if there's a bridge */ | 1029 | /* Pre-empt DP connector creation if there's a bridge */ |
1032 | if (dp->bridge) { | 1030 | if (dp->bridge) { |
1033 | ret = exynos_drm_attach_lcd_bridge(dp, encoder); | 1031 | ret = exynos_drm_attach_lcd_bridge(dp, encoder); |
@@ -1054,20 +1052,22 @@ static int exynos_dp_create_connector(struct exynos_drm_display *display, | |||
1054 | return ret; | 1052 | return ret; |
1055 | } | 1053 | } |
1056 | 1054 | ||
1057 | static void exynos_dp_phy_init(struct exynos_dp_device *dp) | 1055 | static bool exynos_dp_mode_fixup(struct drm_encoder *encoder, |
1056 | const struct drm_display_mode *mode, | ||
1057 | struct drm_display_mode *adjusted_mode) | ||
1058 | { | 1058 | { |
1059 | if (dp->phy) | 1059 | return true; |
1060 | phy_power_on(dp->phy); | ||
1061 | } | 1060 | } |
1062 | 1061 | ||
1063 | static void exynos_dp_phy_exit(struct exynos_dp_device *dp) | 1062 | static void exynos_dp_mode_set(struct drm_encoder *encoder, |
1063 | struct drm_display_mode *mode, | ||
1064 | struct drm_display_mode *adjusted_mode) | ||
1064 | { | 1065 | { |
1065 | if (dp->phy) | ||
1066 | phy_power_off(dp->phy); | ||
1067 | } | 1066 | } |
1068 | 1067 | ||
1069 | static void exynos_dp_poweron(struct exynos_dp_device *dp) | 1068 | static void exynos_dp_enable(struct drm_encoder *encoder) |
1070 | { | 1069 | { |
1070 | struct exynos_dp_device *dp = encoder_to_dp(encoder); | ||
1071 | struct exynos_drm_crtc *crtc = dp_to_crtc(dp); | 1071 | struct exynos_drm_crtc *crtc = dp_to_crtc(dp); |
1072 | 1072 | ||
1073 | if (dp->dpms_mode == DRM_MODE_DPMS_ON) | 1073 | if (dp->dpms_mode == DRM_MODE_DPMS_ON) |
@@ -1084,14 +1084,17 @@ static void exynos_dp_poweron(struct exynos_dp_device *dp) | |||
1084 | crtc->ops->clock_enable(dp_to_crtc(dp), true); | 1084 | crtc->ops->clock_enable(dp_to_crtc(dp), true); |
1085 | 1085 | ||
1086 | clk_prepare_enable(dp->clock); | 1086 | clk_prepare_enable(dp->clock); |
1087 | exynos_dp_phy_init(dp); | 1087 | phy_power_on(dp->phy); |
1088 | exynos_dp_init_dp(dp); | 1088 | exynos_dp_init_dp(dp); |
1089 | enable_irq(dp->irq); | 1089 | enable_irq(dp->irq); |
1090 | exynos_dp_commit(&dp->display); | 1090 | exynos_dp_commit(&dp->encoder); |
1091 | |||
1092 | dp->dpms_mode = DRM_MODE_DPMS_ON; | ||
1091 | } | 1093 | } |
1092 | 1094 | ||
1093 | static void exynos_dp_poweroff(struct exynos_dp_device *dp) | 1095 | static void exynos_dp_disable(struct drm_encoder *encoder) |
1094 | { | 1096 | { |
1097 | struct exynos_dp_device *dp = encoder_to_dp(encoder); | ||
1095 | struct exynos_drm_crtc *crtc = dp_to_crtc(dp); | 1098 | struct exynos_drm_crtc *crtc = dp_to_crtc(dp); |
1096 | 1099 | ||
1097 | if (dp->dpms_mode != DRM_MODE_DPMS_ON) | 1100 | if (dp->dpms_mode != DRM_MODE_DPMS_ON) |
@@ -1106,7 +1109,7 @@ static void exynos_dp_poweroff(struct exynos_dp_device *dp) | |||
1106 | 1109 | ||
1107 | disable_irq(dp->irq); | 1110 | disable_irq(dp->irq); |
1108 | flush_work(&dp->hotplug_work); | 1111 | flush_work(&dp->hotplug_work); |
1109 | exynos_dp_phy_exit(dp); | 1112 | phy_power_off(dp->phy); |
1110 | clk_disable_unprepare(dp->clock); | 1113 | clk_disable_unprepare(dp->clock); |
1111 | 1114 | ||
1112 | if (crtc->ops->clock_enable) | 1115 | if (crtc->ops->clock_enable) |
@@ -1116,31 +1119,19 @@ static void exynos_dp_poweroff(struct exynos_dp_device *dp) | |||
1116 | if (drm_panel_unprepare(dp->panel)) | 1119 | if (drm_panel_unprepare(dp->panel)) |
1117 | DRM_ERROR("failed to turnoff the panel\n"); | 1120 | DRM_ERROR("failed to turnoff the panel\n"); |
1118 | } | 1121 | } |
1119 | } | ||
1120 | |||
1121 | static void exynos_dp_dpms(struct exynos_drm_display *display, int mode) | ||
1122 | { | ||
1123 | struct exynos_dp_device *dp = display_to_dp(display); | ||
1124 | 1122 | ||
1125 | switch (mode) { | 1123 | dp->dpms_mode = DRM_MODE_DPMS_OFF; |
1126 | case DRM_MODE_DPMS_ON: | ||
1127 | exynos_dp_poweron(dp); | ||
1128 | break; | ||
1129 | case DRM_MODE_DPMS_STANDBY: | ||
1130 | case DRM_MODE_DPMS_SUSPEND: | ||
1131 | case DRM_MODE_DPMS_OFF: | ||
1132 | exynos_dp_poweroff(dp); | ||
1133 | break; | ||
1134 | default: | ||
1135 | break; | ||
1136 | } | ||
1137 | dp->dpms_mode = mode; | ||
1138 | } | 1124 | } |
1139 | 1125 | ||
1140 | static struct exynos_drm_display_ops exynos_dp_display_ops = { | 1126 | static struct drm_encoder_helper_funcs exynos_dp_encoder_helper_funcs = { |
1141 | .create_connector = exynos_dp_create_connector, | 1127 | .mode_fixup = exynos_dp_mode_fixup, |
1142 | .dpms = exynos_dp_dpms, | 1128 | .mode_set = exynos_dp_mode_set, |
1143 | .commit = exynos_dp_commit, | 1129 | .enable = exynos_dp_enable, |
1130 | .disable = exynos_dp_disable, | ||
1131 | }; | ||
1132 | |||
1133 | static struct drm_encoder_funcs exynos_dp_encoder_funcs = { | ||
1134 | .destroy = drm_encoder_cleanup, | ||
1144 | }; | 1135 | }; |
1145 | 1136 | ||
1146 | static struct video_info *exynos_dp_dt_parse_pdata(struct device *dev) | 1137 | static struct video_info *exynos_dp_dt_parse_pdata(struct device *dev) |
@@ -1219,9 +1210,10 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data) | |||
1219 | struct exynos_dp_device *dp = dev_get_drvdata(dev); | 1210 | struct exynos_dp_device *dp = dev_get_drvdata(dev); |
1220 | struct platform_device *pdev = to_platform_device(dev); | 1211 | struct platform_device *pdev = to_platform_device(dev); |
1221 | struct drm_device *drm_dev = data; | 1212 | struct drm_device *drm_dev = data; |
1213 | struct drm_encoder *encoder = &dp->encoder; | ||
1222 | struct resource *res; | 1214 | struct resource *res; |
1223 | unsigned int irq_flags; | 1215 | unsigned int irq_flags; |
1224 | int ret = 0; | 1216 | int pipe, ret = 0; |
1225 | 1217 | ||
1226 | dp->dev = &pdev->dev; | 1218 | dp->dev = &pdev->dev; |
1227 | dp->dpms_mode = DRM_MODE_DPMS_OFF; | 1219 | dp->dpms_mode = DRM_MODE_DPMS_OFF; |
@@ -1297,7 +1289,7 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data) | |||
1297 | 1289 | ||
1298 | INIT_WORK(&dp->hotplug_work, exynos_dp_hotplug); | 1290 | INIT_WORK(&dp->hotplug_work, exynos_dp_hotplug); |
1299 | 1291 | ||
1300 | exynos_dp_phy_init(dp); | 1292 | phy_power_on(dp->phy); |
1301 | 1293 | ||
1302 | exynos_dp_init_dp(dp); | 1294 | exynos_dp_init_dp(dp); |
1303 | 1295 | ||
@@ -1311,7 +1303,28 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data) | |||
1311 | 1303 | ||
1312 | dp->drm_dev = drm_dev; | 1304 | dp->drm_dev = drm_dev; |
1313 | 1305 | ||
1314 | return exynos_drm_create_enc_conn(drm_dev, &dp->display); | 1306 | pipe = exynos_drm_crtc_get_pipe_from_type(drm_dev, |
1307 | EXYNOS_DISPLAY_TYPE_LCD); | ||
1308 | if (pipe < 0) | ||
1309 | return pipe; | ||
1310 | |||
1311 | encoder->possible_crtcs = 1 << pipe; | ||
1312 | |||
1313 | DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs); | ||
1314 | |||
1315 | drm_encoder_init(drm_dev, encoder, &exynos_dp_encoder_funcs, | ||
1316 | DRM_MODE_ENCODER_TMDS); | ||
1317 | |||
1318 | drm_encoder_helper_add(encoder, &exynos_dp_encoder_helper_funcs); | ||
1319 | |||
1320 | ret = exynos_dp_create_connector(encoder); | ||
1321 | if (ret) { | ||
1322 | DRM_ERROR("failed to create connector ret = %d\n", ret); | ||
1323 | drm_encoder_cleanup(encoder); | ||
1324 | return ret; | ||
1325 | } | ||
1326 | |||
1327 | return 0; | ||
1315 | } | 1328 | } |
1316 | 1329 | ||
1317 | static void exynos_dp_unbind(struct device *dev, struct device *master, | 1330 | static void exynos_dp_unbind(struct device *dev, struct device *master, |
@@ -1319,7 +1332,7 @@ static void exynos_dp_unbind(struct device *dev, struct device *master, | |||
1319 | { | 1332 | { |
1320 | struct exynos_dp_device *dp = dev_get_drvdata(dev); | 1333 | struct exynos_dp_device *dp = dev_get_drvdata(dev); |
1321 | 1334 | ||
1322 | exynos_dp_dpms(&dp->display, DRM_MODE_DPMS_OFF); | 1335 | exynos_dp_disable(&dp->encoder); |
1323 | } | 1336 | } |
1324 | 1337 | ||
1325 | static const struct component_ops exynos_dp_ops = { | 1338 | static const struct component_ops exynos_dp_ops = { |
@@ -1338,8 +1351,6 @@ static int exynos_dp_probe(struct platform_device *pdev) | |||
1338 | if (!dp) | 1351 | if (!dp) |
1339 | return -ENOMEM; | 1352 | return -ENOMEM; |
1340 | 1353 | ||
1341 | dp->display.type = EXYNOS_DISPLAY_TYPE_LCD; | ||
1342 | dp->display.ops = &exynos_dp_display_ops; | ||
1343 | platform_set_drvdata(pdev, dp); | 1354 | platform_set_drvdata(pdev, dp); |
1344 | 1355 | ||
1345 | panel_node = of_parse_phandle(dev->of_node, "panel", 0); | 1356 | panel_node = of_parse_phandle(dev->of_node, "panel", 0); |
@@ -1377,7 +1388,7 @@ static int exynos_dp_suspend(struct device *dev) | |||
1377 | { | 1388 | { |
1378 | struct exynos_dp_device *dp = dev_get_drvdata(dev); | 1389 | struct exynos_dp_device *dp = dev_get_drvdata(dev); |
1379 | 1390 | ||
1380 | exynos_dp_dpms(&dp->display, DRM_MODE_DPMS_OFF); | 1391 | exynos_dp_disable(&dp->encoder); |
1381 | return 0; | 1392 | return 0; |
1382 | } | 1393 | } |
1383 | 1394 | ||
@@ -1385,7 +1396,7 @@ static int exynos_dp_resume(struct device *dev) | |||
1385 | { | 1396 | { |
1386 | struct exynos_dp_device *dp = dev_get_drvdata(dev); | 1397 | struct exynos_dp_device *dp = dev_get_drvdata(dev); |
1387 | 1398 | ||
1388 | exynos_dp_dpms(&dp->display, DRM_MODE_DPMS_ON); | 1399 | exynos_dp_enable(&dp->encoder); |
1389 | return 0; | 1400 | return 0; |
1390 | } | 1401 | } |
1391 | #endif | 1402 | #endif |
diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.h b/drivers/gpu/drm/exynos/exynos_dp_core.h index a4e799679669..e413b6f7b0e7 100644 --- a/drivers/gpu/drm/exynos/exynos_dp_core.h +++ b/drivers/gpu/drm/exynos/exynos_dp_core.h | |||
@@ -147,11 +147,10 @@ struct link_train { | |||
147 | }; | 147 | }; |
148 | 148 | ||
149 | struct exynos_dp_device { | 149 | struct exynos_dp_device { |
150 | struct exynos_drm_display display; | 150 | struct drm_encoder encoder; |
151 | struct device *dev; | 151 | struct device *dev; |
152 | struct drm_device *drm_dev; | 152 | struct drm_device *drm_dev; |
153 | struct drm_connector connector; | 153 | struct drm_connector connector; |
154 | struct drm_encoder *encoder; | ||
155 | struct drm_panel *panel; | 154 | struct drm_panel *panel; |
156 | struct drm_bridge *bridge; | 155 | struct drm_bridge *bridge; |
157 | struct clk *clock; | 156 | struct clk *clock; |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_buf.c b/drivers/gpu/drm/exynos/exynos_drm_buf.c deleted file mode 100644 index 24994ba10e28..000000000000 --- a/drivers/gpu/drm/exynos/exynos_drm_buf.c +++ /dev/null | |||
@@ -1,186 +0,0 @@ | |||
1 | /* exynos_drm_buf.c | ||
2 | * | ||
3 | * Copyright (c) 2011 Samsung Electronics Co., Ltd. | ||
4 | * Author: Inki Dae <inki.dae@samsung.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <drm/drmP.h> | ||
13 | #include <drm/exynos_drm.h> | ||
14 | |||
15 | #include "exynos_drm_drv.h" | ||
16 | #include "exynos_drm_gem.h" | ||
17 | #include "exynos_drm_buf.h" | ||
18 | #include "exynos_drm_iommu.h" | ||
19 | |||
20 | static int lowlevel_buffer_allocate(struct drm_device *dev, | ||
21 | unsigned int flags, struct exynos_drm_gem_buf *buf) | ||
22 | { | ||
23 | int ret = 0; | ||
24 | enum dma_attr attr; | ||
25 | unsigned int nr_pages; | ||
26 | |||
27 | if (buf->dma_addr) { | ||
28 | DRM_DEBUG_KMS("already allocated.\n"); | ||
29 | return 0; | ||
30 | } | ||
31 | |||
32 | init_dma_attrs(&buf->dma_attrs); | ||
33 | |||
34 | /* | ||
35 | * if EXYNOS_BO_CONTIG, fully physically contiguous memory | ||
36 | * region will be allocated else physically contiguous | ||
37 | * as possible. | ||
38 | */ | ||
39 | if (!(flags & EXYNOS_BO_NONCONTIG)) | ||
40 | dma_set_attr(DMA_ATTR_FORCE_CONTIGUOUS, &buf->dma_attrs); | ||
41 | |||
42 | /* | ||
43 | * if EXYNOS_BO_WC or EXYNOS_BO_NONCACHABLE, writecombine mapping | ||
44 | * else cachable mapping. | ||
45 | */ | ||
46 | if (flags & EXYNOS_BO_WC || !(flags & EXYNOS_BO_CACHABLE)) | ||
47 | attr = DMA_ATTR_WRITE_COMBINE; | ||
48 | else | ||
49 | attr = DMA_ATTR_NON_CONSISTENT; | ||
50 | |||
51 | dma_set_attr(attr, &buf->dma_attrs); | ||
52 | dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &buf->dma_attrs); | ||
53 | |||
54 | nr_pages = buf->size >> PAGE_SHIFT; | ||
55 | |||
56 | if (!is_drm_iommu_supported(dev)) { | ||
57 | dma_addr_t start_addr; | ||
58 | unsigned int i = 0; | ||
59 | |||
60 | buf->pages = drm_calloc_large(nr_pages, sizeof(struct page *)); | ||
61 | if (!buf->pages) { | ||
62 | DRM_ERROR("failed to allocate pages.\n"); | ||
63 | return -ENOMEM; | ||
64 | } | ||
65 | |||
66 | buf->cookie = dma_alloc_attrs(dev->dev, | ||
67 | buf->size, | ||
68 | &buf->dma_addr, GFP_KERNEL, | ||
69 | &buf->dma_attrs); | ||
70 | if (!buf->cookie) { | ||
71 | DRM_ERROR("failed to allocate buffer.\n"); | ||
72 | ret = -ENOMEM; | ||
73 | goto err_free; | ||
74 | } | ||
75 | |||
76 | start_addr = buf->dma_addr; | ||
77 | while (i < nr_pages) { | ||
78 | buf->pages[i] = phys_to_page(start_addr); | ||
79 | start_addr += PAGE_SIZE; | ||
80 | i++; | ||
81 | } | ||
82 | } else { | ||
83 | |||
84 | buf->pages = dma_alloc_attrs(dev->dev, buf->size, | ||
85 | &buf->dma_addr, GFP_KERNEL, | ||
86 | &buf->dma_attrs); | ||
87 | if (!buf->pages) { | ||
88 | DRM_ERROR("failed to allocate buffer.\n"); | ||
89 | return -ENOMEM; | ||
90 | } | ||
91 | } | ||
92 | |||
93 | buf->sgt = drm_prime_pages_to_sg(buf->pages, nr_pages); | ||
94 | if (IS_ERR(buf->sgt)) { | ||
95 | DRM_ERROR("failed to get sg table.\n"); | ||
96 | ret = PTR_ERR(buf->sgt); | ||
97 | goto err_free_attrs; | ||
98 | } | ||
99 | |||
100 | DRM_DEBUG_KMS("dma_addr(0x%lx), size(0x%lx)\n", | ||
101 | (unsigned long)buf->dma_addr, | ||
102 | buf->size); | ||
103 | |||
104 | return ret; | ||
105 | |||
106 | err_free_attrs: | ||
107 | dma_free_attrs(dev->dev, buf->size, buf->pages, | ||
108 | (dma_addr_t)buf->dma_addr, &buf->dma_attrs); | ||
109 | buf->dma_addr = (dma_addr_t)NULL; | ||
110 | err_free: | ||
111 | if (!is_drm_iommu_supported(dev)) | ||
112 | drm_free_large(buf->pages); | ||
113 | |||
114 | return ret; | ||
115 | } | ||
116 | |||
117 | static void lowlevel_buffer_deallocate(struct drm_device *dev, | ||
118 | unsigned int flags, struct exynos_drm_gem_buf *buf) | ||
119 | { | ||
120 | if (!buf->dma_addr) { | ||
121 | DRM_DEBUG_KMS("dma_addr is invalid.\n"); | ||
122 | return; | ||
123 | } | ||
124 | |||
125 | DRM_DEBUG_KMS("dma_addr(0x%lx), size(0x%lx)\n", | ||
126 | (unsigned long)buf->dma_addr, | ||
127 | buf->size); | ||
128 | |||
129 | sg_free_table(buf->sgt); | ||
130 | |||
131 | kfree(buf->sgt); | ||
132 | buf->sgt = NULL; | ||
133 | |||
134 | if (!is_drm_iommu_supported(dev)) { | ||
135 | dma_free_attrs(dev->dev, buf->size, buf->cookie, | ||
136 | (dma_addr_t)buf->dma_addr, &buf->dma_attrs); | ||
137 | drm_free_large(buf->pages); | ||
138 | } else | ||
139 | dma_free_attrs(dev->dev, buf->size, buf->pages, | ||
140 | (dma_addr_t)buf->dma_addr, &buf->dma_attrs); | ||
141 | |||
142 | buf->dma_addr = (dma_addr_t)NULL; | ||
143 | } | ||
144 | |||
145 | struct exynos_drm_gem_buf *exynos_drm_init_buf(struct drm_device *dev, | ||
146 | unsigned int size) | ||
147 | { | ||
148 | struct exynos_drm_gem_buf *buffer; | ||
149 | |||
150 | DRM_DEBUG_KMS("desired size = 0x%x\n", size); | ||
151 | |||
152 | buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); | ||
153 | if (!buffer) | ||
154 | return NULL; | ||
155 | |||
156 | buffer->size = size; | ||
157 | return buffer; | ||
158 | } | ||
159 | |||
160 | void exynos_drm_fini_buf(struct drm_device *dev, | ||
161 | struct exynos_drm_gem_buf *buffer) | ||
162 | { | ||
163 | kfree(buffer); | ||
164 | buffer = NULL; | ||
165 | } | ||
166 | |||
167 | int exynos_drm_alloc_buf(struct drm_device *dev, | ||
168 | struct exynos_drm_gem_buf *buf, unsigned int flags) | ||
169 | { | ||
170 | |||
171 | /* | ||
172 | * allocate memory region and set the memory information | ||
173 | * to vaddr and dma_addr of a buffer object. | ||
174 | */ | ||
175 | if (lowlevel_buffer_allocate(dev, flags, buf) < 0) | ||
176 | return -ENOMEM; | ||
177 | |||
178 | return 0; | ||
179 | } | ||
180 | |||
181 | void exynos_drm_free_buf(struct drm_device *dev, | ||
182 | unsigned int flags, struct exynos_drm_gem_buf *buffer) | ||
183 | { | ||
184 | |||
185 | lowlevel_buffer_deallocate(dev, flags, buffer); | ||
186 | } | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_buf.h b/drivers/gpu/drm/exynos/exynos_drm_buf.h deleted file mode 100644 index a6412f19673c..000000000000 --- a/drivers/gpu/drm/exynos/exynos_drm_buf.h +++ /dev/null | |||
@@ -1,33 +0,0 @@ | |||
1 | /* exynos_drm_buf.h | ||
2 | * | ||
3 | * Copyright (c) 2011 Samsung Electronics Co., Ltd. | ||
4 | * Author: Inki Dae <inki.dae@samsung.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | */ | ||
11 | |||
12 | #ifndef _EXYNOS_DRM_BUF_H_ | ||
13 | #define _EXYNOS_DRM_BUF_H_ | ||
14 | |||
15 | /* create and initialize buffer object. */ | ||
16 | struct exynos_drm_gem_buf *exynos_drm_init_buf(struct drm_device *dev, | ||
17 | unsigned int size); | ||
18 | |||
19 | /* destroy buffer object. */ | ||
20 | void exynos_drm_fini_buf(struct drm_device *dev, | ||
21 | struct exynos_drm_gem_buf *buffer); | ||
22 | |||
23 | /* allocate physical memory region and setup sgt. */ | ||
24 | int exynos_drm_alloc_buf(struct drm_device *dev, | ||
25 | struct exynos_drm_gem_buf *buf, | ||
26 | unsigned int flags); | ||
27 | |||
28 | /* release physical memory region, and sgt. */ | ||
29 | void exynos_drm_free_buf(struct drm_device *dev, | ||
30 | unsigned int flags, | ||
31 | struct exynos_drm_gem_buf *buffer); | ||
32 | |||
33 | #endif | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_core.c b/drivers/gpu/drm/exynos/exynos_drm_core.c index 4c9f972eaa07..c68a6a2a9b57 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_core.c +++ b/drivers/gpu/drm/exynos/exynos_drm_core.c | |||
@@ -15,46 +15,10 @@ | |||
15 | #include <drm/drmP.h> | 15 | #include <drm/drmP.h> |
16 | #include "exynos_drm_drv.h" | 16 | #include "exynos_drm_drv.h" |
17 | #include "exynos_drm_crtc.h" | 17 | #include "exynos_drm_crtc.h" |
18 | #include "exynos_drm_encoder.h" | ||
19 | #include "exynos_drm_fbdev.h" | 18 | #include "exynos_drm_fbdev.h" |
20 | 19 | ||
21 | static LIST_HEAD(exynos_drm_subdrv_list); | 20 | static LIST_HEAD(exynos_drm_subdrv_list); |
22 | 21 | ||
23 | int exynos_drm_create_enc_conn(struct drm_device *dev, | ||
24 | struct exynos_drm_display *display) | ||
25 | { | ||
26 | struct drm_encoder *encoder; | ||
27 | int ret; | ||
28 | unsigned long possible_crtcs = 0; | ||
29 | |||
30 | ret = exynos_drm_crtc_get_pipe_from_type(dev, display->type); | ||
31 | if (ret < 0) | ||
32 | return ret; | ||
33 | |||
34 | possible_crtcs |= 1 << ret; | ||
35 | |||
36 | /* create and initialize a encoder for this sub driver. */ | ||
37 | encoder = exynos_drm_encoder_create(dev, display, possible_crtcs); | ||
38 | if (!encoder) { | ||
39 | DRM_ERROR("failed to create encoder\n"); | ||
40 | return -EFAULT; | ||
41 | } | ||
42 | |||
43 | display->encoder = encoder; | ||
44 | |||
45 | ret = display->ops->create_connector(display, encoder); | ||
46 | if (ret) { | ||
47 | DRM_ERROR("failed to create connector ret = %d\n", ret); | ||
48 | goto err_destroy_encoder; | ||
49 | } | ||
50 | |||
51 | return 0; | ||
52 | |||
53 | err_destroy_encoder: | ||
54 | encoder->funcs->destroy(encoder); | ||
55 | return ret; | ||
56 | } | ||
57 | |||
58 | int exynos_drm_subdrv_register(struct exynos_drm_subdrv *subdrv) | 22 | int exynos_drm_subdrv_register(struct exynos_drm_subdrv *subdrv) |
59 | { | 23 | { |
60 | if (!subdrv) | 24 | if (!subdrv) |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index 1610757230a5..c47899738eb4 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c | |||
@@ -19,7 +19,6 @@ | |||
19 | 19 | ||
20 | #include "exynos_drm_crtc.h" | 20 | #include "exynos_drm_crtc.h" |
21 | #include "exynos_drm_drv.h" | 21 | #include "exynos_drm_drv.h" |
22 | #include "exynos_drm_encoder.h" | ||
23 | #include "exynos_drm_plane.h" | 22 | #include "exynos_drm_plane.h" |
24 | 23 | ||
25 | static void exynos_drm_crtc_enable(struct drm_crtc *crtc) | 24 | static void exynos_drm_crtc_enable(struct drm_crtc *crtc) |
@@ -177,7 +176,7 @@ int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe) | |||
177 | return -EPERM; | 176 | return -EPERM; |
178 | 177 | ||
179 | if (exynos_crtc->ops->enable_vblank) | 178 | if (exynos_crtc->ops->enable_vblank) |
180 | exynos_crtc->ops->enable_vblank(exynos_crtc); | 179 | return exynos_crtc->ops->enable_vblank(exynos_crtc); |
181 | 180 | ||
182 | return 0; | 181 | return 0; |
183 | } | 182 | } |
@@ -195,24 +194,22 @@ void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe) | |||
195 | exynos_crtc->ops->disable_vblank(exynos_crtc); | 194 | exynos_crtc->ops->disable_vblank(exynos_crtc); |
196 | } | 195 | } |
197 | 196 | ||
198 | void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe) | 197 | void exynos_drm_crtc_finish_pageflip(struct exynos_drm_crtc *exynos_crtc) |
199 | { | 198 | { |
200 | struct exynos_drm_private *dev_priv = dev->dev_private; | 199 | struct drm_crtc *crtc = &exynos_crtc->base; |
201 | struct drm_crtc *drm_crtc = dev_priv->crtc[pipe]; | ||
202 | struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(drm_crtc); | ||
203 | unsigned long flags; | 200 | unsigned long flags; |
204 | 201 | ||
205 | spin_lock_irqsave(&dev->event_lock, flags); | 202 | spin_lock_irqsave(&crtc->dev->event_lock, flags); |
206 | if (exynos_crtc->event) { | 203 | if (exynos_crtc->event) { |
207 | 204 | ||
208 | drm_send_vblank_event(dev, -1, exynos_crtc->event); | 205 | drm_crtc_send_vblank_event(crtc, exynos_crtc->event); |
209 | drm_vblank_put(dev, pipe); | 206 | drm_crtc_vblank_put(crtc); |
210 | wake_up(&exynos_crtc->pending_flip_queue); | 207 | wake_up(&exynos_crtc->pending_flip_queue); |
211 | 208 | ||
212 | } | 209 | } |
213 | 210 | ||
214 | exynos_crtc->event = NULL; | 211 | exynos_crtc->event = NULL; |
215 | spin_unlock_irqrestore(&dev->event_lock, flags); | 212 | spin_unlock_irqrestore(&crtc->dev->event_lock, flags); |
216 | } | 213 | } |
217 | 214 | ||
218 | void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb) | 215 | void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb) |
@@ -239,7 +236,7 @@ void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb) | |||
239 | } | 236 | } |
240 | 237 | ||
241 | int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev, | 238 | int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev, |
242 | unsigned int out_type) | 239 | enum exynos_drm_output_type out_type) |
243 | { | 240 | { |
244 | struct drm_crtc *crtc; | 241 | struct drm_crtc *crtc; |
245 | 242 | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.h b/drivers/gpu/drm/exynos/exynos_drm_crtc.h index 0f3aa70818e3..9e7027d6c2f6 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.h +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.h | |||
@@ -25,12 +25,12 @@ struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev, | |||
25 | void *context); | 25 | void *context); |
26 | int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe); | 26 | int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe); |
27 | void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe); | 27 | void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe); |
28 | void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe); | 28 | void exynos_drm_crtc_finish_pageflip(struct exynos_drm_crtc *exynos_crtc); |
29 | void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb); | 29 | void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb); |
30 | 30 | ||
31 | /* This function gets pipe value to crtc device matched with out_type. */ | 31 | /* This function gets pipe value to crtc device matched with out_type. */ |
32 | int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev, | 32 | int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev, |
33 | unsigned int out_type); | 33 | enum exynos_drm_output_type out_type); |
34 | 34 | ||
35 | /* | 35 | /* |
36 | * This function calls the crtc device(manager)'s te_handler() callback | 36 | * This function calls the crtc device(manager)'s te_handler() callback |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c deleted file mode 100644 index cd485c091b30..000000000000 --- a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c +++ /dev/null | |||
@@ -1,286 +0,0 @@ | |||
1 | /* exynos_drm_dmabuf.c | ||
2 | * | ||
3 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. | ||
4 | * Author: Inki Dae <inki.dae@samsung.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <drm/drmP.h> | ||
13 | #include <drm/exynos_drm.h> | ||
14 | #include "exynos_drm_dmabuf.h" | ||
15 | #include "exynos_drm_drv.h" | ||
16 | #include "exynos_drm_gem.h" | ||
17 | |||
18 | #include <linux/dma-buf.h> | ||
19 | |||
20 | struct exynos_drm_dmabuf_attachment { | ||
21 | struct sg_table sgt; | ||
22 | enum dma_data_direction dir; | ||
23 | bool is_mapped; | ||
24 | }; | ||
25 | |||
26 | static struct exynos_drm_gem_obj *dma_buf_to_obj(struct dma_buf *buf) | ||
27 | { | ||
28 | return to_exynos_gem_obj(buf->priv); | ||
29 | } | ||
30 | |||
31 | static int exynos_gem_attach_dma_buf(struct dma_buf *dmabuf, | ||
32 | struct device *dev, | ||
33 | struct dma_buf_attachment *attach) | ||
34 | { | ||
35 | struct exynos_drm_dmabuf_attachment *exynos_attach; | ||
36 | |||
37 | exynos_attach = kzalloc(sizeof(*exynos_attach), GFP_KERNEL); | ||
38 | if (!exynos_attach) | ||
39 | return -ENOMEM; | ||
40 | |||
41 | exynos_attach->dir = DMA_NONE; | ||
42 | attach->priv = exynos_attach; | ||
43 | |||
44 | return 0; | ||
45 | } | ||
46 | |||
47 | static void exynos_gem_detach_dma_buf(struct dma_buf *dmabuf, | ||
48 | struct dma_buf_attachment *attach) | ||
49 | { | ||
50 | struct exynos_drm_dmabuf_attachment *exynos_attach = attach->priv; | ||
51 | struct sg_table *sgt; | ||
52 | |||
53 | if (!exynos_attach) | ||
54 | return; | ||
55 | |||
56 | sgt = &exynos_attach->sgt; | ||
57 | |||
58 | if (exynos_attach->dir != DMA_NONE) | ||
59 | dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents, | ||
60 | exynos_attach->dir); | ||
61 | |||
62 | sg_free_table(sgt); | ||
63 | kfree(exynos_attach); | ||
64 | attach->priv = NULL; | ||
65 | } | ||
66 | |||
67 | static struct sg_table * | ||
68 | exynos_gem_map_dma_buf(struct dma_buf_attachment *attach, | ||
69 | enum dma_data_direction dir) | ||
70 | { | ||
71 | struct exynos_drm_dmabuf_attachment *exynos_attach = attach->priv; | ||
72 | struct exynos_drm_gem_obj *gem_obj = dma_buf_to_obj(attach->dmabuf); | ||
73 | struct drm_device *dev = gem_obj->base.dev; | ||
74 | struct exynos_drm_gem_buf *buf; | ||
75 | struct scatterlist *rd, *wr; | ||
76 | struct sg_table *sgt = NULL; | ||
77 | unsigned int i; | ||
78 | int nents, ret; | ||
79 | |||
80 | /* just return current sgt if already requested. */ | ||
81 | if (exynos_attach->dir == dir && exynos_attach->is_mapped) | ||
82 | return &exynos_attach->sgt; | ||
83 | |||
84 | buf = gem_obj->buffer; | ||
85 | if (!buf) { | ||
86 | DRM_ERROR("buffer is null.\n"); | ||
87 | return ERR_PTR(-ENOMEM); | ||
88 | } | ||
89 | |||
90 | sgt = &exynos_attach->sgt; | ||
91 | |||
92 | ret = sg_alloc_table(sgt, buf->sgt->orig_nents, GFP_KERNEL); | ||
93 | if (ret) { | ||
94 | DRM_ERROR("failed to alloc sgt.\n"); | ||
95 | return ERR_PTR(-ENOMEM); | ||
96 | } | ||
97 | |||
98 | mutex_lock(&dev->struct_mutex); | ||
99 | |||
100 | rd = buf->sgt->sgl; | ||
101 | wr = sgt->sgl; | ||
102 | for (i = 0; i < sgt->orig_nents; ++i) { | ||
103 | sg_set_page(wr, sg_page(rd), rd->length, rd->offset); | ||
104 | rd = sg_next(rd); | ||
105 | wr = sg_next(wr); | ||
106 | } | ||
107 | |||
108 | if (dir != DMA_NONE) { | ||
109 | nents = dma_map_sg(attach->dev, sgt->sgl, sgt->orig_nents, dir); | ||
110 | if (!nents) { | ||
111 | DRM_ERROR("failed to map sgl with iommu.\n"); | ||
112 | sg_free_table(sgt); | ||
113 | sgt = ERR_PTR(-EIO); | ||
114 | goto err_unlock; | ||
115 | } | ||
116 | } | ||
117 | |||
118 | exynos_attach->is_mapped = true; | ||
119 | exynos_attach->dir = dir; | ||
120 | attach->priv = exynos_attach; | ||
121 | |||
122 | DRM_DEBUG_PRIME("buffer size = 0x%lx\n", buf->size); | ||
123 | |||
124 | err_unlock: | ||
125 | mutex_unlock(&dev->struct_mutex); | ||
126 | return sgt; | ||
127 | } | ||
128 | |||
129 | static void exynos_gem_unmap_dma_buf(struct dma_buf_attachment *attach, | ||
130 | struct sg_table *sgt, | ||
131 | enum dma_data_direction dir) | ||
132 | { | ||
133 | /* Nothing to do. */ | ||
134 | } | ||
135 | |||
136 | static void *exynos_gem_dmabuf_kmap_atomic(struct dma_buf *dma_buf, | ||
137 | unsigned long page_num) | ||
138 | { | ||
139 | /* TODO */ | ||
140 | |||
141 | return NULL; | ||
142 | } | ||
143 | |||
144 | static void exynos_gem_dmabuf_kunmap_atomic(struct dma_buf *dma_buf, | ||
145 | unsigned long page_num, | ||
146 | void *addr) | ||
147 | { | ||
148 | /* TODO */ | ||
149 | } | ||
150 | |||
151 | static void *exynos_gem_dmabuf_kmap(struct dma_buf *dma_buf, | ||
152 | unsigned long page_num) | ||
153 | { | ||
154 | /* TODO */ | ||
155 | |||
156 | return NULL; | ||
157 | } | ||
158 | |||
159 | static void exynos_gem_dmabuf_kunmap(struct dma_buf *dma_buf, | ||
160 | unsigned long page_num, void *addr) | ||
161 | { | ||
162 | /* TODO */ | ||
163 | } | ||
164 | |||
165 | static int exynos_gem_dmabuf_mmap(struct dma_buf *dma_buf, | ||
166 | struct vm_area_struct *vma) | ||
167 | { | ||
168 | return -ENOTTY; | ||
169 | } | ||
170 | |||
171 | static struct dma_buf_ops exynos_dmabuf_ops = { | ||
172 | .attach = exynos_gem_attach_dma_buf, | ||
173 | .detach = exynos_gem_detach_dma_buf, | ||
174 | .map_dma_buf = exynos_gem_map_dma_buf, | ||
175 | .unmap_dma_buf = exynos_gem_unmap_dma_buf, | ||
176 | .kmap = exynos_gem_dmabuf_kmap, | ||
177 | .kmap_atomic = exynos_gem_dmabuf_kmap_atomic, | ||
178 | .kunmap = exynos_gem_dmabuf_kunmap, | ||
179 | .kunmap_atomic = exynos_gem_dmabuf_kunmap_atomic, | ||
180 | .mmap = exynos_gem_dmabuf_mmap, | ||
181 | .release = drm_gem_dmabuf_release, | ||
182 | }; | ||
183 | |||
184 | struct dma_buf *exynos_dmabuf_prime_export(struct drm_device *drm_dev, | ||
185 | struct drm_gem_object *obj, int flags) | ||
186 | { | ||
187 | struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj); | ||
188 | DEFINE_DMA_BUF_EXPORT_INFO(exp_info); | ||
189 | |||
190 | exp_info.ops = &exynos_dmabuf_ops; | ||
191 | exp_info.size = exynos_gem_obj->base.size; | ||
192 | exp_info.flags = flags; | ||
193 | exp_info.priv = obj; | ||
194 | |||
195 | return dma_buf_export(&exp_info); | ||
196 | } | ||
197 | |||
198 | struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev, | ||
199 | struct dma_buf *dma_buf) | ||
200 | { | ||
201 | struct dma_buf_attachment *attach; | ||
202 | struct sg_table *sgt; | ||
203 | struct scatterlist *sgl; | ||
204 | struct exynos_drm_gem_obj *exynos_gem_obj; | ||
205 | struct exynos_drm_gem_buf *buffer; | ||
206 | int ret; | ||
207 | |||
208 | /* is this one of own objects? */ | ||
209 | if (dma_buf->ops == &exynos_dmabuf_ops) { | ||
210 | struct drm_gem_object *obj; | ||
211 | |||
212 | obj = dma_buf->priv; | ||
213 | |||
214 | /* is it from our device? */ | ||
215 | if (obj->dev == drm_dev) { | ||
216 | /* | ||
217 | * Importing dmabuf exported from out own gem increases | ||
218 | * refcount on gem itself instead of f_count of dmabuf. | ||
219 | */ | ||
220 | drm_gem_object_reference(obj); | ||
221 | return obj; | ||
222 | } | ||
223 | } | ||
224 | |||
225 | attach = dma_buf_attach(dma_buf, drm_dev->dev); | ||
226 | if (IS_ERR(attach)) | ||
227 | return ERR_PTR(-EINVAL); | ||
228 | |||
229 | get_dma_buf(dma_buf); | ||
230 | |||
231 | sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); | ||
232 | if (IS_ERR(sgt)) { | ||
233 | ret = PTR_ERR(sgt); | ||
234 | goto err_buf_detach; | ||
235 | } | ||
236 | |||
237 | buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); | ||
238 | if (!buffer) { | ||
239 | ret = -ENOMEM; | ||
240 | goto err_unmap_attach; | ||
241 | } | ||
242 | |||
243 | exynos_gem_obj = exynos_drm_gem_init(drm_dev, dma_buf->size); | ||
244 | if (!exynos_gem_obj) { | ||
245 | ret = -ENOMEM; | ||
246 | goto err_free_buffer; | ||
247 | } | ||
248 | |||
249 | sgl = sgt->sgl; | ||
250 | |||
251 | buffer->size = dma_buf->size; | ||
252 | buffer->dma_addr = sg_dma_address(sgl); | ||
253 | |||
254 | if (sgt->nents == 1) { | ||
255 | /* always physically continuous memory if sgt->nents is 1. */ | ||
256 | exynos_gem_obj->flags |= EXYNOS_BO_CONTIG; | ||
257 | } else { | ||
258 | /* | ||
259 | * this case could be CONTIG or NONCONTIG type but for now | ||
260 | * sets NONCONTIG. | ||
261 | * TODO. we have to find a way that exporter can notify | ||
262 | * the type of its own buffer to importer. | ||
263 | */ | ||
264 | exynos_gem_obj->flags |= EXYNOS_BO_NONCONTIG; | ||
265 | } | ||
266 | |||
267 | exynos_gem_obj->buffer = buffer; | ||
268 | buffer->sgt = sgt; | ||
269 | exynos_gem_obj->base.import_attach = attach; | ||
270 | |||
271 | DRM_DEBUG_PRIME("dma_addr = %pad, size = 0x%lx\n", &buffer->dma_addr, | ||
272 | buffer->size); | ||
273 | |||
274 | return &exynos_gem_obj->base; | ||
275 | |||
276 | err_free_buffer: | ||
277 | kfree(buffer); | ||
278 | buffer = NULL; | ||
279 | err_unmap_attach: | ||
280 | dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL); | ||
281 | err_buf_detach: | ||
282 | dma_buf_detach(dma_buf, attach); | ||
283 | dma_buf_put(dma_buf); | ||
284 | |||
285 | return ERR_PTR(ret); | ||
286 | } | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.h b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.h deleted file mode 100644 index 886de9ff484d..000000000000 --- a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.h +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | /* exynos_drm_dmabuf.h | ||
2 | * | ||
3 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. | ||
4 | * Author: Inki Dae <inki.dae@samsung.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | */ | ||
11 | |||
12 | #ifndef _EXYNOS_DRM_DMABUF_H_ | ||
13 | #define _EXYNOS_DRM_DMABUF_H_ | ||
14 | |||
15 | struct dma_buf *exynos_dmabuf_prime_export(struct drm_device *drm_dev, | ||
16 | struct drm_gem_object *obj, int flags); | ||
17 | |||
18 | struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev, | ||
19 | struct dma_buf *dma_buf); | ||
20 | #endif | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dpi.c b/drivers/gpu/drm/exynos/exynos_drm_dpi.c index 7cb6595c1894..c748b8790de3 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dpi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dpi.c | |||
@@ -20,26 +20,24 @@ | |||
20 | #include <video/of_videomode.h> | 20 | #include <video/of_videomode.h> |
21 | #include <video/videomode.h> | 21 | #include <video/videomode.h> |
22 | 22 | ||
23 | #include "exynos_drm_drv.h" | 23 | #include "exynos_drm_crtc.h" |
24 | 24 | ||
25 | struct exynos_dpi { | 25 | struct exynos_dpi { |
26 | struct exynos_drm_display display; | 26 | struct drm_encoder encoder; |
27 | struct device *dev; | 27 | struct device *dev; |
28 | struct device_node *panel_node; | 28 | struct device_node *panel_node; |
29 | 29 | ||
30 | struct drm_panel *panel; | 30 | struct drm_panel *panel; |
31 | struct drm_connector connector; | 31 | struct drm_connector connector; |
32 | struct drm_encoder *encoder; | ||
33 | 32 | ||
34 | struct videomode *vm; | 33 | struct videomode *vm; |
35 | int dpms_mode; | ||
36 | }; | 34 | }; |
37 | 35 | ||
38 | #define connector_to_dpi(c) container_of(c, struct exynos_dpi, connector) | 36 | #define connector_to_dpi(c) container_of(c, struct exynos_dpi, connector) |
39 | 37 | ||
40 | static inline struct exynos_dpi *display_to_dpi(struct exynos_drm_display *d) | 38 | static inline struct exynos_dpi *encoder_to_dpi(struct drm_encoder *e) |
41 | { | 39 | { |
42 | return container_of(d, struct exynos_dpi, display); | 40 | return container_of(e, struct exynos_dpi, encoder); |
43 | } | 41 | } |
44 | 42 | ||
45 | static enum drm_connector_status | 43 | static enum drm_connector_status |
@@ -99,7 +97,7 @@ exynos_dpi_best_encoder(struct drm_connector *connector) | |||
99 | { | 97 | { |
100 | struct exynos_dpi *ctx = connector_to_dpi(connector); | 98 | struct exynos_dpi *ctx = connector_to_dpi(connector); |
101 | 99 | ||
102 | return ctx->encoder; | 100 | return &ctx->encoder; |
103 | } | 101 | } |
104 | 102 | ||
105 | static struct drm_connector_helper_funcs exynos_dpi_connector_helper_funcs = { | 103 | static struct drm_connector_helper_funcs exynos_dpi_connector_helper_funcs = { |
@@ -107,15 +105,12 @@ static struct drm_connector_helper_funcs exynos_dpi_connector_helper_funcs = { | |||
107 | .best_encoder = exynos_dpi_best_encoder, | 105 | .best_encoder = exynos_dpi_best_encoder, |
108 | }; | 106 | }; |
109 | 107 | ||
110 | static int exynos_dpi_create_connector(struct exynos_drm_display *display, | 108 | static int exynos_dpi_create_connector(struct drm_encoder *encoder) |
111 | struct drm_encoder *encoder) | ||
112 | { | 109 | { |
113 | struct exynos_dpi *ctx = display_to_dpi(display); | 110 | struct exynos_dpi *ctx = encoder_to_dpi(encoder); |
114 | struct drm_connector *connector = &ctx->connector; | 111 | struct drm_connector *connector = &ctx->connector; |
115 | int ret; | 112 | int ret; |
116 | 113 | ||
117 | ctx->encoder = encoder; | ||
118 | |||
119 | connector->polled = DRM_CONNECTOR_POLL_HPD; | 114 | connector->polled = DRM_CONNECTOR_POLL_HPD; |
120 | 115 | ||
121 | ret = drm_connector_init(encoder->dev, connector, | 116 | ret = drm_connector_init(encoder->dev, connector, |
@@ -133,46 +128,48 @@ static int exynos_dpi_create_connector(struct exynos_drm_display *display, | |||
133 | return 0; | 128 | return 0; |
134 | } | 129 | } |
135 | 130 | ||
136 | static void exynos_dpi_poweron(struct exynos_dpi *ctx) | 131 | static bool exynos_dpi_mode_fixup(struct drm_encoder *encoder, |
132 | const struct drm_display_mode *mode, | ||
133 | struct drm_display_mode *adjusted_mode) | ||
134 | { | ||
135 | return true; | ||
136 | } | ||
137 | |||
138 | static void exynos_dpi_mode_set(struct drm_encoder *encoder, | ||
139 | struct drm_display_mode *mode, | ||
140 | struct drm_display_mode *adjusted_mode) | ||
137 | { | 141 | { |
142 | } | ||
143 | |||
144 | static void exynos_dpi_enable(struct drm_encoder *encoder) | ||
145 | { | ||
146 | struct exynos_dpi *ctx = encoder_to_dpi(encoder); | ||
147 | |||
138 | if (ctx->panel) { | 148 | if (ctx->panel) { |
139 | drm_panel_prepare(ctx->panel); | 149 | drm_panel_prepare(ctx->panel); |
140 | drm_panel_enable(ctx->panel); | 150 | drm_panel_enable(ctx->panel); |
141 | } | 151 | } |
142 | } | 152 | } |
143 | 153 | ||
144 | static void exynos_dpi_poweroff(struct exynos_dpi *ctx) | 154 | static void exynos_dpi_disable(struct drm_encoder *encoder) |
145 | { | 155 | { |
156 | struct exynos_dpi *ctx = encoder_to_dpi(encoder); | ||
157 | |||
146 | if (ctx->panel) { | 158 | if (ctx->panel) { |
147 | drm_panel_disable(ctx->panel); | 159 | drm_panel_disable(ctx->panel); |
148 | drm_panel_unprepare(ctx->panel); | 160 | drm_panel_unprepare(ctx->panel); |
149 | } | 161 | } |
150 | } | 162 | } |
151 | 163 | ||
152 | static void exynos_dpi_dpms(struct exynos_drm_display *display, int mode) | 164 | static struct drm_encoder_helper_funcs exynos_dpi_encoder_helper_funcs = { |
153 | { | 165 | .mode_fixup = exynos_dpi_mode_fixup, |
154 | struct exynos_dpi *ctx = display_to_dpi(display); | 166 | .mode_set = exynos_dpi_mode_set, |
155 | 167 | .enable = exynos_dpi_enable, | |
156 | switch (mode) { | 168 | .disable = exynos_dpi_disable, |
157 | case DRM_MODE_DPMS_ON: | 169 | }; |
158 | if (ctx->dpms_mode != DRM_MODE_DPMS_ON) | ||
159 | exynos_dpi_poweron(ctx); | ||
160 | break; | ||
161 | case DRM_MODE_DPMS_STANDBY: | ||
162 | case DRM_MODE_DPMS_SUSPEND: | ||
163 | case DRM_MODE_DPMS_OFF: | ||
164 | if (ctx->dpms_mode == DRM_MODE_DPMS_ON) | ||
165 | exynos_dpi_poweroff(ctx); | ||
166 | break; | ||
167 | default: | ||
168 | break; | ||
169 | } | ||
170 | ctx->dpms_mode = mode; | ||
171 | } | ||
172 | 170 | ||
173 | static struct exynos_drm_display_ops exynos_dpi_display_ops = { | 171 | static struct drm_encoder_funcs exynos_dpi_encoder_funcs = { |
174 | .create_connector = exynos_dpi_create_connector, | 172 | .destroy = drm_encoder_cleanup, |
175 | .dpms = exynos_dpi_dpms | ||
176 | }; | 173 | }; |
177 | 174 | ||
178 | /* of_* functions will be removed after merge of of_graph patches */ | 175 | /* of_* functions will be removed after merge of of_graph patches */ |
@@ -299,7 +296,34 @@ static int exynos_dpi_parse_dt(struct exynos_dpi *ctx) | |||
299 | return 0; | 296 | return 0; |
300 | } | 297 | } |
301 | 298 | ||
302 | struct exynos_drm_display *exynos_dpi_probe(struct device *dev) | 299 | int exynos_dpi_bind(struct drm_device *dev, struct drm_encoder *encoder) |
300 | { | ||
301 | int ret; | ||
302 | |||
303 | ret = exynos_drm_crtc_get_pipe_from_type(dev, EXYNOS_DISPLAY_TYPE_LCD); | ||
304 | if (ret < 0) | ||
305 | return ret; | ||
306 | |||
307 | encoder->possible_crtcs = 1 << ret; | ||
308 | |||
309 | DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs); | ||
310 | |||
311 | drm_encoder_init(dev, encoder, &exynos_dpi_encoder_funcs, | ||
312 | DRM_MODE_ENCODER_TMDS); | ||
313 | |||
314 | drm_encoder_helper_add(encoder, &exynos_dpi_encoder_helper_funcs); | ||
315 | |||
316 | ret = exynos_dpi_create_connector(encoder); | ||
317 | if (ret) { | ||
318 | DRM_ERROR("failed to create connector ret = %d\n", ret); | ||
319 | drm_encoder_cleanup(encoder); | ||
320 | return ret; | ||
321 | } | ||
322 | |||
323 | return 0; | ||
324 | } | ||
325 | |||
326 | struct drm_encoder *exynos_dpi_probe(struct device *dev) | ||
303 | { | 327 | { |
304 | struct exynos_dpi *ctx; | 328 | struct exynos_dpi *ctx; |
305 | int ret; | 329 | int ret; |
@@ -308,10 +332,7 @@ struct exynos_drm_display *exynos_dpi_probe(struct device *dev) | |||
308 | if (!ctx) | 332 | if (!ctx) |
309 | return ERR_PTR(-ENOMEM); | 333 | return ERR_PTR(-ENOMEM); |
310 | 334 | ||
311 | ctx->display.type = EXYNOS_DISPLAY_TYPE_LCD; | ||
312 | ctx->display.ops = &exynos_dpi_display_ops; | ||
313 | ctx->dev = dev; | 335 | ctx->dev = dev; |
314 | ctx->dpms_mode = DRM_MODE_DPMS_OFF; | ||
315 | 336 | ||
316 | ret = exynos_dpi_parse_dt(ctx); | 337 | ret = exynos_dpi_parse_dt(ctx); |
317 | if (ret < 0) { | 338 | if (ret < 0) { |
@@ -325,14 +346,14 @@ struct exynos_drm_display *exynos_dpi_probe(struct device *dev) | |||
325 | return ERR_PTR(-EPROBE_DEFER); | 346 | return ERR_PTR(-EPROBE_DEFER); |
326 | } | 347 | } |
327 | 348 | ||
328 | return &ctx->display; | 349 | return &ctx->encoder; |
329 | } | 350 | } |
330 | 351 | ||
331 | int exynos_dpi_remove(struct exynos_drm_display *display) | 352 | int exynos_dpi_remove(struct drm_encoder *encoder) |
332 | { | 353 | { |
333 | struct exynos_dpi *ctx = display_to_dpi(display); | 354 | struct exynos_dpi *ctx = encoder_to_dpi(encoder); |
334 | 355 | ||
335 | exynos_dpi_dpms(&ctx->display, DRM_MODE_DPMS_OFF); | 356 | exynos_dpi_disable(&ctx->encoder); |
336 | 357 | ||
337 | if (ctx->panel) | 358 | if (ctx->panel) |
338 | drm_panel_detach(ctx->panel); | 359 | drm_panel_detach(ctx->panel); |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index 63a68c60a353..fa5194caf259 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c | |||
@@ -21,13 +21,11 @@ | |||
21 | 21 | ||
22 | #include "exynos_drm_drv.h" | 22 | #include "exynos_drm_drv.h" |
23 | #include "exynos_drm_crtc.h" | 23 | #include "exynos_drm_crtc.h" |
24 | #include "exynos_drm_encoder.h" | ||
25 | #include "exynos_drm_fbdev.h" | 24 | #include "exynos_drm_fbdev.h" |
26 | #include "exynos_drm_fb.h" | 25 | #include "exynos_drm_fb.h" |
27 | #include "exynos_drm_gem.h" | 26 | #include "exynos_drm_gem.h" |
28 | #include "exynos_drm_plane.h" | 27 | #include "exynos_drm_plane.h" |
29 | #include "exynos_drm_vidi.h" | 28 | #include "exynos_drm_vidi.h" |
30 | #include "exynos_drm_dmabuf.h" | ||
31 | #include "exynos_drm_g2d.h" | 29 | #include "exynos_drm_g2d.h" |
32 | #include "exynos_drm_ipp.h" | 30 | #include "exynos_drm_ipp.h" |
33 | #include "exynos_drm_iommu.h" | 31 | #include "exynos_drm_iommu.h" |
@@ -41,7 +39,9 @@ | |||
41 | static int exynos_drm_load(struct drm_device *dev, unsigned long flags) | 39 | static int exynos_drm_load(struct drm_device *dev, unsigned long flags) |
42 | { | 40 | { |
43 | struct exynos_drm_private *private; | 41 | struct exynos_drm_private *private; |
44 | int ret; | 42 | struct drm_encoder *encoder; |
43 | unsigned int clone_mask; | ||
44 | int cnt, ret; | ||
45 | 45 | ||
46 | private = kzalloc(sizeof(struct exynos_drm_private), GFP_KERNEL); | 46 | private = kzalloc(sizeof(struct exynos_drm_private), GFP_KERNEL); |
47 | if (!private) | 47 | if (!private) |
@@ -67,7 +67,13 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags) | |||
67 | exynos_drm_mode_config_init(dev); | 67 | exynos_drm_mode_config_init(dev); |
68 | 68 | ||
69 | /* setup possible_clones. */ | 69 | /* setup possible_clones. */ |
70 | exynos_drm_encoder_setup(dev); | 70 | cnt = 0; |
71 | clone_mask = 0; | ||
72 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) | ||
73 | clone_mask |= (1 << (cnt++)); | ||
74 | |||
75 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) | ||
76 | encoder->possible_clones = clone_mask; | ||
71 | 77 | ||
72 | platform_set_drvdata(dev->platformdev, dev); | 78 | platform_set_drvdata(dev->platformdev, dev); |
73 | 79 | ||
@@ -297,8 +303,12 @@ static struct drm_driver exynos_drm_driver = { | |||
297 | .dumb_destroy = drm_gem_dumb_destroy, | 303 | .dumb_destroy = drm_gem_dumb_destroy, |
298 | .prime_handle_to_fd = drm_gem_prime_handle_to_fd, | 304 | .prime_handle_to_fd = drm_gem_prime_handle_to_fd, |
299 | .prime_fd_to_handle = drm_gem_prime_fd_to_handle, | 305 | .prime_fd_to_handle = drm_gem_prime_fd_to_handle, |
300 | .gem_prime_export = exynos_dmabuf_prime_export, | 306 | .gem_prime_export = drm_gem_prime_export, |
301 | .gem_prime_import = exynos_dmabuf_prime_import, | 307 | .gem_prime_import = drm_gem_prime_import, |
308 | .gem_prime_get_sg_table = exynos_drm_gem_prime_get_sg_table, | ||
309 | .gem_prime_import_sg_table = exynos_drm_gem_prime_import_sg_table, | ||
310 | .gem_prime_vmap = exynos_drm_gem_prime_vmap, | ||
311 | .gem_prime_vunmap = exynos_drm_gem_prime_vunmap, | ||
302 | .ioctls = exynos_ioctls, | 312 | .ioctls = exynos_ioctls, |
303 | .num_ioctls = ARRAY_SIZE(exynos_ioctls), | 313 | .num_ioctls = ARRAY_SIZE(exynos_ioctls), |
304 | .fops = &exynos_drm_driver_fops, | 314 | .fops = &exynos_drm_driver_fops, |
@@ -345,9 +355,6 @@ static struct platform_driver exynos_drm_platform_driver; | |||
345 | * because connector requires pipe number of its crtc during initialization. | 355 | * because connector requires pipe number of its crtc during initialization. |
346 | */ | 356 | */ |
347 | static struct platform_driver *const exynos_drm_kms_drivers[] = { | 357 | static struct platform_driver *const exynos_drm_kms_drivers[] = { |
348 | #ifdef CONFIG_DRM_EXYNOS_VIDI | ||
349 | &vidi_driver, | ||
350 | #endif | ||
351 | #ifdef CONFIG_DRM_EXYNOS_FIMD | 358 | #ifdef CONFIG_DRM_EXYNOS_FIMD |
352 | &fimd_driver, | 359 | &fimd_driver, |
353 | #endif | 360 | #endif |
@@ -370,6 +377,9 @@ static struct platform_driver *const exynos_drm_kms_drivers[] = { | |||
370 | &mixer_driver, | 377 | &mixer_driver, |
371 | &hdmi_driver, | 378 | &hdmi_driver, |
372 | #endif | 379 | #endif |
380 | #ifdef CONFIG_DRM_EXYNOS_VIDI | ||
381 | &vidi_driver, | ||
382 | #endif | ||
373 | }; | 383 | }; |
374 | 384 | ||
375 | static struct platform_driver *const exynos_drm_non_kms_drivers[] = { | 385 | static struct platform_driver *const exynos_drm_non_kms_drivers[] = { |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index dd00f160c1e5..6b8a30f23473 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h | |||
@@ -44,23 +44,14 @@ enum exynos_drm_output_type { | |||
44 | * - the unit is screen coordinates. | 44 | * - the unit is screen coordinates. |
45 | * @src_y: offset y on a framebuffer to be displayed. | 45 | * @src_y: offset y on a framebuffer to be displayed. |
46 | * - the unit is screen coordinates. | 46 | * - the unit is screen coordinates. |
47 | * @src_width: width of a partial image to be displayed from framebuffer. | 47 | * @src_w: width of a partial image to be displayed from framebuffer. |
48 | * @src_height: height of a partial image to be displayed from framebuffer. | 48 | * @src_h: height of a partial image to be displayed from framebuffer. |
49 | * @fb_width: width of a framebuffer. | ||
50 | * @fb_height: height of a framebuffer. | ||
51 | * @crtc_x: offset x on hardware screen. | 49 | * @crtc_x: offset x on hardware screen. |
52 | * @crtc_y: offset y on hardware screen. | 50 | * @crtc_y: offset y on hardware screen. |
53 | * @crtc_width: window width to be displayed (hardware screen). | 51 | * @crtc_w: window width to be displayed (hardware screen). |
54 | * @crtc_height: window height to be displayed (hardware screen). | 52 | * @crtc_h: window height to be displayed (hardware screen). |
55 | * @mode_width: width of screen mode. | ||
56 | * @mode_height: height of screen mode. | ||
57 | * @h_ratio: horizontal scaling ratio, 16.16 fixed point | 53 | * @h_ratio: horizontal scaling ratio, 16.16 fixed point |
58 | * @v_ratio: vertical scaling ratio, 16.16 fixed point | 54 | * @v_ratio: vertical scaling ratio, 16.16 fixed point |
59 | * @refresh: refresh rate. | ||
60 | * @scan_flag: interlace or progressive way. | ||
61 | * (it could be DRM_MODE_FLAG_*) | ||
62 | * @bpp: pixel size.(in bit) | ||
63 | * @pixel_format: fourcc pixel format of this overlay | ||
64 | * @dma_addr: array of bus(accessed by dma) address to the memory region | 55 | * @dma_addr: array of bus(accessed by dma) address to the memory region |
65 | * allocated for a overlay. | 56 | * allocated for a overlay. |
66 | * @zpos: order of overlay layer(z position). | 57 | * @zpos: order of overlay layer(z position). |
@@ -73,76 +64,19 @@ struct exynos_drm_plane { | |||
73 | struct drm_plane base; | 64 | struct drm_plane base; |
74 | unsigned int src_x; | 65 | unsigned int src_x; |
75 | unsigned int src_y; | 66 | unsigned int src_y; |
76 | unsigned int src_width; | 67 | unsigned int src_w; |
77 | unsigned int src_height; | 68 | unsigned int src_h; |
78 | unsigned int fb_width; | ||
79 | unsigned int fb_height; | ||
80 | unsigned int crtc_x; | 69 | unsigned int crtc_x; |
81 | unsigned int crtc_y; | 70 | unsigned int crtc_y; |
82 | unsigned int crtc_width; | 71 | unsigned int crtc_w; |
83 | unsigned int crtc_height; | 72 | unsigned int crtc_h; |
84 | unsigned int mode_width; | ||
85 | unsigned int mode_height; | ||
86 | unsigned int h_ratio; | 73 | unsigned int h_ratio; |
87 | unsigned int v_ratio; | 74 | unsigned int v_ratio; |
88 | unsigned int refresh; | ||
89 | unsigned int scan_flag; | ||
90 | unsigned int bpp; | ||
91 | unsigned int pitch; | ||
92 | uint32_t pixel_format; | ||
93 | dma_addr_t dma_addr[MAX_FB_BUFFER]; | 75 | dma_addr_t dma_addr[MAX_FB_BUFFER]; |
94 | unsigned int zpos; | 76 | unsigned int zpos; |
95 | }; | 77 | }; |
96 | 78 | ||
97 | /* | 79 | /* |
98 | * Exynos DRM Display Structure. | ||
99 | * - this structure is common to analog tv, digital tv and lcd panel. | ||
100 | * | ||
101 | * @create_connector: initialize and register a new connector | ||
102 | * @remove: cleans up the display for removal | ||
103 | * @mode_fixup: fix mode data comparing to hw specific display mode. | ||
104 | * @mode_set: convert drm_display_mode to hw specific display mode and | ||
105 | * would be called by encoder->mode_set(). | ||
106 | * @check_mode: check if mode is valid or not. | ||
107 | * @dpms: display device on or off. | ||
108 | * @commit: apply changes to hw | ||
109 | */ | ||
110 | struct exynos_drm_display; | ||
111 | struct exynos_drm_display_ops { | ||
112 | int (*create_connector)(struct exynos_drm_display *display, | ||
113 | struct drm_encoder *encoder); | ||
114 | void (*remove)(struct exynos_drm_display *display); | ||
115 | void (*mode_fixup)(struct exynos_drm_display *display, | ||
116 | struct drm_connector *connector, | ||
117 | const struct drm_display_mode *mode, | ||
118 | struct drm_display_mode *adjusted_mode); | ||
119 | void (*mode_set)(struct exynos_drm_display *display, | ||
120 | struct drm_display_mode *mode); | ||
121 | int (*check_mode)(struct exynos_drm_display *display, | ||
122 | struct drm_display_mode *mode); | ||
123 | void (*dpms)(struct exynos_drm_display *display, int mode); | ||
124 | void (*commit)(struct exynos_drm_display *display); | ||
125 | }; | ||
126 | |||
127 | /* | ||
128 | * Exynos drm display structure, maps 1:1 with an encoder/connector | ||
129 | * | ||
130 | * @list: the list entry for this manager | ||
131 | * @type: one of EXYNOS_DISPLAY_TYPE_LCD and HDMI. | ||
132 | * @encoder: encoder object this display maps to | ||
133 | * @connector: connector object this display maps to | ||
134 | * @ops: pointer to callbacks for exynos drm specific functionality | ||
135 | * @ctx: A pointer to the display's implementation specific context | ||
136 | */ | ||
137 | struct exynos_drm_display { | ||
138 | struct list_head list; | ||
139 | enum exynos_drm_output_type type; | ||
140 | struct drm_encoder *encoder; | ||
141 | struct drm_connector *connector; | ||
142 | struct exynos_drm_display_ops *ops; | ||
143 | }; | ||
144 | |||
145 | /* | ||
146 | * Exynos drm crtc ops | 80 | * Exynos drm crtc ops |
147 | * | 81 | * |
148 | * @enable: enable the device | 82 | * @enable: enable the device |
@@ -153,8 +87,8 @@ struct exynos_drm_display { | |||
153 | * @disable_vblank: specific driver callback for disabling vblank interrupt. | 87 | * @disable_vblank: specific driver callback for disabling vblank interrupt. |
154 | * @wait_for_vblank: wait for vblank interrupt to make sure that | 88 | * @wait_for_vblank: wait for vblank interrupt to make sure that |
155 | * hardware overlay is updated. | 89 | * hardware overlay is updated. |
156 | * @win_commit: apply hardware specific overlay data to registers. | 90 | * @update_plane: apply hardware specific overlay data to registers. |
157 | * @win_disable: disable hardware specific overlay. | 91 | * @disable_plane: disable hardware specific overlay. |
158 | * @te_handler: trigger to transfer video image at the tearing effect | 92 | * @te_handler: trigger to transfer video image at the tearing effect |
159 | * synchronization signal if there is a page flip request. | 93 | * synchronization signal if there is a page flip request. |
160 | * @clock_enable: optional function enabling/disabling display domain clock, | 94 | * @clock_enable: optional function enabling/disabling display domain clock, |
@@ -173,11 +107,12 @@ struct exynos_drm_crtc_ops { | |||
173 | int (*enable_vblank)(struct exynos_drm_crtc *crtc); | 107 | int (*enable_vblank)(struct exynos_drm_crtc *crtc); |
174 | void (*disable_vblank)(struct exynos_drm_crtc *crtc); | 108 | void (*disable_vblank)(struct exynos_drm_crtc *crtc); |
175 | void (*wait_for_vblank)(struct exynos_drm_crtc *crtc); | 109 | void (*wait_for_vblank)(struct exynos_drm_crtc *crtc); |
176 | void (*win_commit)(struct exynos_drm_crtc *crtc, unsigned int zpos); | 110 | void (*update_plane)(struct exynos_drm_crtc *crtc, |
177 | void (*win_disable)(struct exynos_drm_crtc *crtc, unsigned int zpos); | 111 | struct exynos_drm_plane *plane); |
112 | void (*disable_plane)(struct exynos_drm_crtc *crtc, | ||
113 | struct exynos_drm_plane *plane); | ||
178 | void (*te_handler)(struct exynos_drm_crtc *crtc); | 114 | void (*te_handler)(struct exynos_drm_crtc *crtc); |
179 | void (*clock_enable)(struct exynos_drm_crtc *crtc, bool enable); | 115 | void (*clock_enable)(struct exynos_drm_crtc *crtc, bool enable); |
180 | void (*clear_channels)(struct exynos_drm_crtc *crtc); | ||
181 | }; | 116 | }; |
182 | 117 | ||
183 | /* | 118 | /* |
@@ -285,20 +220,23 @@ int exynos_drm_subdrv_open(struct drm_device *dev, struct drm_file *file); | |||
285 | void exynos_drm_subdrv_close(struct drm_device *dev, struct drm_file *file); | 220 | void exynos_drm_subdrv_close(struct drm_device *dev, struct drm_file *file); |
286 | 221 | ||
287 | #ifdef CONFIG_DRM_EXYNOS_DPI | 222 | #ifdef CONFIG_DRM_EXYNOS_DPI |
288 | struct exynos_drm_display * exynos_dpi_probe(struct device *dev); | 223 | struct drm_encoder *exynos_dpi_probe(struct device *dev); |
289 | int exynos_dpi_remove(struct exynos_drm_display *display); | 224 | int exynos_dpi_remove(struct drm_encoder *encoder); |
225 | int exynos_dpi_bind(struct drm_device *dev, struct drm_encoder *encoder); | ||
290 | #else | 226 | #else |
291 | static inline struct exynos_drm_display * | 227 | static inline struct drm_encoder * |
292 | exynos_dpi_probe(struct device *dev) { return NULL; } | 228 | exynos_dpi_probe(struct device *dev) { return NULL; } |
293 | static inline int exynos_dpi_remove(struct exynos_drm_display *display) | 229 | static inline int exynos_dpi_remove(struct drm_encoder *encoder) |
230 | { | ||
231 | return 0; | ||
232 | } | ||
233 | static inline int exynos_dpi_bind(struct drm_device *dev, | ||
234 | struct drm_encoder *encoder) | ||
294 | { | 235 | { |
295 | return 0; | 236 | return 0; |
296 | } | 237 | } |
297 | #endif | 238 | #endif |
298 | 239 | ||
299 | /* This function creates a encoder and a connector, and initializes them. */ | ||
300 | int exynos_drm_create_enc_conn(struct drm_device *dev, | ||
301 | struct exynos_drm_display *display); | ||
302 | 240 | ||
303 | extern struct platform_driver fimd_driver; | 241 | extern struct platform_driver fimd_driver; |
304 | extern struct platform_driver exynos5433_decon_driver; | 242 | extern struct platform_driver exynos5433_decon_driver; |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 0e58b36cb8c2..12b03b364703 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c | |||
@@ -259,7 +259,7 @@ struct exynos_dsi_driver_data { | |||
259 | }; | 259 | }; |
260 | 260 | ||
261 | struct exynos_dsi { | 261 | struct exynos_dsi { |
262 | struct exynos_drm_display display; | 262 | struct drm_encoder encoder; |
263 | struct mipi_dsi_host dsi_host; | 263 | struct mipi_dsi_host dsi_host; |
264 | struct drm_connector connector; | 264 | struct drm_connector connector; |
265 | struct device_node *panel_node; | 265 | struct device_node *panel_node; |
@@ -295,9 +295,9 @@ struct exynos_dsi { | |||
295 | #define host_to_dsi(host) container_of(host, struct exynos_dsi, dsi_host) | 295 | #define host_to_dsi(host) container_of(host, struct exynos_dsi, dsi_host) |
296 | #define connector_to_dsi(c) container_of(c, struct exynos_dsi, connector) | 296 | #define connector_to_dsi(c) container_of(c, struct exynos_dsi, connector) |
297 | 297 | ||
298 | static inline struct exynos_dsi *display_to_dsi(struct exynos_drm_display *d) | 298 | static inline struct exynos_dsi *encoder_to_dsi(struct drm_encoder *e) |
299 | { | 299 | { |
300 | return container_of(d, struct exynos_dsi, display); | 300 | return container_of(e, struct exynos_dsi, encoder); |
301 | } | 301 | } |
302 | 302 | ||
303 | enum reg_idx { | 303 | enum reg_idx { |
@@ -1272,7 +1272,7 @@ static irqreturn_t exynos_dsi_irq(int irq, void *dev_id) | |||
1272 | static irqreturn_t exynos_dsi_te_irq_handler(int irq, void *dev_id) | 1272 | static irqreturn_t exynos_dsi_te_irq_handler(int irq, void *dev_id) |
1273 | { | 1273 | { |
1274 | struct exynos_dsi *dsi = (struct exynos_dsi *)dev_id; | 1274 | struct exynos_dsi *dsi = (struct exynos_dsi *)dev_id; |
1275 | struct drm_encoder *encoder = dsi->display.encoder; | 1275 | struct drm_encoder *encoder = &dsi->encoder; |
1276 | 1276 | ||
1277 | if (dsi->state & DSIM_STATE_VIDOUT_AVAILABLE) | 1277 | if (dsi->state & DSIM_STATE_VIDOUT_AVAILABLE) |
1278 | exynos_drm_crtc_te_handler(encoder->crtc); | 1278 | exynos_drm_crtc_te_handler(encoder->crtc); |
@@ -1518,16 +1518,17 @@ static void exynos_dsi_poweroff(struct exynos_dsi *dsi) | |||
1518 | dev_err(dsi->dev, "cannot disable regulators %d\n", ret); | 1518 | dev_err(dsi->dev, "cannot disable regulators %d\n", ret); |
1519 | } | 1519 | } |
1520 | 1520 | ||
1521 | static int exynos_dsi_enable(struct exynos_dsi *dsi) | 1521 | static void exynos_dsi_enable(struct drm_encoder *encoder) |
1522 | { | 1522 | { |
1523 | struct exynos_dsi *dsi = encoder_to_dsi(encoder); | ||
1523 | int ret; | 1524 | int ret; |
1524 | 1525 | ||
1525 | if (dsi->state & DSIM_STATE_ENABLED) | 1526 | if (dsi->state & DSIM_STATE_ENABLED) |
1526 | return 0; | 1527 | return; |
1527 | 1528 | ||
1528 | ret = exynos_dsi_poweron(dsi); | 1529 | ret = exynos_dsi_poweron(dsi); |
1529 | if (ret < 0) | 1530 | if (ret < 0) |
1530 | return ret; | 1531 | return; |
1531 | 1532 | ||
1532 | dsi->state |= DSIM_STATE_ENABLED; | 1533 | dsi->state |= DSIM_STATE_ENABLED; |
1533 | 1534 | ||
@@ -1535,7 +1536,7 @@ static int exynos_dsi_enable(struct exynos_dsi *dsi) | |||
1535 | if (ret < 0) { | 1536 | if (ret < 0) { |
1536 | dsi->state &= ~DSIM_STATE_ENABLED; | 1537 | dsi->state &= ~DSIM_STATE_ENABLED; |
1537 | exynos_dsi_poweroff(dsi); | 1538 | exynos_dsi_poweroff(dsi); |
1538 | return ret; | 1539 | return; |
1539 | } | 1540 | } |
1540 | 1541 | ||
1541 | exynos_dsi_set_display_mode(dsi); | 1542 | exynos_dsi_set_display_mode(dsi); |
@@ -1547,16 +1548,16 @@ static int exynos_dsi_enable(struct exynos_dsi *dsi) | |||
1547 | exynos_dsi_set_display_enable(dsi, false); | 1548 | exynos_dsi_set_display_enable(dsi, false); |
1548 | drm_panel_unprepare(dsi->panel); | 1549 | drm_panel_unprepare(dsi->panel); |
1549 | exynos_dsi_poweroff(dsi); | 1550 | exynos_dsi_poweroff(dsi); |
1550 | return ret; | 1551 | return; |
1551 | } | 1552 | } |
1552 | 1553 | ||
1553 | dsi->state |= DSIM_STATE_VIDOUT_AVAILABLE; | 1554 | dsi->state |= DSIM_STATE_VIDOUT_AVAILABLE; |
1554 | |||
1555 | return 0; | ||
1556 | } | 1555 | } |
1557 | 1556 | ||
1558 | static void exynos_dsi_disable(struct exynos_dsi *dsi) | 1557 | static void exynos_dsi_disable(struct drm_encoder *encoder) |
1559 | { | 1558 | { |
1559 | struct exynos_dsi *dsi = encoder_to_dsi(encoder); | ||
1560 | |||
1560 | if (!(dsi->state & DSIM_STATE_ENABLED)) | 1561 | if (!(dsi->state & DSIM_STATE_ENABLED)) |
1561 | return; | 1562 | return; |
1562 | 1563 | ||
@@ -1571,26 +1572,6 @@ static void exynos_dsi_disable(struct exynos_dsi *dsi) | |||
1571 | exynos_dsi_poweroff(dsi); | 1572 | exynos_dsi_poweroff(dsi); |
1572 | } | 1573 | } |
1573 | 1574 | ||
1574 | static void exynos_dsi_dpms(struct exynos_drm_display *display, int mode) | ||
1575 | { | ||
1576 | struct exynos_dsi *dsi = display_to_dsi(display); | ||
1577 | |||
1578 | if (dsi->panel) { | ||
1579 | switch (mode) { | ||
1580 | case DRM_MODE_DPMS_ON: | ||
1581 | exynos_dsi_enable(dsi); | ||
1582 | break; | ||
1583 | case DRM_MODE_DPMS_STANDBY: | ||
1584 | case DRM_MODE_DPMS_SUSPEND: | ||
1585 | case DRM_MODE_DPMS_OFF: | ||
1586 | exynos_dsi_disable(dsi); | ||
1587 | break; | ||
1588 | default: | ||
1589 | break; | ||
1590 | } | ||
1591 | } | ||
1592 | } | ||
1593 | |||
1594 | static enum drm_connector_status | 1575 | static enum drm_connector_status |
1595 | exynos_dsi_detect(struct drm_connector *connector, bool force) | 1576 | exynos_dsi_detect(struct drm_connector *connector, bool force) |
1596 | { | 1577 | { |
@@ -1601,10 +1582,10 @@ exynos_dsi_detect(struct drm_connector *connector, bool force) | |||
1601 | if (dsi->panel) | 1582 | if (dsi->panel) |
1602 | drm_panel_attach(dsi->panel, &dsi->connector); | 1583 | drm_panel_attach(dsi->panel, &dsi->connector); |
1603 | } else if (!dsi->panel_node) { | 1584 | } else if (!dsi->panel_node) { |
1604 | struct exynos_drm_display *display; | 1585 | struct drm_encoder *encoder; |
1605 | 1586 | ||
1606 | display = platform_get_drvdata(to_platform_device(dsi->dev)); | 1587 | encoder = platform_get_drvdata(to_platform_device(dsi->dev)); |
1607 | exynos_dsi_dpms(display, DRM_MODE_DPMS_OFF); | 1588 | exynos_dsi_disable(encoder); |
1608 | drm_panel_detach(dsi->panel); | 1589 | drm_panel_detach(dsi->panel); |
1609 | dsi->panel = NULL; | 1590 | dsi->panel = NULL; |
1610 | } | 1591 | } |
@@ -1647,7 +1628,7 @@ exynos_dsi_best_encoder(struct drm_connector *connector) | |||
1647 | { | 1628 | { |
1648 | struct exynos_dsi *dsi = connector_to_dsi(connector); | 1629 | struct exynos_dsi *dsi = connector_to_dsi(connector); |
1649 | 1630 | ||
1650 | return dsi->display.encoder; | 1631 | return &dsi->encoder; |
1651 | } | 1632 | } |
1652 | 1633 | ||
1653 | static struct drm_connector_helper_funcs exynos_dsi_connector_helper_funcs = { | 1634 | static struct drm_connector_helper_funcs exynos_dsi_connector_helper_funcs = { |
@@ -1655,10 +1636,9 @@ static struct drm_connector_helper_funcs exynos_dsi_connector_helper_funcs = { | |||
1655 | .best_encoder = exynos_dsi_best_encoder, | 1636 | .best_encoder = exynos_dsi_best_encoder, |
1656 | }; | 1637 | }; |
1657 | 1638 | ||
1658 | static int exynos_dsi_create_connector(struct exynos_drm_display *display, | 1639 | static int exynos_dsi_create_connector(struct drm_encoder *encoder) |
1659 | struct drm_encoder *encoder) | ||
1660 | { | 1640 | { |
1661 | struct exynos_dsi *dsi = display_to_dsi(display); | 1641 | struct exynos_dsi *dsi = encoder_to_dsi(encoder); |
1662 | struct drm_connector *connector = &dsi->connector; | 1642 | struct drm_connector *connector = &dsi->connector; |
1663 | int ret; | 1643 | int ret; |
1664 | 1644 | ||
@@ -1679,26 +1659,40 @@ static int exynos_dsi_create_connector(struct exynos_drm_display *display, | |||
1679 | return 0; | 1659 | return 0; |
1680 | } | 1660 | } |
1681 | 1661 | ||
1682 | static void exynos_dsi_mode_set(struct exynos_drm_display *display, | 1662 | static bool exynos_dsi_mode_fixup(struct drm_encoder *encoder, |
1683 | struct drm_display_mode *mode) | 1663 | const struct drm_display_mode *mode, |
1664 | struct drm_display_mode *adjusted_mode) | ||
1684 | { | 1665 | { |
1685 | struct exynos_dsi *dsi = display_to_dsi(display); | 1666 | return true; |
1686 | struct videomode *vm = &dsi->vm; | 1667 | } |
1687 | 1668 | ||
1688 | vm->hactive = mode->hdisplay; | 1669 | static void exynos_dsi_mode_set(struct drm_encoder *encoder, |
1689 | vm->vactive = mode->vdisplay; | 1670 | struct drm_display_mode *mode, |
1690 | vm->vfront_porch = mode->vsync_start - mode->vdisplay; | 1671 | struct drm_display_mode *adjusted_mode) |
1691 | vm->vback_porch = mode->vtotal - mode->vsync_end; | 1672 | { |
1692 | vm->vsync_len = mode->vsync_end - mode->vsync_start; | 1673 | struct exynos_dsi *dsi = encoder_to_dsi(encoder); |
1693 | vm->hfront_porch = mode->hsync_start - mode->hdisplay; | 1674 | struct videomode *vm = &dsi->vm; |
1694 | vm->hback_porch = mode->htotal - mode->hsync_end; | 1675 | struct drm_display_mode *m = adjusted_mode; |
1695 | vm->hsync_len = mode->hsync_end - mode->hsync_start; | 1676 | |
1677 | vm->hactive = m->hdisplay; | ||
1678 | vm->vactive = m->vdisplay; | ||
1679 | vm->vfront_porch = m->vsync_start - m->vdisplay; | ||
1680 | vm->vback_porch = m->vtotal - m->vsync_end; | ||
1681 | vm->vsync_len = m->vsync_end - m->vsync_start; | ||
1682 | vm->hfront_porch = m->hsync_start - m->hdisplay; | ||
1683 | vm->hback_porch = m->htotal - m->hsync_end; | ||
1684 | vm->hsync_len = m->hsync_end - m->hsync_start; | ||
1696 | } | 1685 | } |
1697 | 1686 | ||
1698 | static struct exynos_drm_display_ops exynos_dsi_display_ops = { | 1687 | static struct drm_encoder_helper_funcs exynos_dsi_encoder_helper_funcs = { |
1699 | .create_connector = exynos_dsi_create_connector, | 1688 | .mode_fixup = exynos_dsi_mode_fixup, |
1700 | .mode_set = exynos_dsi_mode_set, | 1689 | .mode_set = exynos_dsi_mode_set, |
1701 | .dpms = exynos_dsi_dpms | 1690 | .enable = exynos_dsi_enable, |
1691 | .disable = exynos_dsi_disable, | ||
1692 | }; | ||
1693 | |||
1694 | static struct drm_encoder_funcs exynos_dsi_encoder_funcs = { | ||
1695 | .destroy = drm_encoder_cleanup, | ||
1702 | }; | 1696 | }; |
1703 | 1697 | ||
1704 | MODULE_DEVICE_TABLE(of, exynos_dsi_of_match); | 1698 | MODULE_DEVICE_TABLE(of, exynos_dsi_of_match); |
@@ -1821,22 +1815,35 @@ end: | |||
1821 | static int exynos_dsi_bind(struct device *dev, struct device *master, | 1815 | static int exynos_dsi_bind(struct device *dev, struct device *master, |
1822 | void *data) | 1816 | void *data) |
1823 | { | 1817 | { |
1824 | struct exynos_drm_display *display = dev_get_drvdata(dev); | 1818 | struct drm_encoder *encoder = dev_get_drvdata(dev); |
1825 | struct exynos_dsi *dsi = display_to_dsi(display); | 1819 | struct exynos_dsi *dsi = encoder_to_dsi(encoder); |
1826 | struct drm_device *drm_dev = data; | 1820 | struct drm_device *drm_dev = data; |
1827 | struct drm_bridge *bridge; | 1821 | struct drm_bridge *bridge; |
1828 | int ret; | 1822 | int ret; |
1829 | 1823 | ||
1830 | ret = exynos_drm_create_enc_conn(drm_dev, display); | 1824 | ret = exynos_drm_crtc_get_pipe_from_type(drm_dev, |
1825 | EXYNOS_DISPLAY_TYPE_LCD); | ||
1826 | if (ret < 0) | ||
1827 | return ret; | ||
1828 | |||
1829 | encoder->possible_crtcs = 1 << ret; | ||
1830 | |||
1831 | DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs); | ||
1832 | |||
1833 | drm_encoder_init(drm_dev, encoder, &exynos_dsi_encoder_funcs, | ||
1834 | DRM_MODE_ENCODER_TMDS); | ||
1835 | |||
1836 | drm_encoder_helper_add(encoder, &exynos_dsi_encoder_helper_funcs); | ||
1837 | |||
1838 | ret = exynos_dsi_create_connector(encoder); | ||
1831 | if (ret) { | 1839 | if (ret) { |
1832 | DRM_ERROR("Encoder create [%d] failed with %d\n", | 1840 | DRM_ERROR("failed to create connector ret = %d\n", ret); |
1833 | display->type, ret); | 1841 | drm_encoder_cleanup(encoder); |
1834 | return ret; | 1842 | return ret; |
1835 | } | 1843 | } |
1836 | 1844 | ||
1837 | bridge = of_drm_find_bridge(dsi->bridge_node); | 1845 | bridge = of_drm_find_bridge(dsi->bridge_node); |
1838 | if (bridge) { | 1846 | if (bridge) { |
1839 | display->encoder->bridge = bridge; | ||
1840 | drm_bridge_attach(drm_dev, bridge); | 1847 | drm_bridge_attach(drm_dev, bridge); |
1841 | } | 1848 | } |
1842 | 1849 | ||
@@ -1846,10 +1853,10 @@ static int exynos_dsi_bind(struct device *dev, struct device *master, | |||
1846 | static void exynos_dsi_unbind(struct device *dev, struct device *master, | 1853 | static void exynos_dsi_unbind(struct device *dev, struct device *master, |
1847 | void *data) | 1854 | void *data) |
1848 | { | 1855 | { |
1849 | struct exynos_drm_display *display = dev_get_drvdata(dev); | 1856 | struct drm_encoder *encoder = dev_get_drvdata(dev); |
1850 | struct exynos_dsi *dsi = display_to_dsi(display); | 1857 | struct exynos_dsi *dsi = encoder_to_dsi(encoder); |
1851 | 1858 | ||
1852 | exynos_dsi_dpms(display, DRM_MODE_DPMS_OFF); | 1859 | exynos_dsi_disable(encoder); |
1853 | 1860 | ||
1854 | mipi_dsi_host_unregister(&dsi->dsi_host); | 1861 | mipi_dsi_host_unregister(&dsi->dsi_host); |
1855 | } | 1862 | } |
@@ -1870,9 +1877,6 @@ static int exynos_dsi_probe(struct platform_device *pdev) | |||
1870 | if (!dsi) | 1877 | if (!dsi) |
1871 | return -ENOMEM; | 1878 | return -ENOMEM; |
1872 | 1879 | ||
1873 | dsi->display.type = EXYNOS_DISPLAY_TYPE_LCD; | ||
1874 | dsi->display.ops = &exynos_dsi_display_ops; | ||
1875 | |||
1876 | /* To be checked as invalid one */ | 1880 | /* To be checked as invalid one */ |
1877 | dsi->te_gpio = -ENOENT; | 1881 | dsi->te_gpio = -ENOENT; |
1878 | 1882 | ||
@@ -1948,7 +1952,7 @@ static int exynos_dsi_probe(struct platform_device *pdev) | |||
1948 | return ret; | 1952 | return ret; |
1949 | } | 1953 | } |
1950 | 1954 | ||
1951 | platform_set_drvdata(pdev, &dsi->display); | 1955 | platform_set_drvdata(pdev, &dsi->encoder); |
1952 | 1956 | ||
1953 | return component_add(dev, &exynos_dsi_component_ops); | 1957 | return component_add(dev, &exynos_dsi_component_ops); |
1954 | } | 1958 | } |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c deleted file mode 100644 index 7b89fd520e45..000000000000 --- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c +++ /dev/null | |||
@@ -1,174 +0,0 @@ | |||
1 | /* exynos_drm_encoder.c | ||
2 | * | ||
3 | * Copyright (c) 2011 Samsung Electronics Co., Ltd. | ||
4 | * Authors: | ||
5 | * Inki Dae <inki.dae@samsung.com> | ||
6 | * Joonyoung Shim <jy0922.shim@samsung.com> | ||
7 | * Seung-Woo Kim <sw0312.kim@samsung.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | */ | ||
14 | |||
15 | #include <drm/drmP.h> | ||
16 | #include <drm/drm_crtc_helper.h> | ||
17 | |||
18 | #include "exynos_drm_drv.h" | ||
19 | #include "exynos_drm_encoder.h" | ||
20 | |||
21 | #define to_exynos_encoder(x) container_of(x, struct exynos_drm_encoder,\ | ||
22 | drm_encoder) | ||
23 | |||
24 | /* | ||
25 | * exynos specific encoder structure. | ||
26 | * | ||
27 | * @drm_encoder: encoder object. | ||
28 | * @display: the display structure that maps to this encoder | ||
29 | */ | ||
30 | struct exynos_drm_encoder { | ||
31 | struct drm_encoder drm_encoder; | ||
32 | struct exynos_drm_display *display; | ||
33 | }; | ||
34 | |||
35 | static bool | ||
36 | exynos_drm_encoder_mode_fixup(struct drm_encoder *encoder, | ||
37 | const struct drm_display_mode *mode, | ||
38 | struct drm_display_mode *adjusted_mode) | ||
39 | { | ||
40 | struct drm_device *dev = encoder->dev; | ||
41 | struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); | ||
42 | struct exynos_drm_display *display = exynos_encoder->display; | ||
43 | struct drm_connector *connector; | ||
44 | |||
45 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
46 | if (connector->encoder != encoder) | ||
47 | continue; | ||
48 | |||
49 | if (display->ops->mode_fixup) | ||
50 | display->ops->mode_fixup(display, connector, mode, | ||
51 | adjusted_mode); | ||
52 | } | ||
53 | |||
54 | return true; | ||
55 | } | ||
56 | |||
57 | static void exynos_drm_encoder_mode_set(struct drm_encoder *encoder, | ||
58 | struct drm_display_mode *mode, | ||
59 | struct drm_display_mode *adjusted_mode) | ||
60 | { | ||
61 | struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); | ||
62 | struct exynos_drm_display *display = exynos_encoder->display; | ||
63 | |||
64 | if (display->ops->mode_set) | ||
65 | display->ops->mode_set(display, adjusted_mode); | ||
66 | } | ||
67 | |||
68 | static void exynos_drm_encoder_enable(struct drm_encoder *encoder) | ||
69 | { | ||
70 | struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); | ||
71 | struct exynos_drm_display *display = exynos_encoder->display; | ||
72 | |||
73 | if (display->ops->dpms) | ||
74 | display->ops->dpms(display, DRM_MODE_DPMS_ON); | ||
75 | |||
76 | if (display->ops->commit) | ||
77 | display->ops->commit(display); | ||
78 | } | ||
79 | |||
80 | static void exynos_drm_encoder_disable(struct drm_encoder *encoder) | ||
81 | { | ||
82 | struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); | ||
83 | struct exynos_drm_display *display = exynos_encoder->display; | ||
84 | |||
85 | if (display->ops->dpms) | ||
86 | display->ops->dpms(display, DRM_MODE_DPMS_OFF); | ||
87 | } | ||
88 | |||
89 | static struct drm_encoder_helper_funcs exynos_encoder_helper_funcs = { | ||
90 | .mode_fixup = exynos_drm_encoder_mode_fixup, | ||
91 | .mode_set = exynos_drm_encoder_mode_set, | ||
92 | .enable = exynos_drm_encoder_enable, | ||
93 | .disable = exynos_drm_encoder_disable, | ||
94 | }; | ||
95 | |||
96 | static void exynos_drm_encoder_destroy(struct drm_encoder *encoder) | ||
97 | { | ||
98 | struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); | ||
99 | |||
100 | drm_encoder_cleanup(encoder); | ||
101 | kfree(exynos_encoder); | ||
102 | } | ||
103 | |||
104 | static struct drm_encoder_funcs exynos_encoder_funcs = { | ||
105 | .destroy = exynos_drm_encoder_destroy, | ||
106 | }; | ||
107 | |||
108 | static unsigned int exynos_drm_encoder_clones(struct drm_encoder *encoder) | ||
109 | { | ||
110 | struct drm_encoder *clone; | ||
111 | struct drm_device *dev = encoder->dev; | ||
112 | struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); | ||
113 | struct exynos_drm_display *display = exynos_encoder->display; | ||
114 | unsigned int clone_mask = 0; | ||
115 | int cnt = 0; | ||
116 | |||
117 | list_for_each_entry(clone, &dev->mode_config.encoder_list, head) { | ||
118 | switch (display->type) { | ||
119 | case EXYNOS_DISPLAY_TYPE_LCD: | ||
120 | case EXYNOS_DISPLAY_TYPE_HDMI: | ||
121 | case EXYNOS_DISPLAY_TYPE_VIDI: | ||
122 | clone_mask |= (1 << (cnt++)); | ||
123 | break; | ||
124 | default: | ||
125 | continue; | ||
126 | } | ||
127 | } | ||
128 | |||
129 | return clone_mask; | ||
130 | } | ||
131 | |||
132 | void exynos_drm_encoder_setup(struct drm_device *dev) | ||
133 | { | ||
134 | struct drm_encoder *encoder; | ||
135 | |||
136 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) | ||
137 | encoder->possible_clones = exynos_drm_encoder_clones(encoder); | ||
138 | } | ||
139 | |||
140 | struct drm_encoder * | ||
141 | exynos_drm_encoder_create(struct drm_device *dev, | ||
142 | struct exynos_drm_display *display, | ||
143 | unsigned long possible_crtcs) | ||
144 | { | ||
145 | struct drm_encoder *encoder; | ||
146 | struct exynos_drm_encoder *exynos_encoder; | ||
147 | |||
148 | if (!possible_crtcs) | ||
149 | return NULL; | ||
150 | |||
151 | exynos_encoder = kzalloc(sizeof(*exynos_encoder), GFP_KERNEL); | ||
152 | if (!exynos_encoder) | ||
153 | return NULL; | ||
154 | |||
155 | exynos_encoder->display = display; | ||
156 | encoder = &exynos_encoder->drm_encoder; | ||
157 | encoder->possible_crtcs = possible_crtcs; | ||
158 | |||
159 | DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs); | ||
160 | |||
161 | drm_encoder_init(dev, encoder, &exynos_encoder_funcs, | ||
162 | DRM_MODE_ENCODER_TMDS); | ||
163 | |||
164 | drm_encoder_helper_add(encoder, &exynos_encoder_helper_funcs); | ||
165 | |||
166 | DRM_DEBUG_KMS("encoder has been created\n"); | ||
167 | |||
168 | return encoder; | ||
169 | } | ||
170 | |||
171 | struct exynos_drm_display *exynos_drm_get_display(struct drm_encoder *encoder) | ||
172 | { | ||
173 | return to_exynos_encoder(encoder)->display; | ||
174 | } | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.h b/drivers/gpu/drm/exynos/exynos_drm_encoder.h deleted file mode 100644 index 26305d8dd93a..000000000000 --- a/drivers/gpu/drm/exynos/exynos_drm_encoder.h +++ /dev/null | |||
@@ -1,23 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2011 Samsung Electronics Co., Ltd. | ||
3 | * Authors: | ||
4 | * Inki Dae <inki.dae@samsung.com> | ||
5 | * Joonyoung Shim <jy0922.shim@samsung.com> | ||
6 | * Seung-Woo Kim <sw0312.kim@samsung.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | */ | ||
13 | |||
14 | #ifndef _EXYNOS_DRM_ENCODER_H_ | ||
15 | #define _EXYNOS_DRM_ENCODER_H_ | ||
16 | |||
17 | void exynos_drm_encoder_setup(struct drm_device *dev); | ||
18 | struct drm_encoder *exynos_drm_encoder_create(struct drm_device *dev, | ||
19 | struct exynos_drm_display *mgr, | ||
20 | unsigned long possible_crtcs); | ||
21 | struct exynos_drm_display *exynos_drm_get_display(struct drm_encoder *encoder); | ||
22 | |||
23 | #endif | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c index 2b6320e6eae2..9738f4e0c6eb 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fb.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c | |||
@@ -238,22 +238,22 @@ err_free: | |||
238 | return ERR_PTR(ret); | 238 | return ERR_PTR(ret); |
239 | } | 239 | } |
240 | 240 | ||
241 | struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb, | 241 | struct exynos_drm_gem_obj *exynos_drm_fb_gem_obj(struct drm_framebuffer *fb, |
242 | int index) | 242 | int index) |
243 | { | 243 | { |
244 | struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb); | 244 | struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb); |
245 | struct exynos_drm_gem_buf *buffer; | 245 | struct exynos_drm_gem_obj *obj; |
246 | 246 | ||
247 | if (index >= MAX_FB_BUFFER) | 247 | if (index >= MAX_FB_BUFFER) |
248 | return NULL; | 248 | return NULL; |
249 | 249 | ||
250 | buffer = exynos_fb->exynos_gem_obj[index]->buffer; | 250 | obj = exynos_fb->exynos_gem_obj[index]; |
251 | if (!buffer) | 251 | if (!obj) |
252 | return NULL; | 252 | return NULL; |
253 | 253 | ||
254 | DRM_DEBUG_KMS("dma_addr = 0x%lx\n", (unsigned long)buffer->dma_addr); | 254 | DRM_DEBUG_KMS("dma_addr = 0x%lx\n", (unsigned long)obj->dma_addr); |
255 | 255 | ||
256 | return buffer; | 256 | return obj; |
257 | } | 257 | } |
258 | 258 | ||
259 | static void exynos_drm_output_poll_changed(struct drm_device *dev) | 259 | static void exynos_drm_output_poll_changed(struct drm_device *dev) |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.h b/drivers/gpu/drm/exynos/exynos_drm_fb.h index 517471b37566..1c9e27c32cd1 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fb.h +++ b/drivers/gpu/drm/exynos/exynos_drm_fb.h | |||
@@ -19,8 +19,8 @@ exynos_drm_framebuffer_init(struct drm_device *dev, | |||
19 | struct drm_mode_fb_cmd2 *mode_cmd, | 19 | struct drm_mode_fb_cmd2 *mode_cmd, |
20 | struct drm_gem_object *obj); | 20 | struct drm_gem_object *obj); |
21 | 21 | ||
22 | /* get memory information of a drm framebuffer */ | 22 | /* get gem object of a drm framebuffer */ |
23 | struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb, | 23 | struct exynos_drm_gem_obj *exynos_drm_fb_gem_obj(struct drm_framebuffer *fb, |
24 | int index); | 24 | int index); |
25 | 25 | ||
26 | void exynos_drm_mode_config_init(struct drm_device *dev); | 26 | void exynos_drm_mode_config_init(struct drm_device *dev); |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c index dd64bc04ffbb..624595afbce0 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c | |||
@@ -40,8 +40,7 @@ static int exynos_drm_fb_mmap(struct fb_info *info, | |||
40 | { | 40 | { |
41 | struct drm_fb_helper *helper = info->par; | 41 | struct drm_fb_helper *helper = info->par; |
42 | struct exynos_drm_fbdev *exynos_fbd = to_exynos_fbdev(helper); | 42 | struct exynos_drm_fbdev *exynos_fbd = to_exynos_fbdev(helper); |
43 | struct exynos_drm_gem_obj *exynos_gem_obj = exynos_fbd->exynos_gem_obj; | 43 | struct exynos_drm_gem_obj *obj = exynos_fbd->exynos_gem_obj; |
44 | struct exynos_drm_gem_buf *buffer = exynos_gem_obj->buffer; | ||
45 | unsigned long vm_size; | 44 | unsigned long vm_size; |
46 | int ret; | 45 | int ret; |
47 | 46 | ||
@@ -49,11 +48,11 @@ static int exynos_drm_fb_mmap(struct fb_info *info, | |||
49 | 48 | ||
50 | vm_size = vma->vm_end - vma->vm_start; | 49 | vm_size = vma->vm_end - vma->vm_start; |
51 | 50 | ||
52 | if (vm_size > buffer->size) | 51 | if (vm_size > obj->size) |
53 | return -EINVAL; | 52 | return -EINVAL; |
54 | 53 | ||
55 | ret = dma_mmap_attrs(helper->dev->dev, vma, buffer->pages, | 54 | ret = dma_mmap_attrs(helper->dev->dev, vma, obj->pages, obj->dma_addr, |
56 | buffer->dma_addr, buffer->size, &buffer->dma_attrs); | 55 | obj->size, &obj->dma_attrs); |
57 | if (ret < 0) { | 56 | if (ret < 0) { |
58 | DRM_ERROR("failed to mmap.\n"); | 57 | DRM_ERROR("failed to mmap.\n"); |
59 | return ret; | 58 | return ret; |
@@ -80,7 +79,7 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper, | |||
80 | struct drm_framebuffer *fb) | 79 | struct drm_framebuffer *fb) |
81 | { | 80 | { |
82 | struct fb_info *fbi = helper->fbdev; | 81 | struct fb_info *fbi = helper->fbdev; |
83 | struct exynos_drm_gem_buf *buffer; | 82 | struct exynos_drm_gem_obj *obj; |
84 | unsigned int size = fb->width * fb->height * (fb->bits_per_pixel >> 3); | 83 | unsigned int size = fb->width * fb->height * (fb->bits_per_pixel >> 3); |
85 | unsigned int nr_pages; | 84 | unsigned int nr_pages; |
86 | unsigned long offset; | 85 | unsigned long offset; |
@@ -89,18 +88,17 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper, | |||
89 | drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height); | 88 | drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height); |
90 | 89 | ||
91 | /* RGB formats use only one buffer */ | 90 | /* RGB formats use only one buffer */ |
92 | buffer = exynos_drm_fb_buffer(fb, 0); | 91 | obj = exynos_drm_fb_gem_obj(fb, 0); |
93 | if (!buffer) { | 92 | if (!obj) { |
94 | DRM_DEBUG_KMS("buffer is null.\n"); | 93 | DRM_DEBUG_KMS("gem object is null.\n"); |
95 | return -EFAULT; | 94 | return -EFAULT; |
96 | } | 95 | } |
97 | 96 | ||
98 | nr_pages = buffer->size >> PAGE_SHIFT; | 97 | nr_pages = obj->size >> PAGE_SHIFT; |
99 | 98 | ||
100 | buffer->kvaddr = (void __iomem *) vmap(buffer->pages, | 99 | obj->kvaddr = (void __iomem *) vmap(obj->pages, nr_pages, VM_MAP, |
101 | nr_pages, VM_MAP, | ||
102 | pgprot_writecombine(PAGE_KERNEL)); | 100 | pgprot_writecombine(PAGE_KERNEL)); |
103 | if (!buffer->kvaddr) { | 101 | if (!obj->kvaddr) { |
104 | DRM_ERROR("failed to map pages to kernel space.\n"); | 102 | DRM_ERROR("failed to map pages to kernel space.\n"); |
105 | return -EIO; | 103 | return -EIO; |
106 | } | 104 | } |
@@ -111,7 +109,7 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper, | |||
111 | offset = fbi->var.xoffset * (fb->bits_per_pixel >> 3); | 109 | offset = fbi->var.xoffset * (fb->bits_per_pixel >> 3); |
112 | offset += fbi->var.yoffset * fb->pitches[0]; | 110 | offset += fbi->var.yoffset * fb->pitches[0]; |
113 | 111 | ||
114 | fbi->screen_base = buffer->kvaddr + offset; | 112 | fbi->screen_base = obj->kvaddr + offset; |
115 | fbi->screen_size = size; | 113 | fbi->screen_size = size; |
116 | fbi->fix.smem_len = size; | 114 | fbi->fix.smem_len = size; |
117 | 115 | ||
@@ -290,8 +288,8 @@ static void exynos_drm_fbdev_destroy(struct drm_device *dev, | |||
290 | struct exynos_drm_gem_obj *exynos_gem_obj = exynos_fbd->exynos_gem_obj; | 288 | struct exynos_drm_gem_obj *exynos_gem_obj = exynos_fbd->exynos_gem_obj; |
291 | struct drm_framebuffer *fb; | 289 | struct drm_framebuffer *fb; |
292 | 290 | ||
293 | if (exynos_gem_obj->buffer->kvaddr) | 291 | if (exynos_gem_obj->kvaddr) |
294 | vunmap(exynos_gem_obj->buffer->kvaddr); | 292 | vunmap(exynos_gem_obj->kvaddr); |
295 | 293 | ||
296 | /* release drm framebuffer and real buffer */ | 294 | /* release drm framebuffer and real buffer */ |
297 | if (fb_helper->fb && fb_helper->fb->funcs) { | 295 | if (fb_helper->fb && fb_helper->fb->funcs) { |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index 794e56c8798e..5def6bc073eb 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c | |||
@@ -169,7 +169,7 @@ struct fimd_context { | |||
169 | 169 | ||
170 | struct exynos_drm_panel_info panel; | 170 | struct exynos_drm_panel_info panel; |
171 | struct fimd_driver_data *driver_data; | 171 | struct fimd_driver_data *driver_data; |
172 | struct exynos_drm_display *display; | 172 | struct drm_encoder *encoder; |
173 | }; | 173 | }; |
174 | 174 | ||
175 | static const struct of_device_id fimd_driver_dt_match[] = { | 175 | static const struct of_device_id fimd_driver_dt_match[] = { |
@@ -348,13 +348,6 @@ static void fimd_clear_channels(struct exynos_drm_crtc *crtc) | |||
348 | pm_runtime_put(ctx->dev); | 348 | pm_runtime_put(ctx->dev); |
349 | } | 349 | } |
350 | 350 | ||
351 | static void fimd_iommu_detach_devices(struct fimd_context *ctx) | ||
352 | { | ||
353 | /* detach this sub driver from iommu mapping if supported. */ | ||
354 | if (is_drm_iommu_supported(ctx->drm_dev)) | ||
355 | drm_iommu_detach_device(ctx->drm_dev, ctx->dev); | ||
356 | } | ||
357 | |||
358 | static u32 fimd_calc_clkdiv(struct fimd_context *ctx, | 351 | static u32 fimd_calc_clkdiv(struct fimd_context *ctx, |
359 | const struct drm_display_mode *mode) | 352 | const struct drm_display_mode *mode) |
360 | { | 353 | { |
@@ -486,9 +479,9 @@ static void fimd_commit(struct exynos_drm_crtc *crtc) | |||
486 | } | 479 | } |
487 | 480 | ||
488 | 481 | ||
489 | static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win) | 482 | static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win, |
483 | struct drm_framebuffer *fb) | ||
490 | { | 484 | { |
491 | struct exynos_drm_plane *plane = &ctx->planes[win]; | ||
492 | unsigned long val; | 485 | unsigned long val; |
493 | 486 | ||
494 | val = WINCONx_ENWIN; | 487 | val = WINCONx_ENWIN; |
@@ -498,11 +491,11 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win) | |||
498 | * So the request format is ARGB8888 then change it to XRGB8888. | 491 | * So the request format is ARGB8888 then change it to XRGB8888. |
499 | */ | 492 | */ |
500 | if (ctx->driver_data->has_limited_fmt && !win) { | 493 | if (ctx->driver_data->has_limited_fmt && !win) { |
501 | if (plane->pixel_format == DRM_FORMAT_ARGB8888) | 494 | if (fb->pixel_format == DRM_FORMAT_ARGB8888) |
502 | plane->pixel_format = DRM_FORMAT_XRGB8888; | 495 | fb->pixel_format = DRM_FORMAT_XRGB8888; |
503 | } | 496 | } |
504 | 497 | ||
505 | switch (plane->pixel_format) { | 498 | switch (fb->pixel_format) { |
506 | case DRM_FORMAT_C8: | 499 | case DRM_FORMAT_C8: |
507 | val |= WINCON0_BPPMODE_8BPP_PALETTE; | 500 | val |= WINCON0_BPPMODE_8BPP_PALETTE; |
508 | val |= WINCONx_BURSTLEN_8WORD; | 501 | val |= WINCONx_BURSTLEN_8WORD; |
@@ -538,7 +531,7 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win) | |||
538 | break; | 531 | break; |
539 | } | 532 | } |
540 | 533 | ||
541 | DRM_DEBUG_KMS("bpp = %d\n", plane->bpp); | 534 | DRM_DEBUG_KMS("bpp = %d\n", fb->bits_per_pixel); |
542 | 535 | ||
543 | /* | 536 | /* |
544 | * In case of exynos, setting dma-burst to 16Word causes permanent | 537 | * In case of exynos, setting dma-burst to 16Word causes permanent |
@@ -548,7 +541,7 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win) | |||
548 | * movement causes unstable DMA which results into iommu crash/tear. | 541 | * movement causes unstable DMA which results into iommu crash/tear. |
549 | */ | 542 | */ |
550 | 543 | ||
551 | if (plane->fb_width < MIN_FB_WIDTH_FOR_16WORD_BURST) { | 544 | if (fb->width < MIN_FB_WIDTH_FOR_16WORD_BURST) { |
552 | val &= ~WINCONx_BURSTLEN_MASK; | 545 | val &= ~WINCONx_BURSTLEN_MASK; |
553 | val |= WINCONx_BURSTLEN_4WORD; | 546 | val |= WINCONx_BURSTLEN_4WORD; |
554 | } | 547 | } |
@@ -614,21 +607,17 @@ static void fimd_shadow_protect_win(struct fimd_context *ctx, | |||
614 | writel(val, ctx->regs + reg); | 607 | writel(val, ctx->regs + reg); |
615 | } | 608 | } |
616 | 609 | ||
617 | static void fimd_win_commit(struct exynos_drm_crtc *crtc, unsigned int win) | 610 | static void fimd_update_plane(struct exynos_drm_crtc *crtc, |
611 | struct exynos_drm_plane *plane) | ||
618 | { | 612 | { |
619 | struct fimd_context *ctx = crtc->ctx; | 613 | struct fimd_context *ctx = crtc->ctx; |
620 | struct exynos_drm_plane *plane; | 614 | struct drm_plane_state *state = plane->base.state; |
621 | dma_addr_t dma_addr; | 615 | dma_addr_t dma_addr; |
622 | unsigned long val, size, offset; | 616 | unsigned long val, size, offset; |
623 | unsigned int last_x, last_y, buf_offsize, line_size; | 617 | unsigned int last_x, last_y, buf_offsize, line_size; |
624 | 618 | unsigned int win = plane->zpos; | |
625 | if (ctx->suspended) | 619 | unsigned int bpp = state->fb->bits_per_pixel >> 3; |
626 | return; | 620 | unsigned int pitch = state->fb->pitches[0]; |
627 | |||
628 | if (win < 0 || win >= WINDOWS_NR) | ||
629 | return; | ||
630 | |||
631 | plane = &ctx->planes[win]; | ||
632 | 621 | ||
633 | if (ctx->suspended) | 622 | if (ctx->suspended) |
634 | return; | 623 | return; |
@@ -647,8 +636,8 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, unsigned int win) | |||
647 | fimd_shadow_protect_win(ctx, win, true); | 636 | fimd_shadow_protect_win(ctx, win, true); |
648 | 637 | ||
649 | 638 | ||
650 | offset = plane->src_x * (plane->bpp >> 3); | 639 | offset = plane->src_x * bpp; |
651 | offset += plane->src_y * plane->pitch; | 640 | offset += plane->src_y * pitch; |
652 | 641 | ||
653 | /* buffer start address */ | 642 | /* buffer start address */ |
654 | dma_addr = plane->dma_addr[0] + offset; | 643 | dma_addr = plane->dma_addr[0] + offset; |
@@ -656,18 +645,18 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, unsigned int win) | |||
656 | writel(val, ctx->regs + VIDWx_BUF_START(win, 0)); | 645 | writel(val, ctx->regs + VIDWx_BUF_START(win, 0)); |
657 | 646 | ||
658 | /* buffer end address */ | 647 | /* buffer end address */ |
659 | size = plane->pitch * plane->crtc_height; | 648 | size = pitch * plane->crtc_h; |
660 | val = (unsigned long)(dma_addr + size); | 649 | val = (unsigned long)(dma_addr + size); |
661 | writel(val, ctx->regs + VIDWx_BUF_END(win, 0)); | 650 | writel(val, ctx->regs + VIDWx_BUF_END(win, 0)); |
662 | 651 | ||
663 | DRM_DEBUG_KMS("start addr = 0x%lx, end addr = 0x%lx, size = 0x%lx\n", | 652 | DRM_DEBUG_KMS("start addr = 0x%lx, end addr = 0x%lx, size = 0x%lx\n", |
664 | (unsigned long)dma_addr, val, size); | 653 | (unsigned long)dma_addr, val, size); |
665 | DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n", | 654 | DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n", |
666 | plane->crtc_width, plane->crtc_height); | 655 | plane->crtc_w, plane->crtc_h); |
667 | 656 | ||
668 | /* buffer size */ | 657 | /* buffer size */ |
669 | buf_offsize = plane->pitch - (plane->crtc_width * (plane->bpp >> 3)); | 658 | buf_offsize = pitch - (plane->crtc_w * bpp); |
670 | line_size = plane->crtc_width * (plane->bpp >> 3); | 659 | line_size = plane->crtc_w * bpp; |
671 | val = VIDW_BUF_SIZE_OFFSET(buf_offsize) | | 660 | val = VIDW_BUF_SIZE_OFFSET(buf_offsize) | |
672 | VIDW_BUF_SIZE_PAGEWIDTH(line_size) | | 661 | VIDW_BUF_SIZE_PAGEWIDTH(line_size) | |
673 | VIDW_BUF_SIZE_OFFSET_E(buf_offsize) | | 662 | VIDW_BUF_SIZE_OFFSET_E(buf_offsize) | |
@@ -681,10 +670,10 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, unsigned int win) | |||
681 | VIDOSDxA_TOPLEFT_Y_E(plane->crtc_y); | 670 | VIDOSDxA_TOPLEFT_Y_E(plane->crtc_y); |
682 | writel(val, ctx->regs + VIDOSD_A(win)); | 671 | writel(val, ctx->regs + VIDOSD_A(win)); |
683 | 672 | ||
684 | last_x = plane->crtc_x + plane->crtc_width; | 673 | last_x = plane->crtc_x + plane->crtc_w; |
685 | if (last_x) | 674 | if (last_x) |
686 | last_x--; | 675 | last_x--; |
687 | last_y = plane->crtc_y + plane->crtc_height; | 676 | last_y = plane->crtc_y + plane->crtc_h; |
688 | if (last_y) | 677 | if (last_y) |
689 | last_y--; | 678 | last_y--; |
690 | 679 | ||
@@ -701,13 +690,13 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, unsigned int win) | |||
701 | u32 offset = VIDOSD_D(win); | 690 | u32 offset = VIDOSD_D(win); |
702 | if (win == 0) | 691 | if (win == 0) |
703 | offset = VIDOSD_C(win); | 692 | offset = VIDOSD_C(win); |
704 | val = plane->crtc_width * plane->crtc_height; | 693 | val = plane->crtc_w * plane->crtc_h; |
705 | writel(val, ctx->regs + offset); | 694 | writel(val, ctx->regs + offset); |
706 | 695 | ||
707 | DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val); | 696 | DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val); |
708 | } | 697 | } |
709 | 698 | ||
710 | fimd_win_set_pixfmt(ctx, win); | 699 | fimd_win_set_pixfmt(ctx, win, state->fb); |
711 | 700 | ||
712 | /* hardware window 0 doesn't support color key. */ | 701 | /* hardware window 0 doesn't support color key. */ |
713 | if (win != 0) | 702 | if (win != 0) |
@@ -725,15 +714,11 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, unsigned int win) | |||
725 | atomic_set(&ctx->win_updated, 1); | 714 | atomic_set(&ctx->win_updated, 1); |
726 | } | 715 | } |
727 | 716 | ||
728 | static void fimd_win_disable(struct exynos_drm_crtc *crtc, unsigned int win) | 717 | static void fimd_disable_plane(struct exynos_drm_crtc *crtc, |
718 | struct exynos_drm_plane *plane) | ||
729 | { | 719 | { |
730 | struct fimd_context *ctx = crtc->ctx; | 720 | struct fimd_context *ctx = crtc->ctx; |
731 | struct exynos_drm_plane *plane; | 721 | unsigned int win = plane->zpos; |
732 | |||
733 | if (win < 0 || win >= WINDOWS_NR) | ||
734 | return; | ||
735 | |||
736 | plane = &ctx->planes[win]; | ||
737 | 722 | ||
738 | if (ctx->suspended) | 723 | if (ctx->suspended) |
739 | return; | 724 | return; |
@@ -795,7 +780,7 @@ static void fimd_disable(struct exynos_drm_crtc *crtc) | |||
795 | * a destroyed buffer later. | 780 | * a destroyed buffer later. |
796 | */ | 781 | */ |
797 | for (i = 0; i < WINDOWS_NR; i++) | 782 | for (i = 0; i < WINDOWS_NR; i++) |
798 | fimd_win_disable(crtc, i); | 783 | fimd_disable_plane(crtc, &ctx->planes[i]); |
799 | 784 | ||
800 | fimd_enable_vblank(crtc); | 785 | fimd_enable_vblank(crtc); |
801 | fimd_wait_for_vblank(crtc); | 786 | fimd_wait_for_vblank(crtc); |
@@ -862,7 +847,7 @@ static void fimd_te_handler(struct exynos_drm_crtc *crtc) | |||
862 | } | 847 | } |
863 | 848 | ||
864 | if (test_bit(0, &ctx->irq_flags)) | 849 | if (test_bit(0, &ctx->irq_flags)) |
865 | drm_handle_vblank(ctx->drm_dev, ctx->pipe); | 850 | drm_crtc_handle_vblank(&ctx->crtc->base); |
866 | } | 851 | } |
867 | 852 | ||
868 | static void fimd_dp_clock_enable(struct exynos_drm_crtc *crtc, bool enable) | 853 | static void fimd_dp_clock_enable(struct exynos_drm_crtc *crtc, bool enable) |
@@ -890,11 +875,10 @@ static const struct exynos_drm_crtc_ops fimd_crtc_ops = { | |||
890 | .enable_vblank = fimd_enable_vblank, | 875 | .enable_vblank = fimd_enable_vblank, |
891 | .disable_vblank = fimd_disable_vblank, | 876 | .disable_vblank = fimd_disable_vblank, |
892 | .wait_for_vblank = fimd_wait_for_vblank, | 877 | .wait_for_vblank = fimd_wait_for_vblank, |
893 | .win_commit = fimd_win_commit, | 878 | .update_plane = fimd_update_plane, |
894 | .win_disable = fimd_win_disable, | 879 | .disable_plane = fimd_disable_plane, |
895 | .te_handler = fimd_te_handler, | 880 | .te_handler = fimd_te_handler, |
896 | .clock_enable = fimd_dp_clock_enable, | 881 | .clock_enable = fimd_dp_clock_enable, |
897 | .clear_channels = fimd_clear_channels, | ||
898 | }; | 882 | }; |
899 | 883 | ||
900 | static irqreturn_t fimd_irq_handler(int irq, void *dev_id) | 884 | static irqreturn_t fimd_irq_handler(int irq, void *dev_id) |
@@ -913,13 +897,13 @@ static irqreturn_t fimd_irq_handler(int irq, void *dev_id) | |||
913 | goto out; | 897 | goto out; |
914 | 898 | ||
915 | if (ctx->i80_if) { | 899 | if (ctx->i80_if) { |
916 | exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe); | 900 | exynos_drm_crtc_finish_pageflip(ctx->crtc); |
917 | 901 | ||
918 | /* Exits triggering mode */ | 902 | /* Exits triggering mode */ |
919 | atomic_set(&ctx->triggering, 0); | 903 | atomic_set(&ctx->triggering, 0); |
920 | } else { | 904 | } else { |
921 | drm_handle_vblank(ctx->drm_dev, ctx->pipe); | 905 | drm_crtc_handle_vblank(&ctx->crtc->base); |
922 | exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe); | 906 | exynos_drm_crtc_finish_pageflip(ctx->crtc); |
923 | 907 | ||
924 | /* set wait vsync event to zero and wake up queue. */ | 908 | /* set wait vsync event to zero and wake up queue. */ |
925 | if (atomic_read(&ctx->wait_vsync_event)) { | 909 | if (atomic_read(&ctx->wait_vsync_event)) { |
@@ -961,10 +945,13 @@ static int fimd_bind(struct device *dev, struct device *master, void *data) | |||
961 | if (IS_ERR(ctx->crtc)) | 945 | if (IS_ERR(ctx->crtc)) |
962 | return PTR_ERR(ctx->crtc); | 946 | return PTR_ERR(ctx->crtc); |
963 | 947 | ||
964 | if (ctx->display) | 948 | if (ctx->encoder) |
965 | exynos_drm_create_enc_conn(drm_dev, ctx->display); | 949 | exynos_dpi_bind(drm_dev, ctx->encoder); |
950 | |||
951 | if (is_drm_iommu_supported(drm_dev)) | ||
952 | fimd_clear_channels(ctx->crtc); | ||
966 | 953 | ||
967 | ret = drm_iommu_attach_device_if_possible(ctx->crtc, drm_dev, dev); | 954 | ret = drm_iommu_attach_device(drm_dev, dev); |
968 | if (ret) | 955 | if (ret) |
969 | priv->pipe--; | 956 | priv->pipe--; |
970 | 957 | ||
@@ -978,10 +965,10 @@ static void fimd_unbind(struct device *dev, struct device *master, | |||
978 | 965 | ||
979 | fimd_disable(ctx->crtc); | 966 | fimd_disable(ctx->crtc); |
980 | 967 | ||
981 | fimd_iommu_detach_devices(ctx); | 968 | drm_iommu_detach_device(ctx->drm_dev, ctx->dev); |
982 | 969 | ||
983 | if (ctx->display) | 970 | if (ctx->encoder) |
984 | exynos_dpi_remove(ctx->display); | 971 | exynos_dpi_remove(ctx->encoder); |
985 | } | 972 | } |
986 | 973 | ||
987 | static const struct component_ops fimd_component_ops = { | 974 | static const struct component_ops fimd_component_ops = { |
@@ -1088,10 +1075,9 @@ static int fimd_probe(struct platform_device *pdev) | |||
1088 | 1075 | ||
1089 | platform_set_drvdata(pdev, ctx); | 1076 | platform_set_drvdata(pdev, ctx); |
1090 | 1077 | ||
1091 | ctx->display = exynos_dpi_probe(dev); | 1078 | ctx->encoder = exynos_dpi_probe(dev); |
1092 | if (IS_ERR(ctx->display)) { | 1079 | if (IS_ERR(ctx->encoder)) |
1093 | return PTR_ERR(ctx->display); | 1080 | return PTR_ERR(ctx->encoder); |
1094 | } | ||
1095 | 1081 | ||
1096 | pm_runtime_enable(dev); | 1082 | pm_runtime_enable(dev); |
1097 | 1083 | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index 81a250830808..ba008391a2fc 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c | |||
@@ -1319,9 +1319,6 @@ static int g2d_subdrv_probe(struct drm_device *drm_dev, struct device *dev) | |||
1319 | return ret; | 1319 | return ret; |
1320 | } | 1320 | } |
1321 | 1321 | ||
1322 | if (!is_drm_iommu_supported(drm_dev)) | ||
1323 | return 0; | ||
1324 | |||
1325 | ret = drm_iommu_attach_device(drm_dev, dev); | 1322 | ret = drm_iommu_attach_device(drm_dev, dev); |
1326 | if (ret < 0) { | 1323 | if (ret < 0) { |
1327 | dev_err(dev, "failed to enable iommu.\n"); | 1324 | dev_err(dev, "failed to enable iommu.\n"); |
@@ -1334,9 +1331,6 @@ static int g2d_subdrv_probe(struct drm_device *drm_dev, struct device *dev) | |||
1334 | 1331 | ||
1335 | static void g2d_subdrv_remove(struct drm_device *drm_dev, struct device *dev) | 1332 | static void g2d_subdrv_remove(struct drm_device *drm_dev, struct device *dev) |
1336 | { | 1333 | { |
1337 | if (!is_drm_iommu_supported(drm_dev)) | ||
1338 | return; | ||
1339 | |||
1340 | drm_iommu_detach_device(drm_dev, dev); | 1334 | drm_iommu_detach_device(drm_dev, dev); |
1341 | } | 1335 | } |
1342 | 1336 | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c index 0d5b9698d384..67461b77f040 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c | |||
@@ -13,98 +13,112 @@ | |||
13 | #include <drm/drm_vma_manager.h> | 13 | #include <drm/drm_vma_manager.h> |
14 | 14 | ||
15 | #include <linux/shmem_fs.h> | 15 | #include <linux/shmem_fs.h> |
16 | #include <linux/dma-buf.h> | ||
16 | #include <drm/exynos_drm.h> | 17 | #include <drm/exynos_drm.h> |
17 | 18 | ||
18 | #include "exynos_drm_drv.h" | 19 | #include "exynos_drm_drv.h" |
19 | #include "exynos_drm_gem.h" | 20 | #include "exynos_drm_gem.h" |
20 | #include "exynos_drm_buf.h" | ||
21 | #include "exynos_drm_iommu.h" | 21 | #include "exynos_drm_iommu.h" |
22 | 22 | ||
23 | static unsigned int convert_to_vm_err_msg(int msg) | 23 | static int exynos_drm_alloc_buf(struct exynos_drm_gem_obj *obj) |
24 | { | 24 | { |
25 | unsigned int out_msg; | 25 | struct drm_device *dev = obj->base.dev; |
26 | enum dma_attr attr; | ||
27 | unsigned int nr_pages; | ||
26 | 28 | ||
27 | switch (msg) { | 29 | if (obj->dma_addr) { |
28 | case 0: | 30 | DRM_DEBUG_KMS("already allocated.\n"); |
29 | case -ERESTARTSYS: | 31 | return 0; |
30 | case -EINTR: | 32 | } |
31 | out_msg = VM_FAULT_NOPAGE; | ||
32 | break; | ||
33 | 33 | ||
34 | case -ENOMEM: | 34 | init_dma_attrs(&obj->dma_attrs); |
35 | out_msg = VM_FAULT_OOM; | ||
36 | break; | ||
37 | 35 | ||
38 | default: | 36 | /* |
39 | out_msg = VM_FAULT_SIGBUS; | 37 | * if EXYNOS_BO_CONTIG, fully physically contiguous memory |
40 | break; | 38 | * region will be allocated else physically contiguous |
41 | } | 39 | * as possible. |
40 | */ | ||
41 | if (!(obj->flags & EXYNOS_BO_NONCONTIG)) | ||
42 | dma_set_attr(DMA_ATTR_FORCE_CONTIGUOUS, &obj->dma_attrs); | ||
42 | 43 | ||
43 | return out_msg; | 44 | /* |
44 | } | 45 | * if EXYNOS_BO_WC or EXYNOS_BO_NONCACHABLE, writecombine mapping |
46 | * else cachable mapping. | ||
47 | */ | ||
48 | if (obj->flags & EXYNOS_BO_WC || !(obj->flags & EXYNOS_BO_CACHABLE)) | ||
49 | attr = DMA_ATTR_WRITE_COMBINE; | ||
50 | else | ||
51 | attr = DMA_ATTR_NON_CONSISTENT; | ||
45 | 52 | ||
46 | static int check_gem_flags(unsigned int flags) | 53 | dma_set_attr(attr, &obj->dma_attrs); |
47 | { | 54 | dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &obj->dma_attrs); |
48 | if (flags & ~(EXYNOS_BO_MASK)) { | ||
49 | DRM_ERROR("invalid flags.\n"); | ||
50 | return -EINVAL; | ||
51 | } | ||
52 | 55 | ||
53 | return 0; | 56 | nr_pages = obj->size >> PAGE_SHIFT; |
54 | } | ||
55 | 57 | ||
56 | static void update_vm_cache_attr(struct exynos_drm_gem_obj *obj, | 58 | if (!is_drm_iommu_supported(dev)) { |
57 | struct vm_area_struct *vma) | 59 | dma_addr_t start_addr; |
58 | { | 60 | unsigned int i = 0; |
59 | DRM_DEBUG_KMS("flags = 0x%x\n", obj->flags); | ||
60 | 61 | ||
61 | /* non-cachable as default. */ | 62 | obj->pages = drm_calloc_large(nr_pages, sizeof(struct page *)); |
62 | if (obj->flags & EXYNOS_BO_CACHABLE) | 63 | if (!obj->pages) { |
63 | vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); | 64 | DRM_ERROR("failed to allocate pages.\n"); |
64 | else if (obj->flags & EXYNOS_BO_WC) | 65 | return -ENOMEM; |
65 | vma->vm_page_prot = | 66 | } |
66 | pgprot_writecombine(vm_get_page_prot(vma->vm_flags)); | ||
67 | else | ||
68 | vma->vm_page_prot = | ||
69 | pgprot_noncached(vm_get_page_prot(vma->vm_flags)); | ||
70 | } | ||
71 | 67 | ||
72 | static unsigned long roundup_gem_size(unsigned long size, unsigned int flags) | 68 | obj->cookie = dma_alloc_attrs(dev->dev, |
73 | { | 69 | obj->size, |
74 | /* TODO */ | 70 | &obj->dma_addr, GFP_KERNEL, |
71 | &obj->dma_attrs); | ||
72 | if (!obj->cookie) { | ||
73 | DRM_ERROR("failed to allocate buffer.\n"); | ||
74 | drm_free_large(obj->pages); | ||
75 | return -ENOMEM; | ||
76 | } | ||
77 | |||
78 | start_addr = obj->dma_addr; | ||
79 | while (i < nr_pages) { | ||
80 | obj->pages[i] = phys_to_page(start_addr); | ||
81 | start_addr += PAGE_SIZE; | ||
82 | i++; | ||
83 | } | ||
84 | } else { | ||
85 | obj->pages = dma_alloc_attrs(dev->dev, obj->size, | ||
86 | &obj->dma_addr, GFP_KERNEL, | ||
87 | &obj->dma_attrs); | ||
88 | if (!obj->pages) { | ||
89 | DRM_ERROR("failed to allocate buffer.\n"); | ||
90 | return -ENOMEM; | ||
91 | } | ||
92 | } | ||
93 | |||
94 | DRM_DEBUG_KMS("dma_addr(0x%lx), size(0x%lx)\n", | ||
95 | (unsigned long)obj->dma_addr, | ||
96 | obj->size); | ||
75 | 97 | ||
76 | return roundup(size, PAGE_SIZE); | 98 | return 0; |
77 | } | 99 | } |
78 | 100 | ||
79 | static int exynos_drm_gem_map_buf(struct drm_gem_object *obj, | 101 | static void exynos_drm_free_buf(struct exynos_drm_gem_obj *obj) |
80 | struct vm_area_struct *vma, | ||
81 | unsigned long f_vaddr, | ||
82 | pgoff_t page_offset) | ||
83 | { | 102 | { |
84 | struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj); | 103 | struct drm_device *dev = obj->base.dev; |
85 | struct exynos_drm_gem_buf *buf = exynos_gem_obj->buffer; | ||
86 | struct scatterlist *sgl; | ||
87 | unsigned long pfn; | ||
88 | int i; | ||
89 | |||
90 | if (!buf->sgt) | ||
91 | return -EINTR; | ||
92 | 104 | ||
93 | if (page_offset >= (buf->size >> PAGE_SHIFT)) { | 105 | if (!obj->dma_addr) { |
94 | DRM_ERROR("invalid page offset\n"); | 106 | DRM_DEBUG_KMS("dma_addr is invalid.\n"); |
95 | return -EINVAL; | 107 | return; |
96 | } | 108 | } |
97 | 109 | ||
98 | sgl = buf->sgt->sgl; | 110 | DRM_DEBUG_KMS("dma_addr(0x%lx), size(0x%lx)\n", |
99 | for_each_sg(buf->sgt->sgl, sgl, buf->sgt->nents, i) { | 111 | (unsigned long)obj->dma_addr, obj->size); |
100 | if (page_offset < (sgl->length >> PAGE_SHIFT)) | ||
101 | break; | ||
102 | page_offset -= (sgl->length >> PAGE_SHIFT); | ||
103 | } | ||
104 | 112 | ||
105 | pfn = __phys_to_pfn(sg_phys(sgl)) + page_offset; | 113 | if (!is_drm_iommu_supported(dev)) { |
114 | dma_free_attrs(dev->dev, obj->size, obj->cookie, | ||
115 | (dma_addr_t)obj->dma_addr, &obj->dma_attrs); | ||
116 | drm_free_large(obj->pages); | ||
117 | } else | ||
118 | dma_free_attrs(dev->dev, obj->size, obj->pages, | ||
119 | (dma_addr_t)obj->dma_addr, &obj->dma_attrs); | ||
106 | 120 | ||
107 | return vm_insert_mixed(vma, f_vaddr, pfn); | 121 | obj->dma_addr = (dma_addr_t)NULL; |
108 | } | 122 | } |
109 | 123 | ||
110 | static int exynos_drm_gem_handle_create(struct drm_gem_object *obj, | 124 | static int exynos_drm_gem_handle_create(struct drm_gem_object *obj, |
@@ -131,11 +145,7 @@ static int exynos_drm_gem_handle_create(struct drm_gem_object *obj, | |||
131 | 145 | ||
132 | void exynos_drm_gem_destroy(struct exynos_drm_gem_obj *exynos_gem_obj) | 146 | void exynos_drm_gem_destroy(struct exynos_drm_gem_obj *exynos_gem_obj) |
133 | { | 147 | { |
134 | struct drm_gem_object *obj; | 148 | struct drm_gem_object *obj = &exynos_gem_obj->base; |
135 | struct exynos_drm_gem_buf *buf; | ||
136 | |||
137 | obj = &exynos_gem_obj->base; | ||
138 | buf = exynos_gem_obj->buffer; | ||
139 | 149 | ||
140 | DRM_DEBUG_KMS("handle count = %d\n", obj->handle_count); | 150 | DRM_DEBUG_KMS("handle count = %d\n", obj->handle_count); |
141 | 151 | ||
@@ -148,12 +158,9 @@ void exynos_drm_gem_destroy(struct exynos_drm_gem_obj *exynos_gem_obj) | |||
148 | if (obj->import_attach) | 158 | if (obj->import_attach) |
149 | goto out; | 159 | goto out; |
150 | 160 | ||
151 | exynos_drm_free_buf(obj->dev, exynos_gem_obj->flags, buf); | 161 | exynos_drm_free_buf(exynos_gem_obj); |
152 | 162 | ||
153 | out: | 163 | out: |
154 | exynos_drm_fini_buf(obj->dev, buf); | ||
155 | exynos_gem_obj->buffer = NULL; | ||
156 | |||
157 | drm_gem_free_mmap_offset(obj); | 164 | drm_gem_free_mmap_offset(obj); |
158 | 165 | ||
159 | /* release file pointer to gem object. */ | 166 | /* release file pointer to gem object. */ |
@@ -180,7 +187,7 @@ unsigned long exynos_drm_gem_get_size(struct drm_device *dev, | |||
180 | 187 | ||
181 | drm_gem_object_unreference_unlocked(obj); | 188 | drm_gem_object_unreference_unlocked(obj); |
182 | 189 | ||
183 | return exynos_gem_obj->buffer->size; | 190 | return exynos_gem_obj->size; |
184 | } | 191 | } |
185 | 192 | ||
186 | 193 | ||
@@ -193,7 +200,7 @@ struct exynos_drm_gem_obj *exynos_drm_gem_init(struct drm_device *dev, | |||
193 | 200 | ||
194 | exynos_gem_obj = kzalloc(sizeof(*exynos_gem_obj), GFP_KERNEL); | 201 | exynos_gem_obj = kzalloc(sizeof(*exynos_gem_obj), GFP_KERNEL); |
195 | if (!exynos_gem_obj) | 202 | if (!exynos_gem_obj) |
196 | return NULL; | 203 | return ERR_PTR(-ENOMEM); |
197 | 204 | ||
198 | exynos_gem_obj->size = size; | 205 | exynos_gem_obj->size = size; |
199 | obj = &exynos_gem_obj->base; | 206 | obj = &exynos_gem_obj->base; |
@@ -202,7 +209,7 @@ struct exynos_drm_gem_obj *exynos_drm_gem_init(struct drm_device *dev, | |||
202 | if (ret < 0) { | 209 | if (ret < 0) { |
203 | DRM_ERROR("failed to initialize gem object\n"); | 210 | DRM_ERROR("failed to initialize gem object\n"); |
204 | kfree(exynos_gem_obj); | 211 | kfree(exynos_gem_obj); |
205 | return NULL; | 212 | return ERR_PTR(ret); |
206 | } | 213 | } |
207 | 214 | ||
208 | DRM_DEBUG_KMS("created file object = 0x%x\n", (unsigned int)obj->filp); | 215 | DRM_DEBUG_KMS("created file object = 0x%x\n", (unsigned int)obj->filp); |
@@ -215,47 +222,35 @@ struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev, | |||
215 | unsigned long size) | 222 | unsigned long size) |
216 | { | 223 | { |
217 | struct exynos_drm_gem_obj *exynos_gem_obj; | 224 | struct exynos_drm_gem_obj *exynos_gem_obj; |
218 | struct exynos_drm_gem_buf *buf; | ||
219 | int ret; | 225 | int ret; |
220 | 226 | ||
227 | if (flags & ~(EXYNOS_BO_MASK)) { | ||
228 | DRM_ERROR("invalid flags.\n"); | ||
229 | return ERR_PTR(-EINVAL); | ||
230 | } | ||
231 | |||
221 | if (!size) { | 232 | if (!size) { |
222 | DRM_ERROR("invalid size.\n"); | 233 | DRM_ERROR("invalid size.\n"); |
223 | return ERR_PTR(-EINVAL); | 234 | return ERR_PTR(-EINVAL); |
224 | } | 235 | } |
225 | 236 | ||
226 | size = roundup_gem_size(size, flags); | 237 | size = roundup(size, PAGE_SIZE); |
227 | |||
228 | ret = check_gem_flags(flags); | ||
229 | if (ret) | ||
230 | return ERR_PTR(ret); | ||
231 | |||
232 | buf = exynos_drm_init_buf(dev, size); | ||
233 | if (!buf) | ||
234 | return ERR_PTR(-ENOMEM); | ||
235 | 238 | ||
236 | exynos_gem_obj = exynos_drm_gem_init(dev, size); | 239 | exynos_gem_obj = exynos_drm_gem_init(dev, size); |
237 | if (!exynos_gem_obj) { | 240 | if (IS_ERR(exynos_gem_obj)) |
238 | ret = -ENOMEM; | 241 | return exynos_gem_obj; |
239 | goto err_fini_buf; | ||
240 | } | ||
241 | |||
242 | exynos_gem_obj->buffer = buf; | ||
243 | 242 | ||
244 | /* set memory type and cache attribute from user side. */ | 243 | /* set memory type and cache attribute from user side. */ |
245 | exynos_gem_obj->flags = flags; | 244 | exynos_gem_obj->flags = flags; |
246 | 245 | ||
247 | ret = exynos_drm_alloc_buf(dev, buf, flags); | 246 | ret = exynos_drm_alloc_buf(exynos_gem_obj); |
248 | if (ret < 0) | 247 | if (ret < 0) { |
249 | goto err_gem_fini; | 248 | drm_gem_object_release(&exynos_gem_obj->base); |
249 | kfree(exynos_gem_obj); | ||
250 | return ERR_PTR(ret); | ||
251 | } | ||
250 | 252 | ||
251 | return exynos_gem_obj; | 253 | return exynos_gem_obj; |
252 | |||
253 | err_gem_fini: | ||
254 | drm_gem_object_release(&exynos_gem_obj->base); | ||
255 | kfree(exynos_gem_obj); | ||
256 | err_fini_buf: | ||
257 | exynos_drm_fini_buf(dev, buf); | ||
258 | return ERR_PTR(ret); | ||
259 | } | 254 | } |
260 | 255 | ||
261 | int exynos_drm_gem_create_ioctl(struct drm_device *dev, void *data, | 256 | int exynos_drm_gem_create_ioctl(struct drm_device *dev, void *data, |
@@ -294,7 +289,7 @@ dma_addr_t *exynos_drm_gem_get_dma_addr(struct drm_device *dev, | |||
294 | 289 | ||
295 | exynos_gem_obj = to_exynos_gem_obj(obj); | 290 | exynos_gem_obj = to_exynos_gem_obj(obj); |
296 | 291 | ||
297 | return &exynos_gem_obj->buffer->dma_addr; | 292 | return &exynos_gem_obj->dma_addr; |
298 | } | 293 | } |
299 | 294 | ||
300 | void exynos_drm_gem_put_dma_addr(struct drm_device *dev, | 295 | void exynos_drm_gem_put_dma_addr(struct drm_device *dev, |
@@ -322,7 +317,6 @@ int exynos_drm_gem_mmap_buffer(struct exynos_drm_gem_obj *exynos_gem_obj, | |||
322 | struct vm_area_struct *vma) | 317 | struct vm_area_struct *vma) |
323 | { | 318 | { |
324 | struct drm_device *drm_dev = exynos_gem_obj->base.dev; | 319 | struct drm_device *drm_dev = exynos_gem_obj->base.dev; |
325 | struct exynos_drm_gem_buf *buffer; | ||
326 | unsigned long vm_size; | 320 | unsigned long vm_size; |
327 | int ret; | 321 | int ret; |
328 | 322 | ||
@@ -331,19 +325,13 @@ int exynos_drm_gem_mmap_buffer(struct exynos_drm_gem_obj *exynos_gem_obj, | |||
331 | 325 | ||
332 | vm_size = vma->vm_end - vma->vm_start; | 326 | vm_size = vma->vm_end - vma->vm_start; |
333 | 327 | ||
334 | /* | ||
335 | * a buffer contains information to physically continuous memory | ||
336 | * allocated by user request or at framebuffer creation. | ||
337 | */ | ||
338 | buffer = exynos_gem_obj->buffer; | ||
339 | |||
340 | /* check if user-requested size is valid. */ | 328 | /* check if user-requested size is valid. */ |
341 | if (vm_size > buffer->size) | 329 | if (vm_size > exynos_gem_obj->size) |
342 | return -EINVAL; | 330 | return -EINVAL; |
343 | 331 | ||
344 | ret = dma_mmap_attrs(drm_dev->dev, vma, buffer->pages, | 332 | ret = dma_mmap_attrs(drm_dev->dev, vma, exynos_gem_obj->pages, |
345 | buffer->dma_addr, buffer->size, | 333 | exynos_gem_obj->dma_addr, exynos_gem_obj->size, |
346 | &buffer->dma_attrs); | 334 | &exynos_gem_obj->dma_attrs); |
347 | if (ret < 0) { | 335 | if (ret < 0) { |
348 | DRM_ERROR("failed to mmap.\n"); | 336 | DRM_ERROR("failed to mmap.\n"); |
349 | return ret; | 337 | return ret; |
@@ -503,15 +491,6 @@ void exynos_gem_unmap_sgt_from_dma(struct drm_device *drm_dev, | |||
503 | 491 | ||
504 | void exynos_drm_gem_free_object(struct drm_gem_object *obj) | 492 | void exynos_drm_gem_free_object(struct drm_gem_object *obj) |
505 | { | 493 | { |
506 | struct exynos_drm_gem_obj *exynos_gem_obj; | ||
507 | struct exynos_drm_gem_buf *buf; | ||
508 | |||
509 | exynos_gem_obj = to_exynos_gem_obj(obj); | ||
510 | buf = exynos_gem_obj->buffer; | ||
511 | |||
512 | if (obj->import_attach) | ||
513 | drm_prime_gem_destroy(obj, buf->sgt); | ||
514 | |||
515 | exynos_drm_gem_destroy(to_exynos_gem_obj(obj)); | 494 | exynos_drm_gem_destroy(to_exynos_gem_obj(obj)); |
516 | } | 495 | } |
517 | 496 | ||
@@ -595,24 +574,34 @@ unlock: | |||
595 | int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | 574 | int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) |
596 | { | 575 | { |
597 | struct drm_gem_object *obj = vma->vm_private_data; | 576 | struct drm_gem_object *obj = vma->vm_private_data; |
598 | struct drm_device *dev = obj->dev; | 577 | struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj); |
599 | unsigned long f_vaddr; | 578 | unsigned long pfn; |
600 | pgoff_t page_offset; | 579 | pgoff_t page_offset; |
601 | int ret; | 580 | int ret; |
602 | 581 | ||
603 | page_offset = ((unsigned long)vmf->virtual_address - | 582 | page_offset = ((unsigned long)vmf->virtual_address - |
604 | vma->vm_start) >> PAGE_SHIFT; | 583 | vma->vm_start) >> PAGE_SHIFT; |
605 | f_vaddr = (unsigned long)vmf->virtual_address; | ||
606 | |||
607 | mutex_lock(&dev->struct_mutex); | ||
608 | 584 | ||
609 | ret = exynos_drm_gem_map_buf(obj, vma, f_vaddr, page_offset); | 585 | if (page_offset >= (exynos_gem_obj->size >> PAGE_SHIFT)) { |
610 | if (ret < 0) | 586 | DRM_ERROR("invalid page offset\n"); |
611 | DRM_ERROR("failed to map a buffer with user.\n"); | 587 | ret = -EINVAL; |
588 | goto out; | ||
589 | } | ||
612 | 590 | ||
613 | mutex_unlock(&dev->struct_mutex); | 591 | pfn = page_to_pfn(exynos_gem_obj->pages[page_offset]); |
592 | ret = vm_insert_mixed(vma, (unsigned long)vmf->virtual_address, pfn); | ||
614 | 593 | ||
615 | return convert_to_vm_err_msg(ret); | 594 | out: |
595 | switch (ret) { | ||
596 | case 0: | ||
597 | case -ERESTARTSYS: | ||
598 | case -EINTR: | ||
599 | return VM_FAULT_NOPAGE; | ||
600 | case -ENOMEM: | ||
601 | return VM_FAULT_OOM; | ||
602 | default: | ||
603 | return VM_FAULT_SIGBUS; | ||
604 | } | ||
616 | } | 605 | } |
617 | 606 | ||
618 | int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) | 607 | int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) |
@@ -631,11 +620,17 @@ int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) | |||
631 | obj = vma->vm_private_data; | 620 | obj = vma->vm_private_data; |
632 | exynos_gem_obj = to_exynos_gem_obj(obj); | 621 | exynos_gem_obj = to_exynos_gem_obj(obj); |
633 | 622 | ||
634 | ret = check_gem_flags(exynos_gem_obj->flags); | 623 | DRM_DEBUG_KMS("flags = 0x%x\n", exynos_gem_obj->flags); |
635 | if (ret) | ||
636 | goto err_close_vm; | ||
637 | 624 | ||
638 | update_vm_cache_attr(exynos_gem_obj, vma); | 625 | /* non-cachable as default. */ |
626 | if (exynos_gem_obj->flags & EXYNOS_BO_CACHABLE) | ||
627 | vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); | ||
628 | else if (exynos_gem_obj->flags & EXYNOS_BO_WC) | ||
629 | vma->vm_page_prot = | ||
630 | pgprot_writecombine(vm_get_page_prot(vma->vm_flags)); | ||
631 | else | ||
632 | vma->vm_page_prot = | ||
633 | pgprot_noncached(vm_get_page_prot(vma->vm_flags)); | ||
639 | 634 | ||
640 | ret = exynos_drm_gem_mmap_buffer(exynos_gem_obj, vma); | 635 | ret = exynos_drm_gem_mmap_buffer(exynos_gem_obj, vma); |
641 | if (ret) | 636 | if (ret) |
@@ -649,3 +644,76 @@ err_close_vm: | |||
649 | 644 | ||
650 | return ret; | 645 | return ret; |
651 | } | 646 | } |
647 | |||
648 | /* low-level interface prime helpers */ | ||
649 | struct sg_table *exynos_drm_gem_prime_get_sg_table(struct drm_gem_object *obj) | ||
650 | { | ||
651 | struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj); | ||
652 | int npages; | ||
653 | |||
654 | npages = exynos_gem_obj->size >> PAGE_SHIFT; | ||
655 | |||
656 | return drm_prime_pages_to_sg(exynos_gem_obj->pages, npages); | ||
657 | } | ||
658 | |||
659 | struct drm_gem_object * | ||
660 | exynos_drm_gem_prime_import_sg_table(struct drm_device *dev, | ||
661 | struct dma_buf_attachment *attach, | ||
662 | struct sg_table *sgt) | ||
663 | { | ||
664 | struct exynos_drm_gem_obj *exynos_gem_obj; | ||
665 | int npages; | ||
666 | int ret; | ||
667 | |||
668 | exynos_gem_obj = exynos_drm_gem_init(dev, attach->dmabuf->size); | ||
669 | if (IS_ERR(exynos_gem_obj)) { | ||
670 | ret = PTR_ERR(exynos_gem_obj); | ||
671 | goto err; | ||
672 | } | ||
673 | |||
674 | exynos_gem_obj->dma_addr = sg_dma_address(sgt->sgl); | ||
675 | |||
676 | npages = exynos_gem_obj->size >> PAGE_SHIFT; | ||
677 | exynos_gem_obj->pages = drm_malloc_ab(npages, sizeof(struct page *)); | ||
678 | if (!exynos_gem_obj->pages) { | ||
679 | ret = -ENOMEM; | ||
680 | goto err; | ||
681 | } | ||
682 | |||
683 | ret = drm_prime_sg_to_page_addr_arrays(sgt, exynos_gem_obj->pages, NULL, | ||
684 | npages); | ||
685 | if (ret < 0) | ||
686 | goto err_free_large; | ||
687 | |||
688 | if (sgt->nents == 1) { | ||
689 | /* always physically continuous memory if sgt->nents is 1. */ | ||
690 | exynos_gem_obj->flags |= EXYNOS_BO_CONTIG; | ||
691 | } else { | ||
692 | /* | ||
693 | * this case could be CONTIG or NONCONTIG type but for now | ||
694 | * sets NONCONTIG. | ||
695 | * TODO. we have to find a way that exporter can notify | ||
696 | * the type of its own buffer to importer. | ||
697 | */ | ||
698 | exynos_gem_obj->flags |= EXYNOS_BO_NONCONTIG; | ||
699 | } | ||
700 | |||
701 | return &exynos_gem_obj->base; | ||
702 | |||
703 | err_free_large: | ||
704 | drm_free_large(exynos_gem_obj->pages); | ||
705 | err: | ||
706 | drm_gem_object_release(&exynos_gem_obj->base); | ||
707 | kfree(exynos_gem_obj); | ||
708 | return ERR_PTR(ret); | ||
709 | } | ||
710 | |||
711 | void *exynos_drm_gem_prime_vmap(struct drm_gem_object *obj) | ||
712 | { | ||
713 | return NULL; | ||
714 | } | ||
715 | |||
716 | void exynos_drm_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr) | ||
717 | { | ||
718 | /* Nothing to do */ | ||
719 | } | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.h b/drivers/gpu/drm/exynos/exynos_drm_gem.h index 6f42e2248288..cd62f8410d1e 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.h +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.h | |||
@@ -20,35 +20,6 @@ | |||
20 | #define IS_NONCONTIG_BUFFER(f) (f & EXYNOS_BO_NONCONTIG) | 20 | #define IS_NONCONTIG_BUFFER(f) (f & EXYNOS_BO_NONCONTIG) |
21 | 21 | ||
22 | /* | 22 | /* |
23 | * exynos drm gem buffer structure. | ||
24 | * | ||
25 | * @cookie: cookie returned by dma_alloc_attrs | ||
26 | * @kvaddr: kernel virtual address to allocated memory region. | ||
27 | * *userptr: user space address. | ||
28 | * @dma_addr: bus address(accessed by dma) to allocated memory region. | ||
29 | * - this address could be physical address without IOMMU and | ||
30 | * device address with IOMMU. | ||
31 | * @write: whether pages will be written to by the caller. | ||
32 | * @pages: Array of backing pages. | ||
33 | * @sgt: sg table to transfer page data. | ||
34 | * @size: size of allocated memory region. | ||
35 | * @pfnmap: indicate whether memory region from userptr is mmaped with | ||
36 | * VM_PFNMAP or not. | ||
37 | */ | ||
38 | struct exynos_drm_gem_buf { | ||
39 | void *cookie; | ||
40 | void __iomem *kvaddr; | ||
41 | unsigned long userptr; | ||
42 | dma_addr_t dma_addr; | ||
43 | struct dma_attrs dma_attrs; | ||
44 | unsigned int write; | ||
45 | struct page **pages; | ||
46 | struct sg_table *sgt; | ||
47 | unsigned long size; | ||
48 | bool pfnmap; | ||
49 | }; | ||
50 | |||
51 | /* | ||
52 | * exynos drm buffer structure. | 23 | * exynos drm buffer structure. |
53 | * | 24 | * |
54 | * @base: a gem object. | 25 | * @base: a gem object. |
@@ -59,18 +30,28 @@ struct exynos_drm_gem_buf { | |||
59 | * by user request or at framebuffer creation. | 30 | * by user request or at framebuffer creation. |
60 | * continuous memory region allocated by user request | 31 | * continuous memory region allocated by user request |
61 | * or at framebuffer creation. | 32 | * or at framebuffer creation. |
33 | * @flags: indicate memory type to allocated buffer and cache attruibute. | ||
62 | * @size: size requested from user, in bytes and this size is aligned | 34 | * @size: size requested from user, in bytes and this size is aligned |
63 | * in page unit. | 35 | * in page unit. |
64 | * @flags: indicate memory type to allocated buffer and cache attruibute. | 36 | * @cookie: cookie returned by dma_alloc_attrs |
37 | * @kvaddr: kernel virtual address to allocated memory region. | ||
38 | * @dma_addr: bus address(accessed by dma) to allocated memory region. | ||
39 | * - this address could be physical address without IOMMU and | ||
40 | * device address with IOMMU. | ||
41 | * @pages: Array of backing pages. | ||
65 | * | 42 | * |
66 | * P.S. this object would be transferred to user as kms_bo.handle so | 43 | * P.S. this object would be transferred to user as kms_bo.handle so |
67 | * user can access the buffer through kms_bo.handle. | 44 | * user can access the buffer through kms_bo.handle. |
68 | */ | 45 | */ |
69 | struct exynos_drm_gem_obj { | 46 | struct exynos_drm_gem_obj { |
70 | struct drm_gem_object base; | 47 | struct drm_gem_object base; |
71 | struct exynos_drm_gem_buf *buffer; | 48 | unsigned int flags; |
72 | unsigned long size; | 49 | unsigned long size; |
73 | unsigned int flags; | 50 | void *cookie; |
51 | void __iomem *kvaddr; | ||
52 | dma_addr_t dma_addr; | ||
53 | struct dma_attrs dma_attrs; | ||
54 | struct page **pages; | ||
74 | }; | 55 | }; |
75 | 56 | ||
76 | struct page **exynos_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask); | 57 | struct page **exynos_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask); |
@@ -177,4 +158,13 @@ void exynos_gem_unmap_sgt_from_dma(struct drm_device *drm_dev, | |||
177 | struct sg_table *sgt, | 158 | struct sg_table *sgt, |
178 | enum dma_data_direction dir); | 159 | enum dma_data_direction dir); |
179 | 160 | ||
161 | /* low-level interface prime helpers */ | ||
162 | struct sg_table *exynos_drm_gem_prime_get_sg_table(struct drm_gem_object *obj); | ||
163 | struct drm_gem_object * | ||
164 | exynos_drm_gem_prime_import_sg_table(struct drm_device *dev, | ||
165 | struct dma_buf_attachment *attach, | ||
166 | struct sg_table *sgt); | ||
167 | void *exynos_drm_gem_prime_vmap(struct drm_gem_object *obj); | ||
168 | void exynos_drm_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr); | ||
169 | |||
180 | #endif | 170 | #endif |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c b/drivers/gpu/drm/exynos/exynos_drm_gsc.c index f1c6b76c127f..808a0a013780 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gsc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.c | |||
@@ -582,9 +582,17 @@ static int gsc_src_set_transf(struct device *dev, | |||
582 | break; | 582 | break; |
583 | case EXYNOS_DRM_DEGREE_180: | 583 | case EXYNOS_DRM_DEGREE_180: |
584 | cfg |= GSC_IN_ROT_180; | 584 | cfg |= GSC_IN_ROT_180; |
585 | if (flip & EXYNOS_DRM_FLIP_VERTICAL) | ||
586 | cfg &= ~GSC_IN_ROT_XFLIP; | ||
587 | if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) | ||
588 | cfg &= ~GSC_IN_ROT_YFLIP; | ||
585 | break; | 589 | break; |
586 | case EXYNOS_DRM_DEGREE_270: | 590 | case EXYNOS_DRM_DEGREE_270: |
587 | cfg |= GSC_IN_ROT_270; | 591 | cfg |= GSC_IN_ROT_270; |
592 | if (flip & EXYNOS_DRM_FLIP_VERTICAL) | ||
593 | cfg &= ~GSC_IN_ROT_XFLIP; | ||
594 | if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) | ||
595 | cfg &= ~GSC_IN_ROT_YFLIP; | ||
588 | break; | 596 | break; |
589 | default: | 597 | default: |
590 | dev_err(ippdrv->dev, "inavlid degree value %d.\n", degree); | 598 | dev_err(ippdrv->dev, "inavlid degree value %d.\n", degree); |
@@ -845,9 +853,17 @@ static int gsc_dst_set_transf(struct device *dev, | |||
845 | break; | 853 | break; |
846 | case EXYNOS_DRM_DEGREE_180: | 854 | case EXYNOS_DRM_DEGREE_180: |
847 | cfg |= GSC_IN_ROT_180; | 855 | cfg |= GSC_IN_ROT_180; |
856 | if (flip & EXYNOS_DRM_FLIP_VERTICAL) | ||
857 | cfg &= ~GSC_IN_ROT_XFLIP; | ||
858 | if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) | ||
859 | cfg &= ~GSC_IN_ROT_YFLIP; | ||
848 | break; | 860 | break; |
849 | case EXYNOS_DRM_DEGREE_270: | 861 | case EXYNOS_DRM_DEGREE_270: |
850 | cfg |= GSC_IN_ROT_270; | 862 | cfg |= GSC_IN_ROT_270; |
863 | if (flip & EXYNOS_DRM_FLIP_VERTICAL) | ||
864 | cfg &= ~GSC_IN_ROT_XFLIP; | ||
865 | if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) | ||
866 | cfg &= ~GSC_IN_ROT_YFLIP; | ||
851 | break; | 867 | break; |
852 | default: | 868 | default: |
853 | dev_err(ippdrv->dev, "inavlid degree value %d.\n", degree); | 869 | dev_err(ippdrv->dev, "inavlid degree value %d.\n", degree); |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_iommu.c b/drivers/gpu/drm/exynos/exynos_drm_iommu.c index d4ec7465e9cc..055e8ec2ef21 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_iommu.c +++ b/drivers/gpu/drm/exynos/exynos_drm_iommu.c | |||
@@ -87,10 +87,8 @@ int drm_iommu_attach_device(struct drm_device *drm_dev, | |||
87 | struct device *dev = drm_dev->dev; | 87 | struct device *dev = drm_dev->dev; |
88 | int ret; | 88 | int ret; |
89 | 89 | ||
90 | if (!dev->archdata.mapping) { | 90 | if (!dev->archdata.mapping) |
91 | DRM_ERROR("iommu_mapping is null.\n"); | 91 | return 0; |
92 | return -EFAULT; | ||
93 | } | ||
94 | 92 | ||
95 | subdrv_dev->dma_parms = devm_kzalloc(subdrv_dev, | 93 | subdrv_dev->dma_parms = devm_kzalloc(subdrv_dev, |
96 | sizeof(*subdrv_dev->dma_parms), | 94 | sizeof(*subdrv_dev->dma_parms), |
@@ -144,17 +142,3 @@ void drm_iommu_detach_device(struct drm_device *drm_dev, | |||
144 | iommu_detach_device(mapping->domain, subdrv_dev); | 142 | iommu_detach_device(mapping->domain, subdrv_dev); |
145 | drm_release_iommu_mapping(drm_dev); | 143 | drm_release_iommu_mapping(drm_dev); |
146 | } | 144 | } |
147 | |||
148 | int drm_iommu_attach_device_if_possible(struct exynos_drm_crtc *exynos_crtc, | ||
149 | struct drm_device *drm_dev, struct device *subdrv_dev) | ||
150 | { | ||
151 | int ret = 0; | ||
152 | |||
153 | if (is_drm_iommu_supported(drm_dev)) { | ||
154 | if (exynos_crtc->ops->clear_channels) | ||
155 | exynos_crtc->ops->clear_channels(exynos_crtc); | ||
156 | return drm_iommu_attach_device(drm_dev, subdrv_dev); | ||
157 | } | ||
158 | |||
159 | return ret; | ||
160 | } | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_iommu.h b/drivers/gpu/drm/exynos/exynos_drm_iommu.h index 8341c7a475b4..dc1b5441f491 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_iommu.h +++ b/drivers/gpu/drm/exynos/exynos_drm_iommu.h | |||
@@ -29,19 +29,11 @@ void drm_iommu_detach_device(struct drm_device *dev_dev, | |||
29 | 29 | ||
30 | static inline bool is_drm_iommu_supported(struct drm_device *drm_dev) | 30 | static inline bool is_drm_iommu_supported(struct drm_device *drm_dev) |
31 | { | 31 | { |
32 | #ifdef CONFIG_ARM_DMA_USE_IOMMU | ||
33 | struct device *dev = drm_dev->dev; | 32 | struct device *dev = drm_dev->dev; |
34 | 33 | ||
35 | return dev->archdata.mapping ? true : false; | 34 | return dev->archdata.mapping ? true : false; |
36 | #else | ||
37 | return false; | ||
38 | #endif | ||
39 | } | 35 | } |
40 | 36 | ||
41 | int drm_iommu_attach_device_if_possible( | ||
42 | struct exynos_drm_crtc *exynos_crtc, struct drm_device *drm_dev, | ||
43 | struct device *subdrv_dev); | ||
44 | |||
45 | #else | 37 | #else |
46 | 38 | ||
47 | static inline int drm_create_iommu_mapping(struct drm_device *drm_dev) | 39 | static inline int drm_create_iommu_mapping(struct drm_device *drm_dev) |
@@ -69,12 +61,5 @@ static inline bool is_drm_iommu_supported(struct drm_device *drm_dev) | |||
69 | return false; | 61 | return false; |
70 | } | 62 | } |
71 | 63 | ||
72 | static inline int drm_iommu_attach_device_if_possible( | ||
73 | struct exynos_drm_crtc *exynos_crtc, struct drm_device *drm_dev, | ||
74 | struct device *subdrv_dev) | ||
75 | { | ||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | #endif | 64 | #endif |
80 | #endif | 65 | #endif |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c index 67e5451e066f..67d24236e745 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c +++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c | |||
@@ -1622,12 +1622,10 @@ static int ipp_subdrv_probe(struct drm_device *drm_dev, struct device *dev) | |||
1622 | INIT_LIST_HEAD(&ippdrv->cmd_list); | 1622 | INIT_LIST_HEAD(&ippdrv->cmd_list); |
1623 | mutex_init(&ippdrv->cmd_lock); | 1623 | mutex_init(&ippdrv->cmd_lock); |
1624 | 1624 | ||
1625 | if (is_drm_iommu_supported(drm_dev)) { | 1625 | ret = drm_iommu_attach_device(drm_dev, ippdrv->dev); |
1626 | ret = drm_iommu_attach_device(drm_dev, ippdrv->dev); | 1626 | if (ret) { |
1627 | if (ret) { | 1627 | DRM_ERROR("failed to activate iommu\n"); |
1628 | DRM_ERROR("failed to activate iommu\n"); | 1628 | goto err; |
1629 | goto err; | ||
1630 | } | ||
1631 | } | 1629 | } |
1632 | } | 1630 | } |
1633 | 1631 | ||
@@ -1637,8 +1635,7 @@ err: | |||
1637 | /* get ipp driver entry */ | 1635 | /* get ipp driver entry */ |
1638 | list_for_each_entry_continue_reverse(ippdrv, &exynos_drm_ippdrv_list, | 1636 | list_for_each_entry_continue_reverse(ippdrv, &exynos_drm_ippdrv_list, |
1639 | drv_list) { | 1637 | drv_list) { |
1640 | if (is_drm_iommu_supported(drm_dev)) | 1638 | drm_iommu_detach_device(drm_dev, ippdrv->dev); |
1641 | drm_iommu_detach_device(drm_dev, ippdrv->dev); | ||
1642 | 1639 | ||
1643 | ipp_remove_id(&ctx->ipp_idr, &ctx->ipp_lock, | 1640 | ipp_remove_id(&ctx->ipp_idr, &ctx->ipp_lock, |
1644 | ippdrv->prop_list.ipp_id); | 1641 | ippdrv->prop_list.ipp_id); |
@@ -1654,8 +1651,7 @@ static void ipp_subdrv_remove(struct drm_device *drm_dev, struct device *dev) | |||
1654 | 1651 | ||
1655 | /* get ipp driver entry */ | 1652 | /* get ipp driver entry */ |
1656 | list_for_each_entry_safe(ippdrv, t, &exynos_drm_ippdrv_list, drv_list) { | 1653 | list_for_each_entry_safe(ippdrv, t, &exynos_drm_ippdrv_list, drv_list) { |
1657 | if (is_drm_iommu_supported(drm_dev)) | 1654 | drm_iommu_detach_device(drm_dev, ippdrv->dev); |
1658 | drm_iommu_detach_device(drm_dev, ippdrv->dev); | ||
1659 | 1655 | ||
1660 | ipp_remove_id(&ctx->ipp_idr, &ctx->ipp_lock, | 1656 | ipp_remove_id(&ctx->ipp_idr, &ctx->ipp_lock, |
1661 | ippdrv->prop_list.ipp_id); | 1657 | ippdrv->prop_list.ipp_id); |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index a729980d3c2f..d9a68fd83120 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c | |||
@@ -97,29 +97,18 @@ static void exynos_plane_mode_set(struct drm_plane *plane, | |||
97 | /* set drm framebuffer data. */ | 97 | /* set drm framebuffer data. */ |
98 | exynos_plane->src_x = src_x; | 98 | exynos_plane->src_x = src_x; |
99 | exynos_plane->src_y = src_y; | 99 | exynos_plane->src_y = src_y; |
100 | exynos_plane->src_width = (actual_w * exynos_plane->h_ratio) >> 16; | 100 | exynos_plane->src_w = (actual_w * exynos_plane->h_ratio) >> 16; |
101 | exynos_plane->src_height = (actual_h * exynos_plane->v_ratio) >> 16; | 101 | exynos_plane->src_h = (actual_h * exynos_plane->v_ratio) >> 16; |
102 | exynos_plane->fb_width = fb->width; | ||
103 | exynos_plane->fb_height = fb->height; | ||
104 | exynos_plane->bpp = fb->bits_per_pixel; | ||
105 | exynos_plane->pitch = fb->pitches[0]; | ||
106 | exynos_plane->pixel_format = fb->pixel_format; | ||
107 | 102 | ||
108 | /* set plane range to be displayed. */ | 103 | /* set plane range to be displayed. */ |
109 | exynos_plane->crtc_x = crtc_x; | 104 | exynos_plane->crtc_x = crtc_x; |
110 | exynos_plane->crtc_y = crtc_y; | 105 | exynos_plane->crtc_y = crtc_y; |
111 | exynos_plane->crtc_width = actual_w; | 106 | exynos_plane->crtc_w = actual_w; |
112 | exynos_plane->crtc_height = actual_h; | 107 | exynos_plane->crtc_h = actual_h; |
113 | |||
114 | /* set drm mode data. */ | ||
115 | exynos_plane->mode_width = mode->hdisplay; | ||
116 | exynos_plane->mode_height = mode->vdisplay; | ||
117 | exynos_plane->refresh = mode->vrefresh; | ||
118 | exynos_plane->scan_flag = mode->flags; | ||
119 | 108 | ||
120 | DRM_DEBUG_KMS("plane : offset_x/y(%d,%d), width/height(%d,%d)", | 109 | DRM_DEBUG_KMS("plane : offset_x/y(%d,%d), width/height(%d,%d)", |
121 | exynos_plane->crtc_x, exynos_plane->crtc_y, | 110 | exynos_plane->crtc_x, exynos_plane->crtc_y, |
122 | exynos_plane->crtc_width, exynos_plane->crtc_height); | 111 | exynos_plane->crtc_w, exynos_plane->crtc_h); |
123 | 112 | ||
124 | plane->crtc = crtc; | 113 | plane->crtc = crtc; |
125 | } | 114 | } |
@@ -145,15 +134,15 @@ static int exynos_plane_atomic_check(struct drm_plane *plane, | |||
145 | 134 | ||
146 | nr = exynos_drm_fb_get_buf_cnt(state->fb); | 135 | nr = exynos_drm_fb_get_buf_cnt(state->fb); |
147 | for (i = 0; i < nr; i++) { | 136 | for (i = 0; i < nr; i++) { |
148 | struct exynos_drm_gem_buf *buffer = | 137 | struct exynos_drm_gem_obj *obj = |
149 | exynos_drm_fb_buffer(state->fb, i); | 138 | exynos_drm_fb_gem_obj(state->fb, i); |
150 | 139 | ||
151 | if (!buffer) { | 140 | if (!obj) { |
152 | DRM_DEBUG_KMS("buffer is null\n"); | 141 | DRM_DEBUG_KMS("gem object is null\n"); |
153 | return -EFAULT; | 142 | return -EFAULT; |
154 | } | 143 | } |
155 | 144 | ||
156 | exynos_plane->dma_addr[i] = buffer->dma_addr + | 145 | exynos_plane->dma_addr[i] = obj->dma_addr + |
157 | state->fb->offsets[i]; | 146 | state->fb->offsets[i]; |
158 | 147 | ||
159 | DRM_DEBUG_KMS("buffer: %d, dma_addr = 0x%lx\n", | 148 | DRM_DEBUG_KMS("buffer: %d, dma_addr = 0x%lx\n", |
@@ -179,8 +168,8 @@ static void exynos_plane_atomic_update(struct drm_plane *plane, | |||
179 | state->src_x >> 16, state->src_y >> 16, | 168 | state->src_x >> 16, state->src_y >> 16, |
180 | state->src_w >> 16, state->src_h >> 16); | 169 | state->src_w >> 16, state->src_h >> 16); |
181 | 170 | ||
182 | if (exynos_crtc->ops->win_commit) | 171 | if (exynos_crtc->ops->update_plane) |
183 | exynos_crtc->ops->win_commit(exynos_crtc, exynos_plane->zpos); | 172 | exynos_crtc->ops->update_plane(exynos_crtc, exynos_plane); |
184 | } | 173 | } |
185 | 174 | ||
186 | static void exynos_plane_atomic_disable(struct drm_plane *plane, | 175 | static void exynos_plane_atomic_disable(struct drm_plane *plane, |
@@ -192,9 +181,9 @@ static void exynos_plane_atomic_disable(struct drm_plane *plane, | |||
192 | if (!old_state->crtc) | 181 | if (!old_state->crtc) |
193 | return; | 182 | return; |
194 | 183 | ||
195 | if (exynos_crtc->ops->win_disable) | 184 | if (exynos_crtc->ops->disable_plane) |
196 | exynos_crtc->ops->win_disable(exynos_crtc, | 185 | exynos_crtc->ops->disable_plane(exynos_crtc, |
197 | exynos_plane->zpos); | 186 | exynos_plane); |
198 | } | 187 | } |
199 | 188 | ||
200 | static const struct drm_plane_helper_funcs plane_helper_funcs = { | 189 | static const struct drm_plane_helper_funcs plane_helper_funcs = { |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index 3413393d8a16..581af35861a6 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include "exynos_drm_drv.h" | 25 | #include "exynos_drm_drv.h" |
26 | #include "exynos_drm_crtc.h" | 26 | #include "exynos_drm_crtc.h" |
27 | #include "exynos_drm_plane.h" | 27 | #include "exynos_drm_plane.h" |
28 | #include "exynos_drm_encoder.h" | ||
29 | #include "exynos_drm_vidi.h" | 28 | #include "exynos_drm_vidi.h" |
30 | 29 | ||
31 | /* vidi has totally three virtual windows. */ | 30 | /* vidi has totally three virtual windows. */ |
@@ -35,11 +34,10 @@ | |||
35 | connector) | 34 | connector) |
36 | 35 | ||
37 | struct vidi_context { | 36 | struct vidi_context { |
38 | struct exynos_drm_display display; | 37 | struct drm_encoder encoder; |
39 | struct platform_device *pdev; | 38 | struct platform_device *pdev; |
40 | struct drm_device *drm_dev; | 39 | struct drm_device *drm_dev; |
41 | struct exynos_drm_crtc *crtc; | 40 | struct exynos_drm_crtc *crtc; |
42 | struct drm_encoder *encoder; | ||
43 | struct drm_connector connector; | 41 | struct drm_connector connector; |
44 | struct exynos_drm_plane planes[WINDOWS_NR]; | 42 | struct exynos_drm_plane planes[WINDOWS_NR]; |
45 | struct edid *raw_edid; | 43 | struct edid *raw_edid; |
@@ -55,9 +53,9 @@ struct vidi_context { | |||
55 | int pipe; | 53 | int pipe; |
56 | }; | 54 | }; |
57 | 55 | ||
58 | static inline struct vidi_context *display_to_vidi(struct exynos_drm_display *d) | 56 | static inline struct vidi_context *encoder_to_vidi(struct drm_encoder *e) |
59 | { | 57 | { |
60 | return container_of(d, struct vidi_context, display); | 58 | return container_of(e, struct vidi_context, encoder); |
61 | } | 59 | } |
62 | 60 | ||
63 | static const char fake_edid_info[] = { | 61 | static const char fake_edid_info[] = { |
@@ -100,7 +98,7 @@ static int vidi_enable_vblank(struct exynos_drm_crtc *crtc) | |||
100 | /* | 98 | /* |
101 | * in case of page flip request, vidi_finish_pageflip function | 99 | * in case of page flip request, vidi_finish_pageflip function |
102 | * will not be called because direct_vblank is true and then | 100 | * will not be called because direct_vblank is true and then |
103 | * that function will be called by crtc_ops->win_commit callback | 101 | * that function will be called by crtc_ops->update_plane callback |
104 | */ | 102 | */ |
105 | schedule_work(&ctx->work); | 103 | schedule_work(&ctx->work); |
106 | 104 | ||
@@ -118,19 +116,14 @@ static void vidi_disable_vblank(struct exynos_drm_crtc *crtc) | |||
118 | ctx->vblank_on = false; | 116 | ctx->vblank_on = false; |
119 | } | 117 | } |
120 | 118 | ||
121 | static void vidi_win_commit(struct exynos_drm_crtc *crtc, unsigned int win) | 119 | static void vidi_update_plane(struct exynos_drm_crtc *crtc, |
120 | struct exynos_drm_plane *plane) | ||
122 | { | 121 | { |
123 | struct vidi_context *ctx = crtc->ctx; | 122 | struct vidi_context *ctx = crtc->ctx; |
124 | struct exynos_drm_plane *plane; | ||
125 | 123 | ||
126 | if (ctx->suspended) | 124 | if (ctx->suspended) |
127 | return; | 125 | return; |
128 | 126 | ||
129 | if (win < 0 || win >= WINDOWS_NR) | ||
130 | return; | ||
131 | |||
132 | plane = &ctx->planes[win]; | ||
133 | |||
134 | DRM_DEBUG_KMS("dma_addr = %pad\n", plane->dma_addr); | 127 | DRM_DEBUG_KMS("dma_addr = %pad\n", plane->dma_addr); |
135 | 128 | ||
136 | if (ctx->vblank_on) | 129 | if (ctx->vblank_on) |
@@ -179,7 +172,7 @@ static const struct exynos_drm_crtc_ops vidi_crtc_ops = { | |||
179 | .disable = vidi_disable, | 172 | .disable = vidi_disable, |
180 | .enable_vblank = vidi_enable_vblank, | 173 | .enable_vblank = vidi_enable_vblank, |
181 | .disable_vblank = vidi_disable_vblank, | 174 | .disable_vblank = vidi_disable_vblank, |
182 | .win_commit = vidi_win_commit, | 175 | .update_plane = vidi_update_plane, |
183 | }; | 176 | }; |
184 | 177 | ||
185 | static void vidi_fake_vblank_handler(struct work_struct *work) | 178 | static void vidi_fake_vblank_handler(struct work_struct *work) |
@@ -196,7 +189,7 @@ static void vidi_fake_vblank_handler(struct work_struct *work) | |||
196 | mutex_lock(&ctx->lock); | 189 | mutex_lock(&ctx->lock); |
197 | 190 | ||
198 | if (ctx->direct_vblank) { | 191 | if (ctx->direct_vblank) { |
199 | drm_handle_vblank(ctx->drm_dev, ctx->pipe); | 192 | drm_crtc_handle_vblank(&ctx->crtc->base); |
200 | ctx->direct_vblank = false; | 193 | ctx->direct_vblank = false; |
201 | mutex_unlock(&ctx->lock); | 194 | mutex_unlock(&ctx->lock); |
202 | return; | 195 | return; |
@@ -204,7 +197,7 @@ static void vidi_fake_vblank_handler(struct work_struct *work) | |||
204 | 197 | ||
205 | mutex_unlock(&ctx->lock); | 198 | mutex_unlock(&ctx->lock); |
206 | 199 | ||
207 | exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe); | 200 | exynos_drm_crtc_finish_pageflip(ctx->crtc); |
208 | } | 201 | } |
209 | 202 | ||
210 | static int vidi_show_connection(struct device *dev, | 203 | static int vidi_show_connection(struct device *dev, |
@@ -259,9 +252,7 @@ static DEVICE_ATTR(connection, 0644, vidi_show_connection, | |||
259 | int vidi_connection_ioctl(struct drm_device *drm_dev, void *data, | 252 | int vidi_connection_ioctl(struct drm_device *drm_dev, void *data, |
260 | struct drm_file *file_priv) | 253 | struct drm_file *file_priv) |
261 | { | 254 | { |
262 | struct vidi_context *ctx = NULL; | 255 | struct vidi_context *ctx = dev_get_drvdata(drm_dev->dev); |
263 | struct drm_encoder *encoder; | ||
264 | struct exynos_drm_display *display; | ||
265 | struct drm_exynos_vidi_connection *vidi = data; | 256 | struct drm_exynos_vidi_connection *vidi = data; |
266 | 257 | ||
267 | if (!vidi) { | 258 | if (!vidi) { |
@@ -274,21 +265,6 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data, | |||
274 | return -EINVAL; | 265 | return -EINVAL; |
275 | } | 266 | } |
276 | 267 | ||
277 | list_for_each_entry(encoder, &drm_dev->mode_config.encoder_list, | ||
278 | head) { | ||
279 | display = exynos_drm_get_display(encoder); | ||
280 | |||
281 | if (display->type == EXYNOS_DISPLAY_TYPE_VIDI) { | ||
282 | ctx = display_to_vidi(display); | ||
283 | break; | ||
284 | } | ||
285 | } | ||
286 | |||
287 | if (!ctx) { | ||
288 | DRM_DEBUG_KMS("not found virtual device type encoder.\n"); | ||
289 | return -EINVAL; | ||
290 | } | ||
291 | |||
292 | if (ctx->connected == vidi->connection) { | 268 | if (ctx->connected == vidi->connection) { |
293 | DRM_DEBUG_KMS("same connection request.\n"); | 269 | DRM_DEBUG_KMS("same connection request.\n"); |
294 | return -EINVAL; | 270 | return -EINVAL; |
@@ -381,7 +357,7 @@ static struct drm_encoder *vidi_best_encoder(struct drm_connector *connector) | |||
381 | { | 357 | { |
382 | struct vidi_context *ctx = ctx_from_connector(connector); | 358 | struct vidi_context *ctx = ctx_from_connector(connector); |
383 | 359 | ||
384 | return ctx->encoder; | 360 | return &ctx->encoder; |
385 | } | 361 | } |
386 | 362 | ||
387 | static struct drm_connector_helper_funcs vidi_connector_helper_funcs = { | 363 | static struct drm_connector_helper_funcs vidi_connector_helper_funcs = { |
@@ -389,14 +365,12 @@ static struct drm_connector_helper_funcs vidi_connector_helper_funcs = { | |||
389 | .best_encoder = vidi_best_encoder, | 365 | .best_encoder = vidi_best_encoder, |
390 | }; | 366 | }; |
391 | 367 | ||
392 | static int vidi_create_connector(struct exynos_drm_display *display, | 368 | static int vidi_create_connector(struct drm_encoder *encoder) |
393 | struct drm_encoder *encoder) | ||
394 | { | 369 | { |
395 | struct vidi_context *ctx = display_to_vidi(display); | 370 | struct vidi_context *ctx = encoder_to_vidi(encoder); |
396 | struct drm_connector *connector = &ctx->connector; | 371 | struct drm_connector *connector = &ctx->connector; |
397 | int ret; | 372 | int ret; |
398 | 373 | ||
399 | ctx->encoder = encoder; | ||
400 | connector->polled = DRM_CONNECTOR_POLL_HPD; | 374 | connector->polled = DRM_CONNECTOR_POLL_HPD; |
401 | 375 | ||
402 | ret = drm_connector_init(ctx->drm_dev, connector, | 376 | ret = drm_connector_init(ctx->drm_dev, connector, |
@@ -413,19 +387,47 @@ static int vidi_create_connector(struct exynos_drm_display *display, | |||
413 | return 0; | 387 | return 0; |
414 | } | 388 | } |
415 | 389 | ||
390 | static bool exynos_vidi_mode_fixup(struct drm_encoder *encoder, | ||
391 | const struct drm_display_mode *mode, | ||
392 | struct drm_display_mode *adjusted_mode) | ||
393 | { | ||
394 | return true; | ||
395 | } | ||
396 | |||
397 | static void exynos_vidi_mode_set(struct drm_encoder *encoder, | ||
398 | struct drm_display_mode *mode, | ||
399 | struct drm_display_mode *adjusted_mode) | ||
400 | { | ||
401 | } | ||
416 | 402 | ||
417 | static struct exynos_drm_display_ops vidi_display_ops = { | 403 | static void exynos_vidi_enable(struct drm_encoder *encoder) |
418 | .create_connector = vidi_create_connector, | 404 | { |
405 | } | ||
406 | |||
407 | static void exynos_vidi_disable(struct drm_encoder *encoder) | ||
408 | { | ||
409 | } | ||
410 | |||
411 | static struct drm_encoder_helper_funcs exynos_vidi_encoder_helper_funcs = { | ||
412 | .mode_fixup = exynos_vidi_mode_fixup, | ||
413 | .mode_set = exynos_vidi_mode_set, | ||
414 | .enable = exynos_vidi_enable, | ||
415 | .disable = exynos_vidi_disable, | ||
416 | }; | ||
417 | |||
418 | static struct drm_encoder_funcs exynos_vidi_encoder_funcs = { | ||
419 | .destroy = drm_encoder_cleanup, | ||
419 | }; | 420 | }; |
420 | 421 | ||
421 | static int vidi_bind(struct device *dev, struct device *master, void *data) | 422 | static int vidi_bind(struct device *dev, struct device *master, void *data) |
422 | { | 423 | { |
423 | struct vidi_context *ctx = dev_get_drvdata(dev); | 424 | struct vidi_context *ctx = dev_get_drvdata(dev); |
424 | struct drm_device *drm_dev = data; | 425 | struct drm_device *drm_dev = data; |
426 | struct drm_encoder *encoder = &ctx->encoder; | ||
425 | struct exynos_drm_plane *exynos_plane; | 427 | struct exynos_drm_plane *exynos_plane; |
426 | enum drm_plane_type type; | 428 | enum drm_plane_type type; |
427 | unsigned int zpos; | 429 | unsigned int zpos; |
428 | int ret; | 430 | int pipe, ret; |
429 | 431 | ||
430 | vidi_ctx_initialize(ctx, drm_dev); | 432 | vidi_ctx_initialize(ctx, drm_dev); |
431 | 433 | ||
@@ -447,9 +449,24 @@ static int vidi_bind(struct device *dev, struct device *master, void *data) | |||
447 | return PTR_ERR(ctx->crtc); | 449 | return PTR_ERR(ctx->crtc); |
448 | } | 450 | } |
449 | 451 | ||
450 | ret = exynos_drm_create_enc_conn(drm_dev, &ctx->display); | 452 | pipe = exynos_drm_crtc_get_pipe_from_type(drm_dev, |
453 | EXYNOS_DISPLAY_TYPE_VIDI); | ||
454 | if (pipe < 0) | ||
455 | return pipe; | ||
456 | |||
457 | encoder->possible_crtcs = 1 << pipe; | ||
458 | |||
459 | DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs); | ||
460 | |||
461 | drm_encoder_init(drm_dev, encoder, &exynos_vidi_encoder_funcs, | ||
462 | DRM_MODE_ENCODER_TMDS); | ||
463 | |||
464 | drm_encoder_helper_add(encoder, &exynos_vidi_encoder_helper_funcs); | ||
465 | |||
466 | ret = vidi_create_connector(encoder); | ||
451 | if (ret) { | 467 | if (ret) { |
452 | ctx->crtc->base.funcs->destroy(&ctx->crtc->base); | 468 | DRM_ERROR("failed to create connector ret = %d\n", ret); |
469 | drm_encoder_cleanup(encoder); | ||
453 | return ret; | 470 | return ret; |
454 | } | 471 | } |
455 | 472 | ||
@@ -475,8 +492,6 @@ static int vidi_probe(struct platform_device *pdev) | |||
475 | if (!ctx) | 492 | if (!ctx) |
476 | return -ENOMEM; | 493 | return -ENOMEM; |
477 | 494 | ||
478 | ctx->display.type = EXYNOS_DISPLAY_TYPE_VIDI; | ||
479 | ctx->display.ops = &vidi_display_ops; | ||
480 | ctx->default_win = 0; | 495 | ctx->default_win = 0; |
481 | ctx->pdev = pdev; | 496 | ctx->pdev = pdev; |
482 | 497 | ||
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 4a00990e4ae4..932f7fa240f8 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include "regs-hdmi.h" | 22 | #include "regs-hdmi.h" |
23 | 23 | ||
24 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
25 | #include <linux/spinlock.h> | ||
26 | #include <linux/wait.h> | 25 | #include <linux/wait.h> |
27 | #include <linux/i2c.h> | 26 | #include <linux/i2c.h> |
28 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
@@ -33,8 +32,8 @@ | |||
33 | #include <linux/clk.h> | 32 | #include <linux/clk.h> |
34 | #include <linux/regulator/consumer.h> | 33 | #include <linux/regulator/consumer.h> |
35 | #include <linux/io.h> | 34 | #include <linux/io.h> |
36 | #include <linux/of.h> | ||
37 | #include <linux/of_address.h> | 35 | #include <linux/of_address.h> |
36 | #include <linux/of_device.h> | ||
38 | #include <linux/of_gpio.h> | 37 | #include <linux/of_gpio.h> |
39 | #include <linux/hdmi.h> | 38 | #include <linux/hdmi.h> |
40 | #include <linux/component.h> | 39 | #include <linux/component.h> |
@@ -48,7 +47,6 @@ | |||
48 | #include "exynos_mixer.h" | 47 | #include "exynos_mixer.h" |
49 | 48 | ||
50 | #include <linux/gpio.h> | 49 | #include <linux/gpio.h> |
51 | #include <media/s5p_hdmi.h> | ||
52 | 50 | ||
53 | #define ctx_from_connector(c) container_of(c, struct hdmi_context, connector) | 51 | #define ctx_from_connector(c) container_of(c, struct hdmi_context, connector) |
54 | 52 | ||
@@ -88,109 +86,14 @@ struct hdmi_resources { | |||
88 | int regul_count; | 86 | int regul_count; |
89 | }; | 87 | }; |
90 | 88 | ||
91 | struct hdmi_tg_regs { | ||
92 | u8 cmd[1]; | ||
93 | u8 h_fsz[2]; | ||
94 | u8 hact_st[2]; | ||
95 | u8 hact_sz[2]; | ||
96 | u8 v_fsz[2]; | ||
97 | u8 vsync[2]; | ||
98 | u8 vsync2[2]; | ||
99 | u8 vact_st[2]; | ||
100 | u8 vact_sz[2]; | ||
101 | u8 field_chg[2]; | ||
102 | u8 vact_st2[2]; | ||
103 | u8 vact_st3[2]; | ||
104 | u8 vact_st4[2]; | ||
105 | u8 vsync_top_hdmi[2]; | ||
106 | u8 vsync_bot_hdmi[2]; | ||
107 | u8 field_top_hdmi[2]; | ||
108 | u8 field_bot_hdmi[2]; | ||
109 | u8 tg_3d[1]; | ||
110 | }; | ||
111 | |||
112 | struct hdmi_v13_core_regs { | ||
113 | u8 h_blank[2]; | ||
114 | u8 v_blank[3]; | ||
115 | u8 h_v_line[3]; | ||
116 | u8 vsync_pol[1]; | ||
117 | u8 int_pro_mode[1]; | ||
118 | u8 v_blank_f[3]; | ||
119 | u8 h_sync_gen[3]; | ||
120 | u8 v_sync_gen1[3]; | ||
121 | u8 v_sync_gen2[3]; | ||
122 | u8 v_sync_gen3[3]; | ||
123 | }; | ||
124 | |||
125 | struct hdmi_v14_core_regs { | ||
126 | u8 h_blank[2]; | ||
127 | u8 v2_blank[2]; | ||
128 | u8 v1_blank[2]; | ||
129 | u8 v_line[2]; | ||
130 | u8 h_line[2]; | ||
131 | u8 hsync_pol[1]; | ||
132 | u8 vsync_pol[1]; | ||
133 | u8 int_pro_mode[1]; | ||
134 | u8 v_blank_f0[2]; | ||
135 | u8 v_blank_f1[2]; | ||
136 | u8 h_sync_start[2]; | ||
137 | u8 h_sync_end[2]; | ||
138 | u8 v_sync_line_bef_2[2]; | ||
139 | u8 v_sync_line_bef_1[2]; | ||
140 | u8 v_sync_line_aft_2[2]; | ||
141 | u8 v_sync_line_aft_1[2]; | ||
142 | u8 v_sync_line_aft_pxl_2[2]; | ||
143 | u8 v_sync_line_aft_pxl_1[2]; | ||
144 | u8 v_blank_f2[2]; /* for 3D mode */ | ||
145 | u8 v_blank_f3[2]; /* for 3D mode */ | ||
146 | u8 v_blank_f4[2]; /* for 3D mode */ | ||
147 | u8 v_blank_f5[2]; /* for 3D mode */ | ||
148 | u8 v_sync_line_aft_3[2]; | ||
149 | u8 v_sync_line_aft_4[2]; | ||
150 | u8 v_sync_line_aft_5[2]; | ||
151 | u8 v_sync_line_aft_6[2]; | ||
152 | u8 v_sync_line_aft_pxl_3[2]; | ||
153 | u8 v_sync_line_aft_pxl_4[2]; | ||
154 | u8 v_sync_line_aft_pxl_5[2]; | ||
155 | u8 v_sync_line_aft_pxl_6[2]; | ||
156 | u8 vact_space_1[2]; | ||
157 | u8 vact_space_2[2]; | ||
158 | u8 vact_space_3[2]; | ||
159 | u8 vact_space_4[2]; | ||
160 | u8 vact_space_5[2]; | ||
161 | u8 vact_space_6[2]; | ||
162 | }; | ||
163 | |||
164 | struct hdmi_v13_conf { | ||
165 | struct hdmi_v13_core_regs core; | ||
166 | struct hdmi_tg_regs tg; | ||
167 | }; | ||
168 | |||
169 | struct hdmi_v14_conf { | ||
170 | struct hdmi_v14_core_regs core; | ||
171 | struct hdmi_tg_regs tg; | ||
172 | }; | ||
173 | |||
174 | struct hdmi_conf_regs { | ||
175 | int pixel_clock; | ||
176 | int cea_video_id; | ||
177 | enum hdmi_picture_aspect aspect_ratio; | ||
178 | union { | ||
179 | struct hdmi_v13_conf v13_conf; | ||
180 | struct hdmi_v14_conf v14_conf; | ||
181 | } conf; | ||
182 | }; | ||
183 | |||
184 | struct hdmi_context { | 89 | struct hdmi_context { |
185 | struct exynos_drm_display display; | 90 | struct drm_encoder encoder; |
186 | struct device *dev; | 91 | struct device *dev; |
187 | struct drm_device *drm_dev; | 92 | struct drm_device *drm_dev; |
188 | struct drm_connector connector; | 93 | struct drm_connector connector; |
189 | struct drm_encoder *encoder; | ||
190 | bool hpd; | 94 | bool hpd; |
191 | bool powered; | 95 | bool powered; |
192 | bool dvi_mode; | 96 | bool dvi_mode; |
193 | struct mutex hdmi_mutex; | ||
194 | 97 | ||
195 | void __iomem *regs; | 98 | void __iomem *regs; |
196 | int irq; | 99 | int irq; |
@@ -201,22 +104,20 @@ struct hdmi_context { | |||
201 | 104 | ||
202 | /* current hdmiphy conf regs */ | 105 | /* current hdmiphy conf regs */ |
203 | struct drm_display_mode current_mode; | 106 | struct drm_display_mode current_mode; |
204 | struct hdmi_conf_regs mode_conf; | 107 | u8 cea_video_id; |
205 | 108 | ||
206 | struct hdmi_resources res; | 109 | struct hdmi_resources res; |
110 | const struct hdmi_driver_data *drv_data; | ||
207 | 111 | ||
208 | int hpd_gpio; | 112 | int hpd_gpio; |
209 | void __iomem *regs_hdmiphy; | 113 | void __iomem *regs_hdmiphy; |
210 | const struct hdmiphy_config *phy_confs; | ||
211 | unsigned int phy_conf_count; | ||
212 | 114 | ||
213 | struct regmap *pmureg; | 115 | struct regmap *pmureg; |
214 | enum hdmi_type type; | ||
215 | }; | 116 | }; |
216 | 117 | ||
217 | static inline struct hdmi_context *display_to_hdmi(struct exynos_drm_display *d) | 118 | static inline struct hdmi_context *encoder_to_hdmi(struct drm_encoder *e) |
218 | { | 119 | { |
219 | return container_of(d, struct hdmi_context, display); | 120 | return container_of(e, struct hdmi_context, encoder); |
220 | } | 121 | } |
221 | 122 | ||
222 | struct hdmiphy_config { | 123 | struct hdmiphy_config { |
@@ -624,6 +525,16 @@ static inline void hdmi_reg_writeb(struct hdmi_context *hdata, | |||
624 | writeb(value, hdata->regs + reg_id); | 525 | writeb(value, hdata->regs + reg_id); |
625 | } | 526 | } |
626 | 527 | ||
528 | static inline void hdmi_reg_writev(struct hdmi_context *hdata, u32 reg_id, | ||
529 | int bytes, u32 val) | ||
530 | { | ||
531 | while (--bytes >= 0) { | ||
532 | writeb(val & 0xff, hdata->regs + reg_id); | ||
533 | val >>= 8; | ||
534 | reg_id += 4; | ||
535 | } | ||
536 | } | ||
537 | |||
627 | static inline void hdmi_reg_writemask(struct hdmi_context *hdata, | 538 | static inline void hdmi_reg_writemask(struct hdmi_context *hdata, |
628 | u32 reg_id, u32 value, u32 mask) | 539 | u32 reg_id, u32 value, u32 mask) |
629 | { | 540 | { |
@@ -930,7 +841,7 @@ static void hdmi_v14_regs_dump(struct hdmi_context *hdata, char *prefix) | |||
930 | 841 | ||
931 | static void hdmi_regs_dump(struct hdmi_context *hdata, char *prefix) | 842 | static void hdmi_regs_dump(struct hdmi_context *hdata, char *prefix) |
932 | { | 843 | { |
933 | if (hdata->type == HDMI_TYPE13) | 844 | if (hdata->drv_data->type == HDMI_TYPE13) |
934 | hdmi_v13_regs_dump(hdata, prefix); | 845 | hdmi_v13_regs_dump(hdata, prefix); |
935 | else | 846 | else |
936 | hdmi_v14_regs_dump(hdata, prefix); | 847 | hdmi_v14_regs_dump(hdata, prefix); |
@@ -957,7 +868,7 @@ static void hdmi_reg_infoframe(struct hdmi_context *hdata, | |||
957 | u32 hdr_sum; | 868 | u32 hdr_sum; |
958 | u8 chksum; | 869 | u8 chksum; |
959 | u32 mod; | 870 | u32 mod; |
960 | u32 vic; | 871 | u8 ar; |
961 | 872 | ||
962 | mod = hdmi_reg_read(hdata, HDMI_MODE_SEL); | 873 | mod = hdmi_reg_read(hdata, HDMI_MODE_SEL); |
963 | if (hdata->dvi_mode) { | 874 | if (hdata->dvi_mode) { |
@@ -988,27 +899,22 @@ static void hdmi_reg_infoframe(struct hdmi_context *hdata, | |||
988 | * Set the aspect ratio as per the mode, mentioned in | 899 | * Set the aspect ratio as per the mode, mentioned in |
989 | * Table 9 AVI InfoFrame Data Byte 2 of CEA-861-D Standard | 900 | * Table 9 AVI InfoFrame Data Byte 2 of CEA-861-D Standard |
990 | */ | 901 | */ |
991 | switch (hdata->mode_conf.aspect_ratio) { | 902 | ar = hdata->current_mode.picture_aspect_ratio; |
903 | switch (ar) { | ||
992 | case HDMI_PICTURE_ASPECT_4_3: | 904 | case HDMI_PICTURE_ASPECT_4_3: |
993 | hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2), | 905 | ar |= AVI_4_3_CENTER_RATIO; |
994 | hdata->mode_conf.aspect_ratio | | ||
995 | AVI_4_3_CENTER_RATIO); | ||
996 | break; | 906 | break; |
997 | case HDMI_PICTURE_ASPECT_16_9: | 907 | case HDMI_PICTURE_ASPECT_16_9: |
998 | hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2), | 908 | ar |= AVI_16_9_CENTER_RATIO; |
999 | hdata->mode_conf.aspect_ratio | | ||
1000 | AVI_16_9_CENTER_RATIO); | ||
1001 | break; | 909 | break; |
1002 | case HDMI_PICTURE_ASPECT_NONE: | 910 | case HDMI_PICTURE_ASPECT_NONE: |
1003 | default: | 911 | default: |
1004 | hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2), | 912 | ar |= AVI_SAME_AS_PIC_ASPECT_RATIO; |
1005 | hdata->mode_conf.aspect_ratio | | ||
1006 | AVI_SAME_AS_PIC_ASPECT_RATIO); | ||
1007 | break; | 913 | break; |
1008 | } | 914 | } |
915 | hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2), ar); | ||
1009 | 916 | ||
1010 | vic = hdata->mode_conf.cea_video_id; | 917 | hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(4), hdata->cea_video_id); |
1011 | hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(4), vic); | ||
1012 | 918 | ||
1013 | chksum = hdmi_chksum(hdata, HDMI_AVI_BYTE(1), | 919 | chksum = hdmi_chksum(hdata, HDMI_AVI_BYTE(1), |
1014 | infoframe->any.length, hdr_sum); | 920 | infoframe->any.length, hdr_sum); |
@@ -1038,10 +944,10 @@ static enum drm_connector_status hdmi_detect(struct drm_connector *connector, | |||
1038 | { | 944 | { |
1039 | struct hdmi_context *hdata = ctx_from_connector(connector); | 945 | struct hdmi_context *hdata = ctx_from_connector(connector); |
1040 | 946 | ||
1041 | hdata->hpd = gpio_get_value(hdata->hpd_gpio); | 947 | if (gpio_get_value(hdata->hpd_gpio)) |
948 | return connector_status_connected; | ||
1042 | 949 | ||
1043 | return hdata->hpd ? connector_status_connected : | 950 | return connector_status_disconnected; |
1044 | connector_status_disconnected; | ||
1045 | } | 951 | } |
1046 | 952 | ||
1047 | static void hdmi_connector_destroy(struct drm_connector *connector) | 953 | static void hdmi_connector_destroy(struct drm_connector *connector) |
@@ -1091,8 +997,8 @@ static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock) | |||
1091 | { | 997 | { |
1092 | int i; | 998 | int i; |
1093 | 999 | ||
1094 | for (i = 0; i < hdata->phy_conf_count; i++) | 1000 | for (i = 0; i < hdata->drv_data->phy_conf_count; i++) |
1095 | if (hdata->phy_confs[i].pixel_clock == pixel_clock) | 1001 | if (hdata->drv_data->phy_confs[i].pixel_clock == pixel_clock) |
1096 | return i; | 1002 | return i; |
1097 | 1003 | ||
1098 | DRM_DEBUG_KMS("Could not find phy config for %d\n", pixel_clock); | 1004 | DRM_DEBUG_KMS("Could not find phy config for %d\n", pixel_clock); |
@@ -1125,7 +1031,7 @@ static struct drm_encoder *hdmi_best_encoder(struct drm_connector *connector) | |||
1125 | { | 1031 | { |
1126 | struct hdmi_context *hdata = ctx_from_connector(connector); | 1032 | struct hdmi_context *hdata = ctx_from_connector(connector); |
1127 | 1033 | ||
1128 | return hdata->encoder; | 1034 | return &hdata->encoder; |
1129 | } | 1035 | } |
1130 | 1036 | ||
1131 | static struct drm_connector_helper_funcs hdmi_connector_helper_funcs = { | 1037 | static struct drm_connector_helper_funcs hdmi_connector_helper_funcs = { |
@@ -1134,14 +1040,12 @@ static struct drm_connector_helper_funcs hdmi_connector_helper_funcs = { | |||
1134 | .best_encoder = hdmi_best_encoder, | 1040 | .best_encoder = hdmi_best_encoder, |
1135 | }; | 1041 | }; |
1136 | 1042 | ||
1137 | static int hdmi_create_connector(struct exynos_drm_display *display, | 1043 | static int hdmi_create_connector(struct drm_encoder *encoder) |
1138 | struct drm_encoder *encoder) | ||
1139 | { | 1044 | { |
1140 | struct hdmi_context *hdata = display_to_hdmi(display); | 1045 | struct hdmi_context *hdata = encoder_to_hdmi(encoder); |
1141 | struct drm_connector *connector = &hdata->connector; | 1046 | struct drm_connector *connector = &hdata->connector; |
1142 | int ret; | 1047 | int ret; |
1143 | 1048 | ||
1144 | hdata->encoder = encoder; | ||
1145 | connector->interlace_allowed = true; | 1049 | connector->interlace_allowed = true; |
1146 | connector->polled = DRM_CONNECTOR_POLL_HPD; | 1050 | connector->polled = DRM_CONNECTOR_POLL_HPD; |
1147 | 1051 | ||
@@ -1159,23 +1063,30 @@ static int hdmi_create_connector(struct exynos_drm_display *display, | |||
1159 | return 0; | 1063 | return 0; |
1160 | } | 1064 | } |
1161 | 1065 | ||
1162 | static void hdmi_mode_fixup(struct exynos_drm_display *display, | 1066 | static bool hdmi_mode_fixup(struct drm_encoder *encoder, |
1163 | struct drm_connector *connector, | 1067 | const struct drm_display_mode *mode, |
1164 | const struct drm_display_mode *mode, | 1068 | struct drm_display_mode *adjusted_mode) |
1165 | struct drm_display_mode *adjusted_mode) | ||
1166 | { | 1069 | { |
1070 | struct drm_device *dev = encoder->dev; | ||
1071 | struct drm_connector *connector; | ||
1167 | struct drm_display_mode *m; | 1072 | struct drm_display_mode *m; |
1168 | int mode_ok; | 1073 | int mode_ok; |
1169 | 1074 | ||
1170 | DRM_DEBUG_KMS("%s\n", __FILE__); | ||
1171 | |||
1172 | drm_mode_set_crtcinfo(adjusted_mode, 0); | 1075 | drm_mode_set_crtcinfo(adjusted_mode, 0); |
1173 | 1076 | ||
1077 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
1078 | if (connector->encoder == encoder) | ||
1079 | break; | ||
1080 | } | ||
1081 | |||
1082 | if (connector->encoder != encoder) | ||
1083 | return true; | ||
1084 | |||
1174 | mode_ok = hdmi_mode_valid(connector, adjusted_mode); | 1085 | mode_ok = hdmi_mode_valid(connector, adjusted_mode); |
1175 | 1086 | ||
1176 | /* just return if user desired mode exists. */ | 1087 | /* just return if user desired mode exists. */ |
1177 | if (mode_ok == MODE_OK) | 1088 | if (mode_ok == MODE_OK) |
1178 | return; | 1089 | return true; |
1179 | 1090 | ||
1180 | /* | 1091 | /* |
1181 | * otherwise, find the most suitable mode among modes and change it | 1092 | * otherwise, find the most suitable mode among modes and change it |
@@ -1195,6 +1106,8 @@ static void hdmi_mode_fixup(struct exynos_drm_display *display, | |||
1195 | break; | 1106 | break; |
1196 | } | 1107 | } |
1197 | } | 1108 | } |
1109 | |||
1110 | return true; | ||
1198 | } | 1111 | } |
1199 | 1112 | ||
1200 | static void hdmi_set_acr(u32 freq, u8 *acr) | 1113 | static void hdmi_set_acr(u32 freq, u8 *acr) |
@@ -1257,7 +1170,7 @@ static void hdmi_reg_acr(struct hdmi_context *hdata, u8 *acr) | |||
1257 | hdmi_reg_writeb(hdata, HDMI_ACR_CTS1, acr[2]); | 1170 | hdmi_reg_writeb(hdata, HDMI_ACR_CTS1, acr[2]); |
1258 | hdmi_reg_writeb(hdata, HDMI_ACR_CTS2, acr[1]); | 1171 | hdmi_reg_writeb(hdata, HDMI_ACR_CTS2, acr[1]); |
1259 | 1172 | ||
1260 | if (hdata->type == HDMI_TYPE13) | 1173 | if (hdata->drv_data->type == HDMI_TYPE13) |
1261 | hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 4); | 1174 | hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 4); |
1262 | else | 1175 | else |
1263 | hdmi_reg_writeb(hdata, HDMI_ACR_CON, 4); | 1176 | hdmi_reg_writeb(hdata, HDMI_ACR_CON, 4); |
@@ -1391,7 +1304,7 @@ static void hdmi_conf_init(struct hdmi_context *hdata) | |||
1391 | HDMI_VID_PREAMBLE_DIS | HDMI_GUARD_BAND_DIS); | 1304 | HDMI_VID_PREAMBLE_DIS | HDMI_GUARD_BAND_DIS); |
1392 | } | 1305 | } |
1393 | 1306 | ||
1394 | if (hdata->type == HDMI_TYPE13) { | 1307 | if (hdata->drv_data->type == HDMI_TYPE13) { |
1395 | /* choose bluescreen (fecal) color */ | 1308 | /* choose bluescreen (fecal) color */ |
1396 | hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_0, 0x12); | 1309 | hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_0, 0x12); |
1397 | hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_1, 0x34); | 1310 | hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_1, 0x34); |
@@ -1424,66 +1337,94 @@ static void hdmi_conf_init(struct hdmi_context *hdata) | |||
1424 | 1337 | ||
1425 | static void hdmi_v13_mode_apply(struct hdmi_context *hdata) | 1338 | static void hdmi_v13_mode_apply(struct hdmi_context *hdata) |
1426 | { | 1339 | { |
1427 | const struct hdmi_tg_regs *tg = &hdata->mode_conf.conf.v13_conf.tg; | 1340 | struct drm_display_mode *m = &hdata->current_mode; |
1428 | const struct hdmi_v13_core_regs *core = | 1341 | unsigned int val; |
1429 | &hdata->mode_conf.conf.v13_conf.core; | ||
1430 | int tries; | 1342 | int tries; |
1431 | 1343 | ||
1432 | /* setting core registers */ | 1344 | hdmi_reg_writev(hdata, HDMI_H_BLANK_0, 2, m->htotal - m->hdisplay); |
1433 | hdmi_reg_writeb(hdata, HDMI_H_BLANK_0, core->h_blank[0]); | 1345 | hdmi_reg_writev(hdata, HDMI_V13_H_V_LINE_0, 3, |
1434 | hdmi_reg_writeb(hdata, HDMI_H_BLANK_1, core->h_blank[1]); | 1346 | (m->htotal << 12) | m->vtotal); |
1435 | hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_0, core->v_blank[0]); | 1347 | |
1436 | hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_1, core->v_blank[1]); | 1348 | val = (m->flags & DRM_MODE_FLAG_NVSYNC) ? 1 : 0; |
1437 | hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_2, core->v_blank[2]); | 1349 | hdmi_reg_writev(hdata, HDMI_VSYNC_POL, 1, val); |
1438 | hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_0, core->h_v_line[0]); | 1350 | |
1439 | hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_1, core->h_v_line[1]); | 1351 | val = (m->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0; |
1440 | hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_2, core->h_v_line[2]); | 1352 | hdmi_reg_writev(hdata, HDMI_INT_PRO_MODE, 1, val); |
1441 | hdmi_reg_writeb(hdata, HDMI_VSYNC_POL, core->vsync_pol[0]); | 1353 | |
1442 | hdmi_reg_writeb(hdata, HDMI_INT_PRO_MODE, core->int_pro_mode[0]); | 1354 | val = (m->hsync_start - m->hdisplay - 2); |
1443 | hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_0, core->v_blank_f[0]); | 1355 | val |= ((m->hsync_end - m->hdisplay - 2) << 10); |
1444 | hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_1, core->v_blank_f[1]); | 1356 | val |= ((m->flags & DRM_MODE_FLAG_NHSYNC) ? 1 : 0)<<20; |
1445 | hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_2, core->v_blank_f[2]); | 1357 | hdmi_reg_writev(hdata, HDMI_V13_H_SYNC_GEN_0, 3, val); |
1446 | hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_0, core->h_sync_gen[0]); | 1358 | |
1447 | hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_1, core->h_sync_gen[1]); | 1359 | /* |
1448 | hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_2, core->h_sync_gen[2]); | 1360 | * Quirk requirement for exynos HDMI IP design, |
1449 | hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_0, core->v_sync_gen1[0]); | 1361 | * 2 pixels less than the actual calculation for hsync_start |
1450 | hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_1, core->v_sync_gen1[1]); | 1362 | * and end. |
1451 | hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_2, core->v_sync_gen1[2]); | 1363 | */ |
1452 | hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_0, core->v_sync_gen2[0]); | 1364 | |
1453 | hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_1, core->v_sync_gen2[1]); | 1365 | /* Following values & calculations differ for different type of modes */ |
1454 | hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_2, core->v_sync_gen2[2]); | 1366 | if (m->flags & DRM_MODE_FLAG_INTERLACE) { |
1455 | hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_0, core->v_sync_gen3[0]); | 1367 | /* Interlaced Mode */ |
1456 | hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_1, core->v_sync_gen3[1]); | 1368 | val = ((m->vsync_end - m->vdisplay) / 2); |
1457 | hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_2, core->v_sync_gen3[2]); | 1369 | val |= ((m->vsync_start - m->vdisplay) / 2) << 12; |
1370 | hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_1_0, 3, val); | ||
1371 | |||
1372 | val = m->vtotal / 2; | ||
1373 | val |= ((m->vtotal - m->vdisplay) / 2) << 11; | ||
1374 | hdmi_reg_writev(hdata, HDMI_V13_V_BLANK_0, 3, val); | ||
1375 | |||
1376 | val = (m->vtotal + | ||
1377 | ((m->vsync_end - m->vsync_start) * 4) + 5) / 2; | ||
1378 | val |= m->vtotal << 11; | ||
1379 | hdmi_reg_writev(hdata, HDMI_V13_V_BLANK_F_0, 3, val); | ||
1380 | |||
1381 | val = ((m->vtotal / 2) + 7); | ||
1382 | val |= ((m->vtotal / 2) + 2) << 12; | ||
1383 | hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_2_0, 3, val); | ||
1384 | |||
1385 | val = ((m->htotal / 2) + (m->hsync_start - m->hdisplay)); | ||
1386 | val |= ((m->htotal / 2) + | ||
1387 | (m->hsync_start - m->hdisplay)) << 12; | ||
1388 | hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_3_0, 3, val); | ||
1389 | |||
1390 | hdmi_reg_writev(hdata, HDMI_TG_VACT_ST_L, 2, | ||
1391 | (m->vtotal - m->vdisplay) / 2); | ||
1392 | hdmi_reg_writev(hdata, HDMI_TG_VACT_SZ_L, 2, m->vdisplay / 2); | ||
1393 | |||
1394 | hdmi_reg_writev(hdata, HDMI_TG_VACT_ST2_L, 2, 0x249); | ||
1395 | } else { | ||
1396 | /* Progressive Mode */ | ||
1397 | |||
1398 | val = m->vtotal; | ||
1399 | val |= (m->vtotal - m->vdisplay) << 11; | ||
1400 | hdmi_reg_writev(hdata, HDMI_V13_V_BLANK_0, 3, val); | ||
1401 | |||
1402 | hdmi_reg_writev(hdata, HDMI_V13_V_BLANK_F_0, 3, 0); | ||
1403 | |||
1404 | val = (m->vsync_end - m->vdisplay); | ||
1405 | val |= ((m->vsync_start - m->vdisplay) << 12); | ||
1406 | hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_1_0, 3, val); | ||
1407 | |||
1408 | hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_2_0, 3, 0x1001); | ||
1409 | hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_3_0, 3, 0x1001); | ||
1410 | hdmi_reg_writev(hdata, HDMI_TG_VACT_ST_L, 2, | ||
1411 | m->vtotal - m->vdisplay); | ||
1412 | hdmi_reg_writev(hdata, HDMI_TG_VACT_SZ_L, 2, m->vdisplay); | ||
1413 | hdmi_reg_writev(hdata, HDMI_TG_VACT_ST2_L, 2, 0x248); | ||
1414 | } | ||
1415 | |||
1458 | /* Timing generator registers */ | 1416 | /* Timing generator registers */ |
1459 | hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz[0]); | 1417 | hdmi_reg_writev(hdata, HDMI_TG_H_FSZ_L, 2, m->htotal); |
1460 | hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz[1]); | 1418 | hdmi_reg_writev(hdata, HDMI_TG_HACT_ST_L, 2, m->htotal - m->hdisplay); |
1461 | hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st[0]); | 1419 | hdmi_reg_writev(hdata, HDMI_TG_HACT_SZ_L, 2, m->hdisplay); |
1462 | hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st[1]); | 1420 | hdmi_reg_writev(hdata, HDMI_TG_V_FSZ_L, 2, m->vtotal); |
1463 | hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz[0]); | 1421 | hdmi_reg_writev(hdata, HDMI_TG_VSYNC_L, 2, 0x1); |
1464 | hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz[1]); | 1422 | hdmi_reg_writev(hdata, HDMI_TG_VSYNC2_L, 2, 0x233); |
1465 | hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz[0]); | 1423 | hdmi_reg_writev(hdata, HDMI_TG_FIELD_CHG_L, 2, 0x233); |
1466 | hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz[1]); | 1424 | hdmi_reg_writev(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, 2, 0x1); |
1467 | hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync[0]); | 1425 | hdmi_reg_writev(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, 2, 0x233); |
1468 | hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync[1]); | 1426 | hdmi_reg_writev(hdata, HDMI_TG_FIELD_TOP_HDMI_L, 2, 0x1); |
1469 | hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2[0]); | 1427 | hdmi_reg_writev(hdata, HDMI_TG_FIELD_BOT_HDMI_L, 2, 0x233); |
1470 | hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2[1]); | ||
1471 | hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st[0]); | ||
1472 | hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st[1]); | ||
1473 | hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz[0]); | ||
1474 | hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz[1]); | ||
1475 | hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg[0]); | ||
1476 | hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg[1]); | ||
1477 | hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2[0]); | ||
1478 | hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2[1]); | ||
1479 | hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi[0]); | ||
1480 | hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi[1]); | ||
1481 | hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi[0]); | ||
1482 | hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi[1]); | ||
1483 | hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi[0]); | ||
1484 | hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi[1]); | ||
1485 | hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi[0]); | ||
1486 | hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi[1]); | ||
1487 | 1428 | ||
1488 | /* waiting for HDMIPHY's PLL to get to steady state */ | 1429 | /* waiting for HDMIPHY's PLL to get to steady state */ |
1489 | for (tries = 100; tries; --tries) { | 1430 | for (tries = 100; tries; --tries) { |
@@ -1508,144 +1449,119 @@ static void hdmi_v13_mode_apply(struct hdmi_context *hdata) | |||
1508 | 1449 | ||
1509 | static void hdmi_v14_mode_apply(struct hdmi_context *hdata) | 1450 | static void hdmi_v14_mode_apply(struct hdmi_context *hdata) |
1510 | { | 1451 | { |
1511 | const struct hdmi_tg_regs *tg = &hdata->mode_conf.conf.v14_conf.tg; | 1452 | struct drm_display_mode *m = &hdata->current_mode; |
1512 | const struct hdmi_v14_core_regs *core = | ||
1513 | &hdata->mode_conf.conf.v14_conf.core; | ||
1514 | int tries; | 1453 | int tries; |
1515 | 1454 | ||
1516 | /* setting core registers */ | 1455 | hdmi_reg_writev(hdata, HDMI_H_BLANK_0, 2, m->htotal - m->hdisplay); |
1517 | hdmi_reg_writeb(hdata, HDMI_H_BLANK_0, core->h_blank[0]); | 1456 | hdmi_reg_writev(hdata, HDMI_V_LINE_0, 2, m->vtotal); |
1518 | hdmi_reg_writeb(hdata, HDMI_H_BLANK_1, core->h_blank[1]); | 1457 | hdmi_reg_writev(hdata, HDMI_H_LINE_0, 2, m->htotal); |
1519 | hdmi_reg_writeb(hdata, HDMI_V2_BLANK_0, core->v2_blank[0]); | 1458 | hdmi_reg_writev(hdata, HDMI_HSYNC_POL, 1, |
1520 | hdmi_reg_writeb(hdata, HDMI_V2_BLANK_1, core->v2_blank[1]); | 1459 | (m->flags & DRM_MODE_FLAG_NHSYNC) ? 1 : 0); |
1521 | hdmi_reg_writeb(hdata, HDMI_V1_BLANK_0, core->v1_blank[0]); | 1460 | hdmi_reg_writev(hdata, HDMI_VSYNC_POL, 1, |
1522 | hdmi_reg_writeb(hdata, HDMI_V1_BLANK_1, core->v1_blank[1]); | 1461 | (m->flags & DRM_MODE_FLAG_NVSYNC) ? 1 : 0); |
1523 | hdmi_reg_writeb(hdata, HDMI_V_LINE_0, core->v_line[0]); | 1462 | hdmi_reg_writev(hdata, HDMI_INT_PRO_MODE, 1, |
1524 | hdmi_reg_writeb(hdata, HDMI_V_LINE_1, core->v_line[1]); | 1463 | (m->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0); |
1525 | hdmi_reg_writeb(hdata, HDMI_H_LINE_0, core->h_line[0]); | 1464 | |
1526 | hdmi_reg_writeb(hdata, HDMI_H_LINE_1, core->h_line[1]); | 1465 | /* |
1527 | hdmi_reg_writeb(hdata, HDMI_HSYNC_POL, core->hsync_pol[0]); | 1466 | * Quirk requirement for exynos 5 HDMI IP design, |
1528 | hdmi_reg_writeb(hdata, HDMI_VSYNC_POL, core->vsync_pol[0]); | 1467 | * 2 pixels less than the actual calculation for hsync_start |
1529 | hdmi_reg_writeb(hdata, HDMI_INT_PRO_MODE, core->int_pro_mode[0]); | 1468 | * and end. |
1530 | hdmi_reg_writeb(hdata, HDMI_V_BLANK_F0_0, core->v_blank_f0[0]); | 1469 | */ |
1531 | hdmi_reg_writeb(hdata, HDMI_V_BLANK_F0_1, core->v_blank_f0[1]); | 1470 | |
1532 | hdmi_reg_writeb(hdata, HDMI_V_BLANK_F1_0, core->v_blank_f1[0]); | 1471 | /* Following values & calculations differ for different type of modes */ |
1533 | hdmi_reg_writeb(hdata, HDMI_V_BLANK_F1_1, core->v_blank_f1[1]); | 1472 | if (m->flags & DRM_MODE_FLAG_INTERLACE) { |
1534 | hdmi_reg_writeb(hdata, HDMI_H_SYNC_START_0, core->h_sync_start[0]); | 1473 | /* Interlaced Mode */ |
1535 | hdmi_reg_writeb(hdata, HDMI_H_SYNC_START_1, core->h_sync_start[1]); | 1474 | hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_BEF_2_0, 2, |
1536 | hdmi_reg_writeb(hdata, HDMI_H_SYNC_END_0, core->h_sync_end[0]); | 1475 | (m->vsync_end - m->vdisplay) / 2); |
1537 | hdmi_reg_writeb(hdata, HDMI_H_SYNC_END_1, core->h_sync_end[1]); | 1476 | hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_BEF_1_0, 2, |
1538 | hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_2_0, | 1477 | (m->vsync_start - m->vdisplay) / 2); |
1539 | core->v_sync_line_bef_2[0]); | 1478 | hdmi_reg_writev(hdata, HDMI_V2_BLANK_0, 2, m->vtotal / 2); |
1540 | hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_2_1, | 1479 | hdmi_reg_writev(hdata, HDMI_V1_BLANK_0, 2, |
1541 | core->v_sync_line_bef_2[1]); | 1480 | (m->vtotal - m->vdisplay) / 2); |
1542 | hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_1_0, | 1481 | hdmi_reg_writev(hdata, HDMI_V_BLANK_F0_0, 2, |
1543 | core->v_sync_line_bef_1[0]); | 1482 | m->vtotal - m->vdisplay / 2); |
1544 | hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_1_1, | 1483 | hdmi_reg_writev(hdata, HDMI_V_BLANK_F1_0, 2, m->vtotal); |
1545 | core->v_sync_line_bef_1[1]); | 1484 | hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_2_0, 2, |
1546 | hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_2_0, | 1485 | (m->vtotal / 2) + 7); |
1547 | core->v_sync_line_aft_2[0]); | 1486 | hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_1_0, 2, |
1548 | hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_2_1, | 1487 | (m->vtotal / 2) + 2); |
1549 | core->v_sync_line_aft_2[1]); | 1488 | hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_0, 2, |
1550 | hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_1_0, | 1489 | (m->htotal / 2) + (m->hsync_start - m->hdisplay)); |
1551 | core->v_sync_line_aft_1[0]); | 1490 | hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_0, 2, |
1552 | hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_1_1, | 1491 | (m->htotal / 2) + (m->hsync_start - m->hdisplay)); |
1553 | core->v_sync_line_aft_1[1]); | 1492 | hdmi_reg_writev(hdata, HDMI_TG_VACT_ST_L, 2, |
1554 | hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_0, | 1493 | (m->vtotal - m->vdisplay) / 2); |
1555 | core->v_sync_line_aft_pxl_2[0]); | 1494 | hdmi_reg_writev(hdata, HDMI_TG_VACT_SZ_L, 2, m->vdisplay / 2); |
1556 | hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_1, | 1495 | hdmi_reg_writev(hdata, HDMI_TG_VACT_ST2_L, 2, |
1557 | core->v_sync_line_aft_pxl_2[1]); | 1496 | m->vtotal - m->vdisplay / 2); |
1558 | hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_0, | 1497 | hdmi_reg_writev(hdata, HDMI_TG_VSYNC2_L, 2, |
1559 | core->v_sync_line_aft_pxl_1[0]); | 1498 | (m->vtotal / 2) + 1); |
1560 | hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_1, | 1499 | hdmi_reg_writev(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, 2, |
1561 | core->v_sync_line_aft_pxl_1[1]); | 1500 | (m->vtotal / 2) + 1); |
1562 | hdmi_reg_writeb(hdata, HDMI_V_BLANK_F2_0, core->v_blank_f2[0]); | 1501 | hdmi_reg_writev(hdata, HDMI_TG_FIELD_BOT_HDMI_L, 2, |
1563 | hdmi_reg_writeb(hdata, HDMI_V_BLANK_F2_1, core->v_blank_f2[1]); | 1502 | (m->vtotal / 2) + 1); |
1564 | hdmi_reg_writeb(hdata, HDMI_V_BLANK_F3_0, core->v_blank_f3[0]); | 1503 | hdmi_reg_writev(hdata, HDMI_TG_VACT_ST3_L, 2, 0x0); |
1565 | hdmi_reg_writeb(hdata, HDMI_V_BLANK_F3_1, core->v_blank_f3[1]); | 1504 | hdmi_reg_writev(hdata, HDMI_TG_VACT_ST4_L, 2, 0x0); |
1566 | hdmi_reg_writeb(hdata, HDMI_V_BLANK_F4_0, core->v_blank_f4[0]); | 1505 | } else { |
1567 | hdmi_reg_writeb(hdata, HDMI_V_BLANK_F4_1, core->v_blank_f4[1]); | 1506 | /* Progressive Mode */ |
1568 | hdmi_reg_writeb(hdata, HDMI_V_BLANK_F5_0, core->v_blank_f5[0]); | 1507 | hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_BEF_2_0, 2, |
1569 | hdmi_reg_writeb(hdata, HDMI_V_BLANK_F5_1, core->v_blank_f5[1]); | 1508 | m->vsync_end - m->vdisplay); |
1570 | hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_3_0, | 1509 | hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_BEF_1_0, 2, |
1571 | core->v_sync_line_aft_3[0]); | 1510 | m->vsync_start - m->vdisplay); |
1572 | hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_3_1, | 1511 | hdmi_reg_writev(hdata, HDMI_V2_BLANK_0, 2, m->vtotal); |
1573 | core->v_sync_line_aft_3[1]); | 1512 | hdmi_reg_writev(hdata, HDMI_V1_BLANK_0, 2, |
1574 | hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_4_0, | 1513 | m->vtotal - m->vdisplay); |
1575 | core->v_sync_line_aft_4[0]); | 1514 | hdmi_reg_writev(hdata, HDMI_V_BLANK_F0_0, 2, 0xffff); |
1576 | hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_4_1, | 1515 | hdmi_reg_writev(hdata, HDMI_V_BLANK_F1_0, 2, 0xffff); |
1577 | core->v_sync_line_aft_4[1]); | 1516 | hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_2_0, 2, 0xffff); |
1578 | hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_5_0, | 1517 | hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_1_0, 2, 0xffff); |
1579 | core->v_sync_line_aft_5[0]); | 1518 | hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_0, 2, 0xffff); |
1580 | hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_5_1, | 1519 | hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_0, 2, 0xffff); |
1581 | core->v_sync_line_aft_5[1]); | 1520 | hdmi_reg_writev(hdata, HDMI_TG_VACT_ST_L, 2, |
1582 | hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_6_0, | 1521 | m->vtotal - m->vdisplay); |
1583 | core->v_sync_line_aft_6[0]); | 1522 | hdmi_reg_writev(hdata, HDMI_TG_VACT_SZ_L, 2, m->vdisplay); |
1584 | hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_6_1, | 1523 | hdmi_reg_writev(hdata, HDMI_TG_VACT_ST2_L, 2, 0x248); |
1585 | core->v_sync_line_aft_6[1]); | 1524 | hdmi_reg_writev(hdata, HDMI_TG_VACT_ST3_L, 2, 0x47b); |
1586 | hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_0, | 1525 | hdmi_reg_writev(hdata, HDMI_TG_VACT_ST4_L, 2, 0x6ae); |
1587 | core->v_sync_line_aft_pxl_3[0]); | 1526 | hdmi_reg_writev(hdata, HDMI_TG_VSYNC2_L, 2, 0x233); |
1588 | hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_1, | 1527 | hdmi_reg_writev(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, 2, 0x233); |
1589 | core->v_sync_line_aft_pxl_3[1]); | 1528 | hdmi_reg_writev(hdata, HDMI_TG_FIELD_BOT_HDMI_L, 2, 0x233); |
1590 | hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_0, | 1529 | } |
1591 | core->v_sync_line_aft_pxl_4[0]); | 1530 | |
1592 | hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_1, | 1531 | /* Following values & calculations are same irrespective of mode type */ |
1593 | core->v_sync_line_aft_pxl_4[1]); | 1532 | hdmi_reg_writev(hdata, HDMI_H_SYNC_START_0, 2, |
1594 | hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_0, | 1533 | m->hsync_start - m->hdisplay - 2); |
1595 | core->v_sync_line_aft_pxl_5[0]); | 1534 | hdmi_reg_writev(hdata, HDMI_H_SYNC_END_0, 2, |
1596 | hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_1, | 1535 | m->hsync_end - m->hdisplay - 2); |
1597 | core->v_sync_line_aft_pxl_5[1]); | 1536 | hdmi_reg_writev(hdata, HDMI_VACT_SPACE_1_0, 2, 0xffff); |
1598 | hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_0, | 1537 | hdmi_reg_writev(hdata, HDMI_VACT_SPACE_2_0, 2, 0xffff); |
1599 | core->v_sync_line_aft_pxl_6[0]); | 1538 | hdmi_reg_writev(hdata, HDMI_VACT_SPACE_3_0, 2, 0xffff); |
1600 | hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_1, | 1539 | hdmi_reg_writev(hdata, HDMI_VACT_SPACE_4_0, 2, 0xffff); |
1601 | core->v_sync_line_aft_pxl_6[1]); | 1540 | hdmi_reg_writev(hdata, HDMI_VACT_SPACE_5_0, 2, 0xffff); |
1602 | hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_1_0, core->vact_space_1[0]); | 1541 | hdmi_reg_writev(hdata, HDMI_VACT_SPACE_6_0, 2, 0xffff); |
1603 | hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_1_1, core->vact_space_1[1]); | 1542 | hdmi_reg_writev(hdata, HDMI_V_BLANK_F2_0, 2, 0xffff); |
1604 | hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_2_0, core->vact_space_2[0]); | 1543 | hdmi_reg_writev(hdata, HDMI_V_BLANK_F3_0, 2, 0xffff); |
1605 | hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_2_1, core->vact_space_2[1]); | 1544 | hdmi_reg_writev(hdata, HDMI_V_BLANK_F4_0, 2, 0xffff); |
1606 | hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_3_0, core->vact_space_3[0]); | 1545 | hdmi_reg_writev(hdata, HDMI_V_BLANK_F5_0, 2, 0xffff); |
1607 | hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_3_1, core->vact_space_3[1]); | 1546 | hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_3_0, 2, 0xffff); |
1608 | hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_4_0, core->vact_space_4[0]); | 1547 | hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_4_0, 2, 0xffff); |
1609 | hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_4_1, core->vact_space_4[1]); | 1548 | hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_5_0, 2, 0xffff); |
1610 | hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_5_0, core->vact_space_5[0]); | 1549 | hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_6_0, 2, 0xffff); |
1611 | hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_5_1, core->vact_space_5[1]); | 1550 | hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_0, 2, 0xffff); |
1612 | hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_6_0, core->vact_space_6[0]); | 1551 | hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_0, 2, 0xffff); |
1613 | hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_6_1, core->vact_space_6[1]); | 1552 | hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_0, 2, 0xffff); |
1553 | hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_0, 2, 0xffff); | ||
1614 | 1554 | ||
1615 | /* Timing generator registers */ | 1555 | /* Timing generator registers */ |
1616 | hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz[0]); | 1556 | hdmi_reg_writev(hdata, HDMI_TG_H_FSZ_L, 2, m->htotal); |
1617 | hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz[1]); | 1557 | hdmi_reg_writev(hdata, HDMI_TG_HACT_ST_L, 2, m->htotal - m->hdisplay); |
1618 | hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st[0]); | 1558 | hdmi_reg_writev(hdata, HDMI_TG_HACT_SZ_L, 2, m->hdisplay); |
1619 | hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st[1]); | 1559 | hdmi_reg_writev(hdata, HDMI_TG_V_FSZ_L, 2, m->vtotal); |
1620 | hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz[0]); | 1560 | hdmi_reg_writev(hdata, HDMI_TG_VSYNC_L, 2, 0x1); |
1621 | hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz[1]); | 1561 | hdmi_reg_writev(hdata, HDMI_TG_FIELD_CHG_L, 2, 0x233); |
1622 | hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz[0]); | 1562 | hdmi_reg_writev(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, 2, 0x1); |
1623 | hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz[1]); | 1563 | hdmi_reg_writev(hdata, HDMI_TG_FIELD_TOP_HDMI_L, 2, 0x1); |
1624 | hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync[0]); | 1564 | hdmi_reg_writev(hdata, HDMI_TG_3D, 1, 0x0); |
1625 | hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync[1]); | ||
1626 | hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2[0]); | ||
1627 | hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2[1]); | ||
1628 | hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st[0]); | ||
1629 | hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st[1]); | ||
1630 | hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz[0]); | ||
1631 | hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz[1]); | ||
1632 | hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg[0]); | ||
1633 | hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg[1]); | ||
1634 | hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2[0]); | ||
1635 | hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2[1]); | ||
1636 | hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_L, tg->vact_st3[0]); | ||
1637 | hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_H, tg->vact_st3[1]); | ||
1638 | hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_L, tg->vact_st4[0]); | ||
1639 | hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_H, tg->vact_st4[1]); | ||
1640 | hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi[0]); | ||
1641 | hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi[1]); | ||
1642 | hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi[0]); | ||
1643 | hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi[1]); | ||
1644 | hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi[0]); | ||
1645 | hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi[1]); | ||
1646 | hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi[0]); | ||
1647 | hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi[1]); | ||
1648 | hdmi_reg_writeb(hdata, HDMI_TG_3D, tg->tg_3d[0]); | ||
1649 | 1565 | ||
1650 | /* waiting for HDMIPHY's PLL to get to steady state */ | 1566 | /* waiting for HDMIPHY's PLL to get to steady state */ |
1651 | for (tries = 100; tries; --tries) { | 1567 | for (tries = 100; tries; --tries) { |
@@ -1670,7 +1586,7 @@ static void hdmi_v14_mode_apply(struct hdmi_context *hdata) | |||
1670 | 1586 | ||
1671 | static void hdmi_mode_apply(struct hdmi_context *hdata) | 1587 | static void hdmi_mode_apply(struct hdmi_context *hdata) |
1672 | { | 1588 | { |
1673 | if (hdata->type == HDMI_TYPE13) | 1589 | if (hdata->drv_data->type == HDMI_TYPE13) |
1674 | hdmi_v13_mode_apply(hdata); | 1590 | hdmi_v13_mode_apply(hdata); |
1675 | else | 1591 | else |
1676 | hdmi_v14_mode_apply(hdata); | 1592 | hdmi_v14_mode_apply(hdata); |
@@ -1688,7 +1604,7 @@ static void hdmiphy_conf_reset(struct hdmi_context *hdata) | |||
1688 | hdmiphy_reg_writeb(hdata, HDMIPHY_MODE_SET_DONE, | 1604 | hdmiphy_reg_writeb(hdata, HDMIPHY_MODE_SET_DONE, |
1689 | HDMI_PHY_ENABLE_MODE_SET); | 1605 | HDMI_PHY_ENABLE_MODE_SET); |
1690 | 1606 | ||
1691 | if (hdata->type == HDMI_TYPE13) | 1607 | if (hdata->drv_data->type == HDMI_TYPE13) |
1692 | reg = HDMI_V13_PHY_RSTOUT; | 1608 | reg = HDMI_V13_PHY_RSTOUT; |
1693 | else | 1609 | else |
1694 | reg = HDMI_PHY_RSTOUT; | 1610 | reg = HDMI_PHY_RSTOUT; |
@@ -1702,7 +1618,7 @@ static void hdmiphy_conf_reset(struct hdmi_context *hdata) | |||
1702 | 1618 | ||
1703 | static void hdmiphy_poweron(struct hdmi_context *hdata) | 1619 | static void hdmiphy_poweron(struct hdmi_context *hdata) |
1704 | { | 1620 | { |
1705 | if (hdata->type != HDMI_TYPE14) | 1621 | if (hdata->drv_data->type != HDMI_TYPE14) |
1706 | return; | 1622 | return; |
1707 | 1623 | ||
1708 | DRM_DEBUG_KMS("\n"); | 1624 | DRM_DEBUG_KMS("\n"); |
@@ -1722,7 +1638,7 @@ static void hdmiphy_poweron(struct hdmi_context *hdata) | |||
1722 | 1638 | ||
1723 | static void hdmiphy_poweroff(struct hdmi_context *hdata) | 1639 | static void hdmiphy_poweroff(struct hdmi_context *hdata) |
1724 | { | 1640 | { |
1725 | if (hdata->type != HDMI_TYPE14) | 1641 | if (hdata->drv_data->type != HDMI_TYPE14) |
1726 | return; | 1642 | return; |
1727 | 1643 | ||
1728 | DRM_DEBUG_KMS("\n"); | 1644 | DRM_DEBUG_KMS("\n"); |
@@ -1748,13 +1664,14 @@ static void hdmiphy_conf_apply(struct hdmi_context *hdata) | |||
1748 | int i; | 1664 | int i; |
1749 | 1665 | ||
1750 | /* pixel clock */ | 1666 | /* pixel clock */ |
1751 | i = hdmi_find_phy_conf(hdata, hdata->mode_conf.pixel_clock); | 1667 | i = hdmi_find_phy_conf(hdata, hdata->current_mode.clock * 1000); |
1752 | if (i < 0) { | 1668 | if (i < 0) { |
1753 | DRM_ERROR("failed to find hdmiphy conf\n"); | 1669 | DRM_ERROR("failed to find hdmiphy conf\n"); |
1754 | return; | 1670 | return; |
1755 | } | 1671 | } |
1756 | 1672 | ||
1757 | ret = hdmiphy_reg_write_buf(hdata, 0, hdata->phy_confs[i].conf, 32); | 1673 | ret = hdmiphy_reg_write_buf(hdata, 0, |
1674 | hdata->drv_data->phy_confs[i].conf, 32); | ||
1758 | if (ret) { | 1675 | if (ret) { |
1759 | DRM_ERROR("failed to configure hdmiphy\n"); | 1676 | DRM_ERROR("failed to configure hdmiphy\n"); |
1760 | return; | 1677 | return; |
@@ -1776,10 +1693,8 @@ static void hdmi_conf_apply(struct hdmi_context *hdata) | |||
1776 | hdmiphy_conf_reset(hdata); | 1693 | hdmiphy_conf_reset(hdata); |
1777 | hdmiphy_conf_apply(hdata); | 1694 | hdmiphy_conf_apply(hdata); |
1778 | 1695 | ||
1779 | mutex_lock(&hdata->hdmi_mutex); | ||
1780 | hdmi_start(hdata, false); | 1696 | hdmi_start(hdata, false); |
1781 | hdmi_conf_init(hdata); | 1697 | hdmi_conf_init(hdata); |
1782 | mutex_unlock(&hdata->hdmi_mutex); | ||
1783 | 1698 | ||
1784 | hdmi_audio_init(hdata); | 1699 | hdmi_audio_init(hdata); |
1785 | 1700 | ||
@@ -1790,271 +1705,32 @@ static void hdmi_conf_apply(struct hdmi_context *hdata) | |||
1790 | hdmi_regs_dump(hdata, "start"); | 1705 | hdmi_regs_dump(hdata, "start"); |
1791 | } | 1706 | } |
1792 | 1707 | ||
1793 | static void hdmi_set_reg(u8 *reg_pair, int num_bytes, u32 value) | 1708 | static void hdmi_mode_set(struct drm_encoder *encoder, |
1794 | { | 1709 | struct drm_display_mode *mode, |
1795 | int i; | 1710 | struct drm_display_mode *adjusted_mode) |
1796 | BUG_ON(num_bytes > 4); | ||
1797 | for (i = 0; i < num_bytes; i++) | ||
1798 | reg_pair[i] = (value >> (8 * i)) & 0xff; | ||
1799 | } | ||
1800 | |||
1801 | static void hdmi_v13_mode_set(struct hdmi_context *hdata, | ||
1802 | struct drm_display_mode *m) | ||
1803 | { | 1711 | { |
1804 | struct hdmi_v13_core_regs *core = &hdata->mode_conf.conf.v13_conf.core; | 1712 | struct hdmi_context *hdata = encoder_to_hdmi(encoder); |
1805 | struct hdmi_tg_regs *tg = &hdata->mode_conf.conf.v13_conf.tg; | 1713 | struct drm_display_mode *m = adjusted_mode; |
1806 | unsigned int val; | ||
1807 | |||
1808 | hdata->mode_conf.cea_video_id = | ||
1809 | drm_match_cea_mode((struct drm_display_mode *)m); | ||
1810 | hdata->mode_conf.pixel_clock = m->clock * 1000; | ||
1811 | hdata->mode_conf.aspect_ratio = m->picture_aspect_ratio; | ||
1812 | |||
1813 | hdmi_set_reg(core->h_blank, 2, m->htotal - m->hdisplay); | ||
1814 | hdmi_set_reg(core->h_v_line, 3, (m->htotal << 12) | m->vtotal); | ||
1815 | |||
1816 | val = (m->flags & DRM_MODE_FLAG_NVSYNC) ? 1 : 0; | ||
1817 | hdmi_set_reg(core->vsync_pol, 1, val); | ||
1818 | |||
1819 | val = (m->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0; | ||
1820 | hdmi_set_reg(core->int_pro_mode, 1, val); | ||
1821 | |||
1822 | val = (m->hsync_start - m->hdisplay - 2); | ||
1823 | val |= ((m->hsync_end - m->hdisplay - 2) << 10); | ||
1824 | val |= ((m->flags & DRM_MODE_FLAG_NHSYNC) ? 1 : 0)<<20; | ||
1825 | hdmi_set_reg(core->h_sync_gen, 3, val); | ||
1826 | |||
1827 | /* | ||
1828 | * Quirk requirement for exynos HDMI IP design, | ||
1829 | * 2 pixels less than the actual calculation for hsync_start | ||
1830 | * and end. | ||
1831 | */ | ||
1832 | |||
1833 | /* Following values & calculations differ for different type of modes */ | ||
1834 | if (m->flags & DRM_MODE_FLAG_INTERLACE) { | ||
1835 | /* Interlaced Mode */ | ||
1836 | val = ((m->vsync_end - m->vdisplay) / 2); | ||
1837 | val |= ((m->vsync_start - m->vdisplay) / 2) << 12; | ||
1838 | hdmi_set_reg(core->v_sync_gen1, 3, val); | ||
1839 | |||
1840 | val = m->vtotal / 2; | ||
1841 | val |= ((m->vtotal - m->vdisplay) / 2) << 11; | ||
1842 | hdmi_set_reg(core->v_blank, 3, val); | ||
1843 | |||
1844 | val = (m->vtotal + | ||
1845 | ((m->vsync_end - m->vsync_start) * 4) + 5) / 2; | ||
1846 | val |= m->vtotal << 11; | ||
1847 | hdmi_set_reg(core->v_blank_f, 3, val); | ||
1848 | |||
1849 | val = ((m->vtotal / 2) + 7); | ||
1850 | val |= ((m->vtotal / 2) + 2) << 12; | ||
1851 | hdmi_set_reg(core->v_sync_gen2, 3, val); | ||
1852 | |||
1853 | val = ((m->htotal / 2) + (m->hsync_start - m->hdisplay)); | ||
1854 | val |= ((m->htotal / 2) + | ||
1855 | (m->hsync_start - m->hdisplay)) << 12; | ||
1856 | hdmi_set_reg(core->v_sync_gen3, 3, val); | ||
1857 | |||
1858 | hdmi_set_reg(tg->vact_st, 2, (m->vtotal - m->vdisplay) / 2); | ||
1859 | hdmi_set_reg(tg->vact_sz, 2, m->vdisplay / 2); | ||
1860 | |||
1861 | hdmi_set_reg(tg->vact_st2, 2, 0x249);/* Reset value + 1*/ | ||
1862 | } else { | ||
1863 | /* Progressive Mode */ | ||
1864 | |||
1865 | val = m->vtotal; | ||
1866 | val |= (m->vtotal - m->vdisplay) << 11; | ||
1867 | hdmi_set_reg(core->v_blank, 3, val); | ||
1868 | |||
1869 | hdmi_set_reg(core->v_blank_f, 3, 0); | ||
1870 | |||
1871 | val = (m->vsync_end - m->vdisplay); | ||
1872 | val |= ((m->vsync_start - m->vdisplay) << 12); | ||
1873 | hdmi_set_reg(core->v_sync_gen1, 3, val); | ||
1874 | |||
1875 | hdmi_set_reg(core->v_sync_gen2, 3, 0x1001);/* Reset value */ | ||
1876 | hdmi_set_reg(core->v_sync_gen3, 3, 0x1001);/* Reset value */ | ||
1877 | hdmi_set_reg(tg->vact_st, 2, m->vtotal - m->vdisplay); | ||
1878 | hdmi_set_reg(tg->vact_sz, 2, m->vdisplay); | ||
1879 | hdmi_set_reg(tg->vact_st2, 2, 0x248); /* Reset value */ | ||
1880 | } | ||
1881 | |||
1882 | /* Timing generator registers */ | ||
1883 | hdmi_set_reg(tg->cmd, 1, 0x0); | ||
1884 | hdmi_set_reg(tg->h_fsz, 2, m->htotal); | ||
1885 | hdmi_set_reg(tg->hact_st, 2, m->htotal - m->hdisplay); | ||
1886 | hdmi_set_reg(tg->hact_sz, 2, m->hdisplay); | ||
1887 | hdmi_set_reg(tg->v_fsz, 2, m->vtotal); | ||
1888 | hdmi_set_reg(tg->vsync, 2, 0x1); | ||
1889 | hdmi_set_reg(tg->vsync2, 2, 0x233); /* Reset value */ | ||
1890 | hdmi_set_reg(tg->field_chg, 2, 0x233); /* Reset value */ | ||
1891 | hdmi_set_reg(tg->vsync_top_hdmi, 2, 0x1); /* Reset value */ | ||
1892 | hdmi_set_reg(tg->vsync_bot_hdmi, 2, 0x233); /* Reset value */ | ||
1893 | hdmi_set_reg(tg->field_top_hdmi, 2, 0x1); /* Reset value */ | ||
1894 | hdmi_set_reg(tg->field_bot_hdmi, 2, 0x233); /* Reset value */ | ||
1895 | hdmi_set_reg(tg->tg_3d, 1, 0x0); /* Not used */ | ||
1896 | } | ||
1897 | |||
1898 | static void hdmi_v14_mode_set(struct hdmi_context *hdata, | ||
1899 | struct drm_display_mode *m) | ||
1900 | { | ||
1901 | struct hdmi_tg_regs *tg = &hdata->mode_conf.conf.v14_conf.tg; | ||
1902 | struct hdmi_v14_core_regs *core = | ||
1903 | &hdata->mode_conf.conf.v14_conf.core; | ||
1904 | |||
1905 | hdata->mode_conf.cea_video_id = | ||
1906 | drm_match_cea_mode((struct drm_display_mode *)m); | ||
1907 | hdata->mode_conf.pixel_clock = m->clock * 1000; | ||
1908 | hdata->mode_conf.aspect_ratio = m->picture_aspect_ratio; | ||
1909 | |||
1910 | hdmi_set_reg(core->h_blank, 2, m->htotal - m->hdisplay); | ||
1911 | hdmi_set_reg(core->v_line, 2, m->vtotal); | ||
1912 | hdmi_set_reg(core->h_line, 2, m->htotal); | ||
1913 | hdmi_set_reg(core->hsync_pol, 1, | ||
1914 | (m->flags & DRM_MODE_FLAG_NHSYNC) ? 1 : 0); | ||
1915 | hdmi_set_reg(core->vsync_pol, 1, | ||
1916 | (m->flags & DRM_MODE_FLAG_NVSYNC) ? 1 : 0); | ||
1917 | hdmi_set_reg(core->int_pro_mode, 1, | ||
1918 | (m->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0); | ||
1919 | |||
1920 | /* | ||
1921 | * Quirk requirement for exynos 5 HDMI IP design, | ||
1922 | * 2 pixels less than the actual calculation for hsync_start | ||
1923 | * and end. | ||
1924 | */ | ||
1925 | |||
1926 | /* Following values & calculations differ for different type of modes */ | ||
1927 | if (m->flags & DRM_MODE_FLAG_INTERLACE) { | ||
1928 | /* Interlaced Mode */ | ||
1929 | hdmi_set_reg(core->v_sync_line_bef_2, 2, | ||
1930 | (m->vsync_end - m->vdisplay) / 2); | ||
1931 | hdmi_set_reg(core->v_sync_line_bef_1, 2, | ||
1932 | (m->vsync_start - m->vdisplay) / 2); | ||
1933 | hdmi_set_reg(core->v2_blank, 2, m->vtotal / 2); | ||
1934 | hdmi_set_reg(core->v1_blank, 2, (m->vtotal - m->vdisplay) / 2); | ||
1935 | hdmi_set_reg(core->v_blank_f0, 2, m->vtotal - m->vdisplay / 2); | ||
1936 | hdmi_set_reg(core->v_blank_f1, 2, m->vtotal); | ||
1937 | hdmi_set_reg(core->v_sync_line_aft_2, 2, (m->vtotal / 2) + 7); | ||
1938 | hdmi_set_reg(core->v_sync_line_aft_1, 2, (m->vtotal / 2) + 2); | ||
1939 | hdmi_set_reg(core->v_sync_line_aft_pxl_2, 2, | ||
1940 | (m->htotal / 2) + (m->hsync_start - m->hdisplay)); | ||
1941 | hdmi_set_reg(core->v_sync_line_aft_pxl_1, 2, | ||
1942 | (m->htotal / 2) + (m->hsync_start - m->hdisplay)); | ||
1943 | hdmi_set_reg(tg->vact_st, 2, (m->vtotal - m->vdisplay) / 2); | ||
1944 | hdmi_set_reg(tg->vact_sz, 2, m->vdisplay / 2); | ||
1945 | hdmi_set_reg(tg->vact_st2, 2, m->vtotal - m->vdisplay / 2); | ||
1946 | hdmi_set_reg(tg->vsync2, 2, (m->vtotal / 2) + 1); | ||
1947 | hdmi_set_reg(tg->vsync_bot_hdmi, 2, (m->vtotal / 2) + 1); | ||
1948 | hdmi_set_reg(tg->field_bot_hdmi, 2, (m->vtotal / 2) + 1); | ||
1949 | hdmi_set_reg(tg->vact_st3, 2, 0x0); | ||
1950 | hdmi_set_reg(tg->vact_st4, 2, 0x0); | ||
1951 | } else { | ||
1952 | /* Progressive Mode */ | ||
1953 | hdmi_set_reg(core->v_sync_line_bef_2, 2, | ||
1954 | m->vsync_end - m->vdisplay); | ||
1955 | hdmi_set_reg(core->v_sync_line_bef_1, 2, | ||
1956 | m->vsync_start - m->vdisplay); | ||
1957 | hdmi_set_reg(core->v2_blank, 2, m->vtotal); | ||
1958 | hdmi_set_reg(core->v1_blank, 2, m->vtotal - m->vdisplay); | ||
1959 | hdmi_set_reg(core->v_blank_f0, 2, 0xffff); | ||
1960 | hdmi_set_reg(core->v_blank_f1, 2, 0xffff); | ||
1961 | hdmi_set_reg(core->v_sync_line_aft_2, 2, 0xffff); | ||
1962 | hdmi_set_reg(core->v_sync_line_aft_1, 2, 0xffff); | ||
1963 | hdmi_set_reg(core->v_sync_line_aft_pxl_2, 2, 0xffff); | ||
1964 | hdmi_set_reg(core->v_sync_line_aft_pxl_1, 2, 0xffff); | ||
1965 | hdmi_set_reg(tg->vact_st, 2, m->vtotal - m->vdisplay); | ||
1966 | hdmi_set_reg(tg->vact_sz, 2, m->vdisplay); | ||
1967 | hdmi_set_reg(tg->vact_st2, 2, 0x248); /* Reset value */ | ||
1968 | hdmi_set_reg(tg->vact_st3, 2, 0x47b); /* Reset value */ | ||
1969 | hdmi_set_reg(tg->vact_st4, 2, 0x6ae); /* Reset value */ | ||
1970 | hdmi_set_reg(tg->vsync2, 2, 0x233); /* Reset value */ | ||
1971 | hdmi_set_reg(tg->vsync_bot_hdmi, 2, 0x233); /* Reset value */ | ||
1972 | hdmi_set_reg(tg->field_bot_hdmi, 2, 0x233); /* Reset value */ | ||
1973 | } | ||
1974 | |||
1975 | /* Following values & calculations are same irrespective of mode type */ | ||
1976 | hdmi_set_reg(core->h_sync_start, 2, m->hsync_start - m->hdisplay - 2); | ||
1977 | hdmi_set_reg(core->h_sync_end, 2, m->hsync_end - m->hdisplay - 2); | ||
1978 | hdmi_set_reg(core->vact_space_1, 2, 0xffff); | ||
1979 | hdmi_set_reg(core->vact_space_2, 2, 0xffff); | ||
1980 | hdmi_set_reg(core->vact_space_3, 2, 0xffff); | ||
1981 | hdmi_set_reg(core->vact_space_4, 2, 0xffff); | ||
1982 | hdmi_set_reg(core->vact_space_5, 2, 0xffff); | ||
1983 | hdmi_set_reg(core->vact_space_6, 2, 0xffff); | ||
1984 | hdmi_set_reg(core->v_blank_f2, 2, 0xffff); | ||
1985 | hdmi_set_reg(core->v_blank_f3, 2, 0xffff); | ||
1986 | hdmi_set_reg(core->v_blank_f4, 2, 0xffff); | ||
1987 | hdmi_set_reg(core->v_blank_f5, 2, 0xffff); | ||
1988 | hdmi_set_reg(core->v_sync_line_aft_3, 2, 0xffff); | ||
1989 | hdmi_set_reg(core->v_sync_line_aft_4, 2, 0xffff); | ||
1990 | hdmi_set_reg(core->v_sync_line_aft_5, 2, 0xffff); | ||
1991 | hdmi_set_reg(core->v_sync_line_aft_6, 2, 0xffff); | ||
1992 | hdmi_set_reg(core->v_sync_line_aft_pxl_3, 2, 0xffff); | ||
1993 | hdmi_set_reg(core->v_sync_line_aft_pxl_4, 2, 0xffff); | ||
1994 | hdmi_set_reg(core->v_sync_line_aft_pxl_5, 2, 0xffff); | ||
1995 | hdmi_set_reg(core->v_sync_line_aft_pxl_6, 2, 0xffff); | ||
1996 | |||
1997 | /* Timing generator registers */ | ||
1998 | hdmi_set_reg(tg->cmd, 1, 0x0); | ||
1999 | hdmi_set_reg(tg->h_fsz, 2, m->htotal); | ||
2000 | hdmi_set_reg(tg->hact_st, 2, m->htotal - m->hdisplay); | ||
2001 | hdmi_set_reg(tg->hact_sz, 2, m->hdisplay); | ||
2002 | hdmi_set_reg(tg->v_fsz, 2, m->vtotal); | ||
2003 | hdmi_set_reg(tg->vsync, 2, 0x1); | ||
2004 | hdmi_set_reg(tg->field_chg, 2, 0x233); /* Reset value */ | ||
2005 | hdmi_set_reg(tg->vsync_top_hdmi, 2, 0x1); /* Reset value */ | ||
2006 | hdmi_set_reg(tg->field_top_hdmi, 2, 0x1); /* Reset value */ | ||
2007 | hdmi_set_reg(tg->tg_3d, 1, 0x0); | ||
2008 | } | ||
2009 | |||
2010 | static void hdmi_mode_set(struct exynos_drm_display *display, | ||
2011 | struct drm_display_mode *mode) | ||
2012 | { | ||
2013 | struct hdmi_context *hdata = display_to_hdmi(display); | ||
2014 | struct drm_display_mode *m = mode; | ||
2015 | 1714 | ||
2016 | DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%s\n", | 1715 | DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%s\n", |
2017 | m->hdisplay, m->vdisplay, | 1716 | m->hdisplay, m->vdisplay, |
2018 | m->vrefresh, (m->flags & DRM_MODE_FLAG_INTERLACE) ? | 1717 | m->vrefresh, (m->flags & DRM_MODE_FLAG_INTERLACE) ? |
2019 | "INTERLACED" : "PROGRESSIVE"); | 1718 | "INTERLACED" : "PROGRESSIVE"); |
2020 | 1719 | ||
2021 | /* preserve mode information for later use. */ | 1720 | drm_mode_copy(&hdata->current_mode, m); |
2022 | drm_mode_copy(&hdata->current_mode, mode); | 1721 | hdata->cea_video_id = drm_match_cea_mode(mode); |
2023 | |||
2024 | if (hdata->type == HDMI_TYPE13) | ||
2025 | hdmi_v13_mode_set(hdata, mode); | ||
2026 | else | ||
2027 | hdmi_v14_mode_set(hdata, mode); | ||
2028 | } | ||
2029 | |||
2030 | static void hdmi_commit(struct exynos_drm_display *display) | ||
2031 | { | ||
2032 | struct hdmi_context *hdata = display_to_hdmi(display); | ||
2033 | |||
2034 | mutex_lock(&hdata->hdmi_mutex); | ||
2035 | if (!hdata->powered) { | ||
2036 | mutex_unlock(&hdata->hdmi_mutex); | ||
2037 | return; | ||
2038 | } | ||
2039 | mutex_unlock(&hdata->hdmi_mutex); | ||
2040 | |||
2041 | hdmi_conf_apply(hdata); | ||
2042 | } | 1722 | } |
2043 | 1723 | ||
2044 | static void hdmi_poweron(struct hdmi_context *hdata) | 1724 | static void hdmi_enable(struct drm_encoder *encoder) |
2045 | { | 1725 | { |
1726 | struct hdmi_context *hdata = encoder_to_hdmi(encoder); | ||
2046 | struct hdmi_resources *res = &hdata->res; | 1727 | struct hdmi_resources *res = &hdata->res; |
2047 | 1728 | ||
2048 | mutex_lock(&hdata->hdmi_mutex); | 1729 | if (hdata->powered) |
2049 | if (hdata->powered) { | ||
2050 | mutex_unlock(&hdata->hdmi_mutex); | ||
2051 | return; | 1730 | return; |
2052 | } | ||
2053 | 1731 | ||
2054 | hdata->powered = true; | 1732 | hdata->powered = true; |
2055 | 1733 | ||
2056 | mutex_unlock(&hdata->hdmi_mutex); | ||
2057 | |||
2058 | pm_runtime_get_sync(hdata->dev); | 1734 | pm_runtime_get_sync(hdata->dev); |
2059 | 1735 | ||
2060 | if (regulator_bulk_enable(res->regul_count, res->regul_bulk)) | 1736 | if (regulator_bulk_enable(res->regul_count, res->regul_bulk)) |
@@ -2068,17 +1744,32 @@ static void hdmi_poweron(struct hdmi_context *hdata) | |||
2068 | clk_prepare_enable(res->sclk_hdmi); | 1744 | clk_prepare_enable(res->sclk_hdmi); |
2069 | 1745 | ||
2070 | hdmiphy_poweron(hdata); | 1746 | hdmiphy_poweron(hdata); |
2071 | hdmi_commit(&hdata->display); | 1747 | hdmi_conf_apply(hdata); |
2072 | } | 1748 | } |
2073 | 1749 | ||
2074 | static void hdmi_poweroff(struct hdmi_context *hdata) | 1750 | static void hdmi_disable(struct drm_encoder *encoder) |
2075 | { | 1751 | { |
1752 | struct hdmi_context *hdata = encoder_to_hdmi(encoder); | ||
2076 | struct hdmi_resources *res = &hdata->res; | 1753 | struct hdmi_resources *res = &hdata->res; |
1754 | struct drm_crtc *crtc = encoder->crtc; | ||
1755 | const struct drm_crtc_helper_funcs *funcs = NULL; | ||
2077 | 1756 | ||
2078 | mutex_lock(&hdata->hdmi_mutex); | ||
2079 | if (!hdata->powered) | 1757 | if (!hdata->powered) |
2080 | goto out; | 1758 | return; |
2081 | mutex_unlock(&hdata->hdmi_mutex); | 1759 | |
1760 | /* | ||
1761 | * The SFRs of VP and Mixer are updated by Vertical Sync of | ||
1762 | * Timing generator which is a part of HDMI so the sequence | ||
1763 | * to disable TV Subsystem should be as following, | ||
1764 | * VP -> Mixer -> HDMI | ||
1765 | * | ||
1766 | * Below codes will try to disable Mixer and VP(if used) | ||
1767 | * prior to disabling HDMI. | ||
1768 | */ | ||
1769 | if (crtc) | ||
1770 | funcs = crtc->helper_private; | ||
1771 | if (funcs && funcs->disable) | ||
1772 | (*funcs->disable)(crtc); | ||
2082 | 1773 | ||
2083 | /* HDMI System Disable */ | 1774 | /* HDMI System Disable */ |
2084 | hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_EN); | 1775 | hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_EN); |
@@ -2098,57 +1789,18 @@ static void hdmi_poweroff(struct hdmi_context *hdata) | |||
2098 | 1789 | ||
2099 | pm_runtime_put_sync(hdata->dev); | 1790 | pm_runtime_put_sync(hdata->dev); |
2100 | 1791 | ||
2101 | mutex_lock(&hdata->hdmi_mutex); | ||
2102 | hdata->powered = false; | 1792 | hdata->powered = false; |
2103 | |||
2104 | out: | ||
2105 | mutex_unlock(&hdata->hdmi_mutex); | ||
2106 | } | ||
2107 | |||
2108 | static void hdmi_dpms(struct exynos_drm_display *display, int mode) | ||
2109 | { | ||
2110 | struct hdmi_context *hdata = display_to_hdmi(display); | ||
2111 | struct drm_encoder *encoder = hdata->encoder; | ||
2112 | struct drm_crtc *crtc = encoder->crtc; | ||
2113 | const struct drm_crtc_helper_funcs *funcs = NULL; | ||
2114 | |||
2115 | DRM_DEBUG_KMS("mode %d\n", mode); | ||
2116 | |||
2117 | switch (mode) { | ||
2118 | case DRM_MODE_DPMS_ON: | ||
2119 | hdmi_poweron(hdata); | ||
2120 | break; | ||
2121 | case DRM_MODE_DPMS_STANDBY: | ||
2122 | case DRM_MODE_DPMS_SUSPEND: | ||
2123 | case DRM_MODE_DPMS_OFF: | ||
2124 | /* | ||
2125 | * The SFRs of VP and Mixer are updated by Vertical Sync of | ||
2126 | * Timing generator which is a part of HDMI so the sequence | ||
2127 | * to disable TV Subsystem should be as following, | ||
2128 | * VP -> Mixer -> HDMI | ||
2129 | * | ||
2130 | * Below codes will try to disable Mixer and VP(if used) | ||
2131 | * prior to disabling HDMI. | ||
2132 | */ | ||
2133 | if (crtc) | ||
2134 | funcs = crtc->helper_private; | ||
2135 | if (funcs && funcs->disable) | ||
2136 | (*funcs->disable)(crtc); | ||
2137 | |||
2138 | hdmi_poweroff(hdata); | ||
2139 | break; | ||
2140 | default: | ||
2141 | DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode); | ||
2142 | break; | ||
2143 | } | ||
2144 | } | 1793 | } |
2145 | 1794 | ||
2146 | static struct exynos_drm_display_ops hdmi_display_ops = { | 1795 | static struct drm_encoder_helper_funcs exynos_hdmi_encoder_helper_funcs = { |
2147 | .create_connector = hdmi_create_connector, | ||
2148 | .mode_fixup = hdmi_mode_fixup, | 1796 | .mode_fixup = hdmi_mode_fixup, |
2149 | .mode_set = hdmi_mode_set, | 1797 | .mode_set = hdmi_mode_set, |
2150 | .dpms = hdmi_dpms, | 1798 | .enable = hdmi_enable, |
2151 | .commit = hdmi_commit, | 1799 | .disable = hdmi_disable, |
1800 | }; | ||
1801 | |||
1802 | static struct drm_encoder_funcs exynos_hdmi_encoder_funcs = { | ||
1803 | .destroy = drm_encoder_cleanup, | ||
2152 | }; | 1804 | }; |
2153 | 1805 | ||
2154 | static void hdmi_hotplug_work_func(struct work_struct *work) | 1806 | static void hdmi_hotplug_work_func(struct work_struct *work) |
@@ -2157,10 +1809,6 @@ static void hdmi_hotplug_work_func(struct work_struct *work) | |||
2157 | 1809 | ||
2158 | hdata = container_of(work, struct hdmi_context, hotplug_work.work); | 1810 | hdata = container_of(work, struct hdmi_context, hotplug_work.work); |
2159 | 1811 | ||
2160 | mutex_lock(&hdata->hdmi_mutex); | ||
2161 | hdata->hpd = gpio_get_value(hdata->hpd_gpio); | ||
2162 | mutex_unlock(&hdata->hdmi_mutex); | ||
2163 | |||
2164 | if (hdata->drm_dev) | 1812 | if (hdata->drm_dev) |
2165 | drm_helper_hpd_irq_event(hdata->drm_dev); | 1813 | drm_helper_hpd_irq_event(hdata->drm_dev); |
2166 | } | 1814 | } |
@@ -2259,30 +1907,6 @@ fail: | |||
2259 | return ret; | 1907 | return ret; |
2260 | } | 1908 | } |
2261 | 1909 | ||
2262 | static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata | ||
2263 | (struct device *dev) | ||
2264 | { | ||
2265 | struct device_node *np = dev->of_node; | ||
2266 | struct s5p_hdmi_platform_data *pd; | ||
2267 | u32 value; | ||
2268 | |||
2269 | pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); | ||
2270 | if (!pd) | ||
2271 | goto err_data; | ||
2272 | |||
2273 | if (!of_find_property(np, "hpd-gpio", &value)) { | ||
2274 | DRM_ERROR("no hpd gpio property found\n"); | ||
2275 | goto err_data; | ||
2276 | } | ||
2277 | |||
2278 | pd->hpd_gpio = of_get_named_gpio(np, "hpd-gpio", 0); | ||
2279 | |||
2280 | return pd; | ||
2281 | |||
2282 | err_data: | ||
2283 | return NULL; | ||
2284 | } | ||
2285 | |||
2286 | static struct of_device_id hdmi_match_types[] = { | 1910 | static struct of_device_id hdmi_match_types[] = { |
2287 | { | 1911 | { |
2288 | .compatible = "samsung,exynos5-hdmi", | 1912 | .compatible = "samsung,exynos5-hdmi", |
@@ -2306,10 +1930,33 @@ static int hdmi_bind(struct device *dev, struct device *master, void *data) | |||
2306 | { | 1930 | { |
2307 | struct drm_device *drm_dev = data; | 1931 | struct drm_device *drm_dev = data; |
2308 | struct hdmi_context *hdata = dev_get_drvdata(dev); | 1932 | struct hdmi_context *hdata = dev_get_drvdata(dev); |
1933 | struct drm_encoder *encoder = &hdata->encoder; | ||
1934 | int ret, pipe; | ||
2309 | 1935 | ||
2310 | hdata->drm_dev = drm_dev; | 1936 | hdata->drm_dev = drm_dev; |
2311 | 1937 | ||
2312 | return exynos_drm_create_enc_conn(drm_dev, &hdata->display); | 1938 | pipe = exynos_drm_crtc_get_pipe_from_type(drm_dev, |
1939 | EXYNOS_DISPLAY_TYPE_HDMI); | ||
1940 | if (pipe < 0) | ||
1941 | return pipe; | ||
1942 | |||
1943 | encoder->possible_crtcs = 1 << pipe; | ||
1944 | |||
1945 | DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs); | ||
1946 | |||
1947 | drm_encoder_init(drm_dev, encoder, &exynos_hdmi_encoder_funcs, | ||
1948 | DRM_MODE_ENCODER_TMDS); | ||
1949 | |||
1950 | drm_encoder_helper_add(encoder, &exynos_hdmi_encoder_helper_funcs); | ||
1951 | |||
1952 | ret = hdmi_create_connector(encoder); | ||
1953 | if (ret) { | ||
1954 | DRM_ERROR("failed to create connector ret = %d\n", ret); | ||
1955 | drm_encoder_cleanup(encoder); | ||
1956 | return ret; | ||
1957 | } | ||
1958 | |||
1959 | return 0; | ||
2313 | } | 1960 | } |
2314 | 1961 | ||
2315 | static void hdmi_unbind(struct device *dev, struct device *master, void *data) | 1962 | static void hdmi_unbind(struct device *dev, struct device *master, void *data) |
@@ -2343,43 +1990,30 @@ static struct device_node *hdmi_legacy_phy_dt_binding(struct device *dev) | |||
2343 | static int hdmi_probe(struct platform_device *pdev) | 1990 | static int hdmi_probe(struct platform_device *pdev) |
2344 | { | 1991 | { |
2345 | struct device_node *ddc_node, *phy_node; | 1992 | struct device_node *ddc_node, *phy_node; |
2346 | struct s5p_hdmi_platform_data *pdata; | ||
2347 | struct hdmi_driver_data *drv_data; | ||
2348 | const struct of_device_id *match; | 1993 | const struct of_device_id *match; |
2349 | struct device *dev = &pdev->dev; | 1994 | struct device *dev = &pdev->dev; |
2350 | struct hdmi_context *hdata; | 1995 | struct hdmi_context *hdata; |
2351 | struct resource *res; | 1996 | struct resource *res; |
2352 | int ret; | 1997 | int ret; |
2353 | 1998 | ||
2354 | if (!dev->of_node) | ||
2355 | return -ENODEV; | ||
2356 | |||
2357 | pdata = drm_hdmi_dt_parse_pdata(dev); | ||
2358 | if (!pdata) | ||
2359 | return -EINVAL; | ||
2360 | |||
2361 | hdata = devm_kzalloc(dev, sizeof(struct hdmi_context), GFP_KERNEL); | 1999 | hdata = devm_kzalloc(dev, sizeof(struct hdmi_context), GFP_KERNEL); |
2362 | if (!hdata) | 2000 | if (!hdata) |
2363 | return -ENOMEM; | 2001 | return -ENOMEM; |
2364 | 2002 | ||
2365 | hdata->display.type = EXYNOS_DISPLAY_TYPE_HDMI; | 2003 | match = of_match_device(hdmi_match_types, dev); |
2366 | hdata->display.ops = &hdmi_display_ops; | ||
2367 | |||
2368 | mutex_init(&hdata->hdmi_mutex); | ||
2369 | |||
2370 | platform_set_drvdata(pdev, hdata); | ||
2371 | |||
2372 | match = of_match_node(hdmi_match_types, dev->of_node); | ||
2373 | if (!match) | 2004 | if (!match) |
2374 | return -ENODEV; | 2005 | return -ENODEV; |
2375 | 2006 | ||
2376 | drv_data = (struct hdmi_driver_data *)match->data; | 2007 | hdata->drv_data = match->data; |
2377 | hdata->type = drv_data->type; | 2008 | |
2378 | hdata->phy_confs = drv_data->phy_confs; | 2009 | platform_set_drvdata(pdev, hdata); |
2379 | hdata->phy_conf_count = drv_data->phy_conf_count; | ||
2380 | 2010 | ||
2381 | hdata->hpd_gpio = pdata->hpd_gpio; | ||
2382 | hdata->dev = dev; | 2011 | hdata->dev = dev; |
2012 | hdata->hpd_gpio = of_get_named_gpio(dev->of_node, "hpd-gpio", 0); | ||
2013 | if (hdata->hpd_gpio < 0) { | ||
2014 | DRM_ERROR("cannot get hpd gpio property\n"); | ||
2015 | return hdata->hpd_gpio; | ||
2016 | } | ||
2383 | 2017 | ||
2384 | ret = hdmi_resources_init(hdata); | 2018 | ret = hdmi_resources_init(hdata); |
2385 | if (ret) { | 2019 | if (ret) { |
@@ -2431,7 +2065,7 @@ out_get_ddc_adpt: | |||
2431 | } | 2065 | } |
2432 | 2066 | ||
2433 | out_get_phy_port: | 2067 | out_get_phy_port: |
2434 | if (drv_data->is_apb_phy) { | 2068 | if (hdata->drv_data->is_apb_phy) { |
2435 | hdata->regs_hdmiphy = of_iomap(phy_node, 0); | 2069 | hdata->regs_hdmiphy = of_iomap(phy_node, 0); |
2436 | if (!hdata->regs_hdmiphy) { | 2070 | if (!hdata->regs_hdmiphy) { |
2437 | DRM_ERROR("failed to ioremap hdmi phy\n"); | 2071 | DRM_ERROR("failed to ioremap hdmi phy\n"); |
@@ -2454,8 +2088,6 @@ out_get_phy_port: | |||
2454 | goto err_hdmiphy; | 2088 | goto err_hdmiphy; |
2455 | } | 2089 | } |
2456 | 2090 | ||
2457 | hdata->hpd = gpio_get_value(hdata->hpd_gpio); | ||
2458 | |||
2459 | INIT_DELAYED_WORK(&hdata->hotplug_work, hdmi_hotplug_work_func); | 2091 | INIT_DELAYED_WORK(&hdata->hotplug_work, hdmi_hotplug_work_func); |
2460 | 2092 | ||
2461 | ret = devm_request_threaded_irq(dev, hdata->irq, NULL, | 2093 | ret = devm_request_threaded_irq(dev, hdata->irq, NULL, |
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 4706b56902b4..e68340c77676 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c | |||
@@ -69,6 +69,11 @@ enum mixer_version_id { | |||
69 | MXR_VER_128_0_0_184, | 69 | MXR_VER_128_0_0_184, |
70 | }; | 70 | }; |
71 | 71 | ||
72 | enum mixer_flag_bits { | ||
73 | MXR_BIT_POWERED, | ||
74 | MXR_BIT_VSYNC, | ||
75 | }; | ||
76 | |||
72 | struct mixer_context { | 77 | struct mixer_context { |
73 | struct platform_device *pdev; | 78 | struct platform_device *pdev; |
74 | struct device *dev; | 79 | struct device *dev; |
@@ -76,13 +81,11 @@ struct mixer_context { | |||
76 | struct exynos_drm_crtc *crtc; | 81 | struct exynos_drm_crtc *crtc; |
77 | struct exynos_drm_plane planes[MIXER_WIN_NR]; | 82 | struct exynos_drm_plane planes[MIXER_WIN_NR]; |
78 | int pipe; | 83 | int pipe; |
84 | unsigned long flags; | ||
79 | bool interlace; | 85 | bool interlace; |
80 | bool powered; | ||
81 | bool vp_enabled; | 86 | bool vp_enabled; |
82 | bool has_sclk; | 87 | bool has_sclk; |
83 | u32 int_en; | ||
84 | 88 | ||
85 | struct mutex mixer_mutex; | ||
86 | struct mixer_resources mixer_res; | 89 | struct mixer_resources mixer_res; |
87 | enum mixer_version_id mxr_ver; | 90 | enum mixer_version_id mxr_ver; |
88 | wait_queue_head_t wait_vsync_queue; | 91 | wait_queue_head_t wait_vsync_queue; |
@@ -380,19 +383,20 @@ static void mixer_stop(struct mixer_context *ctx) | |||
380 | usleep_range(10000, 12000); | 383 | usleep_range(10000, 12000); |
381 | } | 384 | } |
382 | 385 | ||
383 | static void vp_video_buffer(struct mixer_context *ctx, unsigned int win) | 386 | static void vp_video_buffer(struct mixer_context *ctx, |
387 | struct exynos_drm_plane *plane) | ||
384 | { | 388 | { |
385 | struct mixer_resources *res = &ctx->mixer_res; | 389 | struct mixer_resources *res = &ctx->mixer_res; |
390 | struct drm_plane_state *state = plane->base.state; | ||
391 | struct drm_framebuffer *fb = state->fb; | ||
392 | struct drm_display_mode *mode = &state->crtc->mode; | ||
386 | unsigned long flags; | 393 | unsigned long flags; |
387 | struct exynos_drm_plane *plane; | ||
388 | dma_addr_t luma_addr[2], chroma_addr[2]; | 394 | dma_addr_t luma_addr[2], chroma_addr[2]; |
389 | bool tiled_mode = false; | 395 | bool tiled_mode = false; |
390 | bool crcb_mode = false; | 396 | bool crcb_mode = false; |
391 | u32 val; | 397 | u32 val; |
392 | 398 | ||
393 | plane = &ctx->planes[win]; | 399 | switch (fb->pixel_format) { |
394 | |||
395 | switch (plane->pixel_format) { | ||
396 | case DRM_FORMAT_NV12: | 400 | case DRM_FORMAT_NV12: |
397 | crcb_mode = false; | 401 | crcb_mode = false; |
398 | break; | 402 | break; |
@@ -401,21 +405,21 @@ static void vp_video_buffer(struct mixer_context *ctx, unsigned int win) | |||
401 | break; | 405 | break; |
402 | default: | 406 | default: |
403 | DRM_ERROR("pixel format for vp is wrong [%d].\n", | 407 | DRM_ERROR("pixel format for vp is wrong [%d].\n", |
404 | plane->pixel_format); | 408 | fb->pixel_format); |
405 | return; | 409 | return; |
406 | } | 410 | } |
407 | 411 | ||
408 | luma_addr[0] = plane->dma_addr[0]; | 412 | luma_addr[0] = plane->dma_addr[0]; |
409 | chroma_addr[0] = plane->dma_addr[1]; | 413 | chroma_addr[0] = plane->dma_addr[1]; |
410 | 414 | ||
411 | if (plane->scan_flag & DRM_MODE_FLAG_INTERLACE) { | 415 | if (mode->flags & DRM_MODE_FLAG_INTERLACE) { |
412 | ctx->interlace = true; | 416 | ctx->interlace = true; |
413 | if (tiled_mode) { | 417 | if (tiled_mode) { |
414 | luma_addr[1] = luma_addr[0] + 0x40; | 418 | luma_addr[1] = luma_addr[0] + 0x40; |
415 | chroma_addr[1] = chroma_addr[0] + 0x40; | 419 | chroma_addr[1] = chroma_addr[0] + 0x40; |
416 | } else { | 420 | } else { |
417 | luma_addr[1] = luma_addr[0] + plane->pitch; | 421 | luma_addr[1] = luma_addr[0] + fb->pitches[0]; |
418 | chroma_addr[1] = chroma_addr[0] + plane->pitch; | 422 | chroma_addr[1] = chroma_addr[0] + fb->pitches[0]; |
419 | } | 423 | } |
420 | } else { | 424 | } else { |
421 | ctx->interlace = false; | 425 | ctx->interlace = false; |
@@ -436,25 +440,25 @@ static void vp_video_buffer(struct mixer_context *ctx, unsigned int win) | |||
436 | vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK); | 440 | vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK); |
437 | 441 | ||
438 | /* setting size of input image */ | 442 | /* setting size of input image */ |
439 | vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(plane->pitch) | | 443 | vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(fb->pitches[0]) | |
440 | VP_IMG_VSIZE(plane->fb_height)); | 444 | VP_IMG_VSIZE(fb->height)); |
441 | /* chroma height has to reduced by 2 to avoid chroma distorions */ | 445 | /* chroma height has to reduced by 2 to avoid chroma distorions */ |
442 | vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(plane->pitch) | | 446 | vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(fb->pitches[0]) | |
443 | VP_IMG_VSIZE(plane->fb_height / 2)); | 447 | VP_IMG_VSIZE(fb->height / 2)); |
444 | 448 | ||
445 | vp_reg_write(res, VP_SRC_WIDTH, plane->src_width); | 449 | vp_reg_write(res, VP_SRC_WIDTH, plane->src_w); |
446 | vp_reg_write(res, VP_SRC_HEIGHT, plane->src_height); | 450 | vp_reg_write(res, VP_SRC_HEIGHT, plane->src_h); |
447 | vp_reg_write(res, VP_SRC_H_POSITION, | 451 | vp_reg_write(res, VP_SRC_H_POSITION, |
448 | VP_SRC_H_POSITION_VAL(plane->src_x)); | 452 | VP_SRC_H_POSITION_VAL(plane->src_x)); |
449 | vp_reg_write(res, VP_SRC_V_POSITION, plane->src_y); | 453 | vp_reg_write(res, VP_SRC_V_POSITION, plane->src_y); |
450 | 454 | ||
451 | vp_reg_write(res, VP_DST_WIDTH, plane->crtc_width); | 455 | vp_reg_write(res, VP_DST_WIDTH, plane->crtc_w); |
452 | vp_reg_write(res, VP_DST_H_POSITION, plane->crtc_x); | 456 | vp_reg_write(res, VP_DST_H_POSITION, plane->crtc_x); |
453 | if (ctx->interlace) { | 457 | if (ctx->interlace) { |
454 | vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_height / 2); | 458 | vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_h / 2); |
455 | vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y / 2); | 459 | vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y / 2); |
456 | } else { | 460 | } else { |
457 | vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_height); | 461 | vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_h); |
458 | vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y); | 462 | vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y); |
459 | } | 463 | } |
460 | 464 | ||
@@ -469,9 +473,9 @@ static void vp_video_buffer(struct mixer_context *ctx, unsigned int win) | |||
469 | vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]); | 473 | vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]); |
470 | vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]); | 474 | vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]); |
471 | 475 | ||
472 | mixer_cfg_scan(ctx, plane->mode_height); | 476 | mixer_cfg_scan(ctx, mode->vdisplay); |
473 | mixer_cfg_rgb_fmt(ctx, plane->mode_height); | 477 | mixer_cfg_rgb_fmt(ctx, mode->vdisplay); |
474 | mixer_cfg_layer(ctx, win, true); | 478 | mixer_cfg_layer(ctx, plane->zpos, true); |
475 | mixer_run(ctx); | 479 | mixer_run(ctx); |
476 | 480 | ||
477 | mixer_vsync_set_update(ctx, true); | 481 | mixer_vsync_set_update(ctx, true); |
@@ -491,15 +495,15 @@ static void mixer_layer_update(struct mixer_context *ctx) | |||
491 | static int mixer_setup_scale(const struct exynos_drm_plane *plane, | 495 | static int mixer_setup_scale(const struct exynos_drm_plane *plane, |
492 | unsigned int *x_ratio, unsigned int *y_ratio) | 496 | unsigned int *x_ratio, unsigned int *y_ratio) |
493 | { | 497 | { |
494 | if (plane->crtc_width != plane->src_width) { | 498 | if (plane->crtc_w != plane->src_w) { |
495 | if (plane->crtc_width == 2 * plane->src_width) | 499 | if (plane->crtc_w == 2 * plane->src_w) |
496 | *x_ratio = 1; | 500 | *x_ratio = 1; |
497 | else | 501 | else |
498 | goto fail; | 502 | goto fail; |
499 | } | 503 | } |
500 | 504 | ||
501 | if (plane->crtc_height != plane->src_height) { | 505 | if (plane->crtc_h != plane->src_h) { |
502 | if (plane->crtc_height == 2 * plane->src_height) | 506 | if (plane->crtc_h == 2 * plane->src_h) |
503 | *y_ratio = 1; | 507 | *y_ratio = 1; |
504 | else | 508 | else |
505 | goto fail; | 509 | goto fail; |
@@ -512,20 +516,22 @@ fail: | |||
512 | return -ENOTSUPP; | 516 | return -ENOTSUPP; |
513 | } | 517 | } |
514 | 518 | ||
515 | static void mixer_graph_buffer(struct mixer_context *ctx, unsigned int win) | 519 | static void mixer_graph_buffer(struct mixer_context *ctx, |
520 | struct exynos_drm_plane *plane) | ||
516 | { | 521 | { |
517 | struct mixer_resources *res = &ctx->mixer_res; | 522 | struct mixer_resources *res = &ctx->mixer_res; |
523 | struct drm_plane_state *state = plane->base.state; | ||
524 | struct drm_framebuffer *fb = state->fb; | ||
525 | struct drm_display_mode *mode = &state->crtc->mode; | ||
518 | unsigned long flags; | 526 | unsigned long flags; |
519 | struct exynos_drm_plane *plane; | 527 | unsigned int win = plane->zpos; |
520 | unsigned int x_ratio = 0, y_ratio = 0; | 528 | unsigned int x_ratio = 0, y_ratio = 0; |
521 | unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset; | 529 | unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset; |
522 | dma_addr_t dma_addr; | 530 | dma_addr_t dma_addr; |
523 | unsigned int fmt; | 531 | unsigned int fmt; |
524 | u32 val; | 532 | u32 val; |
525 | 533 | ||
526 | plane = &ctx->planes[win]; | 534 | switch (fb->pixel_format) { |
527 | |||
528 | switch (plane->pixel_format) { | ||
529 | case DRM_FORMAT_XRGB4444: | 535 | case DRM_FORMAT_XRGB4444: |
530 | fmt = MXR_FORMAT_ARGB4444; | 536 | fmt = MXR_FORMAT_ARGB4444; |
531 | break; | 537 | break; |
@@ -557,12 +563,12 @@ static void mixer_graph_buffer(struct mixer_context *ctx, unsigned int win) | |||
557 | 563 | ||
558 | /* converting dma address base and source offset */ | 564 | /* converting dma address base and source offset */ |
559 | dma_addr = plane->dma_addr[0] | 565 | dma_addr = plane->dma_addr[0] |
560 | + (plane->src_x * plane->bpp >> 3) | 566 | + (plane->src_x * fb->bits_per_pixel >> 3) |
561 | + (plane->src_y * plane->pitch); | 567 | + (plane->src_y * fb->pitches[0]); |
562 | src_x_offset = 0; | 568 | src_x_offset = 0; |
563 | src_y_offset = 0; | 569 | src_y_offset = 0; |
564 | 570 | ||
565 | if (plane->scan_flag & DRM_MODE_FLAG_INTERLACE) | 571 | if (mode->flags & DRM_MODE_FLAG_INTERLACE) |
566 | ctx->interlace = true; | 572 | ctx->interlace = true; |
567 | else | 573 | else |
568 | ctx->interlace = false; | 574 | ctx->interlace = false; |
@@ -576,18 +582,18 @@ static void mixer_graph_buffer(struct mixer_context *ctx, unsigned int win) | |||
576 | 582 | ||
577 | /* setup geometry */ | 583 | /* setup geometry */ |
578 | mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), | 584 | mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), |
579 | plane->pitch / (plane->bpp >> 3)); | 585 | fb->pitches[0] / (fb->bits_per_pixel >> 3)); |
580 | 586 | ||
581 | /* setup display size */ | 587 | /* setup display size */ |
582 | if (ctx->mxr_ver == MXR_VER_128_0_0_184 && | 588 | if (ctx->mxr_ver == MXR_VER_128_0_0_184 && |
583 | win == MIXER_DEFAULT_WIN) { | 589 | win == MIXER_DEFAULT_WIN) { |
584 | val = MXR_MXR_RES_HEIGHT(plane->mode_height); | 590 | val = MXR_MXR_RES_HEIGHT(mode->vdisplay); |
585 | val |= MXR_MXR_RES_WIDTH(plane->mode_width); | 591 | val |= MXR_MXR_RES_WIDTH(mode->hdisplay); |
586 | mixer_reg_write(res, MXR_RESOLUTION, val); | 592 | mixer_reg_write(res, MXR_RESOLUTION, val); |
587 | } | 593 | } |
588 | 594 | ||
589 | val = MXR_GRP_WH_WIDTH(plane->src_width); | 595 | val = MXR_GRP_WH_WIDTH(plane->src_w); |
590 | val |= MXR_GRP_WH_HEIGHT(plane->src_height); | 596 | val |= MXR_GRP_WH_HEIGHT(plane->src_h); |
591 | val |= MXR_GRP_WH_H_SCALE(x_ratio); | 597 | val |= MXR_GRP_WH_H_SCALE(x_ratio); |
592 | val |= MXR_GRP_WH_V_SCALE(y_ratio); | 598 | val |= MXR_GRP_WH_V_SCALE(y_ratio); |
593 | mixer_reg_write(res, MXR_GRAPHIC_WH(win), val); | 599 | mixer_reg_write(res, MXR_GRAPHIC_WH(win), val); |
@@ -605,8 +611,8 @@ static void mixer_graph_buffer(struct mixer_context *ctx, unsigned int win) | |||
605 | /* set buffer address to mixer */ | 611 | /* set buffer address to mixer */ |
606 | mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr); | 612 | mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr); |
607 | 613 | ||
608 | mixer_cfg_scan(ctx, plane->mode_height); | 614 | mixer_cfg_scan(ctx, mode->vdisplay); |
609 | mixer_cfg_rgb_fmt(ctx, plane->mode_height); | 615 | mixer_cfg_rgb_fmt(ctx, mode->vdisplay); |
610 | mixer_cfg_layer(ctx, win, true); | 616 | mixer_cfg_layer(ctx, win, true); |
611 | 617 | ||
612 | /* layer update mandatory for mixer 16.0.33.0 */ | 618 | /* layer update mandatory for mixer 16.0.33.0 */ |
@@ -735,8 +741,8 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg) | |||
735 | goto out; | 741 | goto out; |
736 | } | 742 | } |
737 | 743 | ||
738 | drm_handle_vblank(ctx->drm_dev, ctx->pipe); | 744 | drm_crtc_handle_vblank(&ctx->crtc->base); |
739 | exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe); | 745 | exynos_drm_crtc_finish_pageflip(ctx->crtc); |
740 | 746 | ||
741 | /* set wait vsync event to zero and wake up queue. */ | 747 | /* set wait vsync event to zero and wake up queue. */ |
742 | if (atomic_read(&ctx->wait_vsync_event)) { | 748 | if (atomic_read(&ctx->wait_vsync_event)) { |
@@ -881,8 +887,7 @@ static int mixer_initialize(struct mixer_context *mixer_ctx, | |||
881 | } | 887 | } |
882 | } | 888 | } |
883 | 889 | ||
884 | ret = drm_iommu_attach_device_if_possible(mixer_ctx->crtc, drm_dev, | 890 | ret = drm_iommu_attach_device(drm_dev, mixer_ctx->dev); |
885 | mixer_ctx->dev); | ||
886 | if (ret) | 891 | if (ret) |
887 | priv->pipe--; | 892 | priv->pipe--; |
888 | 893 | ||
@@ -891,8 +896,7 @@ static int mixer_initialize(struct mixer_context *mixer_ctx, | |||
891 | 896 | ||
892 | static void mixer_ctx_remove(struct mixer_context *mixer_ctx) | 897 | static void mixer_ctx_remove(struct mixer_context *mixer_ctx) |
893 | { | 898 | { |
894 | if (is_drm_iommu_supported(mixer_ctx->drm_dev)) | 899 | drm_iommu_detach_device(mixer_ctx->drm_dev, mixer_ctx->dev); |
895 | drm_iommu_detach_device(mixer_ctx->drm_dev, mixer_ctx->dev); | ||
896 | } | 900 | } |
897 | 901 | ||
898 | static int mixer_enable_vblank(struct exynos_drm_crtc *crtc) | 902 | static int mixer_enable_vblank(struct exynos_drm_crtc *crtc) |
@@ -900,10 +904,9 @@ static int mixer_enable_vblank(struct exynos_drm_crtc *crtc) | |||
900 | struct mixer_context *mixer_ctx = crtc->ctx; | 904 | struct mixer_context *mixer_ctx = crtc->ctx; |
901 | struct mixer_resources *res = &mixer_ctx->mixer_res; | 905 | struct mixer_resources *res = &mixer_ctx->mixer_res; |
902 | 906 | ||
903 | if (!mixer_ctx->powered) { | 907 | __set_bit(MXR_BIT_VSYNC, &mixer_ctx->flags); |
904 | mixer_ctx->int_en |= MXR_INT_EN_VSYNC; | 908 | if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags)) |
905 | return 0; | 909 | return 0; |
906 | } | ||
907 | 910 | ||
908 | /* enable vsync interrupt */ | 911 | /* enable vsync interrupt */ |
909 | mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC); | 912 | mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC); |
@@ -917,54 +920,48 @@ static void mixer_disable_vblank(struct exynos_drm_crtc *crtc) | |||
917 | struct mixer_context *mixer_ctx = crtc->ctx; | 920 | struct mixer_context *mixer_ctx = crtc->ctx; |
918 | struct mixer_resources *res = &mixer_ctx->mixer_res; | 921 | struct mixer_resources *res = &mixer_ctx->mixer_res; |
919 | 922 | ||
920 | if (!mixer_ctx->powered) { | 923 | __clear_bit(MXR_BIT_VSYNC, &mixer_ctx->flags); |
921 | mixer_ctx->int_en &= MXR_INT_EN_VSYNC; | 924 | |
925 | if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags)) | ||
922 | return; | 926 | return; |
923 | } | ||
924 | 927 | ||
925 | /* disable vsync interrupt */ | 928 | /* disable vsync interrupt */ |
926 | mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC); | 929 | mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC); |
927 | mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC); | 930 | mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC); |
928 | } | 931 | } |
929 | 932 | ||
930 | static void mixer_win_commit(struct exynos_drm_crtc *crtc, unsigned int win) | 933 | static void mixer_update_plane(struct exynos_drm_crtc *crtc, |
934 | struct exynos_drm_plane *plane) | ||
931 | { | 935 | { |
932 | struct mixer_context *mixer_ctx = crtc->ctx; | 936 | struct mixer_context *mixer_ctx = crtc->ctx; |
933 | 937 | ||
934 | DRM_DEBUG_KMS("win: %d\n", win); | 938 | DRM_DEBUG_KMS("win: %d\n", plane->zpos); |
935 | 939 | ||
936 | mutex_lock(&mixer_ctx->mixer_mutex); | 940 | if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags)) |
937 | if (!mixer_ctx->powered) { | ||
938 | mutex_unlock(&mixer_ctx->mixer_mutex); | ||
939 | return; | 941 | return; |
940 | } | ||
941 | mutex_unlock(&mixer_ctx->mixer_mutex); | ||
942 | 942 | ||
943 | if (win > 1 && mixer_ctx->vp_enabled) | 943 | if (plane->zpos > 1 && mixer_ctx->vp_enabled) |
944 | vp_video_buffer(mixer_ctx, win); | 944 | vp_video_buffer(mixer_ctx, plane); |
945 | else | 945 | else |
946 | mixer_graph_buffer(mixer_ctx, win); | 946 | mixer_graph_buffer(mixer_ctx, plane); |
947 | } | 947 | } |
948 | 948 | ||
949 | static void mixer_win_disable(struct exynos_drm_crtc *crtc, unsigned int win) | 949 | static void mixer_disable_plane(struct exynos_drm_crtc *crtc, |
950 | struct exynos_drm_plane *plane) | ||
950 | { | 951 | { |
951 | struct mixer_context *mixer_ctx = crtc->ctx; | 952 | struct mixer_context *mixer_ctx = crtc->ctx; |
952 | struct mixer_resources *res = &mixer_ctx->mixer_res; | 953 | struct mixer_resources *res = &mixer_ctx->mixer_res; |
953 | unsigned long flags; | 954 | unsigned long flags; |
954 | 955 | ||
955 | DRM_DEBUG_KMS("win: %d\n", win); | 956 | DRM_DEBUG_KMS("win: %d\n", plane->zpos); |
956 | 957 | ||
957 | mutex_lock(&mixer_ctx->mixer_mutex); | 958 | if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags)) |
958 | if (!mixer_ctx->powered) { | ||
959 | mutex_unlock(&mixer_ctx->mixer_mutex); | ||
960 | return; | 959 | return; |
961 | } | ||
962 | mutex_unlock(&mixer_ctx->mixer_mutex); | ||
963 | 960 | ||
964 | spin_lock_irqsave(&res->reg_slock, flags); | 961 | spin_lock_irqsave(&res->reg_slock, flags); |
965 | mixer_vsync_set_update(mixer_ctx, false); | 962 | mixer_vsync_set_update(mixer_ctx, false); |
966 | 963 | ||
967 | mixer_cfg_layer(mixer_ctx, win, false); | 964 | mixer_cfg_layer(mixer_ctx, plane->zpos, false); |
968 | 965 | ||
969 | mixer_vsync_set_update(mixer_ctx, true); | 966 | mixer_vsync_set_update(mixer_ctx, true); |
970 | spin_unlock_irqrestore(&res->reg_slock, flags); | 967 | spin_unlock_irqrestore(&res->reg_slock, flags); |
@@ -975,12 +972,8 @@ static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc) | |||
975 | struct mixer_context *mixer_ctx = crtc->ctx; | 972 | struct mixer_context *mixer_ctx = crtc->ctx; |
976 | int err; | 973 | int err; |
977 | 974 | ||
978 | mutex_lock(&mixer_ctx->mixer_mutex); | 975 | if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags)) |
979 | if (!mixer_ctx->powered) { | ||
980 | mutex_unlock(&mixer_ctx->mixer_mutex); | ||
981 | return; | 976 | return; |
982 | } | ||
983 | mutex_unlock(&mixer_ctx->mixer_mutex); | ||
984 | 977 | ||
985 | err = drm_vblank_get(mixer_ctx->drm_dev, mixer_ctx->pipe); | 978 | err = drm_vblank_get(mixer_ctx->drm_dev, mixer_ctx->pipe); |
986 | if (err < 0) { | 979 | if (err < 0) { |
@@ -1008,13 +1001,8 @@ static void mixer_enable(struct exynos_drm_crtc *crtc) | |||
1008 | struct mixer_resources *res = &ctx->mixer_res; | 1001 | struct mixer_resources *res = &ctx->mixer_res; |
1009 | int ret; | 1002 | int ret; |
1010 | 1003 | ||
1011 | mutex_lock(&ctx->mixer_mutex); | 1004 | if (test_bit(MXR_BIT_POWERED, &ctx->flags)) |
1012 | if (ctx->powered) { | ||
1013 | mutex_unlock(&ctx->mixer_mutex); | ||
1014 | return; | 1005 | return; |
1015 | } | ||
1016 | |||
1017 | mutex_unlock(&ctx->mixer_mutex); | ||
1018 | 1006 | ||
1019 | pm_runtime_get_sync(ctx->dev); | 1007 | pm_runtime_get_sync(ctx->dev); |
1020 | 1008 | ||
@@ -1046,15 +1034,14 @@ static void mixer_enable(struct exynos_drm_crtc *crtc) | |||
1046 | } | 1034 | } |
1047 | } | 1035 | } |
1048 | 1036 | ||
1049 | mutex_lock(&ctx->mixer_mutex); | 1037 | set_bit(MXR_BIT_POWERED, &ctx->flags); |
1050 | ctx->powered = true; | ||
1051 | mutex_unlock(&ctx->mixer_mutex); | ||
1052 | 1038 | ||
1053 | mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET); | 1039 | mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET); |
1054 | 1040 | ||
1055 | if (ctx->int_en & MXR_INT_EN_VSYNC) | 1041 | if (test_bit(MXR_BIT_VSYNC, &ctx->flags)) { |
1056 | mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC); | 1042 | mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC); |
1057 | mixer_reg_write(res, MXR_INT_EN, ctx->int_en); | 1043 | mixer_reg_writemask(res, MXR_INT_EN, ~0, MXR_INT_EN_VSYNC); |
1044 | } | ||
1058 | mixer_win_reset(ctx); | 1045 | mixer_win_reset(ctx); |
1059 | } | 1046 | } |
1060 | 1047 | ||
@@ -1064,24 +1051,16 @@ static void mixer_disable(struct exynos_drm_crtc *crtc) | |||
1064 | struct mixer_resources *res = &ctx->mixer_res; | 1051 | struct mixer_resources *res = &ctx->mixer_res; |
1065 | int i; | 1052 | int i; |
1066 | 1053 | ||
1067 | mutex_lock(&ctx->mixer_mutex); | 1054 | if (!test_bit(MXR_BIT_POWERED, &ctx->flags)) |
1068 | if (!ctx->powered) { | ||
1069 | mutex_unlock(&ctx->mixer_mutex); | ||
1070 | return; | 1055 | return; |
1071 | } | ||
1072 | mutex_unlock(&ctx->mixer_mutex); | ||
1073 | 1056 | ||
1074 | mixer_stop(ctx); | 1057 | mixer_stop(ctx); |
1075 | mixer_regs_dump(ctx); | 1058 | mixer_regs_dump(ctx); |
1076 | 1059 | ||
1077 | for (i = 0; i < MIXER_WIN_NR; i++) | 1060 | for (i = 0; i < MIXER_WIN_NR; i++) |
1078 | mixer_win_disable(crtc, i); | 1061 | mixer_disable_plane(crtc, &ctx->planes[i]); |
1079 | 1062 | ||
1080 | ctx->int_en = mixer_reg_read(res, MXR_INT_EN); | 1063 | clear_bit(MXR_BIT_POWERED, &ctx->flags); |
1081 | |||
1082 | mutex_lock(&ctx->mixer_mutex); | ||
1083 | ctx->powered = false; | ||
1084 | mutex_unlock(&ctx->mixer_mutex); | ||
1085 | 1064 | ||
1086 | clk_disable_unprepare(res->hdmi); | 1065 | clk_disable_unprepare(res->hdmi); |
1087 | clk_disable_unprepare(res->mixer); | 1066 | clk_disable_unprepare(res->mixer); |
@@ -1120,8 +1099,8 @@ static const struct exynos_drm_crtc_ops mixer_crtc_ops = { | |||
1120 | .enable_vblank = mixer_enable_vblank, | 1099 | .enable_vblank = mixer_enable_vblank, |
1121 | .disable_vblank = mixer_disable_vblank, | 1100 | .disable_vblank = mixer_disable_vblank, |
1122 | .wait_for_vblank = mixer_wait_for_vblank, | 1101 | .wait_for_vblank = mixer_wait_for_vblank, |
1123 | .win_commit = mixer_win_commit, | 1102 | .update_plane = mixer_update_plane, |
1124 | .win_disable = mixer_win_disable, | 1103 | .disable_plane = mixer_disable_plane, |
1125 | }; | 1104 | }; |
1126 | 1105 | ||
1127 | static struct mixer_drv_data exynos5420_mxr_drv_data = { | 1106 | static struct mixer_drv_data exynos5420_mxr_drv_data = { |
@@ -1243,8 +1222,6 @@ static int mixer_probe(struct platform_device *pdev) | |||
1243 | return -ENOMEM; | 1222 | return -ENOMEM; |
1244 | } | 1223 | } |
1245 | 1224 | ||
1246 | mutex_init(&ctx->mixer_mutex); | ||
1247 | |||
1248 | if (dev->of_node) { | 1225 | if (dev->of_node) { |
1249 | const struct of_device_id *match; | 1226 | const struct of_device_id *match; |
1250 | 1227 | ||