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