xref: /openbmc/linux/drivers/gpu/drm/sti/sti_plane.c (revision 293d5b43)
1 /*
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
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 	ktime_t now;
44 	struct sti_fps_info *fps;
45 	int fpks, fipks, ms_since_last, num_frames, num_fields;
46 
47 	now = ktime_get();
48 
49 	/* Compute number of frame updates */
50 	fps = &plane->fps_info;
51 
52 	if (new_field)
53 		fps->curr_field_counter++;
54 
55 	/* do not perform fps calcul if new_frame is false */
56 	if (!new_frame)
57 		return;
58 
59 	fps->curr_frame_counter++;
60 	ms_since_last = ktime_to_ms(ktime_sub(now, fps->last_timestamp));
61 	num_frames = fps->curr_frame_counter - fps->last_frame_counter;
62 
63 	if (num_frames <= 0  || ms_since_last < STI_FPS_INTERVAL_MS)
64 		return;
65 
66 	fps->last_timestamp = now;
67 	fps->last_frame_counter = fps->curr_frame_counter;
68 	fpks = (num_frames * 1000000) / ms_since_last;
69 	snprintf(plane->fps_info.fps_str, FPS_LENGTH, "%-6s @ %d.%.3d fps",
70 		 sti_plane_to_str(plane), fpks / 1000, fpks % 1000);
71 
72 	if (fps->curr_field_counter) {
73 		/* Compute number of field updates */
74 		num_fields = fps->curr_field_counter - fps->last_field_counter;
75 		fps->last_field_counter = fps->curr_field_counter;
76 		fipks = (num_fields * 1000000) / ms_since_last;
77 		snprintf(plane->fps_info.fips_str,
78 			 FPS_LENGTH, " - %d.%.3d field/sec",
79 			 fipks / 1000, fipks % 1000);
80 	} else {
81 		plane->fps_info.fips_str[0] = '\0';
82 	}
83 
84 	if (fps->output)
85 		DRM_INFO("%s%s\n",
86 			 plane->fps_info.fps_str,
87 			 plane->fps_info.fips_str);
88 }
89 
90 static int sti_plane_get_default_zpos(enum drm_plane_type type)
91 {
92 	switch (type) {
93 	case DRM_PLANE_TYPE_PRIMARY:
94 		return 0;
95 	case DRM_PLANE_TYPE_OVERLAY:
96 		return 1;
97 	case DRM_PLANE_TYPE_CURSOR:
98 		return 7;
99 	}
100 	return 0;
101 }
102 
103 void sti_plane_reset(struct drm_plane *plane)
104 {
105 	drm_atomic_helper_plane_reset(plane);
106 	plane->state->zpos = sti_plane_get_default_zpos(plane->type);
107 }
108 
109 static void sti_plane_attach_zorder_property(struct drm_plane *drm_plane,
110 					     enum drm_plane_type type)
111 {
112 	int zpos = sti_plane_get_default_zpos(type);
113 
114 	switch (type) {
115 	case DRM_PLANE_TYPE_PRIMARY:
116 	case DRM_PLANE_TYPE_OVERLAY:
117 		drm_plane_create_zpos_property(drm_plane, zpos, 0, 6);
118 		break;
119 	case DRM_PLANE_TYPE_CURSOR:
120 		drm_plane_create_zpos_immutable_property(drm_plane, zpos);
121 		break;
122 	}
123 }
124 
125 void sti_plane_init_property(struct sti_plane *plane,
126 			     enum drm_plane_type type)
127 {
128 	sti_plane_attach_zorder_property(&plane->drm_plane, type);
129 
130 	DRM_DEBUG_DRIVER("drm plane:%d mapped to %s\n",
131 			 plane->drm_plane.base.id, sti_plane_to_str(plane));
132 }
133