diff options
author | Dave Airlie <airlied@redhat.com> | 2017-04-19 23:19:34 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2017-04-19 23:19:34 -0400 |
commit | cb2e77c1d53366696a7f47dbcedba99603ca1b55 (patch) | |
tree | 70d3d3e649b312f715d0239ac8c75ea1637664fd | |
parent | 856ee92e8602bd86d34388ac08381c5cb3918756 (diff) | |
parent | 2da042ac05e91b78e4484b731e8eb335c90385d3 (diff) |
Merge tag 'sunxi-drm-for-4.12' of https://git.kernel.org/pub/scm/linux/kernel/git/mripard/linux into drm-next
Allwinner DRM changes for 4.12
Not any functional changes, but a lot of preliminary rework in order to
support multiple display pipelines.
* tag 'sunxi-drm-for-4.12' of https://git.kernel.org/pub/scm/linux/kernel/git/mripard/linux: (26 commits)
MAINTAINERS: Add sun4i-drm git repo
drm/sun4i: Pass pointer for underlying backend into layer init
drm/sun4i: Pass pointers for associated backend and tcon into crtc init
drm/sun4i: tv: Get tcon and backend pointers from associated crtc
drm/sun4i: Use embedded tcon pointer to get the tcon's output port node
drm/sun4i: Fix tcon channel 0 comment about backporch = backporch + hsync
drm/sun4i: Fix TCON clock and regmap initialization sequence
drm/sun4i: Grab reserved memory region
drm/sun4i: Add backend and tcon pointers to sun4i_crtc
drm/sun4i: Add backend pointer to sun4i_layer
drm/sun4i: rgb: Pass tcon pointer when initializing RGB encoder
drm/sun4i: tv: Switch to drm_of_find_possible_crtcs
drm/sun4i: Drop hardcoded .possible_crtcs values from layers
drm/sun4i: Drop primary layer pointer from sun4i_drv
drm/sun4i: Initialize crtc from tcon bind function
drm/sun4i: Move layers from sun4i_drv to sun4i_crtc
drm/sun4i: Add end of list element for sun4i_layers_init's returned list
drm/sun4i: Set drm_crtc.port to the underlying TCON's output port node
drm/sun4i: Make sunxi_rgb2yuv_coef constant
drm/sun4i: Make sun4i_crtc_init return ERR_PTR style error codes
...
-rw-r--r-- | MAINTAINERS | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/sun4i/Makefile | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_backend.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_crtc.c | 70 | ||||
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_crtc.h | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_drv.c | 47 | ||||
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_drv.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_framebuffer.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_layer.c | 32 | ||||
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_layer.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_rgb.c | 30 | ||||
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_rgb.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_tcon.c | 36 | ||||
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_tcon.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_tv.c | 27 |
15 files changed, 164 insertions, 107 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 93ed0319b3d6..afba0760fdaf 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -4247,6 +4247,7 @@ L: dri-devel@lists.freedesktop.org | |||
4247 | S: Supported | 4247 | S: Supported |
4248 | F: drivers/gpu/drm/sun4i/ | 4248 | F: drivers/gpu/drm/sun4i/ |
4249 | F: Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt | 4249 | F: Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt |
4250 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/mripard/linux.git | ||
4250 | 4251 | ||
4251 | DRM DRIVERS FOR AMLOGIC SOCS | 4252 | DRM DRIVERS FOR AMLOGIC SOCS |
4252 | M: Neil Armstrong <narmstrong@baylibre.com> | 4253 | M: Neil Armstrong <narmstrong@baylibre.com> |
diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile index d625a82a6e5f..59b757350a1f 100644 --- a/drivers/gpu/drm/sun4i/Makefile +++ b/drivers/gpu/drm/sun4i/Makefile | |||
@@ -1,11 +1,11 @@ | |||
1 | sun4i-drm-y += sun4i_crtc.o | ||
2 | sun4i-drm-y += sun4i_drv.o | 1 | sun4i-drm-y += sun4i_drv.o |
3 | sun4i-drm-y += sun4i_framebuffer.o | 2 | sun4i-drm-y += sun4i_framebuffer.o |
4 | sun4i-drm-y += sun4i_layer.o | ||
5 | 3 | ||
6 | sun4i-tcon-y += sun4i_tcon.o | 4 | sun4i-tcon-y += sun4i_tcon.o |
7 | sun4i-tcon-y += sun4i_rgb.o | 5 | sun4i-tcon-y += sun4i_rgb.o |
8 | sun4i-tcon-y += sun4i_dotclock.o | 6 | sun4i-tcon-y += sun4i_dotclock.o |
7 | sun4i-tcon-y += sun4i_crtc.o | ||
8 | sun4i-tcon-y += sun4i_layer.o | ||
9 | 9 | ||
10 | obj-$(CONFIG_DRM_SUN4I) += sun4i-drm.o sun4i-tcon.o | 10 | obj-$(CONFIG_DRM_SUN4I) += sun4i-drm.o sun4i-tcon.o |
11 | obj-$(CONFIG_DRM_SUN4I) += sun4i_backend.o | 11 | obj-$(CONFIG_DRM_SUN4I) += sun4i_backend.o |
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index 08ce15070f80..d660741ba475 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c | |||
@@ -24,7 +24,7 @@ | |||
24 | #include "sun4i_backend.h" | 24 | #include "sun4i_backend.h" |
25 | #include "sun4i_drv.h" | 25 | #include "sun4i_drv.h" |
26 | 26 | ||
27 | static u32 sunxi_rgb2yuv_coef[12] = { | 27 | static const u32 sunxi_rgb2yuv_coef[12] = { |
28 | 0x00000107, 0x00000204, 0x00000064, 0x00000108, | 28 | 0x00000107, 0x00000204, 0x00000064, 0x00000108, |
29 | 0x00003f69, 0x00003ed6, 0x000001c1, 0x00000808, | 29 | 0x00003f69, 0x00003ed6, 0x000001c1, 0x00000808, |
30 | 0x000001c1, 0x00003e88, 0x00003fb8, 0x00000808 | 30 | 0x000001c1, 0x00003e88, 0x00003fb8, 0x00000808 |
diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c index a5d546a68e16..3c876c3a356a 100644 --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/clk-provider.h> | 19 | #include <linux/clk-provider.h> |
20 | #include <linux/ioport.h> | 20 | #include <linux/ioport.h> |
21 | #include <linux/of_address.h> | 21 | #include <linux/of_address.h> |
22 | #include <linux/of_graph.h> | ||
22 | #include <linux/of_irq.h> | 23 | #include <linux/of_irq.h> |
23 | #include <linux/regmap.h> | 24 | #include <linux/regmap.h> |
24 | 25 | ||
@@ -27,6 +28,7 @@ | |||
27 | #include "sun4i_backend.h" | 28 | #include "sun4i_backend.h" |
28 | #include "sun4i_crtc.h" | 29 | #include "sun4i_crtc.h" |
29 | #include "sun4i_drv.h" | 30 | #include "sun4i_drv.h" |
31 | #include "sun4i_layer.h" | ||
30 | #include "sun4i_tcon.h" | 32 | #include "sun4i_tcon.h" |
31 | 33 | ||
32 | static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc, | 34 | static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc, |
@@ -50,12 +52,11 @@ static void sun4i_crtc_atomic_flush(struct drm_crtc *crtc, | |||
50 | struct drm_crtc_state *old_state) | 52 | struct drm_crtc_state *old_state) |
51 | { | 53 | { |
52 | struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc); | 54 | struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc); |
53 | struct sun4i_drv *drv = scrtc->drv; | ||
54 | struct drm_pending_vblank_event *event = crtc->state->event; | 55 | struct drm_pending_vblank_event *event = crtc->state->event; |
55 | 56 | ||
56 | DRM_DEBUG_DRIVER("Committing plane changes\n"); | 57 | DRM_DEBUG_DRIVER("Committing plane changes\n"); |
57 | 58 | ||
58 | sun4i_backend_commit(drv->backend); | 59 | sun4i_backend_commit(scrtc->backend); |
59 | 60 | ||
60 | if (event) { | 61 | if (event) { |
61 | crtc->state->event = NULL; | 62 | crtc->state->event = NULL; |
@@ -72,11 +73,10 @@ static void sun4i_crtc_atomic_flush(struct drm_crtc *crtc, | |||
72 | static void sun4i_crtc_disable(struct drm_crtc *crtc) | 73 | static void sun4i_crtc_disable(struct drm_crtc *crtc) |
73 | { | 74 | { |
74 | struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc); | 75 | struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc); |
75 | struct sun4i_drv *drv = scrtc->drv; | ||
76 | 76 | ||
77 | DRM_DEBUG_DRIVER("Disabling the CRTC\n"); | 77 | DRM_DEBUG_DRIVER("Disabling the CRTC\n"); |
78 | 78 | ||
79 | sun4i_tcon_disable(drv->tcon); | 79 | sun4i_tcon_disable(scrtc->tcon); |
80 | 80 | ||
81 | if (crtc->state->event && !crtc->state->active) { | 81 | if (crtc->state->event && !crtc->state->active) { |
82 | spin_lock_irq(&crtc->dev->event_lock); | 82 | spin_lock_irq(&crtc->dev->event_lock); |
@@ -90,11 +90,10 @@ static void sun4i_crtc_disable(struct drm_crtc *crtc) | |||
90 | static void sun4i_crtc_enable(struct drm_crtc *crtc) | 90 | static void sun4i_crtc_enable(struct drm_crtc *crtc) |
91 | { | 91 | { |
92 | struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc); | 92 | struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc); |
93 | struct sun4i_drv *drv = scrtc->drv; | ||
94 | 93 | ||
95 | DRM_DEBUG_DRIVER("Enabling the CRTC\n"); | 94 | DRM_DEBUG_DRIVER("Enabling the CRTC\n"); |
96 | 95 | ||
97 | sun4i_tcon_enable(drv->tcon); | 96 | sun4i_tcon_enable(scrtc->tcon); |
98 | } | 97 | } |
99 | 98 | ||
100 | static const struct drm_crtc_helper_funcs sun4i_crtc_helper_funcs = { | 99 | static const struct drm_crtc_helper_funcs sun4i_crtc_helper_funcs = { |
@@ -107,11 +106,10 @@ static const struct drm_crtc_helper_funcs sun4i_crtc_helper_funcs = { | |||
107 | static int sun4i_crtc_enable_vblank(struct drm_crtc *crtc) | 106 | static int sun4i_crtc_enable_vblank(struct drm_crtc *crtc) |
108 | { | 107 | { |
109 | struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc); | 108 | struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc); |
110 | struct sun4i_drv *drv = scrtc->drv; | ||
111 | 109 | ||
112 | DRM_DEBUG_DRIVER("Enabling VBLANK on crtc %p\n", crtc); | 110 | DRM_DEBUG_DRIVER("Enabling VBLANK on crtc %p\n", crtc); |
113 | 111 | ||
114 | sun4i_tcon_enable_vblank(drv->tcon, true); | 112 | sun4i_tcon_enable_vblank(scrtc->tcon, true); |
115 | 113 | ||
116 | return 0; | 114 | return 0; |
117 | } | 115 | } |
@@ -119,11 +117,10 @@ static int sun4i_crtc_enable_vblank(struct drm_crtc *crtc) | |||
119 | static void sun4i_crtc_disable_vblank(struct drm_crtc *crtc) | 117 | static void sun4i_crtc_disable_vblank(struct drm_crtc *crtc) |
120 | { | 118 | { |
121 | struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc); | 119 | struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc); |
122 | struct sun4i_drv *drv = scrtc->drv; | ||
123 | 120 | ||
124 | DRM_DEBUG_DRIVER("Disabling VBLANK on crtc %p\n", crtc); | 121 | DRM_DEBUG_DRIVER("Disabling VBLANK on crtc %p\n", crtc); |
125 | 122 | ||
126 | sun4i_tcon_enable_vblank(drv->tcon, false); | 123 | sun4i_tcon_enable_vblank(scrtc->tcon, false); |
127 | } | 124 | } |
128 | 125 | ||
129 | static const struct drm_crtc_funcs sun4i_crtc_funcs = { | 126 | static const struct drm_crtc_funcs sun4i_crtc_funcs = { |
@@ -137,28 +134,67 @@ static const struct drm_crtc_funcs sun4i_crtc_funcs = { | |||
137 | .disable_vblank = sun4i_crtc_disable_vblank, | 134 | .disable_vblank = sun4i_crtc_disable_vblank, |
138 | }; | 135 | }; |
139 | 136 | ||
140 | struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm) | 137 | struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm, |
138 | struct sun4i_backend *backend, | ||
139 | struct sun4i_tcon *tcon) | ||
141 | { | 140 | { |
142 | struct sun4i_drv *drv = drm->dev_private; | ||
143 | struct sun4i_crtc *scrtc; | 141 | struct sun4i_crtc *scrtc; |
144 | int ret; | 142 | struct drm_plane *primary = NULL, *cursor = NULL; |
143 | int ret, i; | ||
145 | 144 | ||
146 | scrtc = devm_kzalloc(drm->dev, sizeof(*scrtc), GFP_KERNEL); | 145 | scrtc = devm_kzalloc(drm->dev, sizeof(*scrtc), GFP_KERNEL); |
147 | if (!scrtc) | 146 | if (!scrtc) |
147 | return ERR_PTR(-ENOMEM); | ||
148 | scrtc->backend = backend; | ||
149 | scrtc->tcon = tcon; | ||
150 | |||
151 | /* Create our layers */ | ||
152 | scrtc->layers = sun4i_layers_init(drm, scrtc->backend); | ||
153 | if (IS_ERR(scrtc->layers)) { | ||
154 | dev_err(drm->dev, "Couldn't create the planes\n"); | ||
148 | return NULL; | 155 | return NULL; |
149 | scrtc->drv = drv; | 156 | } |
157 | |||
158 | /* find primary and cursor planes for drm_crtc_init_with_planes */ | ||
159 | for (i = 0; scrtc->layers[i]; i++) { | ||
160 | struct sun4i_layer *layer = scrtc->layers[i]; | ||
161 | |||
162 | switch (layer->plane.type) { | ||
163 | case DRM_PLANE_TYPE_PRIMARY: | ||
164 | primary = &layer->plane; | ||
165 | break; | ||
166 | case DRM_PLANE_TYPE_CURSOR: | ||
167 | cursor = &layer->plane; | ||
168 | break; | ||
169 | default: | ||
170 | break; | ||
171 | } | ||
172 | } | ||
150 | 173 | ||
151 | ret = drm_crtc_init_with_planes(drm, &scrtc->crtc, | 174 | ret = drm_crtc_init_with_planes(drm, &scrtc->crtc, |
152 | drv->primary, | 175 | primary, |
153 | NULL, | 176 | cursor, |
154 | &sun4i_crtc_funcs, | 177 | &sun4i_crtc_funcs, |
155 | NULL); | 178 | NULL); |
156 | if (ret) { | 179 | if (ret) { |
157 | dev_err(drm->dev, "Couldn't init DRM CRTC\n"); | 180 | dev_err(drm->dev, "Couldn't init DRM CRTC\n"); |
158 | return NULL; | 181 | return ERR_PTR(ret); |
159 | } | 182 | } |
160 | 183 | ||
161 | drm_crtc_helper_add(&scrtc->crtc, &sun4i_crtc_helper_funcs); | 184 | drm_crtc_helper_add(&scrtc->crtc, &sun4i_crtc_helper_funcs); |
162 | 185 | ||
186 | /* Set crtc.port to output port node of the tcon */ | ||
187 | scrtc->crtc.port = of_graph_get_port_by_id(scrtc->tcon->dev->of_node, | ||
188 | 1); | ||
189 | |||
190 | /* Set possible_crtcs to this crtc for overlay planes */ | ||
191 | for (i = 0; scrtc->layers[i]; i++) { | ||
192 | uint32_t possible_crtcs = BIT(drm_crtc_index(&scrtc->crtc)); | ||
193 | struct sun4i_layer *layer = scrtc->layers[i]; | ||
194 | |||
195 | if (layer->plane.type == DRM_PLANE_TYPE_OVERLAY) | ||
196 | layer->plane.possible_crtcs = possible_crtcs; | ||
197 | } | ||
198 | |||
163 | return scrtc; | 199 | return scrtc; |
164 | } | 200 | } |
diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.h b/drivers/gpu/drm/sun4i/sun4i_crtc.h index dec8ce4d9b25..230cb8f0d601 100644 --- a/drivers/gpu/drm/sun4i/sun4i_crtc.h +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.h | |||
@@ -17,7 +17,9 @@ struct sun4i_crtc { | |||
17 | struct drm_crtc crtc; | 17 | struct drm_crtc crtc; |
18 | struct drm_pending_vblank_event *event; | 18 | struct drm_pending_vblank_event *event; |
19 | 19 | ||
20 | struct sun4i_drv *drv; | 20 | struct sun4i_backend *backend; |
21 | struct sun4i_tcon *tcon; | ||
22 | struct sun4i_layer **layers; | ||
21 | }; | 23 | }; |
22 | 24 | ||
23 | static inline struct sun4i_crtc *drm_crtc_to_sun4i_crtc(struct drm_crtc *crtc) | 25 | static inline struct sun4i_crtc *drm_crtc_to_sun4i_crtc(struct drm_crtc *crtc) |
@@ -25,6 +27,8 @@ static inline struct sun4i_crtc *drm_crtc_to_sun4i_crtc(struct drm_crtc *crtc) | |||
25 | return container_of(crtc, struct sun4i_crtc, crtc); | 27 | return container_of(crtc, struct sun4i_crtc, crtc); |
26 | } | 28 | } |
27 | 29 | ||
28 | struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm); | 30 | struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm, |
31 | struct sun4i_backend *backend, | ||
32 | struct sun4i_tcon *tcon); | ||
29 | 33 | ||
30 | #endif /* _SUN4I_CRTC_H_ */ | 34 | #endif /* _SUN4I_CRTC_H_ */ |
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c index 329ea56106a5..8ddd72cd5873 100644 --- a/drivers/gpu/drm/sun4i/sun4i_drv.c +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c | |||
@@ -12,6 +12,7 @@ | |||
12 | 12 | ||
13 | #include <linux/component.h> | 13 | #include <linux/component.h> |
14 | #include <linux/of_graph.h> | 14 | #include <linux/of_graph.h> |
15 | #include <linux/of_reserved_mem.h> | ||
15 | 16 | ||
16 | #include <drm/drmP.h> | 17 | #include <drm/drmP.h> |
17 | #include <drm/drm_crtc_helper.h> | 18 | #include <drm/drm_crtc_helper.h> |
@@ -20,10 +21,9 @@ | |||
20 | #include <drm/drm_fb_helper.h> | 21 | #include <drm/drm_fb_helper.h> |
21 | #include <drm/drm_of.h> | 22 | #include <drm/drm_of.h> |
22 | 23 | ||
23 | #include "sun4i_crtc.h" | ||
24 | #include "sun4i_drv.h" | 24 | #include "sun4i_drv.h" |
25 | #include "sun4i_framebuffer.h" | 25 | #include "sun4i_framebuffer.h" |
26 | #include "sun4i_layer.h" | 26 | #include "sun4i_tcon.h" |
27 | 27 | ||
28 | DEFINE_DRM_GEM_CMA_FOPS(sun4i_drv_fops); | 28 | DEFINE_DRM_GEM_CMA_FOPS(sun4i_drv_fops); |
29 | 29 | ||
@@ -92,30 +92,25 @@ static int sun4i_drv_bind(struct device *dev) | |||
92 | } | 92 | } |
93 | drm->dev_private = drv; | 93 | drm->dev_private = drv; |
94 | 94 | ||
95 | drm_vblank_init(drm, 1); | 95 | ret = of_reserved_mem_device_init(dev); |
96 | if (ret && ret != -ENODEV) { | ||
97 | dev_err(drm->dev, "Couldn't claim our memory region\n"); | ||
98 | goto free_drm; | ||
99 | } | ||
100 | |||
101 | /* drm_vblank_init calls kcalloc, which can fail */ | ||
102 | ret = drm_vblank_init(drm, 1); | ||
103 | if (ret) | ||
104 | goto free_mem_region; | ||
105 | |||
96 | drm_mode_config_init(drm); | 106 | drm_mode_config_init(drm); |
97 | 107 | ||
98 | ret = component_bind_all(drm->dev, drm); | 108 | ret = component_bind_all(drm->dev, drm); |
99 | if (ret) { | 109 | if (ret) { |
100 | dev_err(drm->dev, "Couldn't bind all pipelines components\n"); | 110 | dev_err(drm->dev, "Couldn't bind all pipelines components\n"); |
101 | goto free_drm; | 111 | goto cleanup_mode_config; |
102 | } | ||
103 | |||
104 | /* Create our layers */ | ||
105 | drv->layers = sun4i_layers_init(drm); | ||
106 | if (IS_ERR(drv->layers)) { | ||
107 | dev_err(drm->dev, "Couldn't create the planes\n"); | ||
108 | ret = PTR_ERR(drv->layers); | ||
109 | goto free_drm; | ||
110 | } | 112 | } |
111 | 113 | ||
112 | /* Create our CRTC */ | ||
113 | drv->crtc = sun4i_crtc_init(drm); | ||
114 | if (!drv->crtc) { | ||
115 | dev_err(drm->dev, "Couldn't create the CRTC\n"); | ||
116 | ret = -EINVAL; | ||
117 | goto free_drm; | ||
118 | } | ||
119 | drm->irq_enabled = true; | 114 | drm->irq_enabled = true; |
120 | 115 | ||
121 | /* Remove early framebuffers (ie. simplefb) */ | 116 | /* Remove early framebuffers (ie. simplefb) */ |
@@ -126,7 +121,7 @@ static int sun4i_drv_bind(struct device *dev) | |||
126 | if (IS_ERR(drv->fbdev)) { | 121 | if (IS_ERR(drv->fbdev)) { |
127 | dev_err(drm->dev, "Couldn't create our framebuffer\n"); | 122 | dev_err(drm->dev, "Couldn't create our framebuffer\n"); |
128 | ret = PTR_ERR(drv->fbdev); | 123 | ret = PTR_ERR(drv->fbdev); |
129 | goto free_drm; | 124 | goto cleanup_mode_config; |
130 | } | 125 | } |
131 | 126 | ||
132 | /* Enable connectors polling */ | 127 | /* Enable connectors polling */ |
@@ -134,10 +129,18 @@ static int sun4i_drv_bind(struct device *dev) | |||
134 | 129 | ||
135 | ret = drm_dev_register(drm, 0); | 130 | ret = drm_dev_register(drm, 0); |
136 | if (ret) | 131 | if (ret) |
137 | goto free_drm; | 132 | goto finish_poll; |
138 | 133 | ||
139 | return 0; | 134 | return 0; |
140 | 135 | ||
136 | finish_poll: | ||
137 | drm_kms_helper_poll_fini(drm); | ||
138 | sun4i_framebuffer_free(drm); | ||
139 | cleanup_mode_config: | ||
140 | drm_mode_config_cleanup(drm); | ||
141 | drm_vblank_cleanup(drm); | ||
142 | free_mem_region: | ||
143 | of_reserved_mem_device_release(dev); | ||
141 | free_drm: | 144 | free_drm: |
142 | drm_dev_unref(drm); | 145 | drm_dev_unref(drm); |
143 | return ret; | 146 | return ret; |
@@ -150,7 +153,9 @@ static void sun4i_drv_unbind(struct device *dev) | |||
150 | drm_dev_unregister(drm); | 153 | drm_dev_unregister(drm); |
151 | drm_kms_helper_poll_fini(drm); | 154 | drm_kms_helper_poll_fini(drm); |
152 | sun4i_framebuffer_free(drm); | 155 | sun4i_framebuffer_free(drm); |
156 | drm_mode_config_cleanup(drm); | ||
153 | drm_vblank_cleanup(drm); | 157 | drm_vblank_cleanup(drm); |
158 | of_reserved_mem_device_release(dev); | ||
154 | drm_dev_unref(drm); | 159 | drm_dev_unref(drm); |
155 | } | 160 | } |
156 | 161 | ||
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.h b/drivers/gpu/drm/sun4i/sun4i_drv.h index 597353eab728..5df50126ff52 100644 --- a/drivers/gpu/drm/sun4i/sun4i_drv.h +++ b/drivers/gpu/drm/sun4i/sun4i_drv.h | |||
@@ -18,13 +18,9 @@ | |||
18 | 18 | ||
19 | struct sun4i_drv { | 19 | struct sun4i_drv { |
20 | struct sun4i_backend *backend; | 20 | struct sun4i_backend *backend; |
21 | struct sun4i_crtc *crtc; | ||
22 | struct sun4i_tcon *tcon; | 21 | struct sun4i_tcon *tcon; |
23 | 22 | ||
24 | struct drm_plane *primary; | ||
25 | struct drm_fbdev_cma *fbdev; | 23 | struct drm_fbdev_cma *fbdev; |
26 | |||
27 | struct sun4i_layer **layers; | ||
28 | }; | 24 | }; |
29 | 25 | ||
30 | #endif /* _SUN4I_DRV_H_ */ | 26 | #endif /* _SUN4I_DRV_H_ */ |
diff --git a/drivers/gpu/drm/sun4i/sun4i_framebuffer.c b/drivers/gpu/drm/sun4i/sun4i_framebuffer.c index 2c3beff8b53e..9872e0fc03b0 100644 --- a/drivers/gpu/drm/sun4i/sun4i_framebuffer.c +++ b/drivers/gpu/drm/sun4i/sun4i_framebuffer.c | |||
@@ -48,5 +48,4 @@ void sun4i_framebuffer_free(struct drm_device *drm) | |||
48 | struct sun4i_drv *drv = drm->dev_private; | 48 | struct sun4i_drv *drv = drm->dev_private; |
49 | 49 | ||
50 | drm_fbdev_cma_fini(drv->fbdev); | 50 | drm_fbdev_cma_fini(drv->fbdev); |
51 | drm_mode_config_cleanup(drm); | ||
52 | } | 51 | } |
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c index 5d53c977bca5..f26bde5b9117 100644 --- a/drivers/gpu/drm/sun4i/sun4i_layer.c +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <drm/drmP.h> | 16 | #include <drm/drmP.h> |
17 | 17 | ||
18 | #include "sun4i_backend.h" | 18 | #include "sun4i_backend.h" |
19 | #include "sun4i_drv.h" | ||
20 | #include "sun4i_layer.h" | 19 | #include "sun4i_layer.h" |
21 | 20 | ||
22 | struct sun4i_plane_desc { | 21 | struct sun4i_plane_desc { |
@@ -36,8 +35,7 @@ static void sun4i_backend_layer_atomic_disable(struct drm_plane *plane, | |||
36 | struct drm_plane_state *old_state) | 35 | struct drm_plane_state *old_state) |
37 | { | 36 | { |
38 | struct sun4i_layer *layer = plane_to_sun4i_layer(plane); | 37 | struct sun4i_layer *layer = plane_to_sun4i_layer(plane); |
39 | struct sun4i_drv *drv = layer->drv; | 38 | struct sun4i_backend *backend = layer->backend; |
40 | struct sun4i_backend *backend = drv->backend; | ||
41 | 39 | ||
42 | sun4i_backend_layer_enable(backend, layer->id, false); | 40 | sun4i_backend_layer_enable(backend, layer->id, false); |
43 | } | 41 | } |
@@ -46,8 +44,7 @@ static void sun4i_backend_layer_atomic_update(struct drm_plane *plane, | |||
46 | struct drm_plane_state *old_state) | 44 | struct drm_plane_state *old_state) |
47 | { | 45 | { |
48 | struct sun4i_layer *layer = plane_to_sun4i_layer(plane); | 46 | struct sun4i_layer *layer = plane_to_sun4i_layer(plane); |
49 | struct sun4i_drv *drv = layer->drv; | 47 | struct sun4i_backend *backend = layer->backend; |
50 | struct sun4i_backend *backend = drv->backend; | ||
51 | 48 | ||
52 | sun4i_backend_update_layer_coord(backend, layer->id, plane); | 49 | sun4i_backend_update_layer_coord(backend, layer->id, plane); |
53 | sun4i_backend_update_layer_formats(backend, layer->id, plane); | 50 | sun4i_backend_update_layer_formats(backend, layer->id, plane); |
@@ -104,9 +101,9 @@ static const struct sun4i_plane_desc sun4i_backend_planes[] = { | |||
104 | }; | 101 | }; |
105 | 102 | ||
106 | static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm, | 103 | static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm, |
104 | struct sun4i_backend *backend, | ||
107 | const struct sun4i_plane_desc *plane) | 105 | const struct sun4i_plane_desc *plane) |
108 | { | 106 | { |
109 | struct sun4i_drv *drv = drm->dev_private; | ||
110 | struct sun4i_layer *layer; | 107 | struct sun4i_layer *layer; |
111 | int ret; | 108 | int ret; |
112 | 109 | ||
@@ -114,7 +111,8 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm, | |||
114 | if (!layer) | 111 | if (!layer) |
115 | return ERR_PTR(-ENOMEM); | 112 | return ERR_PTR(-ENOMEM); |
116 | 113 | ||
117 | ret = drm_universal_plane_init(drm, &layer->plane, BIT(0), | 114 | /* possible crtcs are set later */ |
115 | ret = drm_universal_plane_init(drm, &layer->plane, 0, | ||
118 | &sun4i_backend_layer_funcs, | 116 | &sun4i_backend_layer_funcs, |
119 | plane->formats, plane->nformats, | 117 | plane->formats, plane->nformats, |
120 | plane->type, NULL); | 118 | plane->type, NULL); |
@@ -125,22 +123,19 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm, | |||
125 | 123 | ||
126 | drm_plane_helper_add(&layer->plane, | 124 | drm_plane_helper_add(&layer->plane, |
127 | &sun4i_backend_layer_helper_funcs); | 125 | &sun4i_backend_layer_helper_funcs); |
128 | layer->drv = drv; | 126 | layer->backend = backend; |
129 | |||
130 | if (plane->type == DRM_PLANE_TYPE_PRIMARY) | ||
131 | drv->primary = &layer->plane; | ||
132 | 127 | ||
133 | return layer; | 128 | return layer; |
134 | } | 129 | } |
135 | 130 | ||
136 | struct sun4i_layer **sun4i_layers_init(struct drm_device *drm) | 131 | struct sun4i_layer **sun4i_layers_init(struct drm_device *drm, |
132 | struct sun4i_backend *backend) | ||
137 | { | 133 | { |
138 | struct sun4i_drv *drv = drm->dev_private; | ||
139 | struct sun4i_layer **layers; | 134 | struct sun4i_layer **layers; |
140 | int i; | 135 | int i; |
141 | 136 | ||
142 | layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun4i_backend_planes), | 137 | layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun4i_backend_planes) + 1, |
143 | sizeof(**layers), GFP_KERNEL); | 138 | sizeof(*layers), GFP_KERNEL); |
144 | if (!layers) | 139 | if (!layers) |
145 | return ERR_PTR(-ENOMEM); | 140 | return ERR_PTR(-ENOMEM); |
146 | 141 | ||
@@ -167,9 +162,9 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm) | |||
167 | */ | 162 | */ |
168 | for (i = 0; i < ARRAY_SIZE(sun4i_backend_planes); i++) { | 163 | for (i = 0; i < ARRAY_SIZE(sun4i_backend_planes); i++) { |
169 | const struct sun4i_plane_desc *plane = &sun4i_backend_planes[i]; | 164 | const struct sun4i_plane_desc *plane = &sun4i_backend_planes[i]; |
170 | struct sun4i_layer *layer = layers[i]; | 165 | struct sun4i_layer *layer; |
171 | 166 | ||
172 | layer = sun4i_layer_init_one(drm, plane); | 167 | layer = sun4i_layer_init_one(drm, backend, plane); |
173 | if (IS_ERR(layer)) { | 168 | if (IS_ERR(layer)) { |
174 | dev_err(drm->dev, "Couldn't initialize %s plane\n", | 169 | dev_err(drm->dev, "Couldn't initialize %s plane\n", |
175 | i ? "overlay" : "primary"); | 170 | i ? "overlay" : "primary"); |
@@ -178,11 +173,12 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm) | |||
178 | 173 | ||
179 | DRM_DEBUG_DRIVER("Assigning %s plane to pipe %d\n", | 174 | DRM_DEBUG_DRIVER("Assigning %s plane to pipe %d\n", |
180 | i ? "overlay" : "primary", plane->pipe); | 175 | i ? "overlay" : "primary", plane->pipe); |
181 | regmap_update_bits(drv->backend->regs, SUN4I_BACKEND_ATTCTL_REG0(i), | 176 | regmap_update_bits(backend->regs, SUN4I_BACKEND_ATTCTL_REG0(i), |
182 | SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL_MASK, | 177 | SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL_MASK, |
183 | SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL(plane->pipe)); | 178 | SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL(plane->pipe)); |
184 | 179 | ||
185 | layer->id = i; | 180 | layer->id = i; |
181 | layers[i] = layer; | ||
186 | }; | 182 | }; |
187 | 183 | ||
188 | return layers; | 184 | return layers; |
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.h b/drivers/gpu/drm/sun4i/sun4i_layer.h index a2f65d7a3f4e..4be1f0919df2 100644 --- a/drivers/gpu/drm/sun4i/sun4i_layer.h +++ b/drivers/gpu/drm/sun4i/sun4i_layer.h | |||
@@ -16,6 +16,7 @@ | |||
16 | struct sun4i_layer { | 16 | struct sun4i_layer { |
17 | struct drm_plane plane; | 17 | struct drm_plane plane; |
18 | struct sun4i_drv *drv; | 18 | struct sun4i_drv *drv; |
19 | struct sun4i_backend *backend; | ||
19 | int id; | 20 | int id; |
20 | }; | 21 | }; |
21 | 22 | ||
@@ -25,6 +26,7 @@ plane_to_sun4i_layer(struct drm_plane *plane) | |||
25 | return container_of(plane, struct sun4i_layer, plane); | 26 | return container_of(plane, struct sun4i_layer, plane); |
26 | } | 27 | } |
27 | 28 | ||
28 | struct sun4i_layer **sun4i_layers_init(struct drm_device *drm); | 29 | struct sun4i_layer **sun4i_layers_init(struct drm_device *drm, |
30 | struct sun4i_backend *backend); | ||
29 | 31 | ||
30 | #endif /* _SUN4I_LAYER_H_ */ | 32 | #endif /* _SUN4I_LAYER_H_ */ |
diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c index 46280dd70c9e..67f0b91a99de 100644 --- a/drivers/gpu/drm/sun4i/sun4i_rgb.c +++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c | |||
@@ -18,7 +18,7 @@ | |||
18 | #include <drm/drm_of.h> | 18 | #include <drm/drm_of.h> |
19 | #include <drm/drm_panel.h> | 19 | #include <drm/drm_panel.h> |
20 | 20 | ||
21 | #include "sun4i_drv.h" | 21 | #include "sun4i_crtc.h" |
22 | #include "sun4i_tcon.h" | 22 | #include "sun4i_tcon.h" |
23 | #include "sun4i_rgb.h" | 23 | #include "sun4i_rgb.h" |
24 | 24 | ||
@@ -26,7 +26,7 @@ struct sun4i_rgb { | |||
26 | struct drm_connector connector; | 26 | struct drm_connector connector; |
27 | struct drm_encoder encoder; | 27 | struct drm_encoder encoder; |
28 | 28 | ||
29 | struct sun4i_drv *drv; | 29 | struct sun4i_tcon *tcon; |
30 | }; | 30 | }; |
31 | 31 | ||
32 | static inline struct sun4i_rgb * | 32 | static inline struct sun4i_rgb * |
@@ -47,8 +47,7 @@ static int sun4i_rgb_get_modes(struct drm_connector *connector) | |||
47 | { | 47 | { |
48 | struct sun4i_rgb *rgb = | 48 | struct sun4i_rgb *rgb = |
49 | drm_connector_to_sun4i_rgb(connector); | 49 | drm_connector_to_sun4i_rgb(connector); |
50 | struct sun4i_drv *drv = rgb->drv; | 50 | struct sun4i_tcon *tcon = rgb->tcon; |
51 | struct sun4i_tcon *tcon = drv->tcon; | ||
52 | 51 | ||
53 | return drm_panel_get_modes(tcon->panel); | 52 | return drm_panel_get_modes(tcon->panel); |
54 | } | 53 | } |
@@ -57,8 +56,7 @@ static int sun4i_rgb_mode_valid(struct drm_connector *connector, | |||
57 | struct drm_display_mode *mode) | 56 | struct drm_display_mode *mode) |
58 | { | 57 | { |
59 | struct sun4i_rgb *rgb = drm_connector_to_sun4i_rgb(connector); | 58 | struct sun4i_rgb *rgb = drm_connector_to_sun4i_rgb(connector); |
60 | struct sun4i_drv *drv = rgb->drv; | 59 | struct sun4i_tcon *tcon = rgb->tcon; |
61 | struct sun4i_tcon *tcon = drv->tcon; | ||
62 | u32 hsync = mode->hsync_end - mode->hsync_start; | 60 | u32 hsync = mode->hsync_end - mode->hsync_start; |
63 | u32 vsync = mode->vsync_end - mode->vsync_start; | 61 | u32 vsync = mode->vsync_end - mode->vsync_start; |
64 | unsigned long rate = mode->clock * 1000; | 62 | unsigned long rate = mode->clock * 1000; |
@@ -115,8 +113,7 @@ static void | |||
115 | sun4i_rgb_connector_destroy(struct drm_connector *connector) | 113 | sun4i_rgb_connector_destroy(struct drm_connector *connector) |
116 | { | 114 | { |
117 | struct sun4i_rgb *rgb = drm_connector_to_sun4i_rgb(connector); | 115 | struct sun4i_rgb *rgb = drm_connector_to_sun4i_rgb(connector); |
118 | struct sun4i_drv *drv = rgb->drv; | 116 | struct sun4i_tcon *tcon = rgb->tcon; |
119 | struct sun4i_tcon *tcon = drv->tcon; | ||
120 | 117 | ||
121 | drm_panel_detach(tcon->panel); | 118 | drm_panel_detach(tcon->panel); |
122 | drm_connector_cleanup(connector); | 119 | drm_connector_cleanup(connector); |
@@ -141,8 +138,7 @@ static int sun4i_rgb_atomic_check(struct drm_encoder *encoder, | |||
141 | static void sun4i_rgb_encoder_enable(struct drm_encoder *encoder) | 138 | static void sun4i_rgb_encoder_enable(struct drm_encoder *encoder) |
142 | { | 139 | { |
143 | struct sun4i_rgb *rgb = drm_encoder_to_sun4i_rgb(encoder); | 140 | struct sun4i_rgb *rgb = drm_encoder_to_sun4i_rgb(encoder); |
144 | struct sun4i_drv *drv = rgb->drv; | 141 | struct sun4i_tcon *tcon = rgb->tcon; |
145 | struct sun4i_tcon *tcon = drv->tcon; | ||
146 | 142 | ||
147 | DRM_DEBUG_DRIVER("Enabling RGB output\n"); | 143 | DRM_DEBUG_DRIVER("Enabling RGB output\n"); |
148 | 144 | ||
@@ -158,8 +154,7 @@ static void sun4i_rgb_encoder_enable(struct drm_encoder *encoder) | |||
158 | static void sun4i_rgb_encoder_disable(struct drm_encoder *encoder) | 154 | static void sun4i_rgb_encoder_disable(struct drm_encoder *encoder) |
159 | { | 155 | { |
160 | struct sun4i_rgb *rgb = drm_encoder_to_sun4i_rgb(encoder); | 156 | struct sun4i_rgb *rgb = drm_encoder_to_sun4i_rgb(encoder); |
161 | struct sun4i_drv *drv = rgb->drv; | 157 | struct sun4i_tcon *tcon = rgb->tcon; |
162 | struct sun4i_tcon *tcon = drv->tcon; | ||
163 | 158 | ||
164 | DRM_DEBUG_DRIVER("Disabling RGB output\n"); | 159 | DRM_DEBUG_DRIVER("Disabling RGB output\n"); |
165 | 160 | ||
@@ -177,8 +172,7 @@ static void sun4i_rgb_encoder_mode_set(struct drm_encoder *encoder, | |||
177 | struct drm_display_mode *adjusted_mode) | 172 | struct drm_display_mode *adjusted_mode) |
178 | { | 173 | { |
179 | struct sun4i_rgb *rgb = drm_encoder_to_sun4i_rgb(encoder); | 174 | struct sun4i_rgb *rgb = drm_encoder_to_sun4i_rgb(encoder); |
180 | struct sun4i_drv *drv = rgb->drv; | 175 | struct sun4i_tcon *tcon = rgb->tcon; |
181 | struct sun4i_tcon *tcon = drv->tcon; | ||
182 | 176 | ||
183 | sun4i_tcon0_mode_set(tcon, mode); | 177 | sun4i_tcon0_mode_set(tcon, mode); |
184 | 178 | ||
@@ -204,10 +198,8 @@ static struct drm_encoder_funcs sun4i_rgb_enc_funcs = { | |||
204 | .destroy = sun4i_rgb_enc_destroy, | 198 | .destroy = sun4i_rgb_enc_destroy, |
205 | }; | 199 | }; |
206 | 200 | ||
207 | int sun4i_rgb_init(struct drm_device *drm) | 201 | int sun4i_rgb_init(struct drm_device *drm, struct sun4i_tcon *tcon) |
208 | { | 202 | { |
209 | struct sun4i_drv *drv = drm->dev_private; | ||
210 | struct sun4i_tcon *tcon = drv->tcon; | ||
211 | struct drm_encoder *encoder; | 203 | struct drm_encoder *encoder; |
212 | struct drm_bridge *bridge; | 204 | struct drm_bridge *bridge; |
213 | struct sun4i_rgb *rgb; | 205 | struct sun4i_rgb *rgb; |
@@ -216,7 +208,7 @@ int sun4i_rgb_init(struct drm_device *drm) | |||
216 | rgb = devm_kzalloc(drm->dev, sizeof(*rgb), GFP_KERNEL); | 208 | rgb = devm_kzalloc(drm->dev, sizeof(*rgb), GFP_KERNEL); |
217 | if (!rgb) | 209 | if (!rgb) |
218 | return -ENOMEM; | 210 | return -ENOMEM; |
219 | rgb->drv = drv; | 211 | rgb->tcon = tcon; |
220 | encoder = &rgb->encoder; | 212 | encoder = &rgb->encoder; |
221 | 213 | ||
222 | ret = drm_of_find_panel_or_bridge(tcon->dev->of_node, 1, 0, | 214 | ret = drm_of_find_panel_or_bridge(tcon->dev->of_node, 1, 0, |
@@ -239,7 +231,7 @@ int sun4i_rgb_init(struct drm_device *drm) | |||
239 | } | 231 | } |
240 | 232 | ||
241 | /* The RGB encoder can only work with the TCON channel 0 */ | 233 | /* The RGB encoder can only work with the TCON channel 0 */ |
242 | rgb->encoder.possible_crtcs = BIT(0); | 234 | rgb->encoder.possible_crtcs = BIT(drm_crtc_index(&tcon->crtc->crtc)); |
243 | 235 | ||
244 | if (tcon->panel) { | 236 | if (tcon->panel) { |
245 | drm_connector_helper_add(&rgb->connector, | 237 | drm_connector_helper_add(&rgb->connector, |
diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.h b/drivers/gpu/drm/sun4i/sun4i_rgb.h index 7c4da4c8acdd..40c18f4a6c7e 100644 --- a/drivers/gpu/drm/sun4i/sun4i_rgb.h +++ b/drivers/gpu/drm/sun4i/sun4i_rgb.h | |||
@@ -13,6 +13,6 @@ | |||
13 | #ifndef _SUN4I_RGB_H_ | 13 | #ifndef _SUN4I_RGB_H_ |
14 | #define _SUN4I_RGB_H_ | 14 | #define _SUN4I_RGB_H_ |
15 | 15 | ||
16 | int sun4i_rgb_init(struct drm_device *drm); | 16 | int sun4i_rgb_init(struct drm_device *drm, struct sun4i_tcon *tcon); |
17 | 17 | ||
18 | #endif /* _SUN4I_RGB_H_ */ | 18 | #endif /* _SUN4I_RGB_H_ */ |
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c index 2e4e365cecf9..9a83a85529ac 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c | |||
@@ -142,7 +142,7 @@ void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon, | |||
142 | 142 | ||
143 | /* | 143 | /* |
144 | * This is called a backporch in the register documentation, | 144 | * This is called a backporch in the register documentation, |
145 | * but it really is the front porch + hsync | 145 | * but it really is the back porch + hsync |
146 | */ | 146 | */ |
147 | bp = mode->crtc_htotal - mode->crtc_hsync_start; | 147 | bp = mode->crtc_htotal - mode->crtc_hsync_start; |
148 | DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n", | 148 | DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n", |
@@ -155,7 +155,7 @@ void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon, | |||
155 | 155 | ||
156 | /* | 156 | /* |
157 | * This is called a backporch in the register documentation, | 157 | * This is called a backporch in the register documentation, |
158 | * but it really is the front porch + hsync | 158 | * but it really is the back porch + hsync |
159 | */ | 159 | */ |
160 | bp = mode->crtc_vtotal - mode->crtc_vsync_start; | 160 | bp = mode->crtc_vtotal - mode->crtc_vsync_start; |
161 | DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n", | 161 | DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n", |
@@ -289,8 +289,7 @@ static irqreturn_t sun4i_tcon_handler(int irq, void *private) | |||
289 | { | 289 | { |
290 | struct sun4i_tcon *tcon = private; | 290 | struct sun4i_tcon *tcon = private; |
291 | struct drm_device *drm = tcon->drm; | 291 | struct drm_device *drm = tcon->drm; |
292 | struct sun4i_drv *drv = drm->dev_private; | 292 | struct sun4i_crtc *scrtc = tcon->crtc; |
293 | struct sun4i_crtc *scrtc = drv->crtc; | ||
294 | unsigned int status; | 293 | unsigned int status; |
295 | 294 | ||
296 | regmap_read(tcon->regs, SUN4I_TCON_GINT0_REG, &status); | 295 | regmap_read(tcon->regs, SUN4I_TCON_GINT0_REG, &status); |
@@ -335,12 +334,11 @@ static int sun4i_tcon_init_clocks(struct device *dev, | |||
335 | } | 334 | } |
336 | } | 335 | } |
337 | 336 | ||
338 | return sun4i_dclk_create(dev, tcon); | 337 | return 0; |
339 | } | 338 | } |
340 | 339 | ||
341 | static void sun4i_tcon_free_clocks(struct sun4i_tcon *tcon) | 340 | static void sun4i_tcon_free_clocks(struct sun4i_tcon *tcon) |
342 | { | 341 | { |
343 | sun4i_dclk_free(tcon); | ||
344 | clk_disable_unprepare(tcon->clk); | 342 | clk_disable_unprepare(tcon->clk); |
345 | } | 343 | } |
346 | 344 | ||
@@ -437,30 +435,45 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master, | |||
437 | return ret; | 435 | return ret; |
438 | } | 436 | } |
439 | 437 | ||
438 | ret = sun4i_tcon_init_clocks(dev, tcon); | ||
439 | if (ret) { | ||
440 | dev_err(dev, "Couldn't init our TCON clocks\n"); | ||
441 | goto err_assert_reset; | ||
442 | } | ||
443 | |||
440 | ret = sun4i_tcon_init_regmap(dev, tcon); | 444 | ret = sun4i_tcon_init_regmap(dev, tcon); |
441 | if (ret) { | 445 | if (ret) { |
442 | dev_err(dev, "Couldn't init our TCON regmap\n"); | 446 | dev_err(dev, "Couldn't init our TCON regmap\n"); |
443 | goto err_assert_reset; | 447 | goto err_free_clocks; |
444 | } | 448 | } |
445 | 449 | ||
446 | ret = sun4i_tcon_init_clocks(dev, tcon); | 450 | ret = sun4i_dclk_create(dev, tcon); |
447 | if (ret) { | 451 | if (ret) { |
448 | dev_err(dev, "Couldn't init our TCON clocks\n"); | 452 | dev_err(dev, "Couldn't create our TCON dot clock\n"); |
449 | goto err_assert_reset; | 453 | goto err_free_clocks; |
450 | } | 454 | } |
451 | 455 | ||
452 | ret = sun4i_tcon_init_irq(dev, tcon); | 456 | ret = sun4i_tcon_init_irq(dev, tcon); |
453 | if (ret) { | 457 | if (ret) { |
454 | dev_err(dev, "Couldn't init our TCON interrupts\n"); | 458 | dev_err(dev, "Couldn't init our TCON interrupts\n"); |
459 | goto err_free_dotclock; | ||
460 | } | ||
461 | |||
462 | tcon->crtc = sun4i_crtc_init(drm, drv->backend, tcon); | ||
463 | if (IS_ERR(tcon->crtc)) { | ||
464 | dev_err(dev, "Couldn't create our CRTC\n"); | ||
465 | ret = PTR_ERR(tcon->crtc); | ||
455 | goto err_free_clocks; | 466 | goto err_free_clocks; |
456 | } | 467 | } |
457 | 468 | ||
458 | ret = sun4i_rgb_init(drm); | 469 | ret = sun4i_rgb_init(drm, tcon); |
459 | if (ret < 0) | 470 | if (ret < 0) |
460 | goto err_free_clocks; | 471 | goto err_free_clocks; |
461 | 472 | ||
462 | return 0; | 473 | return 0; |
463 | 474 | ||
475 | err_free_dotclock: | ||
476 | sun4i_dclk_free(tcon); | ||
464 | err_free_clocks: | 477 | err_free_clocks: |
465 | sun4i_tcon_free_clocks(tcon); | 478 | sun4i_tcon_free_clocks(tcon); |
466 | err_assert_reset: | 479 | err_assert_reset: |
@@ -473,6 +486,7 @@ static void sun4i_tcon_unbind(struct device *dev, struct device *master, | |||
473 | { | 486 | { |
474 | struct sun4i_tcon *tcon = dev_get_drvdata(dev); | 487 | struct sun4i_tcon *tcon = dev_get_drvdata(dev); |
475 | 488 | ||
489 | sun4i_dclk_free(tcon); | ||
476 | sun4i_tcon_free_clocks(tcon); | 490 | sun4i_tcon_free_clocks(tcon); |
477 | } | 491 | } |
478 | 492 | ||
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h index 166064bafe2e..f636343a935d 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.h +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h | |||
@@ -169,6 +169,9 @@ struct sun4i_tcon { | |||
169 | 169 | ||
170 | /* Platform adjustments */ | 170 | /* Platform adjustments */ |
171 | const struct sun4i_tcon_quirks *quirks; | 171 | const struct sun4i_tcon_quirks *quirks; |
172 | |||
173 | /* Associated crtc */ | ||
174 | struct sun4i_crtc *crtc; | ||
172 | }; | 175 | }; |
173 | 176 | ||
174 | struct drm_bridge *sun4i_tcon_find_bridge(struct device_node *node); | 177 | struct drm_bridge *sun4i_tcon_find_bridge(struct device_node *node); |
diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c index c6f47222e8fc..49c49431a053 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tv.c +++ b/drivers/gpu/drm/sun4i/sun4i_tv.c | |||
@@ -19,9 +19,11 @@ | |||
19 | #include <drm/drmP.h> | 19 | #include <drm/drmP.h> |
20 | #include <drm/drm_atomic_helper.h> | 20 | #include <drm/drm_atomic_helper.h> |
21 | #include <drm/drm_crtc_helper.h> | 21 | #include <drm/drm_crtc_helper.h> |
22 | #include <drm/drm_of.h> | ||
22 | #include <drm/drm_panel.h> | 23 | #include <drm/drm_panel.h> |
23 | 24 | ||
24 | #include "sun4i_backend.h" | 25 | #include "sun4i_backend.h" |
26 | #include "sun4i_crtc.h" | ||
25 | #include "sun4i_drv.h" | 27 | #include "sun4i_drv.h" |
26 | #include "sun4i_tcon.h" | 28 | #include "sun4i_tcon.h" |
27 | 29 | ||
@@ -349,8 +351,9 @@ static int sun4i_tv_atomic_check(struct drm_encoder *encoder, | |||
349 | static void sun4i_tv_disable(struct drm_encoder *encoder) | 351 | static void sun4i_tv_disable(struct drm_encoder *encoder) |
350 | { | 352 | { |
351 | struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder); | 353 | struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder); |
352 | struct sun4i_drv *drv = tv->drv; | 354 | struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc); |
353 | struct sun4i_tcon *tcon = drv->tcon; | 355 | struct sun4i_tcon *tcon = crtc->tcon; |
356 | struct sun4i_backend *backend = crtc->backend; | ||
354 | 357 | ||
355 | DRM_DEBUG_DRIVER("Disabling the TV Output\n"); | 358 | DRM_DEBUG_DRIVER("Disabling the TV Output\n"); |
356 | 359 | ||
@@ -359,18 +362,19 @@ static void sun4i_tv_disable(struct drm_encoder *encoder) | |||
359 | regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG, | 362 | regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG, |
360 | SUN4I_TVE_EN_ENABLE, | 363 | SUN4I_TVE_EN_ENABLE, |
361 | 0); | 364 | 0); |
362 | sun4i_backend_disable_color_correction(drv->backend); | 365 | sun4i_backend_disable_color_correction(backend); |
363 | } | 366 | } |
364 | 367 | ||
365 | static void sun4i_tv_enable(struct drm_encoder *encoder) | 368 | static void sun4i_tv_enable(struct drm_encoder *encoder) |
366 | { | 369 | { |
367 | struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder); | 370 | struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder); |
368 | struct sun4i_drv *drv = tv->drv; | 371 | struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc); |
369 | struct sun4i_tcon *tcon = drv->tcon; | 372 | struct sun4i_tcon *tcon = crtc->tcon; |
373 | struct sun4i_backend *backend = crtc->backend; | ||
370 | 374 | ||
371 | DRM_DEBUG_DRIVER("Enabling the TV Output\n"); | 375 | DRM_DEBUG_DRIVER("Enabling the TV Output\n"); |
372 | 376 | ||
373 | sun4i_backend_apply_color_correction(drv->backend); | 377 | sun4i_backend_apply_color_correction(backend); |
374 | 378 | ||
375 | regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG, | 379 | regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG, |
376 | SUN4I_TVE_EN_ENABLE, | 380 | SUN4I_TVE_EN_ENABLE, |
@@ -384,8 +388,8 @@ static void sun4i_tv_mode_set(struct drm_encoder *encoder, | |||
384 | struct drm_display_mode *adjusted_mode) | 388 | struct drm_display_mode *adjusted_mode) |
385 | { | 389 | { |
386 | struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder); | 390 | struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder); |
387 | struct sun4i_drv *drv = tv->drv; | 391 | struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc); |
388 | struct sun4i_tcon *tcon = drv->tcon; | 392 | struct sun4i_tcon *tcon = crtc->tcon; |
389 | const struct tv_mode *tv_mode = sun4i_tv_find_tv_by_mode(mode); | 393 | const struct tv_mode *tv_mode = sun4i_tv_find_tv_by_mode(mode); |
390 | 394 | ||
391 | sun4i_tcon1_mode_set(tcon, mode); | 395 | sun4i_tcon1_mode_set(tcon, mode); |
@@ -623,7 +627,12 @@ static int sun4i_tv_bind(struct device *dev, struct device *master, | |||
623 | goto err_disable_clk; | 627 | goto err_disable_clk; |
624 | } | 628 | } |
625 | 629 | ||
626 | tv->encoder.possible_crtcs = BIT(0); | 630 | tv->encoder.possible_crtcs = drm_of_find_possible_crtcs(drm, |
631 | dev->of_node); | ||
632 | if (!tv->encoder.possible_crtcs) { | ||
633 | ret = -EPROBE_DEFER; | ||
634 | goto err_disable_clk; | ||
635 | } | ||
627 | 636 | ||
628 | drm_connector_helper_add(&tv->connector, | 637 | drm_connector_helper_add(&tv->connector, |
629 | &sun4i_tv_comp_connector_helper_funcs); | 638 | &sun4i_tv_comp_connector_helper_funcs); |