diff options
Diffstat (limited to 'drivers/gpu/drm/stm/ltdc.c')
-rw-r--r-- | drivers/gpu/drm/stm/ltdc.c | 66 |
1 files changed, 46 insertions, 20 deletions
diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c index 735c9081202a..35e884239f60 100644 --- a/drivers/gpu/drm/stm/ltdc.c +++ b/drivers/gpu/drm/stm/ltdc.c | |||
@@ -33,6 +33,8 @@ | |||
33 | 33 | ||
34 | #define MAX_IRQ 4 | 34 | #define MAX_IRQ 4 |
35 | 35 | ||
36 | #define MAX_ENDPOINTS 2 | ||
37 | |||
36 | #define HWVER_10200 0x010200 | 38 | #define HWVER_10200 0x010200 |
37 | #define HWVER_10300 0x010300 | 39 | #define HWVER_10300 0x010300 |
38 | #define HWVER_20101 0x020101 | 40 | #define HWVER_20101 0x020101 |
@@ -556,7 +558,7 @@ static int ltdc_plane_atomic_check(struct drm_plane *plane, | |||
556 | src_h = state->src_h >> 16; | 558 | src_h = state->src_h >> 16; |
557 | 559 | ||
558 | /* Reject scaling */ | 560 | /* Reject scaling */ |
559 | if ((src_w != state->crtc_w) || (src_h != state->crtc_h)) { | 561 | if (src_w != state->crtc_w || src_h != state->crtc_h) { |
560 | DRM_ERROR("Scaling is not supported"); | 562 | DRM_ERROR("Scaling is not supported"); |
561 | return -EINVAL; | 563 | return -EINVAL; |
562 | } | 564 | } |
@@ -856,18 +858,33 @@ int ltdc_load(struct drm_device *ddev) | |||
856 | struct ltdc_device *ldev = ddev->dev_private; | 858 | struct ltdc_device *ldev = ddev->dev_private; |
857 | struct device *dev = ddev->dev; | 859 | struct device *dev = ddev->dev; |
858 | struct device_node *np = dev->of_node; | 860 | struct device_node *np = dev->of_node; |
859 | struct drm_bridge *bridge; | 861 | struct drm_bridge *bridge[MAX_ENDPOINTS] = {NULL}; |
860 | struct drm_panel *panel; | 862 | struct drm_panel *panel[MAX_ENDPOINTS] = {NULL}; |
861 | struct drm_crtc *crtc; | 863 | struct drm_crtc *crtc; |
862 | struct reset_control *rstc; | 864 | struct reset_control *rstc; |
863 | struct resource *res; | 865 | struct resource *res; |
864 | int irq, ret, i; | 866 | int irq, ret, i, endpoint_not_ready = -ENODEV; |
865 | 867 | ||
866 | DRM_DEBUG_DRIVER("\n"); | 868 | DRM_DEBUG_DRIVER("\n"); |
867 | 869 | ||
868 | ret = drm_of_find_panel_or_bridge(np, 0, 0, &panel, &bridge); | 870 | /* Get endpoints if any */ |
869 | if (ret) | 871 | for (i = 0; i < MAX_ENDPOINTS; i++) { |
870 | return ret; | 872 | ret = drm_of_find_panel_or_bridge(np, 0, i, &panel[i], |
873 | &bridge[i]); | ||
874 | |||
875 | /* | ||
876 | * If at least one endpoint is ready, continue probing, | ||
877 | * else if at least one endpoint is -EPROBE_DEFER and | ||
878 | * there is no previous ready endpoints, defer probing. | ||
879 | */ | ||
880 | if (!ret) | ||
881 | endpoint_not_ready = 0; | ||
882 | else if (ret == -EPROBE_DEFER && endpoint_not_ready) | ||
883 | endpoint_not_ready = -EPROBE_DEFER; | ||
884 | } | ||
885 | |||
886 | if (endpoint_not_ready) | ||
887 | return endpoint_not_ready; | ||
871 | 888 | ||
872 | rstc = devm_reset_control_get_exclusive(dev, NULL); | 889 | rstc = devm_reset_control_get_exclusive(dev, NULL); |
873 | 890 | ||
@@ -928,19 +945,25 @@ int ltdc_load(struct drm_device *ddev) | |||
928 | 945 | ||
929 | DRM_INFO("ltdc hw version 0x%08x - ready\n", ldev->caps.hw_version); | 946 | DRM_INFO("ltdc hw version 0x%08x - ready\n", ldev->caps.hw_version); |
930 | 947 | ||
931 | if (panel) { | 948 | /* Add endpoints panels or bridges if any */ |
932 | bridge = drm_panel_bridge_add(panel, DRM_MODE_CONNECTOR_DPI); | 949 | for (i = 0; i < MAX_ENDPOINTS; i++) { |
933 | if (IS_ERR(bridge)) { | 950 | if (panel[i]) { |
934 | DRM_ERROR("Failed to create panel-bridge\n"); | 951 | bridge[i] = drm_panel_bridge_add(panel[i], |
935 | ret = PTR_ERR(bridge); | 952 | DRM_MODE_CONNECTOR_DPI); |
936 | goto err; | 953 | if (IS_ERR(bridge[i])) { |
954 | DRM_ERROR("panel-bridge endpoint %d\n", i); | ||
955 | ret = PTR_ERR(bridge[i]); | ||
956 | goto err; | ||
957 | } | ||
937 | } | 958 | } |
938 | } | ||
939 | 959 | ||
940 | ret = ltdc_encoder_init(ddev, bridge); | 960 | if (bridge[i]) { |
941 | if (ret) { | 961 | ret = ltdc_encoder_init(ddev, bridge[i]); |
942 | DRM_ERROR("Failed to init encoder\n"); | 962 | if (ret) { |
943 | goto err; | 963 | DRM_ERROR("init encoder endpoint %d\n", i); |
964 | goto err; | ||
965 | } | ||
966 | } | ||
944 | } | 967 | } |
945 | 968 | ||
946 | crtc = devm_kzalloc(dev, sizeof(*crtc), GFP_KERNEL); | 969 | crtc = devm_kzalloc(dev, sizeof(*crtc), GFP_KERNEL); |
@@ -968,7 +991,8 @@ int ltdc_load(struct drm_device *ddev) | |||
968 | return 0; | 991 | return 0; |
969 | 992 | ||
970 | err: | 993 | err: |
971 | drm_panel_bridge_remove(bridge); | 994 | for (i = 0; i < MAX_ENDPOINTS; i++) |
995 | drm_panel_bridge_remove(bridge[i]); | ||
972 | 996 | ||
973 | clk_disable_unprepare(ldev->pixel_clk); | 997 | clk_disable_unprepare(ldev->pixel_clk); |
974 | 998 | ||
@@ -978,10 +1002,12 @@ err: | |||
978 | void ltdc_unload(struct drm_device *ddev) | 1002 | void ltdc_unload(struct drm_device *ddev) |
979 | { | 1003 | { |
980 | struct ltdc_device *ldev = ddev->dev_private; | 1004 | struct ltdc_device *ldev = ddev->dev_private; |
1005 | int i; | ||
981 | 1006 | ||
982 | DRM_DEBUG_DRIVER("\n"); | 1007 | DRM_DEBUG_DRIVER("\n"); |
983 | 1008 | ||
984 | drm_of_panel_bridge_remove(ddev->dev->of_node, 0, 0); | 1009 | for (i = 0; i < MAX_ENDPOINTS; i++) |
1010 | drm_of_panel_bridge_remove(ddev->dev->of_node, 0, i); | ||
985 | 1011 | ||
986 | clk_disable_unprepare(ldev->pixel_clk); | 1012 | clk_disable_unprepare(ldev->pixel_clk); |
987 | } | 1013 | } |