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