aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2015-12-03 21:26:29 -0500
committerDave Airlie <airlied@redhat.com>2015-12-03 21:26:29 -0500
commitf46e699cb6f44e79f3df33966c239ab1f4da5778 (patch)
tree03963163e21618152314a8a729e8d6e474fad34c
parent00b83070b3ba287bf0100b9a8180e06b5b5bbde1 (diff)
parent5e4789d357a575f9777dec317cc0efc7b7458714 (diff)
Merge tag 'imx-drm-fixes-2015-12-01' of git://git.pengutronix.de/git/pza/linux into drm-fixes
imx-drm crtc, plane, parallel panel, and TV encoder fixes - Use drm_crtc_send_vblank_event to fix per crtc vblank handling - Move the crtc device of_node assignment out of the ipuv3-crtc driver into ipu-common code, where the devices are created. - Fix parallel display support with simple-panels - Remove some unused fields and superfluous checks - Switch to universal planes and add error handling for primary plane creation - Fix module autoload for TV encoder driver * tag 'imx-drm-fixes-2015-12-01' of git://git.pengutronix.de/git/pza/linux: drm: imx: imx-tve: Fix module autoload for OF platform driver drm: imx: convert to drm_crtc_send_vblank_event() GPU-DRM-IMX: Delete an unnecessary check before drm_fbdev_cma_restore_mode() drm/imx: Remove of_node assignment from ipuv3-crtc driver probe gpu: ipu-v3: Assign of_node of child platform devices to corresponding ports gpu: ipu-v3: Remove reg_offset field gpu: ipu-v3: drop unused dmfc field from client platform data drm/imx: parallel-display: allow to determine bus format from the connected panel drm/imx: ipuv3-crtc: Return error if ipu_plane_init() fails for primary plane drm/imx: switch to universal planes
-rw-r--r--drivers/gpu/drm/imx/imx-drm-core.c7
-rw-r--r--drivers/gpu/drm/imx/imx-drm.h3
-rw-r--r--drivers/gpu/drm/imx/imx-tve.c1
-rw-r--r--drivers/gpu/drm/imx/ipuv3-crtc.c63
-rw-r--r--drivers/gpu/drm/imx/ipuv3-plane.c9
-rw-r--r--drivers/gpu/drm/imx/ipuv3-plane.h2
-rw-r--r--drivers/gpu/drm/imx/parallel-display.c4
-rw-r--r--drivers/gpu/ipu-v3/ipu-common.c69
-rw-r--r--include/video/imx-ipu-v3.h1
9 files changed, 70 insertions, 89 deletions
diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c
index 64f16ea779ef..7b990b4e96d2 100644
--- a/drivers/gpu/drm/imx/imx-drm-core.c
+++ b/drivers/gpu/drm/imx/imx-drm-core.c
@@ -63,8 +63,7 @@ static void imx_drm_driver_lastclose(struct drm_device *drm)
63#if IS_ENABLED(CONFIG_DRM_IMX_FB_HELPER) 63#if IS_ENABLED(CONFIG_DRM_IMX_FB_HELPER)
64 struct imx_drm_device *imxdrm = drm->dev_private; 64 struct imx_drm_device *imxdrm = drm->dev_private;
65 65
66 if (imxdrm->fbhelper) 66 drm_fbdev_cma_restore_mode(imxdrm->fbhelper);
67 drm_fbdev_cma_restore_mode(imxdrm->fbhelper);
68#endif 67#endif
69} 68}
70 69
@@ -340,7 +339,7 @@ err_kms:
340 * imx_drm_add_crtc - add a new crtc 339 * imx_drm_add_crtc - add a new crtc
341 */ 340 */
342int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc, 341int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc,
343 struct imx_drm_crtc **new_crtc, 342 struct imx_drm_crtc **new_crtc, struct drm_plane *primary_plane,
344 const struct imx_drm_crtc_helper_funcs *imx_drm_helper_funcs, 343 const struct imx_drm_crtc_helper_funcs *imx_drm_helper_funcs,
345 struct device_node *port) 344 struct device_node *port)
346{ 345{
@@ -379,7 +378,7 @@ int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc,
379 drm_crtc_helper_add(crtc, 378 drm_crtc_helper_add(crtc,
380 imx_drm_crtc->imx_drm_helper_funcs.crtc_helper_funcs); 379 imx_drm_crtc->imx_drm_helper_funcs.crtc_helper_funcs);
381 380
382 drm_crtc_init(drm, crtc, 381 drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL,
383 imx_drm_crtc->imx_drm_helper_funcs.crtc_funcs); 382 imx_drm_crtc->imx_drm_helper_funcs.crtc_funcs);
384 383
385 return 0; 384 return 0;
diff --git a/drivers/gpu/drm/imx/imx-drm.h b/drivers/gpu/drm/imx/imx-drm.h
index 28e776d8d9d2..83284b4d4be1 100644
--- a/drivers/gpu/drm/imx/imx-drm.h
+++ b/drivers/gpu/drm/imx/imx-drm.h
@@ -9,6 +9,7 @@ struct drm_display_mode;
9struct drm_encoder; 9struct drm_encoder;
10struct drm_fbdev_cma; 10struct drm_fbdev_cma;
11struct drm_framebuffer; 11struct drm_framebuffer;
12struct drm_plane;
12struct imx_drm_crtc; 13struct imx_drm_crtc;
13struct platform_device; 14struct platform_device;
14 15
@@ -24,7 +25,7 @@ struct imx_drm_crtc_helper_funcs {
24}; 25};
25 26
26int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc, 27int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc,
27 struct imx_drm_crtc **new_crtc, 28 struct imx_drm_crtc **new_crtc, struct drm_plane *primary_plane,
28 const struct imx_drm_crtc_helper_funcs *imx_helper_funcs, 29 const struct imx_drm_crtc_helper_funcs *imx_helper_funcs,
29 struct device_node *port); 30 struct device_node *port);
30int imx_drm_remove_crtc(struct imx_drm_crtc *); 31int imx_drm_remove_crtc(struct imx_drm_crtc *);
diff --git a/drivers/gpu/drm/imx/imx-tve.c b/drivers/gpu/drm/imx/imx-tve.c
index e671ad369416..f9597146dc67 100644
--- a/drivers/gpu/drm/imx/imx-tve.c
+++ b/drivers/gpu/drm/imx/imx-tve.c
@@ -721,6 +721,7 @@ static const struct of_device_id imx_tve_dt_ids[] = {
721 { .compatible = "fsl,imx53-tve", }, 721 { .compatible = "fsl,imx53-tve", },
722 { /* sentinel */ } 722 { /* sentinel */ }
723}; 723};
724MODULE_DEVICE_TABLE(of, imx_tve_dt_ids);
724 725
725static struct platform_driver imx_tve_driver = { 726static struct platform_driver imx_tve_driver = {
726 .probe = imx_tve_probe, 727 .probe = imx_tve_probe,
diff --git a/drivers/gpu/drm/imx/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3-crtc.c
index 7bc8301fafff..4ab841eebee1 100644
--- a/drivers/gpu/drm/imx/ipuv3-crtc.c
+++ b/drivers/gpu/drm/imx/ipuv3-crtc.c
@@ -212,7 +212,8 @@ static void ipu_crtc_handle_pageflip(struct ipu_crtc *ipu_crtc)
212 212
213 spin_lock_irqsave(&drm->event_lock, flags); 213 spin_lock_irqsave(&drm->event_lock, flags);
214 if (ipu_crtc->page_flip_event) 214 if (ipu_crtc->page_flip_event)
215 drm_send_vblank_event(drm, -1, ipu_crtc->page_flip_event); 215 drm_crtc_send_vblank_event(&ipu_crtc->base,
216 ipu_crtc->page_flip_event);
216 ipu_crtc->page_flip_event = NULL; 217 ipu_crtc->page_flip_event = NULL;
217 imx_drm_crtc_vblank_put(ipu_crtc->imx_crtc); 218 imx_drm_crtc_vblank_put(ipu_crtc->imx_crtc);
218 spin_unlock_irqrestore(&drm->event_lock, flags); 219 spin_unlock_irqrestore(&drm->event_lock, flags);
@@ -349,7 +350,6 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
349 struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent); 350 struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
350 int dp = -EINVAL; 351 int dp = -EINVAL;
351 int ret; 352 int ret;
352 int id;
353 353
354 ret = ipu_get_resources(ipu_crtc, pdata); 354 ret = ipu_get_resources(ipu_crtc, pdata);
355 if (ret) { 355 if (ret) {
@@ -358,18 +358,23 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
358 return ret; 358 return ret;
359 } 359 }
360 360
361 if (pdata->dp >= 0)
362 dp = IPU_DP_FLOW_SYNC_BG;
363 ipu_crtc->plane[0] = ipu_plane_init(drm, ipu, pdata->dma[0], dp, 0,
364 DRM_PLANE_TYPE_PRIMARY);
365 if (IS_ERR(ipu_crtc->plane[0])) {
366 ret = PTR_ERR(ipu_crtc->plane[0]);
367 goto err_put_resources;
368 }
369
361 ret = imx_drm_add_crtc(drm, &ipu_crtc->base, &ipu_crtc->imx_crtc, 370 ret = imx_drm_add_crtc(drm, &ipu_crtc->base, &ipu_crtc->imx_crtc,
362 &ipu_crtc_helper_funcs, ipu_crtc->dev->of_node); 371 &ipu_crtc->plane[0]->base, &ipu_crtc_helper_funcs,
372 ipu_crtc->dev->of_node);
363 if (ret) { 373 if (ret) {
364 dev_err(ipu_crtc->dev, "adding crtc failed with %d.\n", ret); 374 dev_err(ipu_crtc->dev, "adding crtc failed with %d.\n", ret);
365 goto err_put_resources; 375 goto err_put_resources;
366 } 376 }
367 377
368 if (pdata->dp >= 0)
369 dp = IPU_DP_FLOW_SYNC_BG;
370 id = imx_drm_crtc_id(ipu_crtc->imx_crtc);
371 ipu_crtc->plane[0] = ipu_plane_init(ipu_crtc->base.dev, ipu,
372 pdata->dma[0], dp, BIT(id), true);
373 ret = ipu_plane_get_resources(ipu_crtc->plane[0]); 378 ret = ipu_plane_get_resources(ipu_crtc->plane[0]);
374 if (ret) { 379 if (ret) {
375 dev_err(ipu_crtc->dev, "getting plane 0 resources failed with %d.\n", 380 dev_err(ipu_crtc->dev, "getting plane 0 resources failed with %d.\n",
@@ -379,10 +384,10 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
379 384
380 /* If this crtc is using the DP, add an overlay plane */ 385 /* If this crtc is using the DP, add an overlay plane */
381 if (pdata->dp >= 0 && pdata->dma[1] > 0) { 386 if (pdata->dp >= 0 && pdata->dma[1] > 0) {
382 ipu_crtc->plane[1] = ipu_plane_init(ipu_crtc->base.dev, ipu, 387 ipu_crtc->plane[1] = ipu_plane_init(drm, ipu, pdata->dma[1],
383 pdata->dma[1], 388 IPU_DP_FLOW_SYNC_FG,
384 IPU_DP_FLOW_SYNC_FG, 389 drm_crtc_mask(&ipu_crtc->base),
385 BIT(id), false); 390 DRM_PLANE_TYPE_OVERLAY);
386 if (IS_ERR(ipu_crtc->plane[1])) 391 if (IS_ERR(ipu_crtc->plane[1]))
387 ipu_crtc->plane[1] = NULL; 392 ipu_crtc->plane[1] = NULL;
388 } 393 }
@@ -407,28 +412,6 @@ err_put_resources:
407 return ret; 412 return ret;
408} 413}
409 414
410static struct device_node *ipu_drm_get_port_by_id(struct device_node *parent,
411 int port_id)
412{
413 struct device_node *port;
414 int id, ret;
415
416 port = of_get_child_by_name(parent, "port");
417 while (port) {
418 ret = of_property_read_u32(port, "reg", &id);
419 if (!ret && id == port_id)
420 return port;
421
422 do {
423 port = of_get_next_child(parent, port);
424 if (!port)
425 return NULL;
426 } while (of_node_cmp(port->name, "port"));
427 }
428
429 return NULL;
430}
431
432static int ipu_drm_bind(struct device *dev, struct device *master, void *data) 415static int ipu_drm_bind(struct device *dev, struct device *master, void *data)
433{ 416{
434 struct ipu_client_platformdata *pdata = dev->platform_data; 417 struct ipu_client_platformdata *pdata = dev->platform_data;
@@ -470,23 +453,11 @@ static const struct component_ops ipu_crtc_ops = {
470static int ipu_drm_probe(struct platform_device *pdev) 453static int ipu_drm_probe(struct platform_device *pdev)
471{ 454{
472 struct device *dev = &pdev->dev; 455 struct device *dev = &pdev->dev;
473 struct ipu_client_platformdata *pdata = dev->platform_data;
474 int ret; 456 int ret;
475 457
476 if (!dev->platform_data) 458 if (!dev->platform_data)
477 return -EINVAL; 459 return -EINVAL;
478 460
479 if (!dev->of_node) {
480 /* Associate crtc device with the corresponding DI port node */
481 dev->of_node = ipu_drm_get_port_by_id(dev->parent->of_node,
482 pdata->di + 2);
483 if (!dev->of_node) {
484 dev_err(dev, "missing port@%d node in %s\n",
485 pdata->di + 2, dev->parent->of_node->full_name);
486 return -ENODEV;
487 }
488 }
489
490 ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); 461 ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
491 if (ret) 462 if (ret)
492 return ret; 463 return ret;
diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c
index 575f4c84388f..e2ff410bab74 100644
--- a/drivers/gpu/drm/imx/ipuv3-plane.c
+++ b/drivers/gpu/drm/imx/ipuv3-plane.c
@@ -381,7 +381,7 @@ static struct drm_plane_funcs ipu_plane_funcs = {
381 381
382struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu, 382struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
383 int dma, int dp, unsigned int possible_crtcs, 383 int dma, int dp, unsigned int possible_crtcs,
384 bool priv) 384 enum drm_plane_type type)
385{ 385{
386 struct ipu_plane *ipu_plane; 386 struct ipu_plane *ipu_plane;
387 int ret; 387 int ret;
@@ -399,10 +399,9 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
399 ipu_plane->dma = dma; 399 ipu_plane->dma = dma;
400 ipu_plane->dp_flow = dp; 400 ipu_plane->dp_flow = dp;
401 401
402 ret = drm_plane_init(dev, &ipu_plane->base, possible_crtcs, 402 ret = drm_universal_plane_init(dev, &ipu_plane->base, possible_crtcs,
403 &ipu_plane_funcs, ipu_plane_formats, 403 &ipu_plane_funcs, ipu_plane_formats,
404 ARRAY_SIZE(ipu_plane_formats), 404 ARRAY_SIZE(ipu_plane_formats), type);
405 priv);
406 if (ret) { 405 if (ret) {
407 DRM_ERROR("failed to initialize plane\n"); 406 DRM_ERROR("failed to initialize plane\n");
408 kfree(ipu_plane); 407 kfree(ipu_plane);
diff --git a/drivers/gpu/drm/imx/ipuv3-plane.h b/drivers/gpu/drm/imx/ipuv3-plane.h
index 9b5eff18f5b8..3a443b413c60 100644
--- a/drivers/gpu/drm/imx/ipuv3-plane.h
+++ b/drivers/gpu/drm/imx/ipuv3-plane.h
@@ -34,7 +34,7 @@ struct ipu_plane {
34 34
35struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu, 35struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
36 int dma, int dp, unsigned int possible_crtcs, 36 int dma, int dp, unsigned int possible_crtcs,
37 bool priv); 37 enum drm_plane_type type);
38 38
39/* Init IDMAC, DMFC, DP */ 39/* Init IDMAC, DMFC, DP */
40int ipu_plane_mode_set(struct ipu_plane *plane, struct drm_crtc *crtc, 40int ipu_plane_mode_set(struct ipu_plane *plane, struct drm_crtc *crtc,
diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c
index b4deb9cf9d71..2e9b9f1b5cd2 100644
--- a/drivers/gpu/drm/imx/parallel-display.c
+++ b/drivers/gpu/drm/imx/parallel-display.c
@@ -54,7 +54,11 @@ static int imx_pd_connector_get_modes(struct drm_connector *connector)
54 54
55 if (imxpd->panel && imxpd->panel->funcs && 55 if (imxpd->panel && imxpd->panel->funcs &&
56 imxpd->panel->funcs->get_modes) { 56 imxpd->panel->funcs->get_modes) {
57 struct drm_display_info *di = &connector->display_info;
58
57 num_modes = imxpd->panel->funcs->get_modes(imxpd->panel); 59 num_modes = imxpd->panel->funcs->get_modes(imxpd->panel);
60 if (!imxpd->bus_format && di->num_bus_formats)
61 imxpd->bus_format = di->bus_formats[0];
58 if (num_modes > 0) 62 if (num_modes > 0)
59 return num_modes; 63 return num_modes;
60 } 64 }
diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c
index ba47b30d28fa..f2e13eb8339f 100644
--- a/drivers/gpu/ipu-v3/ipu-common.c
+++ b/drivers/gpu/ipu-v3/ipu-common.c
@@ -28,6 +28,7 @@
28#include <linux/irqchip/chained_irq.h> 28#include <linux/irqchip/chained_irq.h>
29#include <linux/irqdomain.h> 29#include <linux/irqdomain.h>
30#include <linux/of_device.h> 30#include <linux/of_device.h>
31#include <linux/of_graph.h>
31 32
32#include <drm/drm_fourcc.h> 33#include <drm/drm_fourcc.h>
33 34
@@ -993,12 +994,26 @@ static void platform_device_unregister_children(struct platform_device *pdev)
993struct ipu_platform_reg { 994struct ipu_platform_reg {
994 struct ipu_client_platformdata pdata; 995 struct ipu_client_platformdata pdata;
995 const char *name; 996 const char *name;
996 int reg_offset;
997}; 997};
998 998
999/* These must be in the order of the corresponding device tree port nodes */
999static const struct ipu_platform_reg client_reg[] = { 1000static const struct ipu_platform_reg client_reg[] = {
1000 { 1001 {
1001 .pdata = { 1002 .pdata = {
1003 .csi = 0,
1004 .dma[0] = IPUV3_CHANNEL_CSI0,
1005 .dma[1] = -EINVAL,
1006 },
1007 .name = "imx-ipuv3-camera",
1008 }, {
1009 .pdata = {
1010 .csi = 1,
1011 .dma[0] = IPUV3_CHANNEL_CSI1,
1012 .dma[1] = -EINVAL,
1013 },
1014 .name = "imx-ipuv3-camera",
1015 }, {
1016 .pdata = {
1002 .di = 0, 1017 .di = 0,
1003 .dc = 5, 1018 .dc = 5,
1004 .dp = IPU_DP_FLOW_SYNC_BG, 1019 .dp = IPU_DP_FLOW_SYNC_BG,
@@ -1015,22 +1030,6 @@ static const struct ipu_platform_reg client_reg[] = {
1015 .dma[1] = -EINVAL, 1030 .dma[1] = -EINVAL,
1016 }, 1031 },
1017 .name = "imx-ipuv3-crtc", 1032 .name = "imx-ipuv3-crtc",
1018 }, {
1019 .pdata = {
1020 .csi = 0,
1021 .dma[0] = IPUV3_CHANNEL_CSI0,
1022 .dma[1] = -EINVAL,
1023 },
1024 .reg_offset = IPU_CM_CSI0_REG_OFS,
1025 .name = "imx-ipuv3-camera",
1026 }, {
1027 .pdata = {
1028 .csi = 1,
1029 .dma[0] = IPUV3_CHANNEL_CSI1,
1030 .dma[1] = -EINVAL,
1031 },
1032 .reg_offset = IPU_CM_CSI1_REG_OFS,
1033 .name = "imx-ipuv3-camera",
1034 }, 1033 },
1035}; 1034};
1036 1035
@@ -1051,22 +1050,30 @@ static int ipu_add_client_devices(struct ipu_soc *ipu, unsigned long ipu_base)
1051 for (i = 0; i < ARRAY_SIZE(client_reg); i++) { 1050 for (i = 0; i < ARRAY_SIZE(client_reg); i++) {
1052 const struct ipu_platform_reg *reg = &client_reg[i]; 1051 const struct ipu_platform_reg *reg = &client_reg[i];
1053 struct platform_device *pdev; 1052 struct platform_device *pdev;
1054 struct resource res; 1053
1055 1054 pdev = platform_device_alloc(reg->name, id++);
1056 if (reg->reg_offset) { 1055 if (!pdev) {
1057 memset(&res, 0, sizeof(res)); 1056 ret = -ENOMEM;
1058 res.flags = IORESOURCE_MEM; 1057 goto err_register;
1059 res.start = ipu_base + ipu->devtype->cm_ofs + reg->reg_offset; 1058 }
1060 res.end = res.start + PAGE_SIZE - 1; 1059
1061 pdev = platform_device_register_resndata(dev, reg->name, 1060 pdev->dev.parent = dev;
1062 id++, &res, 1, &reg->pdata, sizeof(reg->pdata)); 1061
1063 } else { 1062 /* Associate subdevice with the corresponding port node */
1064 pdev = platform_device_register_data(dev, reg->name, 1063 pdev->dev.of_node = of_graph_get_port_by_id(dev->of_node, i);
1065 id++, &reg->pdata, sizeof(reg->pdata)); 1064 if (!pdev->dev.of_node) {
1065 dev_err(dev, "missing port@%d node in %s\n", i,
1066 dev->of_node->full_name);
1067 ret = -ENODEV;
1068 goto err_register;
1066 } 1069 }
1067 1070
1068 if (IS_ERR(pdev)) { 1071 ret = platform_device_add_data(pdev, &reg->pdata,
1069 ret = PTR_ERR(pdev); 1072 sizeof(reg->pdata));
1073 if (!ret)
1074 ret = platform_device_add(pdev);
1075 if (ret) {
1076 platform_device_put(pdev);
1070 goto err_register; 1077 goto err_register;
1071 } 1078 }
1072 } 1079 }
diff --git a/include/video/imx-ipu-v3.h b/include/video/imx-ipu-v3.h
index 85dedca3dcfb..eeba75395f7d 100644
--- a/include/video/imx-ipu-v3.h
+++ b/include/video/imx-ipu-v3.h
@@ -343,7 +343,6 @@ struct ipu_client_platformdata {
343 int di; 343 int di;
344 int dc; 344 int dc;
345 int dp; 345 int dp;
346 int dmfc;
347 int dma[2]; 346 int dma[2];
348}; 347};
349 348