blob: d32497a97e61aa5b4cac6b3f003b7aa85a6ff1d8 [file] [log] [blame]
Nirmal Abrahamfdfdb7d2020-06-30 11:15:37 +05301/* Copyright (c) 2012-2018, 2020, The Linux Foundation. All rights reserved.
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13
14#define pr_fmt(fmt) "%s: " fmt, __func__
15
16#include <linux/errno.h>
17#include <linux/kernel.h>
18#include <linux/major.h>
19#include <linux/pm_runtime.h>
20#include <linux/uaccess.h>
21#include <linux/delay.h>
22#include <linux/msm_mdp.h>
23#include <linux/memblock.h>
Sachin Bhayareeeb88892018-01-02 16:36:01 +053024#include <linux/file.h>
25
26#include <soc/qcom/event_timer.h>
27#include "mdp3_ctrl.h"
28#include "mdp3.h"
29#include "mdp3_ppp.h"
30#include "mdp3_ctrl.h"
31#include "mdss_fb.h"
Arun kumar47145e02018-03-23 22:07:51 +053032#include "mdss_sync.h"
Sachin Bhayareeeb88892018-01-02 16:36:01 +053033
34enum {
35 MDP3_RELEASE_FENCE = 0,
36 MDP3_RETIRE_FENCE,
37};
38
Arun kumar47145e02018-03-23 22:07:51 +053039static struct mdss_fence *__mdp3_create_fence(struct msm_fb_data_type *mfd,
Sachin Bhayareeeb88892018-01-02 16:36:01 +053040 struct msm_sync_pt_data *sync_pt_data, u32 fence_type,
41 int *fence_fd, int value)
42{
Arun kumar47145e02018-03-23 22:07:51 +053043 struct mdss_fence *sync_fence = NULL;
Sachin Bhayareeeb88892018-01-02 16:36:01 +053044 char fence_name[32];
45 struct mdp3_session_data *mdp3_session;
46
47 mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
48
49 if (fence_type == MDP3_RETIRE_FENCE)
50 snprintf(fence_name, sizeof(fence_name), "fb%d_retire",
51 mfd->index);
52 else
53 snprintf(fence_name, sizeof(fence_name), "fb%d_release",
54 mfd->index);
55
56 if ((fence_type == MDP3_RETIRE_FENCE) &&
57 (mfd->panel.type == MIPI_CMD_PANEL)) {
Arun kumar47145e02018-03-23 22:07:51 +053058 if (sync_pt_data->timeline_retire) {
59 value = sync_pt_data->timeline_retire->value + 1 +
60 mdp3_session->retire_cnt++;
61 sync_fence = mdss_fb_sync_get_fence(
62 sync_pt_data->timeline_retire,
Sachin Bhayareeeb88892018-01-02 16:36:01 +053063 fence_name, value);
Arun kumar47145e02018-03-23 22:07:51 +053064
Sachin Bhayareeeb88892018-01-02 16:36:01 +053065 } else {
66 return ERR_PTR(-EPERM);
67 }
68 } else {
Arun kumar47145e02018-03-23 22:07:51 +053069 if (fence_type == MDP3_RETIRE_FENCE)
70 sync_fence = mdss_fb_sync_get_fence(
71 sync_pt_data->timeline_retire,
72 fence_name, value);
73 else
74 sync_fence = mdss_fb_sync_get_fence(
75 sync_pt_data->timeline,
76 fence_name, value);
77 }
Sachin Bhayareeeb88892018-01-02 16:36:01 +053078
79 if (IS_ERR_OR_NULL(sync_fence)) {
80 pr_err("%s: unable to retrieve release fence\n", fence_name);
81 goto end;
82 }
83
Arun kumar47145e02018-03-23 22:07:51 +053084 *fence_fd = mdss_get_sync_fence_fd(sync_fence);
Sachin Bhayareeeb88892018-01-02 16:36:01 +053085 if (*fence_fd < 0) {
86 pr_err("%s: get_unused_fd_flags failed error:0x%x\n",
87 fence_name, *fence_fd);
Arun kumar47145e02018-03-23 22:07:51 +053088 mdss_put_sync_fence(sync_fence);
89 sync_fence = NULL;
90 goto end;
Sachin Bhayareeeb88892018-01-02 16:36:01 +053091 }
Arun kumar47145e02018-03-23 22:07:51 +053092 pr_debug("%s:val=%d\n", mdss_get_sync_fence_name(sync_fence), value);
Sachin Bhayareeeb88892018-01-02 16:36:01 +053093end:
Sachin Bhayareeeb88892018-01-02 16:36:01 +053094 return sync_fence;
95}
96
97/*
98 * __handle_buffer_fences() - copy sync fences and return release
99 * fence to caller.
100 *
101 * This function copies all input sync fences to acquire fence array and
102 * returns release fences to caller. It acts like buff_sync ioctl.
103 */
104static int __mdp3_handle_buffer_fences(struct msm_fb_data_type *mfd,
105 struct mdp_layer_commit_v1 *commit, struct mdp_input_layer *layer_list)
106{
Arun kumar47145e02018-03-23 22:07:51 +0530107 struct mdss_fence *fence, *release_fence, *retire_fence;
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530108 struct msm_sync_pt_data *sync_pt_data = NULL;
109 struct mdp_input_layer *layer;
110 int value;
111
112 u32 acq_fen_count, i, ret = 0;
113 u32 layer_count = commit->input_layer_cnt;
114
115 sync_pt_data = &mfd->mdp_sync_pt_data;
116 if (!sync_pt_data) {
117 pr_err("sync point data are NULL\n");
118 return -EINVAL;
119 }
120
121 i = mdss_fb_wait_for_fence(sync_pt_data);
122 if (i > 0)
123 pr_warn("%s: waited on %d active fences\n",
124 sync_pt_data->fence_name, i);
125
126 mutex_lock(&sync_pt_data->sync_mutex);
127 for (i = 0, acq_fen_count = 0; i < layer_count; i++) {
128 layer = &layer_list[i];
129
130 if (layer->buffer.fence < 0)
131 continue;
132
Arun kumar47145e02018-03-23 22:07:51 +0530133 fence = mdss_get_fd_sync_fence(layer->buffer.fence);
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530134 if (!fence) {
135 pr_err("%s: sync fence get failed! fd=%d\n",
136 sync_pt_data->fence_name, layer->buffer.fence);
137 ret = -EINVAL;
138 goto sync_fence_err;
139 } else {
140 sync_pt_data->acq_fen[acq_fen_count++] = fence;
141 }
142 }
143
144 sync_pt_data->acq_fen_cnt = acq_fen_count;
145 if (ret)
146 goto sync_fence_err;
147
Arun kumar47145e02018-03-23 22:07:51 +0530148 value = sync_pt_data->threshold +
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530149 atomic_read(&sync_pt_data->commit_cnt);
150
151 release_fence = __mdp3_create_fence(mfd, sync_pt_data,
152 MDP3_RELEASE_FENCE, &commit->release_fence, value);
153 if (IS_ERR_OR_NULL(release_fence)) {
154 pr_err("unable to retrieve release fence\n");
155 ret = PTR_ERR(release_fence);
156 goto release_fence_err;
157 }
158
159 retire_fence = __mdp3_create_fence(mfd, sync_pt_data,
160 MDP3_RETIRE_FENCE, &commit->retire_fence, value);
161 if (IS_ERR_OR_NULL(retire_fence)) {
162 pr_err("unable to retrieve retire fence\n");
163 ret = PTR_ERR(retire_fence);
164 goto retire_fence_err;
165 }
166
167 mutex_unlock(&sync_pt_data->sync_mutex);
168 return ret;
169
170retire_fence_err:
171 put_unused_fd(commit->release_fence);
Arun kumar47145e02018-03-23 22:07:51 +0530172 mdss_put_sync_fence(release_fence);
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530173release_fence_err:
174 commit->retire_fence = -1;
175 commit->release_fence = -1;
176sync_fence_err:
177 for (i = 0; i < sync_pt_data->acq_fen_cnt; i++)
Arun kumar47145e02018-03-23 22:07:51 +0530178 mdss_put_sync_fence(sync_pt_data->acq_fen[i]);
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530179 sync_pt_data->acq_fen_cnt = 0;
180
181 mutex_unlock(&sync_pt_data->sync_mutex);
182
183 return ret;
184}
185
186/*
187 * __map_layer_buffer() - map input layer buffer
188 *
189 */
190static int __mdp3_map_layer_buffer(struct msm_fb_data_type *mfd,
191 struct mdp_input_layer *input_layer)
192{
193 struct mdp3_session_data *mdp3_session = mfd->mdp.private1;
194 struct mdp3_dma *dma = mdp3_session->dma;
195 struct mdp_input_layer *layer = NULL;
196 struct mdp_layer_buffer *buffer;
197 struct msmfb_data img;
198 bool is_panel_type_cmd = false;
199 struct mdp3_img_data data;
Arun kumardb962812018-05-30 16:31:52 +0530200 int intf_type;
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530201 int rc = 0;
202
203 layer = &input_layer[0];
204 buffer = &layer->buffer;
205
206 /* current implementation only supports one plane mapping */
207 if (buffer->planes[0].fd < 0) {
208 pr_err("invalid file descriptor for layer buffer\n");
209 goto err;
210 }
211
Arun kumardb962812018-05-30 16:31:52 +0530212 intf_type = mdp3_get_ion_client(mfd);
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530213 memset(&img, 0, sizeof(img));
214 img.memory_id = buffer->planes[0].fd;
215 img.offset = buffer->planes[0].offset;
216
217 memset(&data, 0, sizeof(struct mdp3_img_data));
218
Arun kumardb962812018-05-30 16:31:52 +0530219 if (mfd->panel.type == MIPI_CMD_PANEL || intf_type == MDP3_CLIENT_SPI)
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530220 is_panel_type_cmd = true;
221 if (is_panel_type_cmd) {
Arun kumardb962812018-05-30 16:31:52 +0530222 rc = mdp3_iommu_enable(intf_type);
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530223 if (rc) {
224 pr_err("fail to enable iommu\n");
225 return rc;
226 }
227 }
228
Arun kumardb962812018-05-30 16:31:52 +0530229 rc = mdp3_get_img(&img, &data, intf_type);
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530230 if (rc) {
231 pr_err("fail to get overlay buffer\n");
232 goto err;
233 }
234
235 if (data.len < dma->source_config.stride * dma->source_config.height) {
236 pr_err("buf size(0x%lx) is smaller than dma config(0x%x)\n",
237 data.len, (dma->source_config.stride *
238 dma->source_config.height));
Nirmal Abrahamfdfdb7d2020-06-30 11:15:37 +0530239 mdp3_put_img(&data, intf_type);
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530240 rc = -EINVAL;
241 goto err;
242 }
243
244 rc = mdp3_bufq_push(&mdp3_session->bufq_in, &data);
245 if (rc) {
246 pr_err("fail to queue the overlay buffer, buffer drop\n");
Nirmal Abrahamfdfdb7d2020-06-30 11:15:37 +0530247 mdp3_put_img(&data, intf_type);
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530248 goto err;
249 }
250 rc = 0;
251err:
252 if (is_panel_type_cmd)
Nirmal Abrahamfdfdb7d2020-06-30 11:15:37 +0530253 mdp3_iommu_disable(intf_type);
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530254 return rc;
255}
256
257int mdp3_layer_pre_commit(struct msm_fb_data_type *mfd,
258 struct file *file, struct mdp_layer_commit_v1 *commit)
259{
260 int ret;
261 struct mdp_input_layer *layer, *layer_list;
262 struct mdp3_session_data *mdp3_session;
263 struct mdp3_dma *dma;
264 int layer_count = commit->input_layer_cnt;
Arun kumardb962812018-05-30 16:31:52 +0530265 int stride, format, client;
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530266
267 /* Handle NULL commit */
268 if (!layer_count) {
269 pr_debug("Handle NULL commit\n");
270 return 0;
271 }
272
273 mdp3_session = mfd->mdp.private1;
274 dma = mdp3_session->dma;
275
276 mutex_lock(&mdp3_session->lock);
277
Arun kumardb962812018-05-30 16:31:52 +0530278 client = mdp3_get_ion_client(mfd);
279 mdp3_bufq_deinit(&mdp3_session->bufq_in, client);
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530280
281 layer_list = commit->input_layers;
282 layer = &layer_list[0];
283
284 stride = layer->buffer.width * ppp_bpp(layer->buffer.format);
285 format = mdp3_ctrl_get_source_format(layer->buffer.format);
286 pr_debug("stride:%d layer_width:%d", stride, layer->buffer.width);
287
288 if ((dma->source_config.format != format) ||
289 (dma->source_config.stride != stride)) {
290 dma->source_config.format = format;
291 dma->source_config.stride = stride;
292 dma->output_config.pack_pattern =
293 mdp3_ctrl_get_pack_pattern(layer->buffer.format);
294 dma->update_src_cfg = true;
295 }
296 mdp3_session->overlay.id = 1;
297
298 ret = __mdp3_handle_buffer_fences(mfd, commit, layer_list);
299 if (ret) {
300 pr_err("Failed to handle buffer fences\n");
301 mutex_unlock(&mdp3_session->lock);
302 return ret;
303 }
304
305 ret = __mdp3_map_layer_buffer(mfd, layer);
306 if (ret) {
307 pr_err("Failed to map buffer\n");
308 mutex_unlock(&mdp3_session->lock);
309 return ret;
310 }
311
312 pr_debug("mdp3 precommit ret = %d\n", ret);
313 mutex_unlock(&mdp3_session->lock);
314 return ret;
315}
316
317/*
318 * mdp3_layer_atomic_validate() - validate input layers
319 * @mfd: Framebuffer data structure for display
320 * @commit: Commit version-1 structure for display
321 *
322 * This function validates only input layers received from client. It
323 * does perform any validation for mdp_output_layer defined for writeback
324 * display.
325 */
326int mdp3_layer_atomic_validate(struct msm_fb_data_type *mfd,
327 struct file *file, struct mdp_layer_commit_v1 *commit)
328{
329 struct mdp3_session_data *mdp3_session;
330
331 if (!mfd || !commit) {
332 pr_err("invalid input params\n");
333 return -EINVAL;
334 }
335
336 if (mdss_fb_is_power_off(mfd)) {
337 pr_err("display interface is in off state fb:%d\n",
338 mfd->index);
339 return -EPERM;
340 }
341
342 mdp3_session = mfd->mdp.private1;
343
344 if (mdp3_session->in_splash_screen) {
345 mdp3_ctrl_reset(mfd);
346 mdp3_session->in_splash_screen = 0;
347 }
348
349 return 0;
350}
351