aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/sti/Kconfig8
-rw-r--r--drivers/gpu/drm/sti/Makefile21
-rw-r--r--drivers/gpu/drm/sti/sti_awg_utils.c4
-rw-r--r--drivers/gpu/drm/sti/sti_compositor.c4
-rw-r--r--drivers/gpu/drm/sti/sti_crtc.c45
-rw-r--r--drivers/gpu/drm/sti/sti_drv.c33
-rw-r--r--drivers/gpu/drm/sti/sti_drv.h9
-rw-r--r--drivers/gpu/drm/sti/sti_dvo.c7
-rw-r--r--drivers/gpu/drm/sti/sti_gdp.c2
-rw-r--r--drivers/gpu/drm/sti/sti_hda.c7
-rw-r--r--drivers/gpu/drm/sti/sti_hdmi.c69
-rw-r--r--drivers/gpu/drm/sti/sti_hqvdp.c306
-rw-r--r--drivers/gpu/drm/sti/sti_mixer.c14
-rw-r--r--drivers/gpu/drm/sti/sti_plane.c3
-rw-r--r--drivers/gpu/drm/sti/sti_tvout.c2
-rw-r--r--drivers/gpu/drm/sti/sti_vtac.c2
-rw-r--r--drivers/gpu/drm/sti/sti_vtg.c22
-rw-r--r--drivers/gpu/drm/sti/sti_vtg.h4
18 files changed, 283 insertions, 279 deletions
diff --git a/drivers/gpu/drm/sti/Kconfig b/drivers/gpu/drm/sti/Kconfig
index fbccc105819b..10c1b1926e6f 100644
--- a/drivers/gpu/drm/sti/Kconfig
+++ b/drivers/gpu/drm/sti/Kconfig
@@ -6,12 +6,6 @@ config DRM_STI
6 select DRM_GEM_CMA_HELPER 6 select DRM_GEM_CMA_HELPER
7 select DRM_KMS_CMA_HELPER 7 select DRM_KMS_CMA_HELPER
8 select DRM_PANEL 8 select DRM_PANEL
9 select FW_LOADER_USER_HELPER_FALLBACK 9 select FW_LOADER
10 help 10 help
11 Choose this option to enable DRM on STM stiH41x chipset 11 Choose this option to enable DRM on STM stiH41x chipset
12
13config DRM_STI_FBDEV
14 bool "DRM frame buffer device for STMicroelectronics SoC stiH41x Serie"
15 depends on DRM_STI
16 help
17 Choose this option to enable FBDEV on top of DRM for STM stiH41x chipset
diff --git a/drivers/gpu/drm/sti/Makefile b/drivers/gpu/drm/sti/Makefile
index e27490b492a5..b8057620b3b3 100644
--- a/drivers/gpu/drm/sti/Makefile
+++ b/drivers/gpu/drm/sti/Makefile
@@ -1,26 +1,23 @@
1sticompositor-y := \ 1sti-drm-y := \
2 sti_mixer.o \ 2 sti_mixer.o \
3 sti_gdp.o \ 3 sti_gdp.o \
4 sti_vid.o \ 4 sti_vid.o \
5 sti_cursor.o \ 5 sti_cursor.o \
6 sti_compositor.o \ 6 sti_compositor.o \
7 sti_crtc.o \ 7 sti_crtc.o \
8 sti_plane.o 8 sti_plane.o \
9 9 sti_crtc.o \
10stihdmi-y := sti_hdmi.o \ 10 sti_plane.o \
11 sti_hdmi.o \
11 sti_hdmi_tx3g0c55phy.o \ 12 sti_hdmi_tx3g0c55phy.o \
12 sti_hdmi_tx3g4c28phy.o \ 13 sti_hdmi_tx3g4c28phy.o \
13 14 sti_dvo.o \
14stidvo-y := sti_dvo.o \ 15 sti_awg_utils.o \
15 sti_awg_utils.o
16
17obj-$(CONFIG_DRM_STI) = \
18 sti_vtg.o \ 16 sti_vtg.o \
19 sti_vtac.o \ 17 sti_vtac.o \
20 stihdmi.o \
21 sti_hda.o \ 18 sti_hda.o \
22 sti_tvout.o \ 19 sti_tvout.o \
23 sticompositor.o \
24 sti_hqvdp.o \ 20 sti_hqvdp.o \
25 stidvo.o \
26 sti_drv.o 21 sti_drv.o
22
23obj-$(CONFIG_DRM_STI) = sti-drm.o
diff --git a/drivers/gpu/drm/sti/sti_awg_utils.c b/drivers/gpu/drm/sti/sti_awg_utils.c
index 6029a2e3db1d..00d0698be9d3 100644
--- a/drivers/gpu/drm/sti/sti_awg_utils.c
+++ b/drivers/gpu/drm/sti/sti_awg_utils.c
@@ -65,7 +65,6 @@ static int awg_generate_instr(enum opcode opcode,
65 65
66 mux = 0; 66 mux = 0;
67 data_enable = 0; 67 data_enable = 0;
68 arg = (arg << 22) >> 22;
69 arg &= (0x3ff); 68 arg &= (0x3ff);
70 break; 69 break;
71 case REPEAT: 70 case REPEAT:
@@ -77,14 +76,12 @@ static int awg_generate_instr(enum opcode opcode,
77 76
78 mux = 0; 77 mux = 0;
79 data_enable = 0; 78 data_enable = 0;
80 arg = (arg << 22) >> 22;
81 arg &= (0x3ff); 79 arg &= (0x3ff);
82 break; 80 break;
83 case JUMP: 81 case JUMP:
84 mux = 0; 82 mux = 0;
85 data_enable = 0; 83 data_enable = 0;
86 arg |= 0x40; /* for jump instruction 7th bit is 1 */ 84 arg |= 0x40; /* for jump instruction 7th bit is 1 */
87 arg = (arg << 22) >> 22;
88 arg &= 0x3ff; 85 arg &= 0x3ff;
89 break; 86 break;
90 case STOP: 87 case STOP:
@@ -94,7 +91,6 @@ static int awg_generate_instr(enum opcode opcode,
94 case RPTSET: 91 case RPTSET:
95 case RPLSET: 92 case RPLSET:
96 case HOLD: 93 case HOLD:
97 arg = (arg << 24) >> 24;
98 arg &= (0x0ff); 94 arg &= (0x0ff);
99 break; 95 break;
100 default: 96 default:
diff --git a/drivers/gpu/drm/sti/sti_compositor.c b/drivers/gpu/drm/sti/sti_compositor.c
index c652627b1bca..afed2171beb9 100644
--- a/drivers/gpu/drm/sti/sti_compositor.c
+++ b/drivers/gpu/drm/sti/sti_compositor.c
@@ -263,7 +263,7 @@ static int sti_compositor_remove(struct platform_device *pdev)
263 return 0; 263 return 0;
264} 264}
265 265
266static struct platform_driver sti_compositor_driver = { 266struct platform_driver sti_compositor_driver = {
267 .driver = { 267 .driver = {
268 .name = "sti-compositor", 268 .name = "sti-compositor",
269 .of_match_table = compositor_of_match, 269 .of_match_table = compositor_of_match,
@@ -272,8 +272,6 @@ static struct platform_driver sti_compositor_driver = {
272 .remove = sti_compositor_remove, 272 .remove = sti_compositor_remove,
273}; 273};
274 274
275module_platform_driver(sti_compositor_driver);
276
277MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>"); 275MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
278MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver"); 276MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
279MODULE_LICENSE("GPL"); 277MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/sti/sti_crtc.c b/drivers/gpu/drm/sti/sti_crtc.c
index 493c4a3006ad..3ae09dcd4fd8 100644
--- a/drivers/gpu/drm/sti/sti_crtc.c
+++ b/drivers/gpu/drm/sti/sti_crtc.c
@@ -226,7 +226,7 @@ static void sti_crtc_atomic_flush(struct drm_crtc *crtc,
226 } 226 }
227} 227}
228 228
229static struct drm_crtc_helper_funcs sti_crtc_helper_funcs = { 229static const struct drm_crtc_helper_funcs sti_crtc_helper_funcs = {
230 .enable = sti_crtc_enable, 230 .enable = sti_crtc_enable,
231 .disable = sti_crtc_disabling, 231 .disable = sti_crtc_disabling,
232 .mode_fixup = sti_crtc_mode_fixup, 232 .mode_fixup = sti_crtc_mode_fixup,
@@ -254,15 +254,17 @@ static int sti_crtc_set_property(struct drm_crtc *crtc,
254int sti_crtc_vblank_cb(struct notifier_block *nb, 254int sti_crtc_vblank_cb(struct notifier_block *nb,
255 unsigned long event, void *data) 255 unsigned long event, void *data)
256{ 256{
257 struct drm_device *drm_dev;
258 struct sti_compositor *compo = 257 struct sti_compositor *compo =
259 container_of(nb, struct sti_compositor, vtg_vblank_nb); 258 container_of(nb, struct sti_compositor, vtg_vblank_nb);
260 int *crtc = data; 259 struct drm_crtc *crtc = data;
260 struct sti_mixer *mixer;
261 unsigned long flags; 261 unsigned long flags;
262 struct sti_private *priv; 262 struct sti_private *priv;
263 unsigned int pipe;
263 264
264 drm_dev = compo->mixer[*crtc]->drm_crtc.dev; 265 priv = crtc->dev->dev_private;
265 priv = drm_dev->dev_private; 266 pipe = drm_crtc_index(crtc);
267 mixer = compo->mixer[pipe];
266 268
267 if ((event != VTG_TOP_FIELD_EVENT) && 269 if ((event != VTG_TOP_FIELD_EVENT) &&
268 (event != VTG_BOTTOM_FIELD_EVENT)) { 270 (event != VTG_BOTTOM_FIELD_EVENT)) {
@@ -270,30 +272,30 @@ int sti_crtc_vblank_cb(struct notifier_block *nb,
270 return -EINVAL; 272 return -EINVAL;
271 } 273 }
272 274
273 drm_handle_vblank(drm_dev, *crtc); 275 drm_crtc_handle_vblank(crtc);
274 276
275 spin_lock_irqsave(&drm_dev->event_lock, flags); 277 spin_lock_irqsave(&crtc->dev->event_lock, flags);
276 if (compo->mixer[*crtc]->pending_event) { 278 if (mixer->pending_event) {
277 drm_send_vblank_event(drm_dev, -1, 279 drm_crtc_send_vblank_event(crtc, mixer->pending_event);
278 compo->mixer[*crtc]->pending_event); 280 drm_crtc_vblank_put(crtc);
279 drm_vblank_put(drm_dev, *crtc); 281 mixer->pending_event = NULL;
280 compo->mixer[*crtc]->pending_event = NULL;
281 } 282 }
282 spin_unlock_irqrestore(&drm_dev->event_lock, flags); 283 spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
283 284
284 if (compo->mixer[*crtc]->status == STI_MIXER_DISABLING) { 285 if (mixer->status == STI_MIXER_DISABLING) {
285 struct drm_plane *p; 286 struct drm_plane *p;
286 287
287 /* Disable mixer only if all overlay planes (GDP and VDP) 288 /* Disable mixer only if all overlay planes (GDP and VDP)
288 * are disabled */ 289 * are disabled */
289 list_for_each_entry(p, &drm_dev->mode_config.plane_list, head) { 290 list_for_each_entry(p, &crtc->dev->mode_config.plane_list,
291 head) {
290 struct sti_plane *plane = to_sti_plane(p); 292 struct sti_plane *plane = to_sti_plane(p);
291 293
292 if ((plane->desc & STI_PLANE_TYPE_MASK) <= STI_VDP) 294 if ((plane->desc & STI_PLANE_TYPE_MASK) <= STI_VDP)
293 if (plane->status != STI_PLANE_DISABLED) 295 if (plane->status != STI_PLANE_DISABLED)
294 return 0; 296 return 0;
295 } 297 }
296 sti_crtc_disable(&compo->mixer[*crtc]->drm_crtc); 298 sti_crtc_disable(crtc);
297 } 299 }
298 300
299 return 0; 301 return 0;
@@ -304,25 +306,26 @@ int sti_crtc_enable_vblank(struct drm_device *dev, unsigned int pipe)
304 struct sti_private *dev_priv = dev->dev_private; 306 struct sti_private *dev_priv = dev->dev_private;
305 struct sti_compositor *compo = dev_priv->compo; 307 struct sti_compositor *compo = dev_priv->compo;
306 struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb; 308 struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb;
309 struct drm_crtc *crtc = &compo->mixer[pipe]->drm_crtc;
307 310
308 DRM_DEBUG_DRIVER("\n"); 311 DRM_DEBUG_DRIVER("\n");
309 312
310 if (sti_vtg_register_client(pipe == STI_MIXER_MAIN ? 313 if (sti_vtg_register_client(pipe == STI_MIXER_MAIN ?
311 compo->vtg_main : compo->vtg_aux, 314 compo->vtg_main : compo->vtg_aux,
312 vtg_vblank_nb, pipe)) { 315 vtg_vblank_nb, crtc)) {
313 DRM_ERROR("Cannot register VTG notifier\n"); 316 DRM_ERROR("Cannot register VTG notifier\n");
314 return -EINVAL; 317 return -EINVAL;
315 } 318 }
316 319
317 return 0; 320 return 0;
318} 321}
319EXPORT_SYMBOL(sti_crtc_enable_vblank);
320 322
321void sti_crtc_disable_vblank(struct drm_device *drm_dev, unsigned int pipe) 323void sti_crtc_disable_vblank(struct drm_device *drm_dev, unsigned int pipe)
322{ 324{
323 struct sti_private *priv = drm_dev->dev_private; 325 struct sti_private *priv = drm_dev->dev_private;
324 struct sti_compositor *compo = priv->compo; 326 struct sti_compositor *compo = priv->compo;
325 struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb; 327 struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb;
328 struct drm_crtc *crtc = &compo->mixer[pipe]->drm_crtc;
326 329
327 DRM_DEBUG_DRIVER("\n"); 330 DRM_DEBUG_DRIVER("\n");
328 331
@@ -332,13 +335,12 @@ void sti_crtc_disable_vblank(struct drm_device *drm_dev, unsigned int pipe)
332 335
333 /* free the resources of the pending requests */ 336 /* free the resources of the pending requests */
334 if (compo->mixer[pipe]->pending_event) { 337 if (compo->mixer[pipe]->pending_event) {
335 drm_vblank_put(drm_dev, pipe); 338 drm_crtc_vblank_put(crtc);
336 compo->mixer[pipe]->pending_event = NULL; 339 compo->mixer[pipe]->pending_event = NULL;
337 } 340 }
338} 341}
339EXPORT_SYMBOL(sti_crtc_disable_vblank);
340 342
341static struct drm_crtc_funcs sti_crtc_funcs = { 343static const struct drm_crtc_funcs sti_crtc_funcs = {
342 .set_config = drm_atomic_helper_set_config, 344 .set_config = drm_atomic_helper_set_config,
343 .page_flip = drm_atomic_helper_page_flip, 345 .page_flip = drm_atomic_helper_page_flip,
344 .destroy = sti_crtc_destroy, 346 .destroy = sti_crtc_destroy,
@@ -357,7 +359,6 @@ bool sti_crtc_is_main(struct drm_crtc *crtc)
357 359
358 return false; 360 return false;
359} 361}
360EXPORT_SYMBOL(sti_crtc_is_main);
361 362
362int sti_crtc_init(struct drm_device *drm_dev, struct sti_mixer *mixer, 363int sti_crtc_init(struct drm_device *drm_dev, struct sti_mixer *mixer,
363 struct drm_plane *primary, struct drm_plane *cursor) 364 struct drm_plane *primary, struct drm_plane *cursor)
diff --git a/drivers/gpu/drm/sti/sti_drv.c b/drivers/gpu/drm/sti/sti_drv.c
index f8469967a0bf..1469987949d8 100644
--- a/drivers/gpu/drm/sti/sti_drv.c
+++ b/drivers/gpu/drm/sti/sti_drv.c
@@ -107,7 +107,7 @@ static int sti_atomic_commit(struct drm_device *drm,
107 return 0; 107 return 0;
108} 108}
109 109
110static struct drm_mode_config_funcs sti_mode_config_funcs = { 110static const struct drm_mode_config_funcs sti_mode_config_funcs = {
111 .fb_create = drm_fb_cma_create, 111 .fb_create = drm_fb_cma_create,
112 .atomic_check = drm_atomic_helper_check, 112 .atomic_check = drm_atomic_helper_check,
113 .atomic_commit = sti_atomic_commit, 113 .atomic_commit = sti_atomic_commit,
@@ -123,8 +123,8 @@ static void sti_mode_config_init(struct drm_device *dev)
123 * this value would be used to check framebuffer size limitation 123 * this value would be used to check framebuffer size limitation
124 * at drm_mode_addfb(). 124 * at drm_mode_addfb().
125 */ 125 */
126 dev->mode_config.max_width = STI_MAX_FB_HEIGHT; 126 dev->mode_config.max_width = STI_MAX_FB_WIDTH;
127 dev->mode_config.max_height = STI_MAX_FB_WIDTH; 127 dev->mode_config.max_height = STI_MAX_FB_HEIGHT;
128 128
129 dev->mode_config.funcs = &sti_mode_config_funcs; 129 dev->mode_config.funcs = &sti_mode_config_funcs;
130} 130}
@@ -160,11 +160,10 @@ static int sti_load(struct drm_device *dev, unsigned long flags)
160 160
161 drm_mode_config_reset(dev); 161 drm_mode_config_reset(dev);
162 162
163#ifdef CONFIG_DRM_STI_FBDEV
164 drm_fbdev_cma_init(dev, 32, 163 drm_fbdev_cma_init(dev, 32,
165 dev->mode_config.num_crtc, 164 dev->mode_config.num_crtc,
166 dev->mode_config.num_connector); 165 dev->mode_config.num_connector);
167#endif 166
168 return 0; 167 return 0;
169} 168}
170 169
@@ -287,7 +286,29 @@ static struct platform_driver sti_platform_driver = {
287 }, 286 },
288}; 287};
289 288
290module_platform_driver(sti_platform_driver); 289static struct platform_driver * const drivers[] = {
290 &sti_tvout_driver,
291 &sti_vtac_driver,
292 &sti_hqvdp_driver,
293 &sti_hdmi_driver,
294 &sti_hda_driver,
295 &sti_dvo_driver,
296 &sti_vtg_driver,
297 &sti_compositor_driver,
298 &sti_platform_driver,
299};
300
301static int sti_drm_init(void)
302{
303 return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
304}
305module_init(sti_drm_init);
306
307static void sti_drm_exit(void)
308{
309 platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
310}
311module_exit(sti_drm_exit);
291 312
292MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>"); 313MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
293MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver"); 314MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
diff --git a/drivers/gpu/drm/sti/sti_drv.h b/drivers/gpu/drm/sti/sti_drv.h
index 9372f69e1859..30ddc20841c3 100644
--- a/drivers/gpu/drm/sti/sti_drv.h
+++ b/drivers/gpu/drm/sti/sti_drv.h
@@ -32,4 +32,13 @@ struct sti_private {
32 } commit; 32 } commit;
33}; 33};
34 34
35extern struct platform_driver sti_tvout_driver;
36extern struct platform_driver sti_vtac_driver;
37extern struct platform_driver sti_hqvdp_driver;
38extern struct platform_driver sti_hdmi_driver;
39extern struct platform_driver sti_hda_driver;
40extern struct platform_driver sti_dvo_driver;
41extern struct platform_driver sti_vtg_driver;
42extern struct platform_driver sti_compositor_driver;
43
35#endif 44#endif
diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c
index d141d645bd13..45cbe2bf7dd6 100644
--- a/drivers/gpu/drm/sti/sti_dvo.c
+++ b/drivers/gpu/drm/sti/sti_dvo.c
@@ -329,7 +329,8 @@ struct drm_encoder *sti_dvo_best_encoder(struct drm_connector *connector)
329 return dvo_connector->encoder; 329 return dvo_connector->encoder;
330} 330}
331 331
332static struct drm_connector_helper_funcs sti_dvo_connector_helper_funcs = { 332static const
333struct drm_connector_helper_funcs sti_dvo_connector_helper_funcs = {
333 .get_modes = sti_dvo_connector_get_modes, 334 .get_modes = sti_dvo_connector_get_modes,
334 .mode_valid = sti_dvo_connector_mode_valid, 335 .mode_valid = sti_dvo_connector_mode_valid,
335 .best_encoder = sti_dvo_best_encoder, 336 .best_encoder = sti_dvo_best_encoder,
@@ -364,7 +365,7 @@ static void sti_dvo_connector_destroy(struct drm_connector *connector)
364 kfree(dvo_connector); 365 kfree(dvo_connector);
365} 366}
366 367
367static struct drm_connector_funcs sti_dvo_connector_funcs = { 368static const struct drm_connector_funcs sti_dvo_connector_funcs = {
368 .dpms = drm_atomic_helper_connector_dpms, 369 .dpms = drm_atomic_helper_connector_dpms,
369 .fill_modes = drm_helper_probe_single_connector_modes, 370 .fill_modes = drm_helper_probe_single_connector_modes,
370 .detect = sti_dvo_connector_detect, 371 .detect = sti_dvo_connector_detect,
@@ -557,8 +558,6 @@ struct platform_driver sti_dvo_driver = {
557 .remove = sti_dvo_remove, 558 .remove = sti_dvo_remove,
558}; 559};
559 560
560module_platform_driver(sti_dvo_driver);
561
562MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>"); 561MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
563MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver"); 562MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
564MODULE_LICENSE("GPL"); 563MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c
index 9365670427ad..c85dc7d6b005 100644
--- a/drivers/gpu/drm/sti/sti_gdp.c
+++ b/drivers/gpu/drm/sti/sti_gdp.c
@@ -492,7 +492,7 @@ static void sti_gdp_atomic_update(struct drm_plane *drm_plane,
492 /* Register gdp callback */ 492 /* Register gdp callback */
493 if (sti_vtg_register_client(mixer->id == STI_MIXER_MAIN ? 493 if (sti_vtg_register_client(mixer->id == STI_MIXER_MAIN ?
494 compo->vtg_main : compo->vtg_aux, 494 compo->vtg_main : compo->vtg_aux,
495 &gdp->vtg_field_nb, mixer->id)) { 495 &gdp->vtg_field_nb, crtc)) {
496 DRM_ERROR("Cannot register VTG notifier\n"); 496 DRM_ERROR("Cannot register VTG notifier\n");
497 return; 497 return;
498 } 498 }
diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c
index 598cd78b0b16..d735daccd458 100644
--- a/drivers/gpu/drm/sti/sti_hda.c
+++ b/drivers/gpu/drm/sti/sti_hda.c
@@ -589,7 +589,8 @@ struct drm_encoder *sti_hda_best_encoder(struct drm_connector *connector)
589 return hda_connector->encoder; 589 return hda_connector->encoder;
590} 590}
591 591
592static struct drm_connector_helper_funcs sti_hda_connector_helper_funcs = { 592static const
593struct drm_connector_helper_funcs sti_hda_connector_helper_funcs = {
593 .get_modes = sti_hda_connector_get_modes, 594 .get_modes = sti_hda_connector_get_modes,
594 .mode_valid = sti_hda_connector_mode_valid, 595 .mode_valid = sti_hda_connector_mode_valid,
595 .best_encoder = sti_hda_best_encoder, 596 .best_encoder = sti_hda_best_encoder,
@@ -611,7 +612,7 @@ static void sti_hda_connector_destroy(struct drm_connector *connector)
611 kfree(hda_connector); 612 kfree(hda_connector);
612} 613}
613 614
614static struct drm_connector_funcs sti_hda_connector_funcs = { 615static const struct drm_connector_funcs sti_hda_connector_funcs = {
615 .dpms = drm_atomic_helper_connector_dpms, 616 .dpms = drm_atomic_helper_connector_dpms,
616 .fill_modes = drm_helper_probe_single_connector_modes, 617 .fill_modes = drm_helper_probe_single_connector_modes,
617 .detect = sti_hda_connector_detect, 618 .detect = sti_hda_connector_detect,
@@ -784,8 +785,6 @@ struct platform_driver sti_hda_driver = {
784 .remove = sti_hda_remove, 785 .remove = sti_hda_remove,
785}; 786};
786 787
787module_platform_driver(sti_hda_driver);
788
789MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>"); 788MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
790MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver"); 789MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
791MODULE_LICENSE("GPL"); 790MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
index 09e29e43423e..cd501563c0cc 100644
--- a/drivers/gpu/drm/sti/sti_hdmi.c
+++ b/drivers/gpu/drm/sti/sti_hdmi.c
@@ -628,7 +628,8 @@ struct drm_encoder *sti_hdmi_best_encoder(struct drm_connector *connector)
628 return hdmi_connector->encoder; 628 return hdmi_connector->encoder;
629} 629}
630 630
631static struct drm_connector_helper_funcs sti_hdmi_connector_helper_funcs = { 631static const
632struct drm_connector_helper_funcs sti_hdmi_connector_helper_funcs = {
632 .get_modes = sti_hdmi_connector_get_modes, 633 .get_modes = sti_hdmi_connector_get_modes,
633 .mode_valid = sti_hdmi_connector_mode_valid, 634 .mode_valid = sti_hdmi_connector_mode_valid,
634 .best_encoder = sti_hdmi_best_encoder, 635 .best_encoder = sti_hdmi_best_encoder,
@@ -663,7 +664,7 @@ static void sti_hdmi_connector_destroy(struct drm_connector *connector)
663 kfree(hdmi_connector); 664 kfree(hdmi_connector);
664} 665}
665 666
666static struct drm_connector_funcs sti_hdmi_connector_funcs = { 667static const struct drm_connector_funcs sti_hdmi_connector_funcs = {
667 .dpms = drm_atomic_helper_connector_dpms, 668 .dpms = drm_atomic_helper_connector_dpms,
668 .fill_modes = drm_helper_probe_single_connector_modes, 669 .fill_modes = drm_helper_probe_single_connector_modes,
669 .detect = sti_hdmi_connector_detect, 670 .detect = sti_hdmi_connector_detect,
@@ -700,18 +701,17 @@ static int sti_hdmi_bind(struct device *dev, struct device *master, void *data)
700 701
701 encoder = sti_hdmi_find_encoder(drm_dev); 702 encoder = sti_hdmi_find_encoder(drm_dev);
702 if (!encoder) 703 if (!encoder)
703 goto err_adapt; 704 return -EINVAL;
704 705
705 connector = devm_kzalloc(dev, sizeof(*connector), GFP_KERNEL); 706 connector = devm_kzalloc(dev, sizeof(*connector), GFP_KERNEL);
706 if (!connector) 707 if (!connector)
707 goto err_adapt; 708 return -EINVAL;
708
709 709
710 connector->hdmi = hdmi; 710 connector->hdmi = hdmi;
711 711
712 bridge = devm_kzalloc(dev, sizeof(*bridge), GFP_KERNEL); 712 bridge = devm_kzalloc(dev, sizeof(*bridge), GFP_KERNEL);
713 if (!bridge) 713 if (!bridge)
714 goto err_adapt; 714 return -EINVAL;
715 715
716 bridge->driver_private = hdmi; 716 bridge->driver_private = hdmi;
717 bridge->funcs = &sti_hdmi_bridge_funcs; 717 bridge->funcs = &sti_hdmi_bridge_funcs;
@@ -748,8 +748,7 @@ err_sysfs:
748 drm_connector_unregister(drm_connector); 748 drm_connector_unregister(drm_connector);
749err_connector: 749err_connector:
750 drm_connector_cleanup(drm_connector); 750 drm_connector_cleanup(drm_connector);
751err_adapt: 751
752 put_device(&hdmi->ddc_adapt->dev);
753 return -EINVAL; 752 return -EINVAL;
754} 753}
755 754
@@ -794,13 +793,10 @@ static int sti_hdmi_probe(struct platform_device *pdev)
794 793
795 ddc = of_parse_phandle(pdev->dev.of_node, "ddc", 0); 794 ddc = of_parse_phandle(pdev->dev.of_node, "ddc", 0);
796 if (ddc) { 795 if (ddc) {
797 hdmi->ddc_adapt = of_find_i2c_adapter_by_node(ddc); 796 hdmi->ddc_adapt = of_get_i2c_adapter_by_node(ddc);
798 if (!hdmi->ddc_adapt) {
799 of_node_put(ddc);
800 return -EPROBE_DEFER;
801 }
802
803 of_node_put(ddc); 797 of_node_put(ddc);
798 if (!hdmi->ddc_adapt)
799 return -EPROBE_DEFER;
804 } 800 }
805 801
806 hdmi->dev = pdev->dev; 802 hdmi->dev = pdev->dev;
@@ -809,24 +805,29 @@ static int sti_hdmi_probe(struct platform_device *pdev)
809 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi-reg"); 805 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi-reg");
810 if (!res) { 806 if (!res) {
811 DRM_ERROR("Invalid hdmi resource\n"); 807 DRM_ERROR("Invalid hdmi resource\n");
812 return -ENOMEM; 808 ret = -ENOMEM;
809 goto release_adapter;
813 } 810 }
814 hdmi->regs = devm_ioremap_nocache(dev, res->start, resource_size(res)); 811 hdmi->regs = devm_ioremap_nocache(dev, res->start, resource_size(res));
815 if (!hdmi->regs) 812 if (!hdmi->regs) {
816 return -ENOMEM; 813 ret = -ENOMEM;
814 goto release_adapter;
815 }
817 816
818 if (of_device_is_compatible(np, "st,stih416-hdmi")) { 817 if (of_device_is_compatible(np, "st,stih416-hdmi")) {
819 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, 818 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
820 "syscfg"); 819 "syscfg");
821 if (!res) { 820 if (!res) {
822 DRM_ERROR("Invalid syscfg resource\n"); 821 DRM_ERROR("Invalid syscfg resource\n");
823 return -ENOMEM; 822 ret = -ENOMEM;
823 goto release_adapter;
824 } 824 }
825 hdmi->syscfg = devm_ioremap_nocache(dev, res->start, 825 hdmi->syscfg = devm_ioremap_nocache(dev, res->start,
826 resource_size(res)); 826 resource_size(res));
827 if (!hdmi->syscfg) 827 if (!hdmi->syscfg) {
828 return -ENOMEM; 828 ret = -ENOMEM;
829 829 goto release_adapter;
830 }
830 } 831 }
831 832
832 hdmi->phy_ops = (struct hdmi_phy_ops *) 833 hdmi->phy_ops = (struct hdmi_phy_ops *)
@@ -836,25 +837,29 @@ static int sti_hdmi_probe(struct platform_device *pdev)
836 hdmi->clk_pix = devm_clk_get(dev, "pix"); 837 hdmi->clk_pix = devm_clk_get(dev, "pix");
837 if (IS_ERR(hdmi->clk_pix)) { 838 if (IS_ERR(hdmi->clk_pix)) {
838 DRM_ERROR("Cannot get hdmi_pix clock\n"); 839 DRM_ERROR("Cannot get hdmi_pix clock\n");
839 return PTR_ERR(hdmi->clk_pix); 840 ret = PTR_ERR(hdmi->clk_pix);
841 goto release_adapter;
840 } 842 }
841 843
842 hdmi->clk_tmds = devm_clk_get(dev, "tmds"); 844 hdmi->clk_tmds = devm_clk_get(dev, "tmds");
843 if (IS_ERR(hdmi->clk_tmds)) { 845 if (IS_ERR(hdmi->clk_tmds)) {
844 DRM_ERROR("Cannot get hdmi_tmds clock\n"); 846 DRM_ERROR("Cannot get hdmi_tmds clock\n");
845 return PTR_ERR(hdmi->clk_tmds); 847 ret = PTR_ERR(hdmi->clk_tmds);
848 goto release_adapter;
846 } 849 }
847 850
848 hdmi->clk_phy = devm_clk_get(dev, "phy"); 851 hdmi->clk_phy = devm_clk_get(dev, "phy");
849 if (IS_ERR(hdmi->clk_phy)) { 852 if (IS_ERR(hdmi->clk_phy)) {
850 DRM_ERROR("Cannot get hdmi_phy clock\n"); 853 DRM_ERROR("Cannot get hdmi_phy clock\n");
851 return PTR_ERR(hdmi->clk_phy); 854 ret = PTR_ERR(hdmi->clk_phy);
855 goto release_adapter;
852 } 856 }
853 857
854 hdmi->clk_audio = devm_clk_get(dev, "audio"); 858 hdmi->clk_audio = devm_clk_get(dev, "audio");
855 if (IS_ERR(hdmi->clk_audio)) { 859 if (IS_ERR(hdmi->clk_audio)) {
856 DRM_ERROR("Cannot get hdmi_audio clock\n"); 860 DRM_ERROR("Cannot get hdmi_audio clock\n");
857 return PTR_ERR(hdmi->clk_audio); 861 ret = PTR_ERR(hdmi->clk_audio);
862 goto release_adapter;
858 } 863 }
859 864
860 hdmi->hpd = readl(hdmi->regs + HDMI_STA) & HDMI_STA_HOT_PLUG; 865 hdmi->hpd = readl(hdmi->regs + HDMI_STA) & HDMI_STA_HOT_PLUG;
@@ -867,7 +872,7 @@ static int sti_hdmi_probe(struct platform_device *pdev)
867 hdmi_irq_thread, IRQF_ONESHOT, dev_name(dev), hdmi); 872 hdmi_irq_thread, IRQF_ONESHOT, dev_name(dev), hdmi);
868 if (ret) { 873 if (ret) {
869 DRM_ERROR("Failed to register HDMI interrupt\n"); 874 DRM_ERROR("Failed to register HDMI interrupt\n");
870 return ret; 875 goto release_adapter;
871 } 876 }
872 877
873 hdmi->reset = devm_reset_control_get(dev, "hdmi"); 878 hdmi->reset = devm_reset_control_get(dev, "hdmi");
@@ -878,16 +883,20 @@ static int sti_hdmi_probe(struct platform_device *pdev)
878 platform_set_drvdata(pdev, hdmi); 883 platform_set_drvdata(pdev, hdmi);
879 884
880 return component_add(&pdev->dev, &sti_hdmi_ops); 885 return component_add(&pdev->dev, &sti_hdmi_ops);
886
887 release_adapter:
888 i2c_put_adapter(hdmi->ddc_adapt);
889
890 return ret;
881} 891}
882 892
883static int sti_hdmi_remove(struct platform_device *pdev) 893static int sti_hdmi_remove(struct platform_device *pdev)
884{ 894{
885 struct sti_hdmi *hdmi = dev_get_drvdata(&pdev->dev); 895 struct sti_hdmi *hdmi = dev_get_drvdata(&pdev->dev);
886 896
887 if (hdmi->ddc_adapt) 897 i2c_put_adapter(hdmi->ddc_adapt);
888 put_device(&hdmi->ddc_adapt->dev);
889
890 component_del(&pdev->dev, &sti_hdmi_ops); 898 component_del(&pdev->dev, &sti_hdmi_ops);
899
891 return 0; 900 return 0;
892} 901}
893 902
@@ -901,8 +910,6 @@ struct platform_driver sti_hdmi_driver = {
901 .remove = sti_hdmi_remove, 910 .remove = sti_hdmi_remove,
902}; 911};
903 912
904module_platform_driver(sti_hdmi_driver);
905
906MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>"); 913MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
907MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver"); 914MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
908MODULE_LICENSE("GPL"); 915MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c
index 7c8f9b8bfae1..ea0690bc77d5 100644
--- a/drivers/gpu/drm/sti/sti_hqvdp.c
+++ b/drivers/gpu/drm/sti/sti_hqvdp.c
@@ -628,6 +628,153 @@ static void sti_hqvdp_init(struct sti_hqvdp *hqvdp)
628 memset(hqvdp->hqvdp_cmd, 0, size); 628 memset(hqvdp->hqvdp_cmd, 0, size);
629} 629}
630 630
631static void sti_hqvdp_init_plugs(struct sti_hqvdp *hqvdp)
632{
633 /* Configure Plugs (same for RD & WR) */
634 writel(PLUG_PAGE_SIZE_256, hqvdp->regs + HQVDP_RD_PLUG_PAGE_SIZE);
635 writel(PLUG_MIN_OPC_8, hqvdp->regs + HQVDP_RD_PLUG_MIN_OPC);
636 writel(PLUG_MAX_OPC_64, hqvdp->regs + HQVDP_RD_PLUG_MAX_OPC);
637 writel(PLUG_MAX_CHK_2X, hqvdp->regs + HQVDP_RD_PLUG_MAX_CHK);
638 writel(PLUG_MAX_MSG_1X, hqvdp->regs + HQVDP_RD_PLUG_MAX_MSG);
639 writel(PLUG_MIN_SPACE_1, hqvdp->regs + HQVDP_RD_PLUG_MIN_SPACE);
640 writel(PLUG_CONTROL_ENABLE, hqvdp->regs + HQVDP_RD_PLUG_CONTROL);
641
642 writel(PLUG_PAGE_SIZE_256, hqvdp->regs + HQVDP_WR_PLUG_PAGE_SIZE);
643 writel(PLUG_MIN_OPC_8, hqvdp->regs + HQVDP_WR_PLUG_MIN_OPC);
644 writel(PLUG_MAX_OPC_64, hqvdp->regs + HQVDP_WR_PLUG_MAX_OPC);
645 writel(PLUG_MAX_CHK_2X, hqvdp->regs + HQVDP_WR_PLUG_MAX_CHK);
646 writel(PLUG_MAX_MSG_1X, hqvdp->regs + HQVDP_WR_PLUG_MAX_MSG);
647 writel(PLUG_MIN_SPACE_1, hqvdp->regs + HQVDP_WR_PLUG_MIN_SPACE);
648 writel(PLUG_CONTROL_ENABLE, hqvdp->regs + HQVDP_WR_PLUG_CONTROL);
649}
650
651/**
652 * sti_hqvdp_start_xp70
653 * @hqvdp: hqvdp pointer
654 *
655 * Run the xP70 initialization sequence
656 */
657static void sti_hqvdp_start_xp70(struct sti_hqvdp *hqvdp)
658{
659 const struct firmware *firmware;
660 u32 *fw_rd_plug, *fw_wr_plug, *fw_pmem, *fw_dmem;
661 u8 *data;
662 int i;
663 struct fw_header {
664 int rd_size;
665 int wr_size;
666 int pmem_size;
667 int dmem_size;
668 } *header;
669
670 DRM_DEBUG_DRIVER("\n");
671
672 if (hqvdp->xp70_initialized) {
673 DRM_INFO("HQVDP XP70 already initialized\n");
674 return;
675 }
676
677 /* Request firmware */
678 if (request_firmware(&firmware, HQVDP_FMW_NAME, hqvdp->dev)) {
679 DRM_ERROR("Can't get HQVDP firmware\n");
680 return;
681 }
682
683 /* Check firmware parts */
684 if (!firmware) {
685 DRM_ERROR("Firmware not available\n");
686 return;
687 }
688
689 header = (struct fw_header *)firmware->data;
690 if (firmware->size < sizeof(*header)) {
691 DRM_ERROR("Invalid firmware size (%d)\n", firmware->size);
692 goto out;
693 }
694 if ((sizeof(*header) + header->rd_size + header->wr_size +
695 header->pmem_size + header->dmem_size) != firmware->size) {
696 DRM_ERROR("Invalid fmw structure (%d+%d+%d+%d+%d != %d)\n",
697 sizeof(*header), header->rd_size, header->wr_size,
698 header->pmem_size, header->dmem_size,
699 firmware->size);
700 goto out;
701 }
702
703 data = (u8 *)firmware->data;
704 data += sizeof(*header);
705 fw_rd_plug = (void *)data;
706 data += header->rd_size;
707 fw_wr_plug = (void *)data;
708 data += header->wr_size;
709 fw_pmem = (void *)data;
710 data += header->pmem_size;
711 fw_dmem = (void *)data;
712
713 /* Enable clock */
714 if (clk_prepare_enable(hqvdp->clk))
715 DRM_ERROR("Failed to prepare/enable HQVDP clk\n");
716
717 /* Reset */
718 writel(SW_RESET_CTRL_FULL, hqvdp->regs + HQVDP_MBX_SW_RESET_CTRL);
719
720 for (i = 0; i < POLL_MAX_ATTEMPT; i++) {
721 if (readl(hqvdp->regs + HQVDP_MBX_STARTUP_CTRL1)
722 & STARTUP_CTRL1_RST_DONE)
723 break;
724 msleep(POLL_DELAY_MS);
725 }
726 if (i == POLL_MAX_ATTEMPT) {
727 DRM_ERROR("Could not reset\n");
728 goto out;
729 }
730
731 /* Init Read & Write plugs */
732 for (i = 0; i < header->rd_size / 4; i++)
733 writel(fw_rd_plug[i], hqvdp->regs + HQVDP_RD_PLUG + i * 4);
734 for (i = 0; i < header->wr_size / 4; i++)
735 writel(fw_wr_plug[i], hqvdp->regs + HQVDP_WR_PLUG + i * 4);
736
737 sti_hqvdp_init_plugs(hqvdp);
738
739 /* Authorize Idle Mode */
740 writel(STARTUP_CTRL1_AUTH_IDLE, hqvdp->regs + HQVDP_MBX_STARTUP_CTRL1);
741
742 /* Prevent VTG interruption during the boot */
743 writel(SOFT_VSYNC_SW_CTRL_IRQ, hqvdp->regs + HQVDP_MBX_SOFT_VSYNC);
744 writel(0, hqvdp->regs + HQVDP_MBX_NEXT_CMD);
745
746 /* Download PMEM & DMEM */
747 for (i = 0; i < header->pmem_size / 4; i++)
748 writel(fw_pmem[i], hqvdp->regs + HQVDP_PMEM + i * 4);
749 for (i = 0; i < header->dmem_size / 4; i++)
750 writel(fw_dmem[i], hqvdp->regs + HQVDP_DMEM + i * 4);
751
752 /* Enable fetch */
753 writel(STARTUP_CTRL2_FETCH_EN, hqvdp->regs + HQVDP_MBX_STARTUP_CTRL2);
754
755 /* Wait end of boot */
756 for (i = 0; i < POLL_MAX_ATTEMPT; i++) {
757 if (readl(hqvdp->regs + HQVDP_MBX_INFO_XP70)
758 & INFO_XP70_FW_READY)
759 break;
760 msleep(POLL_DELAY_MS);
761 }
762 if (i == POLL_MAX_ATTEMPT) {
763 DRM_ERROR("Could not boot\n");
764 goto out;
765 }
766
767 /* Launch Vsync */
768 writel(SOFT_VSYNC_HW, hqvdp->regs + HQVDP_MBX_SOFT_VSYNC);
769
770 DRM_INFO("HQVDP XP70 initialized\n");
771
772 hqvdp->xp70_initialized = true;
773
774out:
775 release_firmware(firmware);
776}
777
631static void sti_hqvdp_atomic_update(struct drm_plane *drm_plane, 778static void sti_hqvdp_atomic_update(struct drm_plane *drm_plane,
632 struct drm_plane_state *oldstate) 779 struct drm_plane_state *oldstate)
633{ 780{
@@ -754,6 +901,9 @@ static void sti_hqvdp_atomic_update(struct drm_plane *drm_plane,
754 sti_hqvdp_update_hvsrc(HVSRC_VERT, scale_v, &cmd->hvsrc); 901 sti_hqvdp_update_hvsrc(HVSRC_VERT, scale_v, &cmd->hvsrc);
755 902
756 if (first_prepare) { 903 if (first_prepare) {
904 /* Start HQVDP XP70 coprocessor */
905 sti_hqvdp_start_xp70(hqvdp);
906
757 /* Prevent VTG shutdown */ 907 /* Prevent VTG shutdown */
758 if (clk_prepare_enable(hqvdp->clk_pix_main)) { 908 if (clk_prepare_enable(hqvdp->clk_pix_main)) {
759 DRM_ERROR("Failed to prepare/enable pix main clk\n"); 909 DRM_ERROR("Failed to prepare/enable pix main clk\n");
@@ -763,7 +913,7 @@ static void sti_hqvdp_atomic_update(struct drm_plane *drm_plane,
763 /* Register VTG Vsync callback to handle bottom fields */ 913 /* Register VTG Vsync callback to handle bottom fields */
764 if (sti_vtg_register_client(hqvdp->vtg, 914 if (sti_vtg_register_client(hqvdp->vtg,
765 &hqvdp->vtg_nb, 915 &hqvdp->vtg_nb,
766 mixer->id)) { 916 crtc)) {
767 DRM_ERROR("Cannot register VTG notifier\n"); 917 DRM_ERROR("Cannot register VTG notifier\n");
768 return; 918 return;
769 } 919 }
@@ -836,168 +986,16 @@ static struct drm_plane *sti_hqvdp_create(struct drm_device *drm_dev,
836 return &hqvdp->plane.drm_plane; 986 return &hqvdp->plane.drm_plane;
837} 987}
838 988
839static void sti_hqvdp_init_plugs(struct sti_hqvdp *hqvdp)
840{
841 /* Configure Plugs (same for RD & WR) */
842 writel(PLUG_PAGE_SIZE_256, hqvdp->regs + HQVDP_RD_PLUG_PAGE_SIZE);
843 writel(PLUG_MIN_OPC_8, hqvdp->regs + HQVDP_RD_PLUG_MIN_OPC);
844 writel(PLUG_MAX_OPC_64, hqvdp->regs + HQVDP_RD_PLUG_MAX_OPC);
845 writel(PLUG_MAX_CHK_2X, hqvdp->regs + HQVDP_RD_PLUG_MAX_CHK);
846 writel(PLUG_MAX_MSG_1X, hqvdp->regs + HQVDP_RD_PLUG_MAX_MSG);
847 writel(PLUG_MIN_SPACE_1, hqvdp->regs + HQVDP_RD_PLUG_MIN_SPACE);
848 writel(PLUG_CONTROL_ENABLE, hqvdp->regs + HQVDP_RD_PLUG_CONTROL);
849
850 writel(PLUG_PAGE_SIZE_256, hqvdp->regs + HQVDP_WR_PLUG_PAGE_SIZE);
851 writel(PLUG_MIN_OPC_8, hqvdp->regs + HQVDP_WR_PLUG_MIN_OPC);
852 writel(PLUG_MAX_OPC_64, hqvdp->regs + HQVDP_WR_PLUG_MAX_OPC);
853 writel(PLUG_MAX_CHK_2X, hqvdp->regs + HQVDP_WR_PLUG_MAX_CHK);
854 writel(PLUG_MAX_MSG_1X, hqvdp->regs + HQVDP_WR_PLUG_MAX_MSG);
855 writel(PLUG_MIN_SPACE_1, hqvdp->regs + HQVDP_WR_PLUG_MIN_SPACE);
856 writel(PLUG_CONTROL_ENABLE, hqvdp->regs + HQVDP_WR_PLUG_CONTROL);
857}
858
859/**
860 * sti_hqvdp_start_xp70
861 * @firmware: firmware found
862 * @ctxt: hqvdp structure
863 *
864 * Run the xP70 initialization sequence
865 */
866static void sti_hqvdp_start_xp70(const struct firmware *firmware, void *ctxt)
867{
868 struct sti_hqvdp *hqvdp = ctxt;
869 u32 *fw_rd_plug, *fw_wr_plug, *fw_pmem, *fw_dmem;
870 u8 *data;
871 int i;
872 struct fw_header {
873 int rd_size;
874 int wr_size;
875 int pmem_size;
876 int dmem_size;
877 } *header;
878
879 DRM_DEBUG_DRIVER("\n");
880
881 if (hqvdp->xp70_initialized) {
882 DRM_INFO("HQVDP XP70 already initialized\n");
883 return;
884 }
885
886 /* Check firmware parts */
887 if (!firmware) {
888 DRM_ERROR("Firmware not available\n");
889 return;
890 }
891
892 header = (struct fw_header *) firmware->data;
893 if (firmware->size < sizeof(*header)) {
894 DRM_ERROR("Invalid firmware size (%d)\n", firmware->size);
895 goto out;
896 }
897 if ((sizeof(*header) + header->rd_size + header->wr_size +
898 header->pmem_size + header->dmem_size) != firmware->size) {
899 DRM_ERROR("Invalid fmw structure (%d+%d+%d+%d+%d != %d)\n",
900 sizeof(*header), header->rd_size, header->wr_size,
901 header->pmem_size, header->dmem_size,
902 firmware->size);
903 goto out;
904 }
905
906 data = (u8 *) firmware->data;
907 data += sizeof(*header);
908 fw_rd_plug = (void *) data;
909 data += header->rd_size;
910 fw_wr_plug = (void *) data;
911 data += header->wr_size;
912 fw_pmem = (void *) data;
913 data += header->pmem_size;
914 fw_dmem = (void *) data;
915
916 /* Enable clock */
917 if (clk_prepare_enable(hqvdp->clk))
918 DRM_ERROR("Failed to prepare/enable HQVDP clk\n");
919
920 /* Reset */
921 writel(SW_RESET_CTRL_FULL, hqvdp->regs + HQVDP_MBX_SW_RESET_CTRL);
922
923 for (i = 0; i < POLL_MAX_ATTEMPT; i++) {
924 if (readl(hqvdp->regs + HQVDP_MBX_STARTUP_CTRL1)
925 & STARTUP_CTRL1_RST_DONE)
926 break;
927 msleep(POLL_DELAY_MS);
928 }
929 if (i == POLL_MAX_ATTEMPT) {
930 DRM_ERROR("Could not reset\n");
931 goto out;
932 }
933
934 /* Init Read & Write plugs */
935 for (i = 0; i < header->rd_size / 4; i++)
936 writel(fw_rd_plug[i], hqvdp->regs + HQVDP_RD_PLUG + i * 4);
937 for (i = 0; i < header->wr_size / 4; i++)
938 writel(fw_wr_plug[i], hqvdp->regs + HQVDP_WR_PLUG + i * 4);
939
940 sti_hqvdp_init_plugs(hqvdp);
941
942 /* Authorize Idle Mode */
943 writel(STARTUP_CTRL1_AUTH_IDLE, hqvdp->regs + HQVDP_MBX_STARTUP_CTRL1);
944
945 /* Prevent VTG interruption during the boot */
946 writel(SOFT_VSYNC_SW_CTRL_IRQ, hqvdp->regs + HQVDP_MBX_SOFT_VSYNC);
947 writel(0, hqvdp->regs + HQVDP_MBX_NEXT_CMD);
948
949 /* Download PMEM & DMEM */
950 for (i = 0; i < header->pmem_size / 4; i++)
951 writel(fw_pmem[i], hqvdp->regs + HQVDP_PMEM + i * 4);
952 for (i = 0; i < header->dmem_size / 4; i++)
953 writel(fw_dmem[i], hqvdp->regs + HQVDP_DMEM + i * 4);
954
955 /* Enable fetch */
956 writel(STARTUP_CTRL2_FETCH_EN, hqvdp->regs + HQVDP_MBX_STARTUP_CTRL2);
957
958 /* Wait end of boot */
959 for (i = 0; i < POLL_MAX_ATTEMPT; i++) {
960 if (readl(hqvdp->regs + HQVDP_MBX_INFO_XP70)
961 & INFO_XP70_FW_READY)
962 break;
963 msleep(POLL_DELAY_MS);
964 }
965 if (i == POLL_MAX_ATTEMPT) {
966 DRM_ERROR("Could not boot\n");
967 goto out;
968 }
969
970 /* Launch Vsync */
971 writel(SOFT_VSYNC_HW, hqvdp->regs + HQVDP_MBX_SOFT_VSYNC);
972
973 DRM_INFO("HQVDP XP70 initialized\n");
974
975 hqvdp->xp70_initialized = true;
976
977out:
978 release_firmware(firmware);
979}
980
981int sti_hqvdp_bind(struct device *dev, struct device *master, void *data) 989int sti_hqvdp_bind(struct device *dev, struct device *master, void *data)
982{ 990{
983 struct sti_hqvdp *hqvdp = dev_get_drvdata(dev); 991 struct sti_hqvdp *hqvdp = dev_get_drvdata(dev);
984 struct drm_device *drm_dev = data; 992 struct drm_device *drm_dev = data;
985 struct drm_plane *plane; 993 struct drm_plane *plane;
986 int err;
987 994
988 DRM_DEBUG_DRIVER("\n"); 995 DRM_DEBUG_DRIVER("\n");
989 996
990 hqvdp->drm_dev = drm_dev; 997 hqvdp->drm_dev = drm_dev;
991 998
992 /* Request for firmware */
993 err = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
994 HQVDP_FMW_NAME, hqvdp->dev,
995 GFP_KERNEL, hqvdp, sti_hqvdp_start_xp70);
996 if (err) {
997 DRM_ERROR("Can't get HQVDP firmware\n");
998 return err;
999 }
1000
1001 /* Create HQVDP plane once xp70 is initialized */ 999 /* Create HQVDP plane once xp70 is initialized */
1002 plane = sti_hqvdp_create(drm_dev, hqvdp->dev, STI_HQVDP_0); 1000 plane = sti_hqvdp_create(drm_dev, hqvdp->dev, STI_HQVDP_0);
1003 if (!plane) 1001 if (!plane)
@@ -1090,8 +1088,6 @@ struct platform_driver sti_hqvdp_driver = {
1090 .remove = sti_hqvdp_remove, 1088 .remove = sti_hqvdp_remove,
1091}; 1089};
1092 1090
1093module_platform_driver(sti_hqvdp_driver);
1094
1095MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>"); 1091MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
1096MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver"); 1092MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
1097MODULE_LICENSE("GPL"); 1093MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/sti/sti_mixer.c b/drivers/gpu/drm/sti/sti_mixer.c
index 0182e9365004..49db835dce03 100644
--- a/drivers/gpu/drm/sti/sti_mixer.c
+++ b/drivers/gpu/drm/sti/sti_mixer.c
@@ -10,6 +10,11 @@
10#include "sti_mixer.h" 10#include "sti_mixer.h"
11#include "sti_vtg.h" 11#include "sti_vtg.h"
12 12
13/* Module parameter to set the background color of the mixer */
14static unsigned int bkg_color = 0x000000;
15MODULE_PARM_DESC(bkgcolor, "Value of the background color 0xRRGGBB");
16module_param_named(bkgcolor, bkg_color, int, 0644);
17
13/* Identity: G=Y , B=Cb , R=Cr */ 18/* Identity: G=Y , B=Cb , R=Cr */
14static const u32 mixerColorSpaceMatIdentity[] = { 19static const u32 mixerColorSpaceMatIdentity[] = {
15 0x10000000, 0x00000000, 0x10000000, 0x00001000, 20 0x10000000, 0x00000000, 0x10000000, 0x00001000,
@@ -58,7 +63,6 @@ const char *sti_mixer_to_str(struct sti_mixer *mixer)
58 return "<UNKNOWN MIXER>"; 63 return "<UNKNOWN MIXER>";
59 } 64 }
60} 65}
61EXPORT_SYMBOL(sti_mixer_to_str);
62 66
63static inline u32 sti_mixer_reg_read(struct sti_mixer *mixer, u32 reg_id) 67static inline u32 sti_mixer_reg_read(struct sti_mixer *mixer, u32 reg_id)
64{ 68{
@@ -81,11 +85,9 @@ void sti_mixer_set_background_status(struct sti_mixer *mixer, bool enable)
81} 85}
82 86
83static void sti_mixer_set_background_color(struct sti_mixer *mixer, 87static void sti_mixer_set_background_color(struct sti_mixer *mixer,
84 u8 red, u8 green, u8 blue) 88 unsigned int rgb)
85{ 89{
86 u32 val = (red << 16) | (green << 8) | blue; 90 sti_mixer_reg_write(mixer, GAM_MIXER_BKC, rgb);
87
88 sti_mixer_reg_write(mixer, GAM_MIXER_BKC, val);
89} 91}
90 92
91static void sti_mixer_set_background_area(struct sti_mixer *mixer, 93static void sti_mixer_set_background_area(struct sti_mixer *mixer,
@@ -175,7 +177,7 @@ int sti_mixer_active_video_area(struct sti_mixer *mixer,
175 sti_mixer_reg_write(mixer, GAM_MIXER_AVO, ydo << 16 | xdo); 177 sti_mixer_reg_write(mixer, GAM_MIXER_AVO, ydo << 16 | xdo);
176 sti_mixer_reg_write(mixer, GAM_MIXER_AVS, yds << 16 | xds); 178 sti_mixer_reg_write(mixer, GAM_MIXER_AVS, yds << 16 | xds);
177 179
178 sti_mixer_set_background_color(mixer, 0xFF, 0, 0); 180 sti_mixer_set_background_color(mixer, bkg_color);
179 181
180 sti_mixer_set_background_area(mixer, mode); 182 sti_mixer_set_background_area(mixer, mode);
181 sti_mixer_set_background_status(mixer, true); 183 sti_mixer_set_background_status(mixer, true);
diff --git a/drivers/gpu/drm/sti/sti_plane.c b/drivers/gpu/drm/sti/sti_plane.c
index d5c5e91f2956..2e5c751910c5 100644
--- a/drivers/gpu/drm/sti/sti_plane.c
+++ b/drivers/gpu/drm/sti/sti_plane.c
@@ -42,7 +42,6 @@ const char *sti_plane_to_str(struct sti_plane *plane)
42 return "<UNKNOWN PLANE>"; 42 return "<UNKNOWN PLANE>";
43 } 43 }
44} 44}
45EXPORT_SYMBOL(sti_plane_to_str);
46 45
47static void sti_plane_destroy(struct drm_plane *drm_plane) 46static void sti_plane_destroy(struct drm_plane *drm_plane)
48{ 47{
@@ -108,7 +107,6 @@ void sti_plane_init_property(struct sti_plane *plane,
108 plane->drm_plane.base.id, 107 plane->drm_plane.base.id,
109 sti_plane_to_str(plane), plane->zorder); 108 sti_plane_to_str(plane), plane->zorder);
110} 109}
111EXPORT_SYMBOL(sti_plane_init_property);
112 110
113struct drm_plane_funcs sti_plane_helpers_funcs = { 111struct drm_plane_funcs sti_plane_helpers_funcs = {
114 .update_plane = drm_atomic_helper_update_plane, 112 .update_plane = drm_atomic_helper_update_plane,
@@ -119,4 +117,3 @@ struct drm_plane_funcs sti_plane_helpers_funcs = {
119 .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, 117 .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
120 .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, 118 .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
121}; 119};
122EXPORT_SYMBOL(sti_plane_helpers_funcs);
diff --git a/drivers/gpu/drm/sti/sti_tvout.c b/drivers/gpu/drm/sti/sti_tvout.c
index c1aac8e66fb5..c8a4c5dae2b6 100644
--- a/drivers/gpu/drm/sti/sti_tvout.c
+++ b/drivers/gpu/drm/sti/sti_tvout.c
@@ -735,8 +735,6 @@ struct platform_driver sti_tvout_driver = {
735 .remove = sti_tvout_remove, 735 .remove = sti_tvout_remove,
736}; 736};
737 737
738module_platform_driver(sti_tvout_driver);
739
740MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>"); 738MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
741MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver"); 739MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
742MODULE_LICENSE("GPL"); 740MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/sti/sti_vtac.c b/drivers/gpu/drm/sti/sti_vtac.c
index 97bcdac23ae1..b1eb0d77630d 100644
--- a/drivers/gpu/drm/sti/sti_vtac.c
+++ b/drivers/gpu/drm/sti/sti_vtac.c
@@ -216,8 +216,6 @@ struct platform_driver sti_vtac_driver = {
216 .remove = sti_vtac_remove, 216 .remove = sti_vtac_remove,
217}; 217};
218 218
219module_platform_driver(sti_vtac_driver);
220
221MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>"); 219MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
222MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver"); 220MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
223MODULE_LICENSE("GPL"); 221MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/sti/sti_vtg.c b/drivers/gpu/drm/sti/sti_vtg.c
index aa8097137701..d56630c60039 100644
--- a/drivers/gpu/drm/sti/sti_vtg.c
+++ b/drivers/gpu/drm/sti/sti_vtg.c
@@ -79,7 +79,7 @@ LIST_HEAD(vtg_lookup);
79 * @irq: VTG irq 79 * @irq: VTG irq
80 * @type: VTG type (main or aux) 80 * @type: VTG type (main or aux)
81 * @notifier_list: notifier callback 81 * @notifier_list: notifier callback
82 * @crtc_id: the crtc id for vblank event 82 * @crtc: the CRTC for vblank event
83 * @slave: slave vtg 83 * @slave: slave vtg
84 * @link: List node to link the structure in lookup list 84 * @link: List node to link the structure in lookup list
85 */ 85 */
@@ -90,7 +90,7 @@ struct sti_vtg {
90 int irq; 90 int irq;
91 u32 irq_status; 91 u32 irq_status;
92 struct raw_notifier_head notifier_list; 92 struct raw_notifier_head notifier_list;
93 int crtc_id; 93 struct drm_crtc *crtc;
94 struct sti_vtg *slave; 94 struct sti_vtg *slave;
95 struct list_head link; 95 struct list_head link;
96}; 96};
@@ -110,7 +110,6 @@ struct sti_vtg *of_vtg_find(struct device_node *np)
110 } 110 }
111 return NULL; 111 return NULL;
112} 112}
113EXPORT_SYMBOL(of_vtg_find);
114 113
115static void vtg_reset(struct sti_vtg *vtg) 114static void vtg_reset(struct sti_vtg *vtg)
116{ 115{
@@ -242,7 +241,6 @@ void sti_vtg_set_config(struct sti_vtg *vtg,
242 else 241 else
243 vtg_enable_irq(vtg); 242 vtg_enable_irq(vtg);
244} 243}
245EXPORT_SYMBOL(sti_vtg_set_config);
246 244
247/** 245/**
248 * sti_vtg_get_line_number 246 * sti_vtg_get_line_number
@@ -265,7 +263,6 @@ u32 sti_vtg_get_line_number(struct drm_display_mode mode, int y)
265 263
266 return start_line + y; 264 return start_line + y;
267} 265}
268EXPORT_SYMBOL(sti_vtg_get_line_number);
269 266
270/** 267/**
271 * sti_vtg_get_pixel_number 268 * sti_vtg_get_pixel_number
@@ -281,18 +278,16 @@ u32 sti_vtg_get_pixel_number(struct drm_display_mode mode, int x)
281{ 278{
282 return mode.htotal - mode.hsync_start + x; 279 return mode.htotal - mode.hsync_start + x;
283} 280}
284EXPORT_SYMBOL(sti_vtg_get_pixel_number);
285 281
286int sti_vtg_register_client(struct sti_vtg *vtg, 282int sti_vtg_register_client(struct sti_vtg *vtg, struct notifier_block *nb,
287 struct notifier_block *nb, int crtc_id) 283 struct drm_crtc *crtc)
288{ 284{
289 if (vtg->slave) 285 if (vtg->slave)
290 return sti_vtg_register_client(vtg->slave, nb, crtc_id); 286 return sti_vtg_register_client(vtg->slave, nb, crtc);
291 287
292 vtg->crtc_id = crtc_id; 288 vtg->crtc = crtc;
293 return raw_notifier_chain_register(&vtg->notifier_list, nb); 289 return raw_notifier_chain_register(&vtg->notifier_list, nb);
294} 290}
295EXPORT_SYMBOL(sti_vtg_register_client);
296 291
297int sti_vtg_unregister_client(struct sti_vtg *vtg, struct notifier_block *nb) 292int sti_vtg_unregister_client(struct sti_vtg *vtg, struct notifier_block *nb)
298{ 293{
@@ -301,7 +296,6 @@ int sti_vtg_unregister_client(struct sti_vtg *vtg, struct notifier_block *nb)
301 296
302 return raw_notifier_chain_unregister(&vtg->notifier_list, nb); 297 return raw_notifier_chain_unregister(&vtg->notifier_list, nb);
303} 298}
304EXPORT_SYMBOL(sti_vtg_unregister_client);
305 299
306static irqreturn_t vtg_irq_thread(int irq, void *arg) 300static irqreturn_t vtg_irq_thread(int irq, void *arg)
307{ 301{
@@ -311,7 +305,7 @@ static irqreturn_t vtg_irq_thread(int irq, void *arg)
311 event = (vtg->irq_status & VTG_IRQ_TOP) ? 305 event = (vtg->irq_status & VTG_IRQ_TOP) ?
312 VTG_TOP_FIELD_EVENT : VTG_BOTTOM_FIELD_EVENT; 306 VTG_TOP_FIELD_EVENT : VTG_BOTTOM_FIELD_EVENT;
313 307
314 raw_notifier_call_chain(&vtg->notifier_list, event, &vtg->crtc_id); 308 raw_notifier_call_chain(&vtg->notifier_list, event, vtg->crtc);
315 309
316 return IRQ_HANDLED; 310 return IRQ_HANDLED;
317} 311}
@@ -406,8 +400,6 @@ struct platform_driver sti_vtg_driver = {
406 .remove = vtg_remove, 400 .remove = vtg_remove,
407}; 401};
408 402
409module_platform_driver(sti_vtg_driver);
410
411MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>"); 403MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
412MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver"); 404MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
413MODULE_LICENSE("GPL"); 405MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/sti/sti_vtg.h b/drivers/gpu/drm/sti/sti_vtg.h
index e84d23f1f57f..cd2439f89d05 100644
--- a/drivers/gpu/drm/sti/sti_vtg.h
+++ b/drivers/gpu/drm/sti/sti_vtg.h
@@ -17,8 +17,8 @@ struct notifier_block;
17struct sti_vtg *of_vtg_find(struct device_node *np); 17struct sti_vtg *of_vtg_find(struct device_node *np);
18void sti_vtg_set_config(struct sti_vtg *vtg, 18void sti_vtg_set_config(struct sti_vtg *vtg,
19 const struct drm_display_mode *mode); 19 const struct drm_display_mode *mode);
20int sti_vtg_register_client(struct sti_vtg *vtg, 20int sti_vtg_register_client(struct sti_vtg *vtg, struct notifier_block *nb,
21 struct notifier_block *nb, int crtc_id); 21 struct drm_crtc *crtc);
22int sti_vtg_unregister_client(struct sti_vtg *vtg, 22int sti_vtg_unregister_client(struct sti_vtg *vtg,
23 struct notifier_block *nb); 23 struct notifier_block *nb);
24 24