2 * Copyright (C) STMicroelectronics SA 2014
3 * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
4 * Fabien Dessenne <fabien.dessenne@st.com>
5 * for STMicroelectronics.
6 * License terms: GNU General Public License (GPL), version 2
9 #include <linux/component.h>
10 #include <linux/module.h>
11 #include <linux/platform_device.h>
12 #include <linux/reset.h>
16 #include "sti_compositor.h"
18 #include "sti_cursor.h"
21 #include "sti_plane.h"
26 * stiH407 compositor properties
28 static const struct sti_compositor_data stih407_compositor_data
= {
31 {STI_CURSOR_SUBDEV
, (int)STI_CURSOR
, 0x000},
32 {STI_GPD_SUBDEV
, (int)STI_GDP_0
, 0x100},
33 {STI_GPD_SUBDEV
, (int)STI_GDP_1
, 0x200},
34 {STI_GPD_SUBDEV
, (int)STI_GDP_2
, 0x300},
35 {STI_GPD_SUBDEV
, (int)STI_GDP_3
, 0x400},
36 {STI_VID_SUBDEV
, (int)STI_HQVDP_0
, 0x700},
37 {STI_MIXER_MAIN_SUBDEV
, STI_MIXER_MAIN
, 0xC00},
38 {STI_MIXER_AUX_SUBDEV
, STI_MIXER_AUX
, 0xD00},
42 int sti_compositor_debugfs_init(struct sti_compositor
*compo
,
43 struct drm_minor
*minor
)
47 for (i
= 0; i
< STI_MAX_VID
; i
++)
49 vid_debugfs_init(compo
->vid
[i
], minor
);
51 for (i
= 0; i
< STI_MAX_MIXER
; i
++)
53 sti_mixer_debugfs_init(compo
->mixer
[i
], minor
);
58 static int sti_compositor_bind(struct device
*dev
,
59 struct device
*master
,
62 struct sti_compositor
*compo
= dev_get_drvdata(dev
);
63 struct drm_device
*drm_dev
= data
;
64 unsigned int i
, mixer_id
= 0, vid_id
= 0, crtc_id
= 0;
65 struct sti_private
*dev_priv
= drm_dev
->dev_private
;
66 struct drm_plane
*cursor
= NULL
;
67 struct drm_plane
*primary
= NULL
;
68 struct sti_compositor_subdev_descriptor
*desc
= compo
->data
.subdev_desc
;
69 unsigned int array_size
= compo
->data
.nb_subdev
;
71 dev_priv
->compo
= compo
;
73 /* Register mixer subdev and video subdev first */
74 for (i
= 0; i
< array_size
; i
++) {
75 switch (desc
[i
].type
) {
77 compo
->vid
[vid_id
++] =
78 sti_vid_create(compo
->dev
, drm_dev
, desc
[i
].id
,
79 compo
->regs
+ desc
[i
].offset
);
81 case STI_MIXER_MAIN_SUBDEV
:
82 case STI_MIXER_AUX_SUBDEV
:
83 compo
->mixer
[mixer_id
++] =
84 sti_mixer_create(compo
->dev
, drm_dev
, desc
[i
].id
,
85 compo
->regs
+ desc
[i
].offset
);
88 case STI_CURSOR_SUBDEV
:
89 /* Nothing to do, wait for the second round */
92 DRM_ERROR("Unknown subdev component type\n");
97 /* Register the other subdevs, create crtc and planes */
98 for (i
= 0; i
< array_size
; i
++) {
99 enum drm_plane_type plane_type
= DRM_PLANE_TYPE_OVERLAY
;
101 if (crtc_id
< mixer_id
)
102 plane_type
= DRM_PLANE_TYPE_PRIMARY
;
104 switch (desc
[i
].type
) {
105 case STI_MIXER_MAIN_SUBDEV
:
106 case STI_MIXER_AUX_SUBDEV
:
108 /* Nothing to do, already done at the first round */
110 case STI_CURSOR_SUBDEV
:
111 cursor
= sti_cursor_create(drm_dev
, compo
->dev
,
113 compo
->regs
+ desc
[i
].offset
,
116 DRM_ERROR("Can't create CURSOR plane\n");
121 primary
= sti_gdp_create(drm_dev
, compo
->dev
,
123 compo
->regs
+ desc
[i
].offset
,
127 DRM_ERROR("Can't create GDP plane\n");
132 DRM_ERROR("Unknown subdev component type\n");
136 /* The first planes are reserved for primary planes*/
137 if (crtc_id
< mixer_id
&& primary
) {
138 sti_crtc_init(drm_dev
, compo
->mixer
[crtc_id
],
146 drm_vblank_init(drm_dev
, crtc_id
);
147 /* Allow usage of vblank without having to call drm_irq_install */
148 drm_dev
->irq_enabled
= 1;
153 static void sti_compositor_unbind(struct device
*dev
, struct device
*master
,
159 static const struct component_ops sti_compositor_ops
= {
160 .bind
= sti_compositor_bind
,
161 .unbind
= sti_compositor_unbind
,
164 static const struct of_device_id compositor_of_match
[] = {
166 .compatible
= "st,stih407-compositor",
167 .data
= &stih407_compositor_data
,
172 MODULE_DEVICE_TABLE(of
, compositor_of_match
);
174 static int sti_compositor_probe(struct platform_device
*pdev
)
176 struct device
*dev
= &pdev
->dev
;
177 struct device_node
*np
= dev
->of_node
;
178 struct device_node
*vtg_np
;
179 struct sti_compositor
*compo
;
180 struct resource
*res
;
183 compo
= devm_kzalloc(dev
, sizeof(*compo
), GFP_KERNEL
);
185 DRM_ERROR("Failed to allocate compositor context\n");
189 for (i
= 0; i
< STI_MAX_MIXER
; i
++)
190 compo
->vtg_vblank_nb
[i
].notifier_call
= sti_crtc_vblank_cb
;
192 /* populate data structure depending on compatibility */
193 BUG_ON(!of_match_node(compositor_of_match
, np
)->data
);
195 memcpy(&compo
->data
, of_match_node(compositor_of_match
, np
)->data
,
196 sizeof(struct sti_compositor_data
));
198 /* Get Memory ressources */
199 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
201 DRM_ERROR("Get memory resource failed\n");
204 compo
->regs
= devm_ioremap(dev
, res
->start
, resource_size(res
));
205 if (compo
->regs
== NULL
) {
206 DRM_ERROR("Register mapping failed\n");
210 /* Get clock resources */
211 compo
->clk_compo_main
= devm_clk_get(dev
, "compo_main");
212 if (IS_ERR(compo
->clk_compo_main
)) {
213 DRM_ERROR("Cannot get compo_main clock\n");
214 return PTR_ERR(compo
->clk_compo_main
);
217 compo
->clk_compo_aux
= devm_clk_get(dev
, "compo_aux");
218 if (IS_ERR(compo
->clk_compo_aux
)) {
219 DRM_ERROR("Cannot get compo_aux clock\n");
220 return PTR_ERR(compo
->clk_compo_aux
);
223 compo
->clk_pix_main
= devm_clk_get(dev
, "pix_main");
224 if (IS_ERR(compo
->clk_pix_main
)) {
225 DRM_ERROR("Cannot get pix_main clock\n");
226 return PTR_ERR(compo
->clk_pix_main
);
229 compo
->clk_pix_aux
= devm_clk_get(dev
, "pix_aux");
230 if (IS_ERR(compo
->clk_pix_aux
)) {
231 DRM_ERROR("Cannot get pix_aux clock\n");
232 return PTR_ERR(compo
->clk_pix_aux
);
235 /* Get reset resources */
236 compo
->rst_main
= devm_reset_control_get_shared(dev
, "compo-main");
237 /* Take compo main out of reset */
238 if (!IS_ERR(compo
->rst_main
))
239 reset_control_deassert(compo
->rst_main
);
241 compo
->rst_aux
= devm_reset_control_get_shared(dev
, "compo-aux");
242 /* Take compo aux out of reset */
243 if (!IS_ERR(compo
->rst_aux
))
244 reset_control_deassert(compo
->rst_aux
);
246 vtg_np
= of_parse_phandle(pdev
->dev
.of_node
, "st,vtg", 0);
248 compo
->vtg
[STI_MIXER_MAIN
] = of_vtg_find(vtg_np
);
251 vtg_np
= of_parse_phandle(pdev
->dev
.of_node
, "st,vtg", 1);
253 compo
->vtg
[STI_MIXER_AUX
] = of_vtg_find(vtg_np
);
256 platform_set_drvdata(pdev
, compo
);
258 return component_add(&pdev
->dev
, &sti_compositor_ops
);
261 static int sti_compositor_remove(struct platform_device
*pdev
)
263 component_del(&pdev
->dev
, &sti_compositor_ops
);
267 struct platform_driver sti_compositor_driver
= {
269 .name
= "sti-compositor",
270 .of_match_table
= compositor_of_match
,
272 .probe
= sti_compositor_probe
,
273 .remove
= sti_compositor_remove
,
276 MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
277 MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
278 MODULE_LICENSE("GPL");