diff options
author | Dave Airlie <airlied@redhat.com> | 2016-05-11 20:10:53 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2016-05-11 20:10:53 -0400 |
commit | 6d23abf58a9afd3bc28aaf0384155b04c4b77912 (patch) | |
tree | 4ba843ececa274bca4b5b484ca7fd44dd9760551 | |
parent | 19ea5da07a1f315191212e094ec44fb1caec9580 (diff) | |
parent | dd65a6867454117ecaeb8944dc231a4737681782 (diff) |
Merge branch 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos into drm-next
Summary:
- expose HDMI-PHY clock to other drivers.
. this patch was included in below patch series but I missed.
http://www.spinics.net/lists/dri-devel/msg103097.html
- some fixups about DECON5433 driver
. this patch corrects vblank handling and fixes up trigger
configuration.
- use generic functions - gem_prime_mmap and dma_buf_mmap.
- use DMA-Mapping API instead of specific one.
- some code cleanups and fixeups.
* 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos:
drm/exynos/decon5433: fix trigger configuration
drm/exynos/dsi: use of_graph_get_endpoint_by_regs helper
drm/exynos/dpi: use of_graph_get_endpoint_by_regs helper
drm/exynos: Nuke dummy fb->dirty callback
drm/exynos: use directly DMA mapping APIs on g2d
drm/exynos/hdmi: Don't print error on deferral due to regulators
drm/exynos: fix imported dma-buf to be mapped
drm/exynos: support gem_prime_mmap
drm/exynos: fimd: harden fimd_calc_clkdiv()
drm/exynos: fix cancel page flip code
drm/exynos/decon5433: do not use unnecessary software trigger
drm/exynos/decon5433: handle vblank in vblank interrupt
drm/exynos/hdmi: expose HDMI-PHY clock as pipeline clock
-rw-r--r-- | drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 16 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_crtc.c | 15 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_dpi.c | 69 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_drv.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_dsi.c | 57 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_fb.c | 11 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_fimd.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_g2d.c | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_gem.c | 70 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_gem.h | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_hdmi.c | 73 |
11 files changed, 120 insertions, 223 deletions
diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c index 4ab5bfc23647..ac21b4000835 100644 --- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c | |||
@@ -147,11 +147,13 @@ static void decon_commit(struct exynos_drm_crtc *crtc) | |||
147 | val = CMU_CLKGAGE_MODE_SFR_F | CMU_CLKGAGE_MODE_MEM_F; | 147 | val = CMU_CLKGAGE_MODE_SFR_F | CMU_CLKGAGE_MODE_MEM_F; |
148 | writel(val, ctx->addr + DECON_CMU); | 148 | writel(val, ctx->addr + DECON_CMU); |
149 | 149 | ||
150 | if (ctx->out_type & (IFTYPE_I80 | I80_HW_TRG)) | ||
151 | decon_setup_trigger(ctx); | ||
152 | |||
150 | /* lcd on and use command if */ | 153 | /* lcd on and use command if */ |
151 | val = VIDOUT_LCD_ON; | 154 | val = VIDOUT_LCD_ON; |
152 | if (ctx->out_type & IFTYPE_I80) { | 155 | if (ctx->out_type & IFTYPE_I80) { |
153 | val |= VIDOUT_COMMAND_IF; | 156 | val |= VIDOUT_COMMAND_IF; |
154 | decon_setup_trigger(ctx); | ||
155 | } else { | 157 | } else { |
156 | val |= VIDOUT_RGB_IF; | 158 | val |= VIDOUT_RGB_IF; |
157 | } | 159 | } |
@@ -376,9 +378,6 @@ static void decon_swreset(struct decon_context *ctx) | |||
376 | writel(VIDCON1_VCLK_RUN_VDEN_DISABLE, ctx->addr + DECON_VIDCON1); | 378 | writel(VIDCON1_VCLK_RUN_VDEN_DISABLE, ctx->addr + DECON_VIDCON1); |
377 | writel(CRCCTRL_CRCEN | CRCCTRL_CRCSTART_F | CRCCTRL_CRCCLKEN, | 379 | writel(CRCCTRL_CRCEN | CRCCTRL_CRCSTART_F | CRCCTRL_CRCCLKEN, |
378 | ctx->addr + DECON_CRCCTRL); | 380 | ctx->addr + DECON_CRCCTRL); |
379 | |||
380 | if (ctx->out_type & IFTYPE_I80) | ||
381 | decon_setup_trigger(ctx); | ||
382 | } | 381 | } |
383 | 382 | ||
384 | static void decon_enable(struct exynos_drm_crtc *crtc) | 383 | static void decon_enable(struct exynos_drm_crtc *crtc) |
@@ -434,13 +433,12 @@ static void decon_te_irq_handler(struct exynos_drm_crtc *crtc) | |||
434 | { | 433 | { |
435 | struct decon_context *ctx = crtc->ctx; | 434 | struct decon_context *ctx = crtc->ctx; |
436 | 435 | ||
437 | if (!test_bit(BIT_CLKS_ENABLED, &ctx->flags)) | 436 | if (!test_bit(BIT_CLKS_ENABLED, &ctx->flags) || |
437 | (ctx->out_type & I80_HW_TRG)) | ||
438 | return; | 438 | return; |
439 | 439 | ||
440 | if (test_and_clear_bit(BIT_WIN_UPDATED, &ctx->flags)) | 440 | if (test_and_clear_bit(BIT_WIN_UPDATED, &ctx->flags)) |
441 | decon_set_bits(ctx, DECON_TRIGCON, TRIGCON_SWTRIGCMD, ~0); | 441 | decon_set_bits(ctx, DECON_TRIGCON, TRIGCON_SWTRIGCMD, ~0); |
442 | |||
443 | drm_crtc_handle_vblank(&ctx->crtc->base); | ||
444 | } | 442 | } |
445 | 443 | ||
446 | static void decon_clear_channels(struct exynos_drm_crtc *crtc) | 444 | static void decon_clear_channels(struct exynos_drm_crtc *crtc) |
@@ -573,6 +571,7 @@ static irqreturn_t decon_irq_handler(int irq, void *dev_id) | |||
573 | 571 | ||
574 | /* clear */ | 572 | /* clear */ |
575 | writel(val, ctx->addr + DECON_VIDINTCON1); | 573 | writel(val, ctx->addr + DECON_VIDINTCON1); |
574 | drm_crtc_handle_vblank(&ctx->crtc->base); | ||
576 | } | 575 | } |
577 | 576 | ||
578 | out: | 577 | out: |
@@ -648,9 +647,8 @@ static int exynos5433_decon_probe(struct platform_device *pdev) | |||
648 | 647 | ||
649 | if (ctx->out_type & IFTYPE_HDMI) { | 648 | if (ctx->out_type & IFTYPE_HDMI) { |
650 | ctx->first_win = 1; | 649 | ctx->first_win = 1; |
651 | ctx->out_type = IFTYPE_I80; | ||
652 | } else if (of_get_child_by_name(dev->of_node, "i80-if-timings")) { | 650 | } else if (of_get_child_by_name(dev->of_node, "i80-if-timings")) { |
653 | ctx->out_type = IFTYPE_I80; | 651 | ctx->out_type |= IFTYPE_I80; |
654 | } | 652 | } |
655 | 653 | ||
656 | for (i = 0; i < ARRAY_SIZE(decon_clks_name); i++) { | 654 | for (i = 0; i < ARRAY_SIZE(decon_clks_name); i++) { |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index 50dd33d5045d..785ffa6cc309 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c | |||
@@ -233,20 +233,15 @@ void exynos_drm_crtc_cancel_page_flip(struct drm_crtc *crtc, | |||
233 | unsigned long flags; | 233 | unsigned long flags; |
234 | 234 | ||
235 | spin_lock_irqsave(&crtc->dev->event_lock, flags); | 235 | spin_lock_irqsave(&crtc->dev->event_lock, flags); |
236 | |||
236 | e = exynos_crtc->event; | 237 | e = exynos_crtc->event; |
237 | if (e && e->base.file_priv == file) { | 238 | if (e && e->base.file_priv == file) { |
238 | exynos_crtc->event = NULL; | 239 | exynos_crtc->event = NULL; |
239 | /* | ||
240 | * event will be destroyed by core part | ||
241 | * so below line should be removed later with core changes | ||
242 | */ | ||
243 | e->base.destroy(&e->base); | ||
244 | /* | ||
245 | * event_space will be increased by core part | ||
246 | * so below line should be removed later with core changes. | ||
247 | */ | ||
248 | file->event_space += sizeof(e->event); | ||
249 | atomic_dec(&exynos_crtc->pending_update); | 240 | atomic_dec(&exynos_crtc->pending_update); |
250 | } | 241 | } |
242 | |||
251 | spin_unlock_irqrestore(&crtc->dev->event_lock, flags); | 243 | spin_unlock_irqrestore(&crtc->dev->event_lock, flags); |
244 | |||
245 | if (e && e->base.file_priv == file) | ||
246 | drm_event_cancel_free(crtc->dev, &e->base); | ||
252 | } | 247 | } |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dpi.c b/drivers/gpu/drm/exynos/exynos_drm_dpi.c index 75e570f45259..5e38e749ac17 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dpi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dpi.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <drm/drm_panel.h> | 15 | #include <drm/drm_panel.h> |
16 | #include <drm/drm_atomic_helper.h> | 16 | #include <drm/drm_atomic_helper.h> |
17 | 17 | ||
18 | #include <linux/of_graph.h> | ||
18 | #include <linux/regulator/consumer.h> | 19 | #include <linux/regulator/consumer.h> |
19 | 20 | ||
20 | #include <video/of_videomode.h> | 21 | #include <video/of_videomode.h> |
@@ -164,67 +165,6 @@ static const struct drm_encoder_funcs exynos_dpi_encoder_funcs = { | |||
164 | .destroy = drm_encoder_cleanup, | 165 | .destroy = drm_encoder_cleanup, |
165 | }; | 166 | }; |
166 | 167 | ||
167 | /* of_* functions will be removed after merge of of_graph patches */ | ||
168 | static struct device_node * | ||
169 | of_get_child_by_name_reg(struct device_node *parent, const char *name, u32 reg) | ||
170 | { | ||
171 | struct device_node *np; | ||
172 | |||
173 | for_each_child_of_node(parent, np) { | ||
174 | u32 r; | ||
175 | |||
176 | if (!np->name || of_node_cmp(np->name, name)) | ||
177 | continue; | ||
178 | |||
179 | if (of_property_read_u32(np, "reg", &r) < 0) | ||
180 | r = 0; | ||
181 | |||
182 | if (reg == r) | ||
183 | break; | ||
184 | } | ||
185 | |||
186 | return np; | ||
187 | } | ||
188 | |||
189 | static struct device_node *of_graph_get_port_by_reg(struct device_node *parent, | ||
190 | u32 reg) | ||
191 | { | ||
192 | struct device_node *ports, *port; | ||
193 | |||
194 | ports = of_get_child_by_name(parent, "ports"); | ||
195 | if (ports) | ||
196 | parent = ports; | ||
197 | |||
198 | port = of_get_child_by_name_reg(parent, "port", reg); | ||
199 | |||
200 | of_node_put(ports); | ||
201 | |||
202 | return port; | ||
203 | } | ||
204 | |||
205 | static struct device_node * | ||
206 | of_graph_get_endpoint_by_reg(struct device_node *port, u32 reg) | ||
207 | { | ||
208 | return of_get_child_by_name_reg(port, "endpoint", reg); | ||
209 | } | ||
210 | |||
211 | static struct device_node * | ||
212 | of_graph_get_remote_port_parent(const struct device_node *node) | ||
213 | { | ||
214 | struct device_node *np; | ||
215 | unsigned int depth; | ||
216 | |||
217 | np = of_parse_phandle(node, "remote-endpoint", 0); | ||
218 | |||
219 | /* Walk 3 levels up only if there is 'ports' node. */ | ||
220 | for (depth = 3; depth && np; depth--) { | ||
221 | np = of_get_next_parent(np); | ||
222 | if (depth == 2 && of_node_cmp(np->name, "ports")) | ||
223 | break; | ||
224 | } | ||
225 | return np; | ||
226 | } | ||
227 | |||
228 | enum { | 168 | enum { |
229 | FIMD_PORT_IN0, | 169 | FIMD_PORT_IN0, |
230 | FIMD_PORT_IN1, | 170 | FIMD_PORT_IN1, |
@@ -237,12 +177,7 @@ static struct device_node *exynos_dpi_of_find_panel_node(struct device *dev) | |||
237 | { | 177 | { |
238 | struct device_node *np, *ep; | 178 | struct device_node *np, *ep; |
239 | 179 | ||
240 | np = of_graph_get_port_by_reg(dev->of_node, FIMD_PORT_RGB); | 180 | ep = of_graph_get_endpoint_by_regs(dev->of_node, FIMD_PORT_RGB, 0); |
241 | if (!np) | ||
242 | return NULL; | ||
243 | |||
244 | ep = of_graph_get_endpoint_by_reg(np, 0); | ||
245 | of_node_put(np); | ||
246 | if (!ep) | 181 | if (!ep) |
247 | return NULL; | 182 | return NULL; |
248 | 183 | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index 8ff355ddcf51..6c4dd49de993 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c | |||
@@ -431,6 +431,7 @@ static struct drm_driver exynos_drm_driver = { | |||
431 | .gem_prime_import_sg_table = exynos_drm_gem_prime_import_sg_table, | 431 | .gem_prime_import_sg_table = exynos_drm_gem_prime_import_sg_table, |
432 | .gem_prime_vmap = exynos_drm_gem_prime_vmap, | 432 | .gem_prime_vmap = exynos_drm_gem_prime_vmap, |
433 | .gem_prime_vunmap = exynos_drm_gem_prime_vunmap, | 433 | .gem_prime_vunmap = exynos_drm_gem_prime_vunmap, |
434 | .gem_prime_mmap = exynos_drm_gem_prime_mmap, | ||
434 | .ioctls = exynos_ioctls, | 435 | .ioctls = exynos_ioctls, |
435 | .num_ioctls = ARRAY_SIZE(exynos_ioctls), | 436 | .num_ioctls = ARRAY_SIZE(exynos_ioctls), |
436 | .fops = &exynos_drm_driver_fops, | 437 | .fops = &exynos_drm_driver_fops, |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 72c3565d22ee..601ecf8006a7 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c | |||
@@ -1632,50 +1632,6 @@ static const struct drm_encoder_funcs exynos_dsi_encoder_funcs = { | |||
1632 | 1632 | ||
1633 | MODULE_DEVICE_TABLE(of, exynos_dsi_of_match); | 1633 | MODULE_DEVICE_TABLE(of, exynos_dsi_of_match); |
1634 | 1634 | ||
1635 | /* of_* functions will be removed after merge of of_graph patches */ | ||
1636 | static struct device_node * | ||
1637 | of_get_child_by_name_reg(struct device_node *parent, const char *name, u32 reg) | ||
1638 | { | ||
1639 | struct device_node *np; | ||
1640 | |||
1641 | for_each_child_of_node(parent, np) { | ||
1642 | u32 r; | ||
1643 | |||
1644 | if (!np->name || of_node_cmp(np->name, name)) | ||
1645 | continue; | ||
1646 | |||
1647 | if (of_property_read_u32(np, "reg", &r) < 0) | ||
1648 | r = 0; | ||
1649 | |||
1650 | if (reg == r) | ||
1651 | break; | ||
1652 | } | ||
1653 | |||
1654 | return np; | ||
1655 | } | ||
1656 | |||
1657 | static struct device_node *of_graph_get_port_by_reg(struct device_node *parent, | ||
1658 | u32 reg) | ||
1659 | { | ||
1660 | struct device_node *ports, *port; | ||
1661 | |||
1662 | ports = of_get_child_by_name(parent, "ports"); | ||
1663 | if (ports) | ||
1664 | parent = ports; | ||
1665 | |||
1666 | port = of_get_child_by_name_reg(parent, "port", reg); | ||
1667 | |||
1668 | of_node_put(ports); | ||
1669 | |||
1670 | return port; | ||
1671 | } | ||
1672 | |||
1673 | static struct device_node * | ||
1674 | of_graph_get_endpoint_by_reg(struct device_node *port, u32 reg) | ||
1675 | { | ||
1676 | return of_get_child_by_name_reg(port, "endpoint", reg); | ||
1677 | } | ||
1678 | |||
1679 | static int exynos_dsi_of_read_u32(const struct device_node *np, | 1635 | static int exynos_dsi_of_read_u32(const struct device_node *np, |
1680 | const char *propname, u32 *out_value) | 1636 | const char *propname, u32 *out_value) |
1681 | { | 1637 | { |
@@ -1697,7 +1653,7 @@ static int exynos_dsi_parse_dt(struct exynos_dsi *dsi) | |||
1697 | { | 1653 | { |
1698 | struct device *dev = dsi->dev; | 1654 | struct device *dev = dsi->dev; |
1699 | struct device_node *node = dev->of_node; | 1655 | struct device_node *node = dev->of_node; |
1700 | struct device_node *port, *ep; | 1656 | struct device_node *ep; |
1701 | int ret; | 1657 | int ret; |
1702 | 1658 | ||
1703 | ret = exynos_dsi_of_read_u32(node, "samsung,pll-clock-frequency", | 1659 | ret = exynos_dsi_of_read_u32(node, "samsung,pll-clock-frequency", |
@@ -1705,16 +1661,9 @@ static int exynos_dsi_parse_dt(struct exynos_dsi *dsi) | |||
1705 | if (ret < 0) | 1661 | if (ret < 0) |
1706 | return ret; | 1662 | return ret; |
1707 | 1663 | ||
1708 | port = of_graph_get_port_by_reg(node, DSI_PORT_OUT); | 1664 | ep = of_graph_get_endpoint_by_regs(node, DSI_PORT_OUT, 0); |
1709 | if (!port) { | ||
1710 | dev_err(dev, "no output port specified\n"); | ||
1711 | return -EINVAL; | ||
1712 | } | ||
1713 | |||
1714 | ep = of_graph_get_endpoint_by_reg(port, 0); | ||
1715 | of_node_put(port); | ||
1716 | if (!ep) { | 1665 | if (!ep) { |
1717 | dev_err(dev, "no endpoint specified in output port\n"); | 1666 | dev_err(dev, "no output port with endpoint specified\n"); |
1718 | return -EINVAL; | 1667 | return -EINVAL; |
1719 | } | 1668 | } |
1720 | 1669 | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c index 81cc5537cf25..f851a40ac6cb 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fb.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c | |||
@@ -97,20 +97,9 @@ static int exynos_drm_fb_create_handle(struct drm_framebuffer *fb, | |||
97 | &exynos_fb->exynos_gem[0]->base, handle); | 97 | &exynos_fb->exynos_gem[0]->base, handle); |
98 | } | 98 | } |
99 | 99 | ||
100 | static int exynos_drm_fb_dirty(struct drm_framebuffer *fb, | ||
101 | struct drm_file *file_priv, unsigned flags, | ||
102 | unsigned color, struct drm_clip_rect *clips, | ||
103 | unsigned num_clips) | ||
104 | { | ||
105 | /* TODO */ | ||
106 | |||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | static const struct drm_framebuffer_funcs exynos_drm_fb_funcs = { | 100 | static const struct drm_framebuffer_funcs exynos_drm_fb_funcs = { |
111 | .destroy = exynos_drm_fb_destroy, | 101 | .destroy = exynos_drm_fb_destroy, |
112 | .create_handle = exynos_drm_fb_create_handle, | 102 | .create_handle = exynos_drm_fb_create_handle, |
113 | .dirty = exynos_drm_fb_dirty, | ||
114 | }; | 103 | }; |
115 | 104 | ||
116 | struct drm_framebuffer * | 105 | struct drm_framebuffer * |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index cec508f9a335..3efe1aa89416 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c | |||
@@ -397,9 +397,16 @@ static void fimd_clear_channels(struct exynos_drm_crtc *crtc) | |||
397 | static u32 fimd_calc_clkdiv(struct fimd_context *ctx, | 397 | static u32 fimd_calc_clkdiv(struct fimd_context *ctx, |
398 | const struct drm_display_mode *mode) | 398 | const struct drm_display_mode *mode) |
399 | { | 399 | { |
400 | unsigned long ideal_clk = mode->htotal * mode->vtotal * mode->vrefresh; | 400 | unsigned long ideal_clk; |
401 | u32 clkdiv; | 401 | u32 clkdiv; |
402 | 402 | ||
403 | if (mode->clock == 0) { | ||
404 | DRM_ERROR("Mode has zero clock value.\n"); | ||
405 | return 0xff; | ||
406 | } | ||
407 | |||
408 | ideal_clk = mode->clock * 1000; | ||
409 | |||
403 | if (ctx->i80_if) { | 410 | if (ctx->i80_if) { |
404 | /* | 411 | /* |
405 | * The frame done interrupt should be occurred prior to the | 412 | * The frame done interrupt should be occurred prior to the |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index 193d3602dffb..493552368295 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c | |||
@@ -383,8 +383,8 @@ static void g2d_userptr_put_dma_addr(struct drm_device *drm_dev, | |||
383 | return; | 383 | return; |
384 | 384 | ||
385 | out: | 385 | out: |
386 | exynos_gem_unmap_sgt_from_dma(drm_dev, g2d_userptr->sgt, | 386 | dma_unmap_sg(to_dma_dev(drm_dev), g2d_userptr->sgt->sgl, |
387 | DMA_BIDIRECTIONAL); | 387 | g2d_userptr->sgt->nents, DMA_BIDIRECTIONAL); |
388 | 388 | ||
389 | pages = frame_vector_pages(g2d_userptr->vec); | 389 | pages = frame_vector_pages(g2d_userptr->vec); |
390 | if (!IS_ERR(pages)) { | 390 | if (!IS_ERR(pages)) { |
@@ -501,10 +501,10 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev, | |||
501 | 501 | ||
502 | g2d_userptr->sgt = sgt; | 502 | g2d_userptr->sgt = sgt; |
503 | 503 | ||
504 | ret = exynos_gem_map_sgt_with_dma(drm_dev, g2d_userptr->sgt, | 504 | if (!dma_map_sg(to_dma_dev(drm_dev), sgt->sgl, sgt->nents, |
505 | DMA_BIDIRECTIONAL); | 505 | DMA_BIDIRECTIONAL)) { |
506 | if (ret < 0) { | ||
507 | DRM_ERROR("failed to map sgt with dma region.\n"); | 506 | DRM_ERROR("failed to map sgt with dma region.\n"); |
507 | ret = -ENOMEM; | ||
508 | goto err_sg_free_table; | 508 | goto err_sg_free_table; |
509 | } | 509 | } |
510 | 510 | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c index 6fb98f4c3544..72d9414bd944 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c | |||
@@ -378,28 +378,6 @@ int exynos_drm_gem_get_ioctl(struct drm_device *dev, void *data, | |||
378 | return 0; | 378 | return 0; |
379 | } | 379 | } |
380 | 380 | ||
381 | int exynos_gem_map_sgt_with_dma(struct drm_device *drm_dev, | ||
382 | struct sg_table *sgt, | ||
383 | enum dma_data_direction dir) | ||
384 | { | ||
385 | int nents; | ||
386 | |||
387 | nents = dma_map_sg(to_dma_dev(drm_dev), sgt->sgl, sgt->nents, dir); | ||
388 | if (!nents) { | ||
389 | DRM_ERROR("failed to map sgl with dma.\n"); | ||
390 | return nents; | ||
391 | } | ||
392 | |||
393 | return 0; | ||
394 | } | ||
395 | |||
396 | void exynos_gem_unmap_sgt_from_dma(struct drm_device *drm_dev, | ||
397 | struct sg_table *sgt, | ||
398 | enum dma_data_direction dir) | ||
399 | { | ||
400 | dma_unmap_sg(to_dma_dev(drm_dev), sgt->sgl, sgt->nents, dir); | ||
401 | } | ||
402 | |||
403 | void exynos_drm_gem_free_object(struct drm_gem_object *obj) | 381 | void exynos_drm_gem_free_object(struct drm_gem_object *obj) |
404 | { | 382 | { |
405 | exynos_drm_gem_destroy(to_exynos_gem(obj)); | 383 | exynos_drm_gem_destroy(to_exynos_gem(obj)); |
@@ -503,22 +481,12 @@ out: | |||
503 | } | 481 | } |
504 | } | 482 | } |
505 | 483 | ||
506 | int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) | 484 | static int exynos_drm_gem_mmap_obj(struct drm_gem_object *obj, |
485 | struct vm_area_struct *vma) | ||
507 | { | 486 | { |
508 | struct exynos_drm_gem *exynos_gem; | 487 | struct exynos_drm_gem *exynos_gem = to_exynos_gem(obj); |
509 | struct drm_gem_object *obj; | ||
510 | int ret; | 488 | int ret; |
511 | 489 | ||
512 | /* set vm_area_struct. */ | ||
513 | ret = drm_gem_mmap(filp, vma); | ||
514 | if (ret < 0) { | ||
515 | DRM_ERROR("failed to mmap.\n"); | ||
516 | return ret; | ||
517 | } | ||
518 | |||
519 | obj = vma->vm_private_data; | ||
520 | exynos_gem = to_exynos_gem(obj); | ||
521 | |||
522 | DRM_DEBUG_KMS("flags = 0x%x\n", exynos_gem->flags); | 490 | DRM_DEBUG_KMS("flags = 0x%x\n", exynos_gem->flags); |
523 | 491 | ||
524 | /* non-cachable as default. */ | 492 | /* non-cachable as default. */ |
@@ -543,6 +511,26 @@ err_close_vm: | |||
543 | return ret; | 511 | return ret; |
544 | } | 512 | } |
545 | 513 | ||
514 | int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) | ||
515 | { | ||
516 | struct drm_gem_object *obj; | ||
517 | int ret; | ||
518 | |||
519 | /* set vm_area_struct. */ | ||
520 | ret = drm_gem_mmap(filp, vma); | ||
521 | if (ret < 0) { | ||
522 | DRM_ERROR("failed to mmap.\n"); | ||
523 | return ret; | ||
524 | } | ||
525 | |||
526 | obj = vma->vm_private_data; | ||
527 | |||
528 | if (obj->import_attach) | ||
529 | return dma_buf_mmap(obj->dma_buf, vma, 0); | ||
530 | |||
531 | return exynos_drm_gem_mmap_obj(obj, vma); | ||
532 | } | ||
533 | |||
546 | /* low-level interface prime helpers */ | 534 | /* low-level interface prime helpers */ |
547 | struct sg_table *exynos_drm_gem_prime_get_sg_table(struct drm_gem_object *obj) | 535 | struct sg_table *exynos_drm_gem_prime_get_sg_table(struct drm_gem_object *obj) |
548 | { | 536 | { |
@@ -617,3 +605,15 @@ void exynos_drm_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr) | |||
617 | { | 605 | { |
618 | /* Nothing to do */ | 606 | /* Nothing to do */ |
619 | } | 607 | } |
608 | |||
609 | int exynos_drm_gem_prime_mmap(struct drm_gem_object *obj, | ||
610 | struct vm_area_struct *vma) | ||
611 | { | ||
612 | int ret; | ||
613 | |||
614 | ret = drm_gem_mmap_obj(obj, obj->size, vma); | ||
615 | if (ret < 0) | ||
616 | return ret; | ||
617 | |||
618 | return exynos_drm_gem_mmap_obj(obj, vma); | ||
619 | } | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.h b/drivers/gpu/drm/exynos/exynos_drm_gem.h index 00223052b87b..78100742281d 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.h +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.h | |||
@@ -121,16 +121,6 @@ int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); | |||
121 | /* set vm_flags and we can change the vm attribute to other one at here. */ | 121 | /* set vm_flags and we can change the vm attribute to other one at here. */ |
122 | int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma); | 122 | int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma); |
123 | 123 | ||
124 | /* map sgt with dma region. */ | ||
125 | int exynos_gem_map_sgt_with_dma(struct drm_device *drm_dev, | ||
126 | struct sg_table *sgt, | ||
127 | enum dma_data_direction dir); | ||
128 | |||
129 | /* unmap sgt from dma region. */ | ||
130 | void exynos_gem_unmap_sgt_from_dma(struct drm_device *drm_dev, | ||
131 | struct sg_table *sgt, | ||
132 | enum dma_data_direction dir); | ||
133 | |||
134 | /* low-level interface prime helpers */ | 124 | /* low-level interface prime helpers */ |
135 | struct sg_table *exynos_drm_gem_prime_get_sg_table(struct drm_gem_object *obj); | 125 | struct sg_table *exynos_drm_gem_prime_get_sg_table(struct drm_gem_object *obj); |
136 | struct drm_gem_object * | 126 | struct drm_gem_object * |
@@ -139,5 +129,7 @@ exynos_drm_gem_prime_import_sg_table(struct drm_device *dev, | |||
139 | struct sg_table *sgt); | 129 | struct sg_table *sgt); |
140 | void *exynos_drm_gem_prime_vmap(struct drm_gem_object *obj); | 130 | void *exynos_drm_gem_prime_vmap(struct drm_gem_object *obj); |
141 | void exynos_drm_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr); | 131 | void exynos_drm_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr); |
132 | int exynos_drm_gem_prime_mmap(struct drm_gem_object *obj, | ||
133 | struct vm_area_struct *vma); | ||
142 | 134 | ||
143 | #endif | 135 | #endif |
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 0f87acb4cf21..6cd09944405f 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c | |||
@@ -146,6 +146,7 @@ struct hdmi_context { | |||
146 | struct clk **clk_muxes; | 146 | struct clk **clk_muxes; |
147 | struct regulator_bulk_data regul_bulk[ARRAY_SIZE(supply)]; | 147 | struct regulator_bulk_data regul_bulk[ARRAY_SIZE(supply)]; |
148 | struct regulator *reg_hdmi_en; | 148 | struct regulator *reg_hdmi_en; |
149 | struct exynos_drm_clk phy_clk; | ||
149 | }; | 150 | }; |
150 | 151 | ||
151 | static inline struct hdmi_context *encoder_to_hdmi(struct drm_encoder *e) | 152 | static inline struct hdmi_context *encoder_to_hdmi(struct drm_encoder *e) |
@@ -1445,7 +1446,6 @@ static void hdmiphy_conf_apply(struct hdmi_context *hdata) | |||
1445 | 1446 | ||
1446 | static void hdmi_conf_apply(struct hdmi_context *hdata) | 1447 | static void hdmi_conf_apply(struct hdmi_context *hdata) |
1447 | { | 1448 | { |
1448 | hdmiphy_conf_apply(hdata); | ||
1449 | hdmi_start(hdata, false); | 1449 | hdmi_start(hdata, false); |
1450 | hdmi_conf_init(hdata); | 1450 | hdmi_conf_init(hdata); |
1451 | hdmi_audio_init(hdata); | 1451 | hdmi_audio_init(hdata); |
@@ -1478,10 +1478,8 @@ static void hdmi_set_refclk(struct hdmi_context *hdata, bool on) | |||
1478 | SYSREG_HDMI_REFCLK_INT_CLK, on ? ~0 : 0); | 1478 | SYSREG_HDMI_REFCLK_INT_CLK, on ? ~0 : 0); |
1479 | } | 1479 | } |
1480 | 1480 | ||
1481 | static void hdmi_enable(struct drm_encoder *encoder) | 1481 | static void hdmiphy_enable(struct hdmi_context *hdata) |
1482 | { | 1482 | { |
1483 | struct hdmi_context *hdata = encoder_to_hdmi(encoder); | ||
1484 | |||
1485 | if (hdata->powered) | 1483 | if (hdata->powered) |
1486 | return; | 1484 | return; |
1487 | 1485 | ||
@@ -1497,11 +1495,40 @@ static void hdmi_enable(struct drm_encoder *encoder) | |||
1497 | 1495 | ||
1498 | hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, 0, HDMI_PHY_POWER_OFF_EN); | 1496 | hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, 0, HDMI_PHY_POWER_OFF_EN); |
1499 | 1497 | ||
1500 | hdmi_conf_apply(hdata); | 1498 | hdmiphy_conf_apply(hdata); |
1501 | 1499 | ||
1502 | hdata->powered = true; | 1500 | hdata->powered = true; |
1503 | } | 1501 | } |
1504 | 1502 | ||
1503 | static void hdmiphy_disable(struct hdmi_context *hdata) | ||
1504 | { | ||
1505 | if (!hdata->powered) | ||
1506 | return; | ||
1507 | |||
1508 | hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_EN); | ||
1509 | |||
1510 | hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, ~0, HDMI_PHY_POWER_OFF_EN); | ||
1511 | |||
1512 | hdmi_set_refclk(hdata, false); | ||
1513 | |||
1514 | regmap_update_bits(hdata->pmureg, PMU_HDMI_PHY_CONTROL, | ||
1515 | PMU_HDMI_PHY_ENABLE_BIT, 0); | ||
1516 | |||
1517 | regulator_bulk_disable(ARRAY_SIZE(supply), hdata->regul_bulk); | ||
1518 | |||
1519 | pm_runtime_put_sync(hdata->dev); | ||
1520 | |||
1521 | hdata->powered = false; | ||
1522 | } | ||
1523 | |||
1524 | static void hdmi_enable(struct drm_encoder *encoder) | ||
1525 | { | ||
1526 | struct hdmi_context *hdata = encoder_to_hdmi(encoder); | ||
1527 | |||
1528 | hdmiphy_enable(hdata); | ||
1529 | hdmi_conf_apply(hdata); | ||
1530 | } | ||
1531 | |||
1505 | static void hdmi_disable(struct drm_encoder *encoder) | 1532 | static void hdmi_disable(struct drm_encoder *encoder) |
1506 | { | 1533 | { |
1507 | struct hdmi_context *hdata = encoder_to_hdmi(encoder); | 1534 | struct hdmi_context *hdata = encoder_to_hdmi(encoder); |
@@ -1525,22 +1552,9 @@ static void hdmi_disable(struct drm_encoder *encoder) | |||
1525 | if (funcs && funcs->disable) | 1552 | if (funcs && funcs->disable) |
1526 | (*funcs->disable)(crtc); | 1553 | (*funcs->disable)(crtc); |
1527 | 1554 | ||
1528 | hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_EN); | ||
1529 | |||
1530 | cancel_delayed_work(&hdata->hotplug_work); | 1555 | cancel_delayed_work(&hdata->hotplug_work); |
1531 | 1556 | ||
1532 | hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, ~0, HDMI_PHY_POWER_OFF_EN); | 1557 | hdmiphy_disable(hdata); |
1533 | |||
1534 | hdmi_set_refclk(hdata, false); | ||
1535 | |||
1536 | regmap_update_bits(hdata->pmureg, PMU_HDMI_PHY_CONTROL, | ||
1537 | PMU_HDMI_PHY_ENABLE_BIT, 0); | ||
1538 | |||
1539 | regulator_bulk_disable(ARRAY_SIZE(supply), hdata->regul_bulk); | ||
1540 | |||
1541 | pm_runtime_put_sync(hdata->dev); | ||
1542 | |||
1543 | hdata->powered = false; | ||
1544 | } | 1558 | } |
1545 | 1559 | ||
1546 | static const struct drm_encoder_helper_funcs exynos_hdmi_encoder_helper_funcs = { | 1560 | static const struct drm_encoder_helper_funcs exynos_hdmi_encoder_helper_funcs = { |
@@ -1625,6 +1639,17 @@ static int hdmi_clk_init(struct hdmi_context *hdata) | |||
1625 | } | 1639 | } |
1626 | 1640 | ||
1627 | 1641 | ||
1642 | static void hdmiphy_clk_enable(struct exynos_drm_clk *clk, bool enable) | ||
1643 | { | ||
1644 | struct hdmi_context *hdata = container_of(clk, struct hdmi_context, | ||
1645 | phy_clk); | ||
1646 | |||
1647 | if (enable) | ||
1648 | hdmiphy_enable(hdata); | ||
1649 | else | ||
1650 | hdmiphy_disable(hdata); | ||
1651 | } | ||
1652 | |||
1628 | static int hdmi_resources_init(struct hdmi_context *hdata) | 1653 | static int hdmi_resources_init(struct hdmi_context *hdata) |
1629 | { | 1654 | { |
1630 | struct device *dev = hdata->dev; | 1655 | struct device *dev = hdata->dev; |
@@ -1658,7 +1683,8 @@ static int hdmi_resources_init(struct hdmi_context *hdata) | |||
1658 | } | 1683 | } |
1659 | ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(supply), hdata->regul_bulk); | 1684 | ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(supply), hdata->regul_bulk); |
1660 | if (ret) { | 1685 | if (ret) { |
1661 | DRM_ERROR("failed to get regulators\n"); | 1686 | if (ret != -EPROBE_DEFER) |
1687 | DRM_ERROR("failed to get regulators\n"); | ||
1662 | return ret; | 1688 | return ret; |
1663 | } | 1689 | } |
1664 | 1690 | ||
@@ -1710,6 +1736,10 @@ static int hdmi_bind(struct device *dev, struct device *master, void *data) | |||
1710 | if (pipe < 0) | 1736 | if (pipe < 0) |
1711 | return pipe; | 1737 | return pipe; |
1712 | 1738 | ||
1739 | hdata->phy_clk.enable = hdmiphy_clk_enable; | ||
1740 | |||
1741 | exynos_drm_crtc_from_pipe(drm_dev, pipe)->pipe_clk = &hdata->phy_clk; | ||
1742 | |||
1713 | encoder->possible_crtcs = 1 << pipe; | 1743 | encoder->possible_crtcs = 1 << pipe; |
1714 | 1744 | ||
1715 | DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs); | 1745 | DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs); |
@@ -1777,7 +1807,8 @@ static int hdmi_probe(struct platform_device *pdev) | |||
1777 | 1807 | ||
1778 | ret = hdmi_resources_init(hdata); | 1808 | ret = hdmi_resources_init(hdata); |
1779 | if (ret) { | 1809 | if (ret) { |
1780 | DRM_ERROR("hdmi_resources_init failed\n"); | 1810 | if (ret != -EPROBE_DEFER) |
1811 | DRM_ERROR("hdmi_resources_init failed\n"); | ||
1781 | return ret; | 1812 | return ret; |
1782 | } | 1813 | } |
1783 | 1814 | ||