xref: /openbmc/linux/drivers/gpu/drm/sti/sti_crtc.c (revision 254e5e88)
1e2842570SBenjamin Gaignard // SPDX-License-Identifier: GPL-2.0
29e1f05b2SVincent Abriou /*
39e1f05b2SVincent Abriou  * Copyright (C) STMicroelectronics SA 2014
49e1f05b2SVincent Abriou  * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
59e1f05b2SVincent Abriou  *          Fabien Dessenne <fabien.dessenne@st.com>
69e1f05b2SVincent Abriou  *          for STMicroelectronics.
79e1f05b2SVincent Abriou  */
89e1f05b2SVincent Abriou 
99e1f05b2SVincent Abriou #include <linux/clk.h>
109e1f05b2SVincent Abriou 
119e1f05b2SVincent Abriou #include <drm/drm_atomic.h>
129e1f05b2SVincent Abriou #include <drm/drm_atomic_helper.h>
135e2f97a9SSam Ravnborg #include <drm/drm_device.h>
145e2f97a9SSam Ravnborg #include <drm/drm_print.h>
15fcd70cd3SDaniel Vetter #include <drm/drm_probe_helper.h>
165e2f97a9SSam Ravnborg #include <drm/drm_vblank.h>
179e1f05b2SVincent Abriou 
189e1f05b2SVincent Abriou #include "sti_compositor.h"
199e1f05b2SVincent Abriou #include "sti_crtc.h"
209e1f05b2SVincent Abriou #include "sti_drv.h"
2129d1dc62SVincent Abriou #include "sti_vid.h"
229e1f05b2SVincent Abriou #include "sti_vtg.h"
239e1f05b2SVincent Abriou 
sti_crtc_atomic_enable(struct drm_crtc * crtc,struct drm_atomic_state * state)240b20a0f8SLaurent Pinchart static void sti_crtc_atomic_enable(struct drm_crtc *crtc,
25351f950dSMaxime Ripard 				   struct drm_atomic_state *state)
269e1f05b2SVincent Abriou {
279e1f05b2SVincent Abriou 	struct sti_mixer *mixer = to_sti_mixer(crtc);
289e1f05b2SVincent Abriou 
2929d1dc62SVincent Abriou 	DRM_DEBUG_DRIVER("\n");
3029d1dc62SVincent Abriou 
3129d1dc62SVincent Abriou 	mixer->status = STI_MIXER_READY;
329e1f05b2SVincent Abriou 
3329d1dc62SVincent Abriou 	drm_crtc_vblank_on(crtc);
349e1f05b2SVincent Abriou }
359e1f05b2SVincent Abriou 
sti_crtc_atomic_disable(struct drm_crtc * crtc,struct drm_atomic_state * state)3664581714SLaurent Pinchart static void sti_crtc_atomic_disable(struct drm_crtc *crtc,
37351f950dSMaxime Ripard 				    struct drm_atomic_state *state)
389e1f05b2SVincent Abriou {
399e1f05b2SVincent Abriou 	struct sti_mixer *mixer = to_sti_mixer(crtc);
409e1f05b2SVincent Abriou 
4129d1dc62SVincent Abriou 	DRM_DEBUG_DRIVER("\n");
429e1f05b2SVincent Abriou 
4329d1dc62SVincent Abriou 	mixer->status = STI_MIXER_DISABLING;
44885054f9SBenjamin Gaignard 
45885054f9SBenjamin Gaignard 	drm_crtc_wait_one_vblank(crtc);
469e1f05b2SVincent Abriou }
479e1f05b2SVincent Abriou 
489e1f05b2SVincent Abriou static int
sti_crtc_mode_set(struct drm_crtc * crtc,struct drm_display_mode * mode)499e1f05b2SVincent Abriou sti_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode)
509e1f05b2SVincent Abriou {
519e1f05b2SVincent Abriou 	struct sti_mixer *mixer = to_sti_mixer(crtc);
529e1f05b2SVincent Abriou 	struct device *dev = mixer->dev;
539e1f05b2SVincent Abriou 	struct sti_compositor *compo = dev_get_drvdata(dev);
5432e14592SBenjamin Gaignard 	struct clk *compo_clk, *pix_clk;
559e1f05b2SVincent Abriou 	int rate = mode->clock * 1000;
569e1f05b2SVincent Abriou 
575e8345a0SShayenne Moura 	DRM_DEBUG_KMS("CRTC:%d (%s) mode: (%s)\n",
585e8345a0SShayenne Moura 		      crtc->base.id, sti_mixer_to_str(mixer), mode->name);
599e1f05b2SVincent Abriou 
605e8345a0SShayenne Moura 	DRM_DEBUG_KMS(DRM_MODE_FMT "\n", DRM_MODE_ARG(mode));
619e1f05b2SVincent Abriou 
6232e14592SBenjamin Gaignard 	if (mixer->id == STI_MIXER_MAIN) {
6332e14592SBenjamin Gaignard 		compo_clk = compo->clk_compo_main;
6432e14592SBenjamin Gaignard 		pix_clk = compo->clk_pix_main;
6532e14592SBenjamin Gaignard 	} else {
6632e14592SBenjamin Gaignard 		compo_clk = compo->clk_compo_aux;
6732e14592SBenjamin Gaignard 		pix_clk = compo->clk_pix_aux;
689e1f05b2SVincent Abriou 	}
6932e14592SBenjamin Gaignard 
7032e14592SBenjamin Gaignard 	/* Prepare and enable the compo IP clock */
7132e14592SBenjamin Gaignard 	if (clk_prepare_enable(compo_clk)) {
7232e14592SBenjamin Gaignard 		DRM_INFO("Failed to prepare/enable compositor clk\n");
7332e14592SBenjamin Gaignard 		goto compo_error;
7432e14592SBenjamin Gaignard 	}
7532e14592SBenjamin Gaignard 
7632e14592SBenjamin Gaignard 	/* Set rate and prepare/enable pixel clock */
7732e14592SBenjamin Gaignard 	if (clk_set_rate(pix_clk, rate) < 0) {
7832e14592SBenjamin Gaignard 		DRM_ERROR("Cannot set rate (%dHz) for pix clk\n", rate);
7932e14592SBenjamin Gaignard 		goto pix_error;
8032e14592SBenjamin Gaignard 	}
8132e14592SBenjamin Gaignard 	if (clk_prepare_enable(pix_clk)) {
829e1f05b2SVincent Abriou 		DRM_ERROR("Failed to prepare/enable pix clk\n");
8332e14592SBenjamin Gaignard 		goto pix_error;
849e1f05b2SVincent Abriou 	}
859e1f05b2SVincent Abriou 
86ffdbb82cSFabien Dessenne 	sti_vtg_set_config(compo->vtg[mixer->id], &crtc->mode);
879e1f05b2SVincent Abriou 
8832e14592SBenjamin Gaignard 	if (sti_mixer_active_video_area(mixer, &crtc->mode)) {
899e1f05b2SVincent Abriou 		DRM_ERROR("Can't set active video area\n");
9032e14592SBenjamin Gaignard 		goto mixer_error;
919e1f05b2SVincent Abriou 	}
929e1f05b2SVincent Abriou 
9332e14592SBenjamin Gaignard 	return 0;
9432e14592SBenjamin Gaignard 
9532e14592SBenjamin Gaignard mixer_error:
9632e14592SBenjamin Gaignard 	clk_disable_unprepare(pix_clk);
9732e14592SBenjamin Gaignard pix_error:
9832e14592SBenjamin Gaignard 	clk_disable_unprepare(compo_clk);
9932e14592SBenjamin Gaignard compo_error:
10032e14592SBenjamin Gaignard 	return -EINVAL;
1019e1f05b2SVincent Abriou }
1029e1f05b2SVincent Abriou 
sti_crtc_disable(struct drm_crtc * crtc)1039e1f05b2SVincent Abriou static void sti_crtc_disable(struct drm_crtc *crtc)
1049e1f05b2SVincent Abriou {
1059e1f05b2SVincent Abriou 	struct sti_mixer *mixer = to_sti_mixer(crtc);
1069e1f05b2SVincent Abriou 	struct device *dev = mixer->dev;
1079e1f05b2SVincent Abriou 	struct sti_compositor *compo = dev_get_drvdata(dev);
1089e1f05b2SVincent Abriou 
1099e1f05b2SVincent Abriou 	DRM_DEBUG_KMS("CRTC:%d (%s)\n", crtc->base.id, sti_mixer_to_str(mixer));
1109e1f05b2SVincent Abriou 
1119e1f05b2SVincent Abriou 	/* Disable Background */
1129e1f05b2SVincent Abriou 	sti_mixer_set_background_status(mixer, false);
1139e1f05b2SVincent Abriou 
1149e1f05b2SVincent Abriou 	drm_crtc_vblank_off(crtc);
1159e1f05b2SVincent Abriou 
1169e1f05b2SVincent Abriou 	/* Disable pixel clock and compo IP clocks */
1179e1f05b2SVincent Abriou 	if (mixer->id == STI_MIXER_MAIN) {
1189e1f05b2SVincent Abriou 		clk_disable_unprepare(compo->clk_pix_main);
1199e1f05b2SVincent Abriou 		clk_disable_unprepare(compo->clk_compo_main);
1209e1f05b2SVincent Abriou 	} else {
1219e1f05b2SVincent Abriou 		clk_disable_unprepare(compo->clk_pix_aux);
1229e1f05b2SVincent Abriou 		clk_disable_unprepare(compo->clk_compo_aux);
1239e1f05b2SVincent Abriou 	}
1249e1f05b2SVincent Abriou 
12529d1dc62SVincent Abriou 	mixer->status = STI_MIXER_DISABLED;
1269e1f05b2SVincent Abriou }
1279e1f05b2SVincent Abriou 
1289e1f05b2SVincent Abriou static void
sti_crtc_mode_set_nofb(struct drm_crtc * crtc)1299e1f05b2SVincent Abriou sti_crtc_mode_set_nofb(struct drm_crtc *crtc)
1309e1f05b2SVincent Abriou {
1319e1f05b2SVincent Abriou 	sti_crtc_mode_set(crtc, &crtc->state->adjusted_mode);
1329e1f05b2SVincent Abriou }
1339e1f05b2SVincent Abriou 
sti_crtc_atomic_flush(struct drm_crtc * crtc,struct drm_atomic_state * state)134e1474e7bSDave Airlie static void sti_crtc_atomic_flush(struct drm_crtc *crtc,
135*f6ebe9f9SMaxime Ripard 				  struct drm_atomic_state *state)
1369e1f05b2SVincent Abriou {
13729d1dc62SVincent Abriou 	struct drm_device *drm_dev = crtc->dev;
13829d1dc62SVincent Abriou 	struct sti_mixer *mixer = to_sti_mixer(crtc);
13929d1dc62SVincent Abriou 	struct sti_compositor *compo = dev_get_drvdata(mixer->dev);
14029d1dc62SVincent Abriou 	struct drm_plane *p;
141c62052d1SFabien DESSENNE 	struct drm_pending_vblank_event *event;
142c62052d1SFabien DESSENNE 	unsigned long flags;
14329d1dc62SVincent Abriou 
14429d1dc62SVincent Abriou 	DRM_DEBUG_DRIVER("\n");
14529d1dc62SVincent Abriou 
14629d1dc62SVincent Abriou 	/* perform plane actions */
14729d1dc62SVincent Abriou 	list_for_each_entry(p, &drm_dev->mode_config.plane_list, head) {
14829d1dc62SVincent Abriou 		struct sti_plane *plane = to_sti_plane(p);
14929d1dc62SVincent Abriou 
15029d1dc62SVincent Abriou 		switch (plane->status) {
15129d1dc62SVincent Abriou 		case STI_PLANE_UPDATED:
1523bc6b01dSFabien Dessenne 			/* ignore update for other CRTC */
1533bc6b01dSFabien Dessenne 			if (p->state->crtc != crtc)
1543bc6b01dSFabien Dessenne 				continue;
1553bc6b01dSFabien Dessenne 
15629d1dc62SVincent Abriou 			/* update planes tag as updated */
15729d1dc62SVincent Abriou 			DRM_DEBUG_DRIVER("update plane %s\n",
15829d1dc62SVincent Abriou 					 sti_plane_to_str(plane));
15929d1dc62SVincent Abriou 
16029d1dc62SVincent Abriou 			if (sti_mixer_set_plane_depth(mixer, plane)) {
16129d1dc62SVincent Abriou 				DRM_ERROR("Cannot set plane %s depth\n",
16229d1dc62SVincent Abriou 					  sti_plane_to_str(plane));
16329d1dc62SVincent Abriou 				break;
16429d1dc62SVincent Abriou 			}
16529d1dc62SVincent Abriou 
16629d1dc62SVincent Abriou 			if (sti_mixer_set_plane_status(mixer, plane, true)) {
16729d1dc62SVincent Abriou 				DRM_ERROR("Cannot enable plane %s at mixer\n",
16829d1dc62SVincent Abriou 					  sti_plane_to_str(plane));
16929d1dc62SVincent Abriou 				break;
17029d1dc62SVincent Abriou 			}
17129d1dc62SVincent Abriou 
17229d1dc62SVincent Abriou 			/* if plane is HQVDP_0 then commit the vid[0] */
17329d1dc62SVincent Abriou 			if (plane->desc == STI_HQVDP_0)
17429d1dc62SVincent Abriou 				sti_vid_commit(compo->vid[0], p->state);
17529d1dc62SVincent Abriou 
17629d1dc62SVincent Abriou 			plane->status = STI_PLANE_READY;
17729d1dc62SVincent Abriou 
17829d1dc62SVincent Abriou 			break;
17929d1dc62SVincent Abriou 		case STI_PLANE_DISABLING:
18029d1dc62SVincent Abriou 			/* disabling sequence for planes tag as disabling */
18129d1dc62SVincent Abriou 			DRM_DEBUG_DRIVER("disable plane %s from mixer\n",
18229d1dc62SVincent Abriou 					 sti_plane_to_str(plane));
18329d1dc62SVincent Abriou 
18429d1dc62SVincent Abriou 			if (sti_mixer_set_plane_status(mixer, plane, false)) {
18529d1dc62SVincent Abriou 				DRM_ERROR("Cannot disable plane %s at mixer\n",
18629d1dc62SVincent Abriou 					  sti_plane_to_str(plane));
18729d1dc62SVincent Abriou 				continue;
18829d1dc62SVincent Abriou 			}
18929d1dc62SVincent Abriou 
19029d1dc62SVincent Abriou 			if (plane->desc == STI_CURSOR)
19129d1dc62SVincent Abriou 				/* tag plane status for disabled */
19229d1dc62SVincent Abriou 				plane->status = STI_PLANE_DISABLED;
19329d1dc62SVincent Abriou 			else
19429d1dc62SVincent Abriou 				/* tag plane status for flushing */
19529d1dc62SVincent Abriou 				plane->status = STI_PLANE_FLUSHING;
19629d1dc62SVincent Abriou 
19729d1dc62SVincent Abriou 			/* if plane is HQVDP_0 then disable the vid[0] */
19829d1dc62SVincent Abriou 			if (plane->desc == STI_HQVDP_0)
19929d1dc62SVincent Abriou 				sti_vid_disable(compo->vid[0]);
20029d1dc62SVincent Abriou 
20129d1dc62SVincent Abriou 			break;
20229d1dc62SVincent Abriou 		default:
20329d1dc62SVincent Abriou 			/* Other status case are not handled */
20429d1dc62SVincent Abriou 			break;
20529d1dc62SVincent Abriou 		}
20629d1dc62SVincent Abriou 	}
207c62052d1SFabien DESSENNE 
208c62052d1SFabien DESSENNE 	event = crtc->state->event;
209c62052d1SFabien DESSENNE 	if (event) {
210c62052d1SFabien DESSENNE 		crtc->state->event = NULL;
211c62052d1SFabien DESSENNE 
212c62052d1SFabien DESSENNE 		spin_lock_irqsave(&crtc->dev->event_lock, flags);
213c62052d1SFabien DESSENNE 		if (drm_crtc_vblank_get(crtc) == 0)
214c62052d1SFabien DESSENNE 			drm_crtc_arm_vblank_event(crtc, event);
215c62052d1SFabien DESSENNE 		else
216c62052d1SFabien DESSENNE 			drm_crtc_send_vblank_event(crtc, event);
217c62052d1SFabien DESSENNE 		spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
218c62052d1SFabien DESSENNE 	}
2199e1f05b2SVincent Abriou }
2209e1f05b2SVincent Abriou 
221c5de4853SVille Syrjälä static const struct drm_crtc_helper_funcs sti_crtc_helper_funcs = {
2229e1f05b2SVincent Abriou 	.mode_set_nofb = sti_crtc_mode_set_nofb,
2239e1f05b2SVincent Abriou 	.atomic_flush = sti_crtc_atomic_flush,
2240b20a0f8SLaurent Pinchart 	.atomic_enable = sti_crtc_atomic_enable,
22564581714SLaurent Pinchart 	.atomic_disable = sti_crtc_atomic_disable,
2269e1f05b2SVincent Abriou };
2279e1f05b2SVincent Abriou 
sti_crtc_destroy(struct drm_crtc * crtc)2289e1f05b2SVincent Abriou static void sti_crtc_destroy(struct drm_crtc *crtc)
2299e1f05b2SVincent Abriou {
2309e1f05b2SVincent Abriou 	DRM_DEBUG_KMS("\n");
2319e1f05b2SVincent Abriou 	drm_crtc_cleanup(crtc);
2329e1f05b2SVincent Abriou }
2339e1f05b2SVincent Abriou 
sti_crtc_set_property(struct drm_crtc * crtc,struct drm_property * property,uint64_t val)2349e1f05b2SVincent Abriou static int sti_crtc_set_property(struct drm_crtc *crtc,
2359e1f05b2SVincent Abriou 				 struct drm_property *property,
2369e1f05b2SVincent Abriou 				 uint64_t val)
2379e1f05b2SVincent Abriou {
2389e1f05b2SVincent Abriou 	DRM_DEBUG_KMS("\n");
2399e1f05b2SVincent Abriou 	return 0;
2409e1f05b2SVincent Abriou }
2419e1f05b2SVincent Abriou 
sti_crtc_vblank_cb(struct notifier_block * nb,unsigned long event,void * data)2429e1f05b2SVincent Abriou int sti_crtc_vblank_cb(struct notifier_block *nb,
2439e1f05b2SVincent Abriou 		       unsigned long event, void *data)
2449e1f05b2SVincent Abriou {
245ae217850SFabien Dessenne 	struct sti_compositor *compo;
2462388693eSThierry Reding 	struct drm_crtc *crtc = data;
2472388693eSThierry Reding 	struct sti_mixer *mixer;
2482388693eSThierry Reding 	unsigned int pipe;
2499e1f05b2SVincent Abriou 
2502388693eSThierry Reding 	pipe = drm_crtc_index(crtc);
251ae217850SFabien Dessenne 	compo = container_of(nb, struct sti_compositor, vtg_vblank_nb[pipe]);
2522388693eSThierry Reding 	mixer = compo->mixer[pipe];
2539e1f05b2SVincent Abriou 
2549e1f05b2SVincent Abriou 	if ((event != VTG_TOP_FIELD_EVENT) &&
2559e1f05b2SVincent Abriou 	    (event != VTG_BOTTOM_FIELD_EVENT)) {
2569e1f05b2SVincent Abriou 		DRM_ERROR("unknown event: %lu\n", event);
2579e1f05b2SVincent Abriou 		return -EINVAL;
2589e1f05b2SVincent Abriou 	}
2599e1f05b2SVincent Abriou 
2602388693eSThierry Reding 	drm_crtc_handle_vblank(crtc);
2619e1f05b2SVincent Abriou 
2622388693eSThierry Reding 	if (mixer->status == STI_MIXER_DISABLING) {
26329d1dc62SVincent Abriou 		struct drm_plane *p;
26429d1dc62SVincent Abriou 
26529d1dc62SVincent Abriou 		/* Disable mixer only if all overlay planes (GDP and VDP)
26629d1dc62SVincent Abriou 		 * are disabled */
2672388693eSThierry Reding 		list_for_each_entry(p, &crtc->dev->mode_config.plane_list,
2682388693eSThierry Reding 				    head) {
26929d1dc62SVincent Abriou 			struct sti_plane *plane = to_sti_plane(p);
27029d1dc62SVincent Abriou 
27129d1dc62SVincent Abriou 			if ((plane->desc & STI_PLANE_TYPE_MASK) <= STI_VDP)
27229d1dc62SVincent Abriou 				if (plane->status != STI_PLANE_DISABLED)
27329d1dc62SVincent Abriou 					return 0;
27429d1dc62SVincent Abriou 		}
2752388693eSThierry Reding 		sti_crtc_disable(crtc);
27629d1dc62SVincent Abriou 	}
27729d1dc62SVincent Abriou 
2789e1f05b2SVincent Abriou 	return 0;
2799e1f05b2SVincent Abriou }
2809e1f05b2SVincent Abriou 
sti_crtc_enable_vblank(struct drm_crtc * crtc)28187b09c62SThomas Zimmermann static int sti_crtc_enable_vblank(struct drm_crtc *crtc)
2829e1f05b2SVincent Abriou {
28387b09c62SThomas Zimmermann 	struct drm_device *dev = crtc->dev;
28487b09c62SThomas Zimmermann 	unsigned int pipe = crtc->index;
2859e1f05b2SVincent Abriou 	struct sti_private *dev_priv = dev->dev_private;
2869e1f05b2SVincent Abriou 	struct sti_compositor *compo = dev_priv->compo;
287ae217850SFabien Dessenne 	struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb[pipe];
288ffdbb82cSFabien Dessenne 	struct sti_vtg *vtg = compo->vtg[pipe];
2899e1f05b2SVincent Abriou 
2909e1f05b2SVincent Abriou 	DRM_DEBUG_DRIVER("\n");
2919e1f05b2SVincent Abriou 
292ffdbb82cSFabien Dessenne 	if (sti_vtg_register_client(vtg, vtg_vblank_nb, crtc)) {
2939e1f05b2SVincent Abriou 		DRM_ERROR("Cannot register VTG notifier\n");
2949e1f05b2SVincent Abriou 		return -EINVAL;
2959e1f05b2SVincent Abriou 	}
2969e1f05b2SVincent Abriou 
2979e1f05b2SVincent Abriou 	return 0;
2989e1f05b2SVincent Abriou }
2999e1f05b2SVincent Abriou 
sti_crtc_disable_vblank(struct drm_crtc * crtc)30087b09c62SThomas Zimmermann static void sti_crtc_disable_vblank(struct drm_crtc *crtc)
3019e1f05b2SVincent Abriou {
30287b09c62SThomas Zimmermann 	struct drm_device *drm_dev = crtc->dev;
30387b09c62SThomas Zimmermann 	unsigned int pipe = crtc->index;
30429d1dc62SVincent Abriou 	struct sti_private *priv = drm_dev->dev_private;
3059e1f05b2SVincent Abriou 	struct sti_compositor *compo = priv->compo;
306ae217850SFabien Dessenne 	struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb[pipe];
307ffdbb82cSFabien Dessenne 	struct sti_vtg *vtg = compo->vtg[pipe];
3089e1f05b2SVincent Abriou 
3099e1f05b2SVincent Abriou 	DRM_DEBUG_DRIVER("\n");
3109e1f05b2SVincent Abriou 
311ffdbb82cSFabien Dessenne 	if (sti_vtg_unregister_client(vtg, vtg_vblank_nb))
3129e1f05b2SVincent Abriou 		DRM_DEBUG_DRIVER("Warning: cannot unregister VTG notifier\n");
3139e1f05b2SVincent Abriou }
3149e1f05b2SVincent Abriou 
sti_crtc_late_register(struct drm_crtc * crtc)31583af0a48SBenjamin Gaignard static int sti_crtc_late_register(struct drm_crtc *crtc)
31683af0a48SBenjamin Gaignard {
31783af0a48SBenjamin Gaignard 	struct sti_mixer *mixer = to_sti_mixer(crtc);
31883af0a48SBenjamin Gaignard 	struct sti_compositor *compo = dev_get_drvdata(mixer->dev);
31983af0a48SBenjamin Gaignard 
32083af0a48SBenjamin Gaignard 	if (drm_crtc_index(crtc) == 0)
32154ac836bSWambui Karuga 		sti_compositor_debugfs_init(compo, crtc->dev->primary);
32283af0a48SBenjamin Gaignard 
32383af0a48SBenjamin Gaignard 	return 0;
32483af0a48SBenjamin Gaignard }
32583af0a48SBenjamin Gaignard 
326c5de4853SVille Syrjälä static const struct drm_crtc_funcs sti_crtc_funcs = {
3279e1f05b2SVincent Abriou 	.set_config = drm_atomic_helper_set_config,
3289e1f05b2SVincent Abriou 	.page_flip = drm_atomic_helper_page_flip,
3299e1f05b2SVincent Abriou 	.destroy = sti_crtc_destroy,
3309e1f05b2SVincent Abriou 	.set_property = sti_crtc_set_property,
3319e1f05b2SVincent Abriou 	.reset = drm_atomic_helper_crtc_reset,
3329e1f05b2SVincent Abriou 	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
3339e1f05b2SVincent Abriou 	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
33483af0a48SBenjamin Gaignard 	.late_register = sti_crtc_late_register,
33587b09c62SThomas Zimmermann 	.enable_vblank = sti_crtc_enable_vblank,
33687b09c62SThomas Zimmermann 	.disable_vblank = sti_crtc_disable_vblank,
3379e1f05b2SVincent Abriou };
3389e1f05b2SVincent Abriou 
sti_crtc_is_main(struct drm_crtc * crtc)3399e1f05b2SVincent Abriou bool sti_crtc_is_main(struct drm_crtc *crtc)
3409e1f05b2SVincent Abriou {
3419e1f05b2SVincent Abriou 	struct sti_mixer *mixer = to_sti_mixer(crtc);
3429e1f05b2SVincent Abriou 
3439e1f05b2SVincent Abriou 	if (mixer->id == STI_MIXER_MAIN)
3449e1f05b2SVincent Abriou 		return true;
3459e1f05b2SVincent Abriou 
3469e1f05b2SVincent Abriou 	return false;
3479e1f05b2SVincent Abriou }
3489e1f05b2SVincent Abriou 
sti_crtc_init(struct drm_device * drm_dev,struct sti_mixer * mixer,struct drm_plane * primary,struct drm_plane * cursor)3499e1f05b2SVincent Abriou int sti_crtc_init(struct drm_device *drm_dev, struct sti_mixer *mixer,
3509e1f05b2SVincent Abriou 		  struct drm_plane *primary, struct drm_plane *cursor)
3519e1f05b2SVincent Abriou {
3529e1f05b2SVincent Abriou 	struct drm_crtc *crtc = &mixer->drm_crtc;
3539e1f05b2SVincent Abriou 	int res;
3549e1f05b2SVincent Abriou 
3559e1f05b2SVincent Abriou 	res = drm_crtc_init_with_planes(drm_dev, crtc, primary, cursor,
356f9882876SVille Syrjälä 					&sti_crtc_funcs, NULL);
3579e1f05b2SVincent Abriou 	if (res) {
358304f72e5SColin Ian King 		DRM_ERROR("Can't initialize CRTC\n");
3599e1f05b2SVincent Abriou 		return -EINVAL;
3609e1f05b2SVincent Abriou 	}
3619e1f05b2SVincent Abriou 
3629e1f05b2SVincent Abriou 	drm_crtc_helper_add(crtc, &sti_crtc_helper_funcs);
3639e1f05b2SVincent Abriou 
3649e1f05b2SVincent Abriou 	DRM_DEBUG_DRIVER("drm CRTC:%d mapped to %s\n",
3659e1f05b2SVincent Abriou 			 crtc->base.id, sti_mixer_to_str(mixer));
3669e1f05b2SVincent Abriou 
3679e1f05b2SVincent Abriou 	return 0;
3689e1f05b2SVincent Abriou }
369