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