xref: /linux/drivers/gpu/drm/sti/sti_plane.c (revision e5c86679d5e864947a52fb31e45a425dea3e7fa9)
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 
69 	if (plane->drm_plane.fb) {
70 		fpks = (num_frames * 1000000) / ms_since_last;
71 		snprintf(plane->fps_info.fps_str, FPS_LENGTH,
72 			 "%-8s %4dx%-4d %.4s @ %3d.%-3.3d fps (%s)",
73 			 plane->drm_plane.name,
74 			 plane->drm_plane.fb->width,
75 			 plane->drm_plane.fb->height,
76 			 (char *)&plane->drm_plane.fb->format->format,
77 			 fpks / 1000, fpks % 1000,
78 			 sti_plane_to_str(plane));
79 	}
80 
81 	if (fps->curr_field_counter) {
82 		/* Compute number of field updates */
83 		num_fields = fps->curr_field_counter - fps->last_field_counter;
84 		fps->last_field_counter = fps->curr_field_counter;
85 		fipks = (num_fields * 1000000) / ms_since_last;
86 		snprintf(plane->fps_info.fips_str,
87 			 FPS_LENGTH, " - %3d.%-3.3d field/sec",
88 			 fipks / 1000, fipks % 1000);
89 	} else {
90 		plane->fps_info.fips_str[0] = '\0';
91 	}
92 
93 	if (fps->output)
94 		DRM_INFO("%s%s\n",
95 			 plane->fps_info.fps_str,
96 			 plane->fps_info.fips_str);
97 }
98 
99 static int sti_plane_get_default_zpos(enum drm_plane_type type)
100 {
101 	switch (type) {
102 	case DRM_PLANE_TYPE_PRIMARY:
103 		return 0;
104 	case DRM_PLANE_TYPE_OVERLAY:
105 		return 1;
106 	case DRM_PLANE_TYPE_CURSOR:
107 		return 7;
108 	}
109 	return 0;
110 }
111 
112 void sti_plane_reset(struct drm_plane *plane)
113 {
114 	drm_atomic_helper_plane_reset(plane);
115 	plane->state->zpos = sti_plane_get_default_zpos(plane->type);
116 }
117 
118 static void sti_plane_attach_zorder_property(struct drm_plane *drm_plane,
119 					     enum drm_plane_type type)
120 {
121 	int zpos = sti_plane_get_default_zpos(type);
122 
123 	switch (type) {
124 	case DRM_PLANE_TYPE_PRIMARY:
125 	case DRM_PLANE_TYPE_OVERLAY:
126 		drm_plane_create_zpos_property(drm_plane, zpos, 0, 6);
127 		break;
128 	case DRM_PLANE_TYPE_CURSOR:
129 		drm_plane_create_zpos_immutable_property(drm_plane, zpos);
130 		break;
131 	}
132 }
133 
134 void sti_plane_init_property(struct sti_plane *plane,
135 			     enum drm_plane_type type)
136 {
137 	sti_plane_attach_zorder_property(&plane->drm_plane, type);
138 
139 	DRM_DEBUG_DRIVER("drm plane:%d mapped to %s\n",
140 			 plane->drm_plane.base.id, sti_plane_to_str(plane));
141 }
142