xref: /openbmc/linux/drivers/gpu/drm/sti/sti_plane.c (revision ba61bb17)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) STMicroelectronics SA 2014
4  * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
5  *          Fabien Dessenne <fabien.dessenne@st.com>
6  *          for STMicroelectronics.
7  */
8 
9 #include <drm/drmP.h>
10 #include <drm/drm_fb_cma_helper.h>
11 #include <drm/drm_gem_cma_helper.h>
12 
13 #include "sti_compositor.h"
14 #include "sti_drv.h"
15 #include "sti_plane.h"
16 
17 const char *sti_plane_to_str(struct sti_plane *plane)
18 {
19 	switch (plane->desc) {
20 	case STI_GDP_0:
21 		return "GDP0";
22 	case STI_GDP_1:
23 		return "GDP1";
24 	case STI_GDP_2:
25 		return "GDP2";
26 	case STI_GDP_3:
27 		return "GDP3";
28 	case STI_HQVDP_0:
29 		return "HQVDP0";
30 	case STI_CURSOR:
31 		return "CURSOR";
32 	default:
33 		return "<UNKNOWN PLANE>";
34 	}
35 }
36 
37 #define STI_FPS_INTERVAL_MS     3000
38 
39 void sti_plane_update_fps(struct sti_plane *plane,
40 			  bool new_frame,
41 			  bool new_field)
42 {
43 	struct drm_plane_state *state = plane->drm_plane.state;
44 	ktime_t now;
45 	struct sti_fps_info *fps;
46 	int fpks, fipks, ms_since_last, num_frames, num_fields;
47 
48 	now = ktime_get();
49 
50 	/* Compute number of frame updates */
51 	fps = &plane->fps_info;
52 
53 	if (new_field)
54 		fps->curr_field_counter++;
55 
56 	/* do not perform fps calcul if new_frame is false */
57 	if (!new_frame)
58 		return;
59 
60 	fps->curr_frame_counter++;
61 	ms_since_last = ktime_to_ms(ktime_sub(now, fps->last_timestamp));
62 	num_frames = fps->curr_frame_counter - fps->last_frame_counter;
63 
64 	if (num_frames <= 0  || ms_since_last < STI_FPS_INTERVAL_MS)
65 		return;
66 
67 	fps->last_timestamp = now;
68 	fps->last_frame_counter = fps->curr_frame_counter;
69 
70 	if (state->fb) {
71 		fpks = (num_frames * 1000000) / ms_since_last;
72 		snprintf(plane->fps_info.fps_str, FPS_LENGTH,
73 			 "%-8s %4dx%-4d %.4s @ %3d.%-3.3d fps (%s)",
74 			 plane->drm_plane.name,
75 			 state->fb->width,
76 			 state->fb->height,
77 			 (char *)&state->fb->format->format,
78 			 fpks / 1000, fpks % 1000,
79 			 sti_plane_to_str(plane));
80 	}
81 
82 	if (fps->curr_field_counter) {
83 		/* Compute number of field updates */
84 		num_fields = fps->curr_field_counter - fps->last_field_counter;
85 		fps->last_field_counter = fps->curr_field_counter;
86 		fipks = (num_fields * 1000000) / ms_since_last;
87 		snprintf(plane->fps_info.fips_str,
88 			 FPS_LENGTH, " - %3d.%-3.3d field/sec",
89 			 fipks / 1000, fipks % 1000);
90 	} else {
91 		plane->fps_info.fips_str[0] = '\0';
92 	}
93 
94 	if (fps->output)
95 		DRM_INFO("%s%s\n",
96 			 plane->fps_info.fps_str,
97 			 plane->fps_info.fips_str);
98 }
99 
100 static int sti_plane_get_default_zpos(enum drm_plane_type type)
101 {
102 	switch (type) {
103 	case DRM_PLANE_TYPE_PRIMARY:
104 		return 0;
105 	case DRM_PLANE_TYPE_OVERLAY:
106 		return 1;
107 	case DRM_PLANE_TYPE_CURSOR:
108 		return 7;
109 	}
110 	return 0;
111 }
112 
113 void sti_plane_reset(struct drm_plane *plane)
114 {
115 	drm_atomic_helper_plane_reset(plane);
116 	plane->state->zpos = sti_plane_get_default_zpos(plane->type);
117 }
118 
119 static void sti_plane_attach_zorder_property(struct drm_plane *drm_plane,
120 					     enum drm_plane_type type)
121 {
122 	int zpos = sti_plane_get_default_zpos(type);
123 
124 	switch (type) {
125 	case DRM_PLANE_TYPE_PRIMARY:
126 	case DRM_PLANE_TYPE_OVERLAY:
127 		drm_plane_create_zpos_property(drm_plane, zpos, 0, 6);
128 		break;
129 	case DRM_PLANE_TYPE_CURSOR:
130 		drm_plane_create_zpos_immutable_property(drm_plane, zpos);
131 		break;
132 	}
133 }
134 
135 void sti_plane_init_property(struct sti_plane *plane,
136 			     enum drm_plane_type type)
137 {
138 	sti_plane_attach_zorder_property(&plane->drm_plane, type);
139 
140 	DRM_DEBUG_DRIVER("drm plane:%d mapped to %s\n",
141 			 plane->drm_plane.base.id, sti_plane_to_str(plane));
142 }
143