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