blob: 79a2495a2bfb56c48cdd1d9b378efbf4fff9c318 [file] [log] [blame]
Sachin Bhayareeeb88892018-01-02 16:36:01 +05301/*
2 * Core MDSS framebuffer driver.
3 *
4 * Copyright (C) 2007 Google Incorporated
5 * Copyright (c) 2008-2018, The Linux Foundation. All rights reserved.
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#define pr_fmt(fmt) "%s: " fmt, __func__
18
19#include <linux/videodev2.h>
20#include <linux/bootmem.h>
21#include <linux/console.h>
22#include <linux/debugfs.h>
23#include <linux/delay.h>
24#include <linux/device.h>
25#include <linux/dma-mapping.h>
26#include <linux/dma-buf.h>
27#include <linux/fb.h>
28#include <linux/init.h>
29#include <linux/ioport.h>
30#include <linux/kernel.h>
31#include <linux/memory.h>
32#include <linux/mm.h>
33#include <linux/module.h>
34#include <linux/moduleparam.h>
35#include <linux/msm_mdp.h>
36#include <linux/of.h>
37#include <linux/of_address.h>
38#include <linux/of_platform.h>
39#include <linux/proc_fs.h>
40#include <linux/pm_runtime.h>
41#include <linux/slab.h>
42#include <linux/string.h>
43#include <linux/uaccess.h>
44#include <linux/version.h>
45#include <linux/vmalloc.h>
Sachin Bhayareeeb88892018-01-02 16:36:01 +053046#include <linux/file.h>
47#include <linux/kthread.h>
48#include <linux/dma-buf.h>
49#include "mdss_fb.h"
50#include "mdss_mdp_splash_logo.h"
51#define CREATE_TRACE_POINTS
52#include "mdss_debug.h"
53#include "mdss_smmu.h"
54#include "mdss_mdp.h"
55#include "mdp3_ctrl.h"
Sachin Bhayare2b6d0042018-01-13 19:38:21 +053056#include "mdss_sync.h"
Sachin Bhayareeeb88892018-01-02 16:36:01 +053057
58#ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
59#define MDSS_FB_NUM 3
60#else
61#define MDSS_FB_NUM 2
62#endif
63
64#ifndef EXPORT_COMPAT
65#define EXPORT_COMPAT(x)
66#endif
67
68#define MAX_FBI_LIST 32
69
70#ifndef TARGET_HW_MDSS_MDP3
71#define BLANK_FLAG_LP FB_BLANK_NORMAL
72#define BLANK_FLAG_ULP FB_BLANK_VSYNC_SUSPEND
73#else
74#define BLANK_FLAG_LP FB_BLANK_VSYNC_SUSPEND
75#define BLANK_FLAG_ULP FB_BLANK_NORMAL
76#endif
77
78/*
79 * Time period for fps calulation in micro seconds.
80 * Default value is set to 1 sec.
81 */
82#define MDP_TIME_PERIOD_CALC_FPS_US 1000000
83
84static struct fb_info *fbi_list[MAX_FBI_LIST];
85static int fbi_list_index;
86
87static u32 mdss_fb_pseudo_palette[16] = {
88 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff,
89 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
90 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
91 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
92};
93
94static struct msm_mdp_interface *mdp_instance;
95
96static int mdss_fb_register(struct msm_fb_data_type *mfd);
97static int mdss_fb_open(struct fb_info *info, int user);
98static int mdss_fb_release(struct fb_info *info, int user);
99static int mdss_fb_release_all(struct fb_info *info, bool release_all);
100static int mdss_fb_pan_display(struct fb_var_screeninfo *var,
101 struct fb_info *info);
102static int mdss_fb_check_var(struct fb_var_screeninfo *var,
103 struct fb_info *info);
104static int mdss_fb_set_par(struct fb_info *info);
105static int mdss_fb_blank_sub(int blank_mode, struct fb_info *info,
106 int op_enable);
107static int mdss_fb_suspend_sub(struct msm_fb_data_type *mfd);
108static int mdss_fb_ioctl(struct fb_info *info, unsigned int cmd,
109 unsigned long arg, struct file *file);
110static int mdss_fb_fbmem_ion_mmap(struct fb_info *info,
111 struct vm_area_struct *vma);
112static int mdss_fb_alloc_fb_ion_memory(struct msm_fb_data_type *mfd,
113 size_t size);
114static void mdss_fb_release_fences(struct msm_fb_data_type *mfd);
115static int __mdss_fb_sync_buf_done_callback(struct notifier_block *p,
116 unsigned long val, void *data);
117
118static int __mdss_fb_display_thread(void *data);
119static int mdss_fb_pan_idle(struct msm_fb_data_type *mfd);
120static int mdss_fb_send_panel_event(struct msm_fb_data_type *mfd,
121 int event, void *arg);
122static void mdss_fb_set_mdp_sync_pt_threshold(struct msm_fb_data_type *mfd,
123 int type);
124void mdss_fb_no_update_notify_timer_cb(unsigned long data)
125{
126 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)data;
127
128 if (!mfd) {
129 pr_err("%s mfd NULL\n", __func__);
130 return;
131 }
132 mfd->no_update.value = NOTIFY_TYPE_NO_UPDATE;
133 complete(&mfd->no_update.comp);
134}
135
136void mdss_fb_bl_update_notify(struct msm_fb_data_type *mfd,
137 uint32_t notification_type)
138{
139#ifndef TARGET_HW_MDSS_MDP3
140 struct mdss_overlay_private *mdp5_data = NULL;
141#endif
142#ifdef TARGET_HW_MDSS_MDP3
143 struct mdp3_session_data *mdp3_session = NULL;
144#endif
145 if (!mfd) {
146 pr_err("%s mfd NULL\n", __func__);
147 return;
148 }
149 mutex_lock(&mfd->update.lock);
150 if (mfd->update.is_suspend) {
151 mutex_unlock(&mfd->update.lock);
152 return;
153 }
154 if (mfd->update.ref_count > 0) {
155 mutex_unlock(&mfd->update.lock);
156 mfd->update.value = notification_type;
157 complete(&mfd->update.comp);
158 mutex_lock(&mfd->update.lock);
159 }
160 mutex_unlock(&mfd->update.lock);
161
162 mutex_lock(&mfd->no_update.lock);
163 if (mfd->no_update.ref_count > 0) {
164 mutex_unlock(&mfd->no_update.lock);
165 mfd->no_update.value = notification_type;
166 complete(&mfd->no_update.comp);
167 mutex_lock(&mfd->no_update.lock);
168 }
169 mutex_unlock(&mfd->no_update.lock);
170#ifndef TARGET_HW_MDSS_MDP3
171 mdp5_data = mfd_to_mdp5_data(mfd);
172 if (mdp5_data) {
173 if (notification_type == NOTIFY_TYPE_BL_AD_ATTEN_UPDATE) {
174 mdp5_data->ad_bl_events++;
175 sysfs_notify_dirent(mdp5_data->ad_bl_event_sd);
176 } else if (notification_type == NOTIFY_TYPE_BL_UPDATE) {
177 mdp5_data->bl_events++;
178 sysfs_notify_dirent(mdp5_data->bl_event_sd);
179 }
180 }
181#endif
182#ifdef TARGET_HW_MDSS_MDP3
183 mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
184 if (mdp3_session) {
185 mdp3_session->bl_events++;
186 sysfs_notify_dirent(mdp3_session->bl_event_sd);
187 pr_debug("bl_event = %u\n", mdp3_session->bl_events);
188 }
189#endif
190}
191
192static int mdss_fb_notify_update(struct msm_fb_data_type *mfd,
193 unsigned long *argp)
194{
195 int ret;
196 unsigned int notify = 0x0, to_user = 0x0;
197
198 ret = copy_from_user(&notify, argp, sizeof(unsigned int));
199 if (ret) {
200 pr_err("%s:ioctl failed\n", __func__);
201 return ret;
202 }
203
204 if (notify > NOTIFY_UPDATE_POWER_OFF)
205 return -EINVAL;
206
207 if (notify == NOTIFY_UPDATE_INIT) {
208 mutex_lock(&mfd->update.lock);
209 mfd->update.init_done = true;
210 mutex_unlock(&mfd->update.lock);
211 ret = 1;
212 } else if (notify == NOTIFY_UPDATE_DEINIT) {
213 mutex_lock(&mfd->update.lock);
214 mfd->update.init_done = false;
215 mutex_unlock(&mfd->update.lock);
216 complete(&mfd->update.comp);
217 complete(&mfd->no_update.comp);
218 ret = 1;
219 } else if (mfd->update.is_suspend) {
220 to_user = NOTIFY_TYPE_SUSPEND;
221 mfd->update.is_suspend = 0;
222 ret = 1;
223 } else if (notify == NOTIFY_UPDATE_START) {
224 mutex_lock(&mfd->update.lock);
225 if (mfd->update.init_done)
226 reinit_completion(&mfd->update.comp);
227 else {
228 mutex_unlock(&mfd->update.lock);
229 pr_err("notify update start called without init\n");
230 return -EINVAL;
231 }
232 mfd->update.ref_count++;
233 mutex_unlock(&mfd->update.lock);
234 ret = wait_for_completion_interruptible_timeout(
235 &mfd->update.comp, 4 * HZ);
236 mutex_lock(&mfd->update.lock);
237 mfd->update.ref_count--;
238 mutex_unlock(&mfd->update.lock);
239 to_user = (unsigned int)mfd->update.value;
240 if (mfd->update.type == NOTIFY_TYPE_SUSPEND) {
241 to_user = (unsigned int)mfd->update.type;
242 ret = 1;
243 }
244 } else if (notify == NOTIFY_UPDATE_STOP) {
245 mutex_lock(&mfd->update.lock);
246 if (mfd->update.init_done)
247 reinit_completion(&mfd->no_update.comp);
248 else {
249 mutex_unlock(&mfd->update.lock);
250 pr_err("notify update stop called without init\n");
251 return -EINVAL;
252 }
253 mfd->no_update.ref_count++;
254 mutex_unlock(&mfd->no_update.lock);
255 ret = wait_for_completion_interruptible_timeout(
256 &mfd->no_update.comp, 4 * HZ);
257 mutex_lock(&mfd->no_update.lock);
258 mfd->no_update.ref_count--;
259 mutex_unlock(&mfd->no_update.lock);
260 to_user = (unsigned int)mfd->no_update.value;
261 } else {
262 if (mdss_fb_is_power_on(mfd)) {
263 reinit_completion(&mfd->power_off_comp);
264 ret = wait_for_completion_interruptible_timeout(
265 &mfd->power_off_comp, 1 * HZ);
266 }
267 }
268
269 if (ret == 0)
270 ret = -ETIMEDOUT;
271 else if (ret > 0)
272 ret = copy_to_user(argp, &to_user, sizeof(unsigned int));
273 return ret;
274}
275
276static int lcd_backlight_registered;
277
278static void mdss_fb_set_bl_brightness(struct led_classdev *led_cdev,
279 enum led_brightness value)
280{
281 struct msm_fb_data_type *mfd = dev_get_drvdata(led_cdev->dev->parent);
Sachin Bhayareb6b5a0f2018-03-02 19:50:39 +0530282 u64 bl_lvl;
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530283
284 if (mfd->boot_notification_led) {
285 led_trigger_event(mfd->boot_notification_led, 0);
286 mfd->boot_notification_led = NULL;
287 }
288
289 if (value > mfd->panel_info->brightness_max)
290 value = mfd->panel_info->brightness_max;
291
292 /* This maps android backlight level 0 to 255 into
293 * driver backlight level 0 to bl_max with rounding
294 */
295 MDSS_BRIGHT_TO_BL(bl_lvl, value, mfd->panel_info->bl_max,
296 mfd->panel_info->brightness_max);
297
298 if (!bl_lvl && value)
299 bl_lvl = 1;
300
301 if (!IS_CALIB_MODE_BL(mfd) && (!mfd->ext_bl_ctrl || !value ||
302 !mfd->bl_level)) {
303 mutex_lock(&mfd->bl_lock);
304 mdss_fb_set_backlight(mfd, bl_lvl);
305 mutex_unlock(&mfd->bl_lock);
306 }
307}
308
309static struct led_classdev backlight_led = {
310 .name = "lcd-backlight",
311 .brightness = MDSS_MAX_BL_BRIGHTNESS / 2,
312 .brightness_set = mdss_fb_set_bl_brightness,
313 .max_brightness = MDSS_MAX_BL_BRIGHTNESS,
314};
315
316static ssize_t mdss_fb_get_type(struct device *dev,
317 struct device_attribute *attr, char *buf)
318{
319 ssize_t ret = 0;
320 struct fb_info *fbi = dev_get_drvdata(dev);
321 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par;
322
323 switch (mfd->panel.type) {
324 case NO_PANEL:
325 ret = snprintf(buf, PAGE_SIZE, "no panel\n");
326 break;
327 case HDMI_PANEL:
328 ret = snprintf(buf, PAGE_SIZE, "hdmi panel\n");
329 break;
330 case LVDS_PANEL:
331 ret = snprintf(buf, PAGE_SIZE, "lvds panel\n");
332 break;
333 case DTV_PANEL:
334 ret = snprintf(buf, PAGE_SIZE, "dtv panel\n");
335 break;
336 case MIPI_VIDEO_PANEL:
337 ret = snprintf(buf, PAGE_SIZE, "mipi dsi video panel\n");
338 break;
339 case MIPI_CMD_PANEL:
340 ret = snprintf(buf, PAGE_SIZE, "mipi dsi cmd panel\n");
341 break;
342 case WRITEBACK_PANEL:
343 ret = snprintf(buf, PAGE_SIZE, "writeback panel\n");
344 break;
345 case EDP_PANEL:
346 ret = snprintf(buf, PAGE_SIZE, "edp panel\n");
347 break;
348 default:
349 ret = snprintf(buf, PAGE_SIZE, "unknown panel\n");
350 break;
351 }
352
353 return ret;
354}
355
356static int mdss_fb_get_panel_xres(struct mdss_panel_info *pinfo)
357{
358 struct mdss_panel_data *pdata;
359 int xres;
360
361 pdata = container_of(pinfo, struct mdss_panel_data, panel_info);
362
363 xres = pinfo->xres;
364 if (pdata->next && pdata->next->active)
365 xres += mdss_fb_get_panel_xres(&pdata->next->panel_info);
366
367 return xres;
368}
369
370static inline int mdss_fb_validate_split(int left, int right,
371 struct msm_fb_data_type *mfd)
372{
373 int rc = -EINVAL;
374 u32 panel_xres = mdss_fb_get_panel_xres(mfd->panel_info);
375
376 pr_debug("%pS: split_mode = %d left=%d right=%d panel_xres=%d\n",
377 __builtin_return_address(0), mfd->split_mode,
378 left, right, panel_xres);
379
380 /* more validate condition could be added if needed */
381 if (left && right) {
382 if (panel_xres == left + right) {
383 mfd->split_fb_left = left;
384 mfd->split_fb_right = right;
385 rc = 0;
386 }
387 } else {
388 if (mfd->split_mode == MDP_DUAL_LM_DUAL_DISPLAY) {
389 mfd->split_fb_left = mfd->panel_info->xres;
390 mfd->split_fb_right = panel_xres - mfd->split_fb_left;
391 rc = 0;
392 } else {
393 mfd->split_fb_left = mfd->split_fb_right = 0;
394 }
395 }
396
397 return rc;
398}
399
400static ssize_t mdss_fb_store_split(struct device *dev,
401 struct device_attribute *attr, const char *buf, size_t len)
402{
403 int data[2] = {0};
404 struct fb_info *fbi = dev_get_drvdata(dev);
405 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par;
406
407 if (sscanf(buf, "%d %d", &data[0], &data[1]) != 2)
408 pr_debug("Not able to read split values\n");
409 else if (!mdss_fb_validate_split(data[0], data[1], mfd))
410 pr_debug("split left=%d right=%d\n", data[0], data[1]);
411
412 return len;
413}
414
415static ssize_t mdss_fb_show_split(struct device *dev,
416 struct device_attribute *attr, char *buf)
417{
418 ssize_t ret = 0;
419 struct fb_info *fbi = dev_get_drvdata(dev);
420 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par;
421
422 ret = snprintf(buf, PAGE_SIZE, "%d %d\n",
423 mfd->split_fb_left, mfd->split_fb_right);
424 return ret;
425}
426
427static void mdss_fb_get_split(struct msm_fb_data_type *mfd)
428{
429 if ((mfd->split_mode == MDP_SPLIT_MODE_NONE) &&
430 (mfd->split_fb_left && mfd->split_fb_right))
431 mfd->split_mode = MDP_DUAL_LM_SINGLE_DISPLAY;
432
433 pr_debug("split fb%d left=%d right=%d mode=%d\n", mfd->index,
434 mfd->split_fb_left, mfd->split_fb_right, mfd->split_mode);
435}
436
437static ssize_t mdss_fb_get_src_split_info(struct device *dev,
438 struct device_attribute *attr, char *buf)
439{
440 int ret = 0;
441 struct fb_info *fbi = dev_get_drvdata(dev);
442 struct msm_fb_data_type *mfd = fbi->par;
443
444 if (is_split_lm(mfd) && (fbi->var.yres > fbi->var.xres)) {
445 pr_debug("always split mode enabled\n");
446 ret = scnprintf(buf, PAGE_SIZE,
447 "src_split_always\n");
448 }
449
450 return ret;
451}
452
453static ssize_t mdss_fb_get_thermal_level(struct device *dev,
454 struct device_attribute *attr, char *buf)
455{
456 struct fb_info *fbi = dev_get_drvdata(dev);
457 struct msm_fb_data_type *mfd = fbi->par;
458 int ret;
459
460 ret = scnprintf(buf, PAGE_SIZE, "thermal_level=%d\n",
461 mfd->thermal_level);
462
463 return ret;
464}
465
466static ssize_t mdss_fb_set_thermal_level(struct device *dev,
467 struct device_attribute *attr, const char *buf, size_t count)
468{
469 struct fb_info *fbi = dev_get_drvdata(dev);
470 struct msm_fb_data_type *mfd = fbi->par;
471 int rc = 0;
472 int thermal_level = 0;
473
474 rc = kstrtoint(buf, 10, &thermal_level);
475 if (rc) {
476 pr_err("kstrtoint failed. rc=%d\n", rc);
477 return rc;
478 }
479
480 pr_debug("Thermal level set to %d\n", thermal_level);
481 mfd->thermal_level = thermal_level;
482 sysfs_notify(&mfd->fbi->dev->kobj, NULL, "msm_fb_thermal_level");
483
484 return count;
485}
486
487static ssize_t mdss_mdp_show_blank_event(struct device *dev,
488 struct device_attribute *attr, char *buf)
489{
490 struct fb_info *fbi = dev_get_drvdata(dev);
491 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par;
492 int ret;
493
494 pr_debug("fb%d panel_power_state = %d\n", mfd->index,
495 mfd->panel_power_state);
496 ret = scnprintf(buf, PAGE_SIZE, "panel_power_on = %d\n",
497 mfd->panel_power_state);
498
499 return ret;
500}
501
502static void __mdss_fb_idle_notify_work(struct work_struct *work)
503{
504 struct delayed_work *dw = to_delayed_work(work);
505 struct msm_fb_data_type *mfd = container_of(dw, struct msm_fb_data_type,
506 idle_notify_work);
507
508 /* Notify idle-ness here */
509 pr_debug("Idle timeout %dms expired!\n", mfd->idle_time);
510 if (mfd->idle_time)
511 sysfs_notify(&mfd->fbi->dev->kobj, NULL, "idle_notify");
512 mfd->idle_state = MDSS_FB_IDLE;
513}
514
515
516static ssize_t mdss_fb_get_fps_info(struct device *dev,
517 struct device_attribute *attr, char *buf)
518{
519 struct fb_info *fbi = dev_get_drvdata(dev);
520 struct msm_fb_data_type *mfd = fbi->par;
Sachin Bhayareb6b5a0f2018-03-02 19:50:39 +0530521 u64 fps_int, fps_float;
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530522
523 if (mfd->panel_power_state != MDSS_PANEL_POWER_ON)
524 mfd->fps_info.measured_fps = 0;
Sachin Bhayareb6b5a0f2018-03-02 19:50:39 +0530525 fps_int = (u64) mfd->fps_info.measured_fps;
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530526 fps_float = do_div(fps_int, 10);
Sachin Bhayareb6b5a0f2018-03-02 19:50:39 +0530527 return scnprintf(buf, PAGE_SIZE, "%llu.%llu\n", fps_int, fps_float);
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530528
529}
530
531static ssize_t mdss_fb_get_idle_time(struct device *dev,
532 struct device_attribute *attr, char *buf)
533{
534 struct fb_info *fbi = dev_get_drvdata(dev);
535 struct msm_fb_data_type *mfd = fbi->par;
536 int ret;
537
538 ret = scnprintf(buf, PAGE_SIZE, "%d", mfd->idle_time);
539
540 return ret;
541}
542
543static ssize_t mdss_fb_set_idle_time(struct device *dev,
544 struct device_attribute *attr, const char *buf, size_t count)
545{
546 struct fb_info *fbi = dev_get_drvdata(dev);
547 struct msm_fb_data_type *mfd = fbi->par;
548 int rc = 0;
549 int idle_time = 0;
550
551 rc = kstrtoint(buf, 10, &idle_time);
552 if (rc) {
553 pr_err("kstrtoint failed. rc=%d\n", rc);
554 return rc;
555 }
556
557 pr_debug("Idle time = %d\n", idle_time);
558 mfd->idle_time = idle_time;
559
560 return count;
561}
562
563static ssize_t mdss_fb_get_idle_notify(struct device *dev,
564 struct device_attribute *attr, char *buf)
565{
566 struct fb_info *fbi = dev_get_drvdata(dev);
567 struct msm_fb_data_type *mfd = fbi->par;
568 int ret;
569
570 ret = scnprintf(buf, PAGE_SIZE, "%s",
571 work_busy(&mfd->idle_notify_work.work) ? "no" : "yes");
572
573 return ret;
574}
575
576static ssize_t mdss_fb_get_panel_info(struct device *dev,
577 struct device_attribute *attr, char *buf)
578{
579 struct fb_info *fbi = dev_get_drvdata(dev);
580 struct msm_fb_data_type *mfd = fbi->par;
581 struct mdss_panel_info *pinfo = mfd->panel_info;
582 int ret;
583
584 ret = scnprintf(buf, PAGE_SIZE,
585 "pu_en=%d\nxstart=%d\nwalign=%d\nystart=%d\nhalign=%d\n"
586 "min_w=%d\nmin_h=%d\nroi_merge=%d\ndyn_fps_en=%d\n"
587 "min_fps=%d\nmax_fps=%d\npanel_name=%s\n"
588 "primary_panel=%d\nis_pluggable=%d\ndisplay_id=%s\n"
589 "is_cec_supported=%d\nis_pingpong_split=%d\n"
590 "is_hdr_enabled=%d\n"
591 "peak_brightness=%d\nblackness_level=%d\n"
592 "white_chromaticity_x=%d\nwhite_chromaticity_y=%d\n"
593 "red_chromaticity_x=%d\nred_chromaticity_y=%d\n"
594 "green_chromaticity_x=%d\ngreen_chromaticity_y=%d\n"
595 "blue_chromaticity_x=%d\nblue_chromaticity_y=%d\n",
596 pinfo->partial_update_enabled,
597 pinfo->roi_alignment.xstart_pix_align,
598 pinfo->roi_alignment.width_pix_align,
599 pinfo->roi_alignment.ystart_pix_align,
600 pinfo->roi_alignment.height_pix_align,
601 pinfo->roi_alignment.min_width,
602 pinfo->roi_alignment.min_height,
603 pinfo->partial_update_roi_merge,
604 pinfo->dynamic_fps, pinfo->min_fps, pinfo->max_fps,
605 pinfo->panel_name, pinfo->is_prim_panel,
606 pinfo->is_pluggable, pinfo->display_id,
607 pinfo->is_cec_supported, is_pingpong_split(mfd),
608 pinfo->hdr_properties.hdr_enabled,
609 pinfo->hdr_properties.peak_brightness,
610 pinfo->hdr_properties.blackness_level,
611 pinfo->hdr_properties.display_primaries[0],
612 pinfo->hdr_properties.display_primaries[1],
613 pinfo->hdr_properties.display_primaries[2],
614 pinfo->hdr_properties.display_primaries[3],
615 pinfo->hdr_properties.display_primaries[4],
616 pinfo->hdr_properties.display_primaries[5],
617 pinfo->hdr_properties.display_primaries[6],
618 pinfo->hdr_properties.display_primaries[7]);
619
620 return ret;
621}
622
623static ssize_t mdss_fb_get_panel_status(struct device *dev,
624 struct device_attribute *attr, char *buf)
625{
626 struct fb_info *fbi = dev_get_drvdata(dev);
627 struct msm_fb_data_type *mfd = fbi->par;
628 int ret;
629 int panel_status;
630
631 if (mdss_panel_is_power_off(mfd->panel_power_state)) {
632 ret = scnprintf(buf, PAGE_SIZE, "panel_status=%s\n", "suspend");
633 } else {
634 panel_status = mdss_fb_send_panel_event(mfd,
635 MDSS_EVENT_DSI_PANEL_STATUS, NULL);
636 ret = scnprintf(buf, PAGE_SIZE, "panel_status=%s\n",
637 panel_status > 0 ? "alive" : "dead");
638 }
639
640 return ret;
641}
642
643static ssize_t mdss_fb_force_panel_dead(struct device *dev,
644 struct device_attribute *attr, const char *buf, size_t len)
645{
646 struct fb_info *fbi = dev_get_drvdata(dev);
647 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par;
648 struct mdss_panel_data *pdata;
649
650 pdata = dev_get_platdata(&mfd->pdev->dev);
651 if (!pdata) {
652 pr_err("no panel connected!\n");
653 return len;
654 }
655
656 if (kstrtouint(buf, 0, &pdata->panel_info.panel_force_dead))
657 pr_err("kstrtouint buf error!\n");
658
659 return len;
660}
661
662/*
663 * mdss_fb_blanking_mode_switch() - Function triggers dynamic mode switch
664 * @mfd: Framebuffer data structure for display
665 * @mode: Enabled/Disable LowPowerMode
666 * 1: Enter into LowPowerMode
667 * 0: Exit from LowPowerMode
668 *
669 * This Function dynamically switches to and from video mode. This
670 * swtich involves the panel turning off backlight during trantision.
671 */
672static int mdss_fb_blanking_mode_switch(struct msm_fb_data_type *mfd, int mode)
673{
674 int ret = 0;
675 u32 bl_lvl = 0;
676 struct mdss_panel_info *pinfo = NULL;
677 struct mdss_panel_data *pdata;
678
679 if (!mfd || !mfd->panel_info)
680 return -EINVAL;
681
682 pinfo = mfd->panel_info;
683
684 if (!pinfo->mipi.dms_mode) {
685 pr_warn("Panel does not support dynamic switch!\n");
686 return 0;
687 }
688
689 if (mode == pinfo->mipi.mode) {
690 pr_debug("Already in requested mode!\n");
691 return 0;
692 }
693 pr_debug("Enter mode: %d\n", mode);
694
695 pdata = dev_get_platdata(&mfd->pdev->dev);
696
697 pdata->panel_info.dynamic_switch_pending = true;
698 ret = mdss_fb_pan_idle(mfd);
699 if (ret) {
700 pr_err("mdss_fb_pan_idle for fb%d failed. ret=%d\n",
701 mfd->index, ret);
702 pdata->panel_info.dynamic_switch_pending = false;
703 return ret;
704 }
705
706 mutex_lock(&mfd->bl_lock);
707 bl_lvl = mfd->bl_level;
708 mdss_fb_set_backlight(mfd, 0);
709 mutex_unlock(&mfd->bl_lock);
710
711 lock_fb_info(mfd->fbi);
712 ret = mdss_fb_blank_sub(FB_BLANK_POWERDOWN, mfd->fbi,
713 mfd->op_enable);
714 if (ret) {
715 pr_err("can't turn off display!\n");
716 unlock_fb_info(mfd->fbi);
717 return ret;
718 }
719
720 mfd->op_enable = false;
721
722 ret = mfd->mdp.configure_panel(mfd, mode, 1);
723 mdss_fb_set_mdp_sync_pt_threshold(mfd, mfd->panel.type);
724
725 mfd->op_enable = true;
726
727 ret = mdss_fb_blank_sub(FB_BLANK_UNBLANK, mfd->fbi,
728 mfd->op_enable);
729 if (ret) {
730 pr_err("can't turn on display!\n");
731 unlock_fb_info(mfd->fbi);
732 return ret;
733 }
734 unlock_fb_info(mfd->fbi);
735
736 mutex_lock(&mfd->bl_lock);
737 mfd->allow_bl_update = true;
738 mdss_fb_set_backlight(mfd, bl_lvl);
739 mutex_unlock(&mfd->bl_lock);
740
741 pdata->panel_info.dynamic_switch_pending = false;
742 pdata->panel_info.is_lpm_mode = mode ? 1 : 0;
743
744 if (ret) {
745 pr_err("can't turn on display!\n");
746 return ret;
747 }
748
749 pr_debug("Exit mode: %d\n", mode);
750
751 return 0;
752}
753
754static ssize_t mdss_fb_change_dfps_mode(struct device *dev,
755 struct device_attribute *attr, const char *buf, size_t len)
756{
757 struct fb_info *fbi = dev_get_drvdata(dev);
758 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par;
759 struct mdss_panel_data *pdata;
760 struct mdss_panel_info *pinfo;
761 u32 dfps_mode;
762
763 pdata = dev_get_platdata(&mfd->pdev->dev);
764 if (!pdata) {
765 pr_err("no panel connected!\n");
766 return len;
767 }
768 pinfo = &pdata->panel_info;
769
770 if (kstrtouint(buf, 0, &dfps_mode)) {
771 pr_err("kstrtouint buf error!\n");
772 return len;
773 }
774
775 if (dfps_mode >= DFPS_MODE_MAX) {
776 pinfo->dynamic_fps = false;
777 return len;
778 }
779
780 if (mfd->idle_time != 0) {
781 pr_err("ERROR: Idle time is not disabled.\n");
782 return len;
783 }
784
785 if (pinfo->current_fps != pinfo->default_fps) {
786 pr_err("ERROR: panel not configured to default fps\n");
787 return len;
788 }
789
790 pinfo->dynamic_fps = true;
791 pinfo->dfps_update = dfps_mode;
792
793 if (pdata->next)
794 pdata->next->panel_info.dfps_update = dfps_mode;
795
796 return len;
797}
798
799static ssize_t mdss_fb_get_dfps_mode(struct device *dev,
800 struct device_attribute *attr, char *buf)
801{
802 struct fb_info *fbi = dev_get_drvdata(dev);
803 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par;
804 struct mdss_panel_data *pdata;
805 struct mdss_panel_info *pinfo;
806 int ret;
807
808 pdata = dev_get_platdata(&mfd->pdev->dev);
809 if (!pdata) {
810 pr_err("no panel connected!\n");
811 return -EINVAL;
812 }
813 pinfo = &pdata->panel_info;
814
815 ret = scnprintf(buf, PAGE_SIZE, "dfps enabled=%d mode=%d\n",
816 pinfo->dynamic_fps, pinfo->dfps_update);
817
818 return ret;
819}
820
821static ssize_t mdss_fb_change_persist_mode(struct device *dev,
822 struct device_attribute *attr, const char *buf, size_t len)
823{
824 struct fb_info *fbi = dev_get_drvdata(dev);
825 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par;
826 struct mdss_panel_info *pinfo = NULL;
827 struct mdss_panel_data *pdata;
828 int ret = 0;
829 u32 persist_mode;
830
831 if (!mfd || !mfd->panel_info) {
832 pr_err("%s: Panel info is NULL!\n", __func__);
833 return len;
834 }
835
836 pinfo = mfd->panel_info;
837
838 if (kstrtouint(buf, 0, &persist_mode)) {
839 pr_err("kstrtouint buf error!\n");
840 return len;
841 }
842
843 mutex_lock(&mfd->mdss_sysfs_lock);
844 if (mdss_panel_is_power_off(mfd->panel_power_state)) {
845 pinfo->persist_mode = persist_mode;
846 goto end;
847 }
848
849 mutex_lock(&mfd->bl_lock);
850
851 pdata = dev_get_platdata(&mfd->pdev->dev);
852 if ((pdata) && (pdata->apply_display_setting))
853 ret = pdata->apply_display_setting(pdata, persist_mode);
854
855 mutex_unlock(&mfd->bl_lock);
856
857 if (!ret) {
858 pr_debug("%s: Persist mode %d\n", __func__, persist_mode);
859 pinfo->persist_mode = persist_mode;
860 }
861
862end:
863 mutex_unlock(&mfd->mdss_sysfs_lock);
864 return len;
865}
866
867static ssize_t mdss_fb_get_persist_mode(struct device *dev,
868 struct device_attribute *attr, char *buf)
869{
870 struct fb_info *fbi = dev_get_drvdata(dev);
871 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par;
872 struct mdss_panel_data *pdata;
873 struct mdss_panel_info *pinfo;
874 int ret;
875
876 pdata = dev_get_platdata(&mfd->pdev->dev);
877 if (!pdata) {
878 pr_err("no panel connected!\n");
879 return -EINVAL;
880 }
881 pinfo = &pdata->panel_info;
882
883 ret = scnprintf(buf, PAGE_SIZE, "%d\n", pinfo->persist_mode);
884
885 return ret;
886}
887
888static DEVICE_ATTR(msm_fb_type, 0444, mdss_fb_get_type, NULL);
889static DEVICE_ATTR(msm_fb_split, 0644, mdss_fb_show_split,
890 mdss_fb_store_split);
891static DEVICE_ATTR(show_blank_event, 0444, mdss_mdp_show_blank_event, NULL);
892static DEVICE_ATTR(idle_time, 0644,
893 mdss_fb_get_idle_time, mdss_fb_set_idle_time);
894static DEVICE_ATTR(idle_notify, 0444, mdss_fb_get_idle_notify, NULL);
895static DEVICE_ATTR(msm_fb_panel_info, 0444, mdss_fb_get_panel_info, NULL);
896static DEVICE_ATTR(msm_fb_src_split_info, 0444, mdss_fb_get_src_split_info,
897 NULL);
898static DEVICE_ATTR(msm_fb_thermal_level, 0644,
899 mdss_fb_get_thermal_level, mdss_fb_set_thermal_level);
900static DEVICE_ATTR(msm_fb_panel_status, 0644,
901 mdss_fb_get_panel_status, mdss_fb_force_panel_dead);
902static DEVICE_ATTR(msm_fb_dfps_mode, 0644,
903 mdss_fb_get_dfps_mode, mdss_fb_change_dfps_mode);
904static DEVICE_ATTR(measured_fps, 0664,
905 mdss_fb_get_fps_info, NULL);
906static DEVICE_ATTR(msm_fb_persist_mode, 0644,
907 mdss_fb_get_persist_mode, mdss_fb_change_persist_mode);
908static struct attribute *mdss_fb_attrs[] = {
909 &dev_attr_msm_fb_type.attr,
910 &dev_attr_msm_fb_split.attr,
911 &dev_attr_show_blank_event.attr,
912 &dev_attr_idle_time.attr,
913 &dev_attr_idle_notify.attr,
914 &dev_attr_msm_fb_panel_info.attr,
915 &dev_attr_msm_fb_src_split_info.attr,
916 &dev_attr_msm_fb_thermal_level.attr,
917 &dev_attr_msm_fb_panel_status.attr,
918 &dev_attr_msm_fb_dfps_mode.attr,
919 &dev_attr_measured_fps.attr,
920 &dev_attr_msm_fb_persist_mode.attr,
921 NULL,
922};
923
924static struct attribute_group mdss_fb_attr_group = {
925 .attrs = mdss_fb_attrs,
926};
927
928static int mdss_fb_create_sysfs(struct msm_fb_data_type *mfd)
929{
930 int rc;
931
932 rc = sysfs_create_group(&mfd->fbi->dev->kobj, &mdss_fb_attr_group);
933 if (rc)
934 pr_err("sysfs group creation failed, rc=%d\n", rc);
935 return rc;
936}
937
938static void mdss_fb_remove_sysfs(struct msm_fb_data_type *mfd)
939{
940 sysfs_remove_group(&mfd->fbi->dev->kobj, &mdss_fb_attr_group);
941}
942
943static void mdss_fb_shutdown(struct platform_device *pdev)
944{
945 struct msm_fb_data_type *mfd = platform_get_drvdata(pdev);
946
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530947 mfd->shutdown_pending = true;
948
949 /* wake up threads waiting on idle or kickoff queues */
950 wake_up_all(&mfd->idle_wait_q);
951 wake_up_all(&mfd->kickoff_wait_q);
952
953 lock_fb_info(mfd->fbi);
954 mdss_fb_release_all(mfd->fbi, true);
955 sysfs_notify(&mfd->fbi->dev->kobj, NULL, "show_blank_event");
956 unlock_fb_info(mfd->fbi);
957}
958
959static void mdss_fb_input_event_handler(struct input_handle *handle,
960 unsigned int type,
961 unsigned int code,
962 int value)
963{
964 struct msm_fb_data_type *mfd = handle->handler->private;
965 int rc;
966
967 if ((type != EV_ABS) || !mdss_fb_is_power_on(mfd))
968 return;
969
970 if (mfd->mdp.input_event_handler) {
971 rc = mfd->mdp.input_event_handler(mfd);
972 if (rc)
973 pr_err("mdp input event handler failed\n");
974 }
975}
976
977static int mdss_fb_input_connect(struct input_handler *handler,
978 struct input_dev *dev,
979 const struct input_device_id *id)
980{
981 int rc;
982 struct input_handle *handle;
983
984 handle = kzalloc(sizeof(*handle), GFP_KERNEL);
985 if (!handle)
986 return -ENOMEM;
987
988 handle->dev = dev;
989 handle->handler = handler;
990 handle->name = handler->name;
991
992 rc = input_register_handle(handle);
993 if (rc) {
994 pr_err("failed to register input handle, rc = %d\n", rc);
995 goto error;
996 }
997
998 rc = input_open_device(handle);
999 if (rc) {
1000 pr_err("failed to open input device, rc = %d\n", rc);
1001 goto error_unregister;
1002 }
1003
1004 return 0;
1005
1006error_unregister:
1007 input_unregister_handle(handle);
1008error:
1009 kfree(handle);
1010 return rc;
1011}
1012
1013static void mdss_fb_input_disconnect(struct input_handle *handle)
1014{
1015 input_close_device(handle);
1016 input_unregister_handle(handle);
1017 kfree(handle);
1018}
1019
1020/*
1021 * Structure for specifying event parameters on which to receive callbacks.
1022 * This structure will trigger a callback in case of a touch event (specified by
1023 * EV_ABS) where there is a change in X and Y coordinates,
1024 */
1025static const struct input_device_id mdss_fb_input_ids[] = {
1026 {
1027 .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
1028 .evbit = { BIT_MASK(EV_ABS) },
1029 .absbit = { [BIT_WORD(ABS_MT_POSITION_X)] =
1030 BIT_MASK(ABS_MT_POSITION_X) |
1031 BIT_MASK(ABS_MT_POSITION_Y) },
1032 },
1033 { },
1034};
1035
1036static int mdss_fb_register_input_handler(struct msm_fb_data_type *mfd)
1037{
1038 int rc;
1039 struct input_handler *handler;
1040
1041 if (mfd->input_handler)
1042 return -EINVAL;
1043
1044 handler = kzalloc(sizeof(*handler), GFP_KERNEL);
1045 if (!handler)
1046 return -ENOMEM;
1047
1048 handler->event = mdss_fb_input_event_handler;
1049 handler->connect = mdss_fb_input_connect;
1050 handler->disconnect = mdss_fb_input_disconnect,
1051 handler->name = "mdss_fb",
1052 handler->id_table = mdss_fb_input_ids;
1053 handler->private = mfd;
1054
1055 rc = input_register_handler(handler);
1056 if (rc) {
1057 pr_err("Unable to register the input handler\n");
1058 kfree(handler);
1059 } else {
1060 mfd->input_handler = handler;
1061 }
1062
1063 return rc;
1064}
1065
1066static void mdss_fb_unregister_input_handler(struct msm_fb_data_type *mfd)
1067{
1068 if (!mfd->input_handler)
1069 return;
1070
1071 input_unregister_handler(mfd->input_handler);
1072 kfree(mfd->input_handler);
1073}
1074
1075static void mdss_fb_videomode_from_panel_timing(struct fb_videomode *videomode,
1076 struct mdss_panel_timing *pt)
1077{
1078 videomode->name = pt->name;
1079 videomode->xres = pt->xres;
1080 videomode->yres = pt->yres;
1081 videomode->left_margin = pt->h_back_porch;
1082 videomode->right_margin = pt->h_front_porch;
1083 videomode->hsync_len = pt->h_pulse_width;
1084 videomode->upper_margin = pt->v_back_porch;
1085 videomode->lower_margin = pt->v_front_porch;
1086 videomode->vsync_len = pt->v_pulse_width;
1087 videomode->refresh = pt->frame_rate;
1088 videomode->flag = 0;
1089 videomode->vmode = 0;
1090 videomode->sync = 0;
1091
1092 if (videomode->refresh) {
1093 unsigned long clk_rate, h_total, v_total;
1094
1095 h_total = videomode->xres + videomode->left_margin
1096 + videomode->right_margin + videomode->hsync_len;
1097 v_total = videomode->yres + videomode->lower_margin
1098 + videomode->upper_margin + videomode->vsync_len;
1099 clk_rate = h_total * v_total * videomode->refresh;
1100 videomode->pixclock =
1101 KHZ2PICOS(clk_rate / 1000);
1102 } else {
1103 videomode->pixclock =
1104 KHZ2PICOS((unsigned long)pt->clk_rate / 1000);
1105 }
1106}
1107
1108static void mdss_fb_set_split_mode(struct msm_fb_data_type *mfd,
1109 struct mdss_panel_data *pdata)
1110{
1111 if (pdata->panel_info.is_split_display) {
1112 struct mdss_panel_data *pnext = pdata->next;
1113
1114 mfd->split_fb_left = pdata->panel_info.lm_widths[0];
1115 if (pnext)
1116 mfd->split_fb_right = pnext->panel_info.lm_widths[0];
1117
1118 if (pdata->panel_info.use_pingpong_split)
1119 mfd->split_mode = MDP_PINGPONG_SPLIT;
1120 else
1121 mfd->split_mode = MDP_DUAL_LM_DUAL_DISPLAY;
1122 } else if ((pdata->panel_info.lm_widths[0] != 0)
1123 && (pdata->panel_info.lm_widths[1] != 0)) {
1124 mfd->split_fb_left = pdata->panel_info.lm_widths[0];
1125 mfd->split_fb_right = pdata->panel_info.lm_widths[1];
1126 mfd->split_mode = MDP_DUAL_LM_SINGLE_DISPLAY;
1127 } else {
1128 mfd->split_mode = MDP_SPLIT_MODE_NONE;
1129 }
1130}
1131
1132static int mdss_fb_init_panel_modes(struct msm_fb_data_type *mfd,
1133 struct mdss_panel_data *pdata)
1134{
1135 struct fb_info *fbi = mfd->fbi;
1136 struct fb_videomode *modedb;
1137 struct mdss_panel_timing *pt;
1138 struct list_head *pos;
1139 int num_timings = 0;
1140 int i = 0;
1141
1142 /* check if multiple modes are supported */
1143 if (!pdata->timings_list.prev || !pdata->timings_list.next)
1144 INIT_LIST_HEAD(&pdata->timings_list);
1145
1146 if (!fbi || !pdata->current_timing || list_empty(&pdata->timings_list))
1147 return 0;
1148
1149 list_for_each(pos, &pdata->timings_list)
1150 num_timings++;
1151
1152 modedb = devm_kzalloc(fbi->dev, num_timings * sizeof(*modedb),
1153 GFP_KERNEL);
1154 if (!modedb)
1155 return -ENOMEM;
1156
1157 list_for_each_entry(pt, &pdata->timings_list, list) {
1158 struct mdss_panel_timing *spt = NULL;
1159
1160 mdss_fb_videomode_from_panel_timing(modedb + i, pt);
1161 if (pdata->next) {
1162 spt = mdss_panel_get_timing_by_name(pdata->next,
1163 modedb[i].name);
1164 if (!IS_ERR_OR_NULL(spt))
1165 modedb[i].xres += spt->xres;
1166 else
1167 pr_debug("no matching split config for %s\n",
1168 modedb[i].name);
1169
1170 /*
1171 * if no panel timing found for current, need to
1172 * disable it otherwise mark it as active
1173 */
1174 if (pt == pdata->current_timing)
1175 pdata->next->active = !IS_ERR_OR_NULL(spt);
1176 }
1177
1178 if (pt == pdata->current_timing) {
1179 pr_debug("found current mode: %s\n", pt->name);
1180 fbi->mode = modedb + i;
1181 }
1182 i++;
1183 }
1184
1185 fbi->monspecs.modedb = modedb;
1186 fbi->monspecs.modedb_len = num_timings;
1187
1188 /* destroy and recreate modelist */
1189 fb_destroy_modelist(&fbi->modelist);
1190
1191 if (fbi->mode)
1192 fb_videomode_to_var(&fbi->var, fbi->mode);
1193 fb_videomode_to_modelist(modedb, num_timings, &fbi->modelist);
1194
1195 return 0;
1196}
1197
1198static int mdss_fb_probe(struct platform_device *pdev)
1199{
1200 struct msm_fb_data_type *mfd = NULL;
1201 struct mdss_panel_data *pdata;
1202 struct fb_info *fbi;
1203 int rc;
1204
1205 if (fbi_list_index >= MAX_FBI_LIST)
1206 return -ENOMEM;
1207
1208 pdata = dev_get_platdata(&pdev->dev);
1209 if (!pdata)
1210 return -EPROBE_DEFER;
1211
1212 if (!mdp_instance) {
1213 pr_err("mdss mdp resource not initialized yet\n");
1214 return -ENODEV;
1215 }
1216
1217 /*
1218 * alloc framebuffer info + par data
1219 */
1220 fbi = framebuffer_alloc(sizeof(struct msm_fb_data_type), NULL);
1221 if (fbi == NULL) {
1222 pr_err("can't allocate framebuffer info data!\n");
1223 return -ENOMEM;
1224 }
1225
1226 mfd = (struct msm_fb_data_type *)fbi->par;
1227 mfd->key = MFD_KEY;
1228 mfd->fbi = fbi;
1229 mfd->panel_info = &pdata->panel_info;
1230 mfd->panel.type = pdata->panel_info.type;
1231 mfd->panel.id = mfd->index;
1232 mfd->fb_page = MDSS_FB_NUM;
1233 mfd->index = fbi_list_index;
1234 mfd->mdp_fb_page_protection = MDP_FB_PAGE_PROTECTION_WRITECOMBINE;
1235
1236 mfd->ext_ad_ctrl = -1;
1237 if (mfd->panel_info && mfd->panel_info->brightness_max > 0)
1238 MDSS_BRIGHT_TO_BL(mfd->bl_level, backlight_led.brightness,
1239 mfd->panel_info->bl_max, mfd->panel_info->brightness_max);
1240 else
1241 mfd->bl_level = 0;
1242
1243 mfd->bl_scale = 1024;
1244 mfd->bl_min_lvl = 30;
1245 mfd->ad_bl_level = 0;
1246 mfd->fb_imgType = MDP_RGBA_8888;
1247 mfd->calib_mode_bl = 0;
1248 mfd->unset_bl_level = U32_MAX;
1249
1250 mfd->pdev = pdev;
1251
1252 mfd->split_fb_left = mfd->split_fb_right = 0;
1253
1254 mdss_fb_set_split_mode(mfd, pdata);
1255 pr_info("fb%d: split_mode:%d left:%d right:%d\n", mfd->index,
1256 mfd->split_mode, mfd->split_fb_left, mfd->split_fb_right);
1257
1258 mfd->mdp = *mdp_instance;
1259
1260 rc = of_property_read_bool(pdev->dev.of_node,
1261 "qcom,boot-indication-enabled");
1262
1263 if (rc) {
1264 led_trigger_register_simple("boot-indication",
1265 &(mfd->boot_notification_led));
1266 }
1267
1268 INIT_LIST_HEAD(&mfd->file_list);
1269
1270 mutex_init(&mfd->bl_lock);
1271 mutex_init(&mfd->mdss_sysfs_lock);
1272 mutex_init(&mfd->switch_lock);
1273
1274 fbi_list[fbi_list_index++] = fbi;
1275
1276 platform_set_drvdata(pdev, mfd);
1277
1278 rc = mdss_fb_register(mfd);
1279 if (rc)
1280 return rc;
1281
1282 mdss_fb_create_sysfs(mfd);
1283 mdss_fb_send_panel_event(mfd, MDSS_EVENT_FB_REGISTERED, fbi);
1284
1285 if (mfd->mdp.init_fnc) {
1286 rc = mfd->mdp.init_fnc(mfd);
1287 if (rc) {
1288 pr_err("init_fnc failed\n");
1289 return rc;
1290 }
1291 }
1292 mdss_fb_init_fps_info(mfd);
1293
1294 rc = pm_runtime_set_active(mfd->fbi->dev);
1295 if (rc < 0)
1296 pr_err("pm_runtime: fail to set active.\n");
1297 pm_runtime_enable(mfd->fbi->dev);
1298
1299 /* android supports only one lcd-backlight/lcd for now */
1300 if (!lcd_backlight_registered) {
1301 backlight_led.brightness = mfd->panel_info->brightness_max;
1302 backlight_led.max_brightness = mfd->panel_info->brightness_max;
1303 if (led_classdev_register(&pdev->dev, &backlight_led))
1304 pr_err("led_classdev_register failed\n");
1305 else
1306 lcd_backlight_registered = 1;
1307 }
1308
1309 mdss_fb_init_panel_modes(mfd, pdata);
1310
1311 mfd->mdp_sync_pt_data.fence_name = "mdp-fence";
1312 if (mfd->mdp_sync_pt_data.timeline == NULL) {
Sachin Bhayare2b6d0042018-01-13 19:38:21 +05301313 char timeline_name[32];
Sachin Bhayareeeb88892018-01-02 16:36:01 +05301314
1315 snprintf(timeline_name, sizeof(timeline_name),
1316 "mdss_fb_%d", mfd->index);
1317 mfd->mdp_sync_pt_data.timeline =
Sachin Bhayare2b6d0042018-01-13 19:38:21 +05301318 mdss_create_timeline(timeline_name);
1319 if (mfd->mdp_sync_pt_data.timeline == NULL) {
1320 pr_err("cannot create release fence time line\n");
1321 return -ENOMEM;
1322 }
Krishna Manikandanb296a2b2018-03-21 17:16:31 +05301323
Sachin Bhayareeeb88892018-01-02 16:36:01 +05301324 mfd->mdp_sync_pt_data.notifier.notifier_call =
1325 __mdss_fb_sync_buf_done_callback;
1326 }
1327
1328 mdss_fb_set_mdp_sync_pt_threshold(mfd, mfd->panel.type);
1329
1330 if (mfd->mdp.splash_init_fnc)
1331 mfd->mdp.splash_init_fnc(mfd);
1332
1333 /*
1334 * Register with input driver for a callback for command mode panels.
1335 * When there is an input event, mdp clocks will be turned on to reduce
1336 * latency when a frame update happens.
1337 * For video mode panels, idle timeout will be delayed so that userspace
1338 * does not get an idle event while new frames are expected. In case of
1339 * an idle event, user space tries to fall back to GPU composition which
1340 * can lead to increased load when there are new frames.
1341 */
1342 if (mfd->mdp.input_event_handler &&
1343 ((mfd->panel_info->type == MIPI_CMD_PANEL) ||
1344 (mfd->panel_info->type == MIPI_VIDEO_PANEL)))
1345 if (mdss_fb_register_input_handler(mfd))
1346 pr_err("failed to register input handler\n");
1347
1348 INIT_DELAYED_WORK(&mfd->idle_notify_work, __mdss_fb_idle_notify_work);
1349
1350 return rc;
1351}
1352
1353static void mdss_fb_set_mdp_sync_pt_threshold(struct msm_fb_data_type *mfd,
1354 int type)
1355{
1356 if (!mfd)
1357 return;
1358
1359 switch (type) {
1360 case WRITEBACK_PANEL:
1361 mfd->mdp_sync_pt_data.threshold = 1;
1362 mfd->mdp_sync_pt_data.retire_threshold = 0;
1363 break;
1364 case MIPI_CMD_PANEL:
1365 mfd->mdp_sync_pt_data.threshold = 1;
1366 mfd->mdp_sync_pt_data.retire_threshold = 1;
1367 break;
1368 default:
1369 mfd->mdp_sync_pt_data.threshold = 2;
1370 mfd->mdp_sync_pt_data.retire_threshold = 0;
1371 break;
1372 }
1373}
1374
1375static int mdss_fb_remove(struct platform_device *pdev)
1376{
1377 struct msm_fb_data_type *mfd;
1378
1379 mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
1380
1381 if (!mfd)
1382 return -ENODEV;
1383
1384 mdss_fb_remove_sysfs(mfd);
1385
1386 pm_runtime_disable(mfd->fbi->dev);
1387
1388 if (mfd->key != MFD_KEY)
1389 return -EINVAL;
1390
1391 mdss_fb_unregister_input_handler(mfd);
1392 mdss_panel_debugfs_cleanup(mfd->panel_info);
1393
1394 if (mdss_fb_suspend_sub(mfd))
1395 pr_err("msm_fb_remove: can't stop the device %d\n",
1396 mfd->index);
1397
1398 /* remove /dev/fb* */
1399 unregister_framebuffer(mfd->fbi);
1400
1401 if (lcd_backlight_registered) {
1402 lcd_backlight_registered = 0;
1403 led_classdev_unregister(&backlight_led);
1404 }
1405
1406 return 0;
1407}
1408
1409static int mdss_fb_send_panel_event(struct msm_fb_data_type *mfd,
1410 int event, void *arg)
1411{
1412 int ret = 0;
1413 struct mdss_panel_data *pdata;
1414
1415 pdata = dev_get_platdata(&mfd->pdev->dev);
1416 if (!pdata) {
1417 pr_err("no panel connected\n");
1418 return -ENODEV;
1419 }
1420
1421 pr_debug("sending event=%d for fb%d\n", event, mfd->index);
1422
1423 do {
1424 if (pdata->event_handler)
1425 ret = pdata->event_handler(pdata, event, arg);
1426
1427 pdata = pdata->next;
1428 } while (!ret && pdata);
1429
1430 return ret;
1431}
1432
1433static int mdss_fb_suspend_sub(struct msm_fb_data_type *mfd)
1434{
1435 int ret = 0;
1436
1437 if ((!mfd) || (mfd->key != MFD_KEY))
1438 return 0;
1439
1440 pr_debug("mdss_fb suspend index=%d\n", mfd->index);
1441
1442 ret = mdss_fb_pan_idle(mfd);
1443 if (ret) {
1444 pr_warn("mdss_fb_pan_idle for fb%d failed. ret=%d\n",
1445 mfd->index, ret);
1446 goto exit;
1447 }
1448
1449 ret = mdss_fb_send_panel_event(mfd, MDSS_EVENT_SUSPEND, NULL);
1450 if (ret) {
1451 pr_warn("unable to suspend fb%d (%d)\n", mfd->index, ret);
1452 goto exit;
1453 }
1454
1455 mfd->suspend.op_enable = mfd->op_enable;
1456 mfd->suspend.panel_power_state = mfd->panel_power_state;
1457
1458 if (mfd->op_enable) {
1459 /*
1460 * Ideally, display should have either been blanked by now, or
1461 * should have transitioned to a low power state. If not, then
1462 * as a fall back option, enter ulp state to leave the display
1463 * on, but turn off all interface clocks.
1464 */
1465 if (mdss_fb_is_power_on(mfd)) {
1466 ret = mdss_fb_blank_sub(BLANK_FLAG_ULP, mfd->fbi,
1467 mfd->suspend.op_enable);
1468 if (ret) {
1469 pr_err("can't turn off display!\n");
1470 goto exit;
1471 }
1472 }
1473 mfd->op_enable = false;
1474 fb_set_suspend(mfd->fbi, FBINFO_STATE_SUSPENDED);
1475 }
1476exit:
1477 return ret;
1478}
1479
1480static int mdss_fb_resume_sub(struct msm_fb_data_type *mfd)
1481{
1482 int ret = 0;
1483
1484 if ((!mfd) || (mfd->key != MFD_KEY))
1485 return 0;
1486
1487 reinit_completion(&mfd->power_set_comp);
1488 mfd->is_power_setting = true;
1489 pr_debug("mdss_fb resume index=%d\n", mfd->index);
1490
1491 ret = mdss_fb_pan_idle(mfd);
1492 if (ret) {
1493 pr_warn("mdss_fb_pan_idle for fb%d failed. ret=%d\n",
1494 mfd->index, ret);
1495 return ret;
1496 }
1497
1498 ret = mdss_fb_send_panel_event(mfd, MDSS_EVENT_RESUME, NULL);
1499 if (ret) {
1500 pr_warn("unable to resume fb%d (%d)\n", mfd->index, ret);
1501 return ret;
1502 }
1503
1504 /* resume state var recover */
1505 mfd->op_enable = mfd->suspend.op_enable;
1506
1507 /*
1508 * If the fb was explicitly blanked or transitioned to ulp during
1509 * suspend, then undo it during resume with the appropriate unblank
1510 * flag. If fb was in ulp state when entering suspend, then nothing
1511 * needs to be done.
1512 */
1513 if (mdss_panel_is_power_on(mfd->suspend.panel_power_state) &&
1514 !mdss_panel_is_power_on_ulp(mfd->suspend.panel_power_state)) {
1515 int unblank_flag = mdss_panel_is_power_on_interactive(
1516 mfd->suspend.panel_power_state) ? FB_BLANK_UNBLANK :
1517 BLANK_FLAG_LP;
1518
1519 ret = mdss_fb_blank_sub(unblank_flag, mfd->fbi, mfd->op_enable);
1520 if (ret)
1521 pr_warn("can't turn on display!\n");
1522 else
1523 fb_set_suspend(mfd->fbi, FBINFO_STATE_RUNNING);
1524 }
1525 mfd->is_power_setting = false;
1526 complete_all(&mfd->power_set_comp);
1527
1528 return ret;
1529}
1530
1531#if defined(CONFIG_PM) && !defined(CONFIG_PM_SLEEP)
1532static int mdss_fb_suspend(struct platform_device *pdev, pm_message_t state)
1533{
1534 struct msm_fb_data_type *mfd = platform_get_drvdata(pdev);
1535
1536 if (!mfd)
1537 return -ENODEV;
1538
1539 dev_dbg(&pdev->dev, "display suspend\n");
1540
1541 return mdss_fb_suspend_sub(mfd);
1542}
1543
1544static int mdss_fb_resume(struct platform_device *pdev)
1545{
1546 struct msm_fb_data_type *mfd = platform_get_drvdata(pdev);
1547
1548 if (!mfd)
1549 return -ENODEV;
1550
1551 dev_dbg(&pdev->dev, "display resume\n");
1552
1553 return mdss_fb_resume_sub(mfd);
1554}
1555#else
1556#define mdss_fb_suspend NULL
1557#define mdss_fb_resume NULL
1558#endif
1559
1560#ifdef CONFIG_PM_SLEEP
1561static int mdss_fb_pm_suspend(struct device *dev)
1562{
1563 struct msm_fb_data_type *mfd = dev_get_drvdata(dev);
1564
1565 if (!mfd)
1566 return -ENODEV;
1567
1568 dev_dbg(dev, "display pm suspend\n");
1569
1570 return mdss_fb_suspend_sub(mfd);
1571}
1572
1573static int mdss_fb_pm_resume(struct device *dev)
1574{
1575 struct msm_fb_data_type *mfd = dev_get_drvdata(dev);
1576
1577 if (!mfd)
1578 return -ENODEV;
1579
1580 dev_dbg(dev, "display pm resume\n");
1581
1582 /*
1583 * It is possible that the runtime status of the fb device may
1584 * have been active when the system was suspended. Reset the runtime
1585 * status to suspended state after a complete system resume.
1586 */
1587 pm_runtime_disable(dev);
1588 pm_runtime_set_suspended(dev);
1589 pm_runtime_enable(dev);
1590
1591 return mdss_fb_resume_sub(mfd);
1592}
1593#endif
1594
1595static const struct dev_pm_ops mdss_fb_pm_ops = {
1596 SET_SYSTEM_SLEEP_PM_OPS(mdss_fb_pm_suspend, mdss_fb_pm_resume)
1597};
1598
1599static const struct of_device_id mdss_fb_dt_match[] = {
1600 { .compatible = "qcom,mdss-fb",},
1601 {}
1602};
1603EXPORT_COMPAT("qcom,mdss-fb");
1604
1605static struct platform_driver mdss_fb_driver = {
1606 .probe = mdss_fb_probe,
1607 .remove = mdss_fb_remove,
1608 .suspend = mdss_fb_suspend,
1609 .resume = mdss_fb_resume,
1610 .shutdown = mdss_fb_shutdown,
1611 .driver = {
1612 .name = "mdss_fb",
1613 .of_match_table = mdss_fb_dt_match,
1614 .pm = &mdss_fb_pm_ops,
1615 },
1616};
1617
1618static void mdss_fb_scale_bl(struct msm_fb_data_type *mfd, u32 *bl_lvl)
1619{
1620 u32 temp = *bl_lvl;
1621
1622 pr_debug("input = %d, scale = %d\n", temp, mfd->bl_scale);
1623 if (temp >= mfd->bl_min_lvl) {
1624 if (temp > mfd->panel_info->bl_max) {
1625 pr_warn("%s: invalid bl level\n",
1626 __func__);
1627 temp = mfd->panel_info->bl_max;
1628 }
1629 if (mfd->bl_scale > 1024) {
1630 pr_warn("%s: invalid bl scale\n",
1631 __func__);
1632 mfd->bl_scale = 1024;
1633 }
1634 /*
1635 * bl_scale is the numerator of
1636 * scaling fraction (x/1024)
1637 */
1638 temp = (temp * mfd->bl_scale) / 1024;
1639
1640 /*if less than minimum level, use min level*/
1641 if (temp < mfd->bl_min_lvl)
1642 temp = mfd->bl_min_lvl;
1643 }
1644 pr_debug("output = %d\n", temp);
1645
1646 (*bl_lvl) = temp;
1647}
1648
1649/* must call this function from within mfd->bl_lock */
1650void mdss_fb_set_backlight(struct msm_fb_data_type *mfd, u32 bkl_lvl)
1651{
1652 struct mdss_panel_data *pdata;
1653 u32 temp = bkl_lvl;
1654 bool ad_bl_notify_needed = false;
1655 bool bl_notify_needed = false;
1656
1657 if ((((mdss_fb_is_power_off(mfd) && mfd->dcm_state != DCM_ENTER)
1658 || !mfd->allow_bl_update) && !IS_CALIB_MODE_BL(mfd)) ||
1659 mfd->panel_info->cont_splash_enabled) {
1660 mfd->unset_bl_level = bkl_lvl;
1661 return;
1662 } else if (mdss_fb_is_power_on(mfd) && mfd->panel_info->panel_dead) {
1663 mfd->unset_bl_level = mfd->bl_level;
1664 } else {
1665 mfd->unset_bl_level = U32_MAX;
1666 }
1667
1668 pdata = dev_get_platdata(&mfd->pdev->dev);
1669
1670 if ((pdata) && (pdata->set_backlight)) {
1671 if (mfd->mdp.ad_calc_bl)
1672 (*mfd->mdp.ad_calc_bl)(mfd, temp, &temp,
1673 &ad_bl_notify_needed);
1674 if (!IS_CALIB_MODE_BL(mfd))
1675 mdss_fb_scale_bl(mfd, &temp);
1676 /*
1677 * Even though backlight has been scaled, want to show that
1678 * backlight has been set to bkl_lvl to those that read from
1679 * sysfs node. Thus, need to set bl_level even if it appears
1680 * the backlight has already been set to the level it is at,
1681 * as well as setting bl_level to bkl_lvl even though the
1682 * backlight has been set to the scaled value.
1683 */
1684 if (mfd->bl_level_scaled == temp) {
1685 mfd->bl_level = bkl_lvl;
1686 } else {
1687 if (mfd->bl_level != bkl_lvl)
1688 bl_notify_needed = true;
1689 pr_debug("backlight sent to panel :%d\n", temp);
1690 pdata->set_backlight(pdata, temp);
1691 mfd->bl_level = bkl_lvl;
1692 mfd->bl_level_scaled = temp;
1693 }
1694 if (ad_bl_notify_needed)
1695 mdss_fb_bl_update_notify(mfd,
1696 NOTIFY_TYPE_BL_AD_ATTEN_UPDATE);
1697 if (bl_notify_needed)
1698 mdss_fb_bl_update_notify(mfd,
1699 NOTIFY_TYPE_BL_UPDATE);
1700 }
1701}
1702
1703void mdss_fb_update_backlight(struct msm_fb_data_type *mfd)
1704{
1705 struct mdss_panel_data *pdata;
1706 u32 temp;
1707 bool bl_notify = false;
1708
1709 if (mfd->unset_bl_level == U32_MAX)
1710 return;
1711 mutex_lock(&mfd->bl_lock);
1712 if (!mfd->allow_bl_update) {
1713 pdata = dev_get_platdata(&mfd->pdev->dev);
1714 if ((pdata) && (pdata->set_backlight)) {
1715 mfd->bl_level = mfd->unset_bl_level;
1716 temp = mfd->bl_level;
1717 if (mfd->mdp.ad_calc_bl)
1718 (*mfd->mdp.ad_calc_bl)(mfd, temp, &temp,
1719 &bl_notify);
1720 if (bl_notify)
1721 mdss_fb_bl_update_notify(mfd,
1722 NOTIFY_TYPE_BL_AD_ATTEN_UPDATE);
1723 mdss_fb_bl_update_notify(mfd, NOTIFY_TYPE_BL_UPDATE);
1724 pdata->set_backlight(pdata, temp);
1725 mfd->bl_level_scaled = mfd->unset_bl_level;
1726 mfd->allow_bl_update = true;
1727 }
1728 }
1729 mutex_unlock(&mfd->bl_lock);
1730}
1731
1732static int mdss_fb_start_disp_thread(struct msm_fb_data_type *mfd)
1733{
1734 int ret = 0;
1735
1736 pr_debug("%pS: start display thread fb%d\n",
1737 __builtin_return_address(0), mfd->index);
1738
1739 /* this is needed for new split request from debugfs */
1740 mdss_fb_get_split(mfd);
1741
1742 atomic_set(&mfd->commits_pending, 0);
1743 mfd->disp_thread = kthread_run(__mdss_fb_display_thread,
1744 mfd, "mdss_fb%d", mfd->index);
1745
1746 if (IS_ERR(mfd->disp_thread)) {
1747 pr_err("ERROR: unable to start display thread %d\n",
1748 mfd->index);
1749 ret = PTR_ERR(mfd->disp_thread);
1750 mfd->disp_thread = NULL;
1751 }
1752
1753 return ret;
1754}
1755
1756static void mdss_fb_stop_disp_thread(struct msm_fb_data_type *mfd)
1757{
1758 pr_debug("%pS: stop display thread fb%d\n",
1759 __builtin_return_address(0), mfd->index);
1760
1761 kthread_stop(mfd->disp_thread);
1762 mfd->disp_thread = NULL;
1763}
1764
1765static void mdss_panel_validate_debugfs_info(struct msm_fb_data_type *mfd)
1766{
1767 struct mdss_panel_info *panel_info = mfd->panel_info;
1768 struct fb_info *fbi = mfd->fbi;
1769 struct fb_var_screeninfo *var = &fbi->var;
1770 struct mdss_panel_data *pdata = container_of(panel_info,
1771 struct mdss_panel_data, panel_info);
1772
1773 if (panel_info->debugfs_info->override_flag) {
1774 if (mfd->mdp.off_fnc) {
1775 mfd->panel_reconfig = true;
1776 mfd->mdp.off_fnc(mfd);
1777 mfd->panel_reconfig = false;
1778 }
1779
1780 pr_debug("Overriding panel_info with debugfs_info\n");
1781 panel_info->debugfs_info->override_flag = 0;
1782 mdss_panel_debugfsinfo_to_panelinfo(panel_info);
1783 if (is_panel_split(mfd) && pdata->next)
1784 mdss_fb_validate_split(pdata->panel_info.xres,
1785 pdata->next->panel_info.xres, mfd);
1786 mdss_panelinfo_to_fb_var(panel_info, var);
1787 if (mdss_fb_send_panel_event(mfd, MDSS_EVENT_CHECK_PARAMS,
1788 panel_info))
1789 pr_err("Failed to send panel event CHECK_PARAMS\n");
1790 }
1791}
1792
1793static int mdss_fb_blank_blank(struct msm_fb_data_type *mfd,
1794 int req_power_state)
1795{
1796 int ret = 0;
1797 int cur_power_state, current_bl;
1798
1799 if (!mfd)
1800 return -EINVAL;
1801
1802 if (!mdss_fb_is_power_on(mfd) || !mfd->mdp.off_fnc)
1803 return 0;
1804
1805 cur_power_state = mfd->panel_power_state;
1806
1807 pr_debug("Transitioning from %d --> %d\n", cur_power_state,
1808 req_power_state);
1809
1810 if (cur_power_state == req_power_state) {
1811 pr_debug("No change in power state\n");
1812 return 0;
1813 }
1814
1815 mutex_lock(&mfd->update.lock);
1816 mfd->update.type = NOTIFY_TYPE_SUSPEND;
1817 mfd->update.is_suspend = 1;
1818 mutex_unlock(&mfd->update.lock);
1819 complete(&mfd->update.comp);
1820 del_timer(&mfd->no_update.timer);
1821 mfd->no_update.value = NOTIFY_TYPE_SUSPEND;
1822 complete(&mfd->no_update.comp);
1823
1824 mfd->op_enable = false;
1825 if (mdss_panel_is_power_off(req_power_state)) {
1826 /* Stop Display thread */
1827 if (mfd->disp_thread)
1828 mdss_fb_stop_disp_thread(mfd);
1829 mutex_lock(&mfd->bl_lock);
1830 current_bl = mfd->bl_level;
1831 mfd->allow_bl_update = true;
1832 mdss_fb_set_backlight(mfd, 0);
1833 mfd->allow_bl_update = false;
1834 mfd->unset_bl_level = current_bl;
1835 mutex_unlock(&mfd->bl_lock);
1836 }
1837 mfd->panel_power_state = req_power_state;
1838
1839 ret = mfd->mdp.off_fnc(mfd);
1840 if (ret)
1841 mfd->panel_power_state = cur_power_state;
1842 else if (mdss_panel_is_power_off(req_power_state))
1843 mdss_fb_release_fences(mfd);
1844 mfd->op_enable = true;
1845 complete(&mfd->power_off_comp);
1846
1847 return ret;
1848}
1849
1850static int mdss_fb_blank_unblank(struct msm_fb_data_type *mfd)
1851{
1852 int ret = 0;
1853 int cur_power_state;
1854
1855 if (!mfd)
1856 return -EINVAL;
1857
1858 if (mfd->panel_info->debugfs_info)
1859 mdss_panel_validate_debugfs_info(mfd);
1860
1861 /* Start Display thread */
1862 if (mfd->disp_thread == NULL) {
1863 ret = mdss_fb_start_disp_thread(mfd);
Sachin Bhayare3d3767e2018-01-02 21:10:57 +05301864 if (IS_ERR_VALUE((unsigned long)ret))
Sachin Bhayareeeb88892018-01-02 16:36:01 +05301865 return ret;
1866 }
1867
1868 cur_power_state = mfd->panel_power_state;
1869 pr_debug("Transitioning from %d --> %d\n", cur_power_state,
1870 MDSS_PANEL_POWER_ON);
1871
1872 if (mdss_panel_is_power_on_interactive(cur_power_state)) {
1873 pr_debug("No change in power state\n");
1874 return 0;
1875 }
1876
1877 if (mfd->mdp.on_fnc) {
1878 struct mdss_panel_info *panel_info = mfd->panel_info;
1879 struct fb_var_screeninfo *var = &mfd->fbi->var;
1880
1881 ret = mfd->mdp.on_fnc(mfd);
1882 if (ret) {
1883 mdss_fb_stop_disp_thread(mfd);
1884 goto error;
1885 }
1886
1887 mfd->panel_power_state = MDSS_PANEL_POWER_ON;
1888 mfd->panel_info->panel_dead = false;
1889 mutex_lock(&mfd->update.lock);
1890 mfd->update.type = NOTIFY_TYPE_UPDATE;
1891 mfd->update.is_suspend = 0;
1892 mutex_unlock(&mfd->update.lock);
1893
1894 /*
1895 * Panel info can change depending in the information
1896 * programmed in the controller.
1897 * Update this info in the upstream structs.
1898 */
1899 mdss_panelinfo_to_fb_var(panel_info, var);
1900
1901 /* Start the work thread to signal idle time */
1902 if (mfd->idle_time)
1903 schedule_delayed_work(&mfd->idle_notify_work,
1904 msecs_to_jiffies(mfd->idle_time));
1905 }
1906
1907 /* Reset the backlight only if the panel was off */
1908 if (mdss_panel_is_power_off(cur_power_state)) {
1909 mutex_lock(&mfd->bl_lock);
1910 if (!mfd->allow_bl_update) {
1911 mfd->allow_bl_update = true;
1912 /*
1913 * If in AD calibration mode then frameworks would not
1914 * be allowed to update backlight hence post unblank
1915 * the backlight would remain 0 (0 is set in blank).
1916 * Hence resetting back to calibration mode value
1917 */
1918 if (IS_CALIB_MODE_BL(mfd))
1919 mdss_fb_set_backlight(mfd, mfd->calib_mode_bl);
1920 else if ((!mfd->panel_info->mipi.post_init_delay) &&
1921 (mfd->unset_bl_level != U32_MAX))
1922 mdss_fb_set_backlight(mfd, mfd->unset_bl_level);
1923
1924 /*
1925 * it blocks the backlight update between unblank and
1926 * first kickoff to avoid backlight turn on before black
1927 * frame is transferred to panel through unblank call.
1928 */
1929 mfd->allow_bl_update = false;
1930 }
1931 mutex_unlock(&mfd->bl_lock);
1932 }
1933
1934error:
1935 return ret;
1936}
1937
1938static int mdss_fb_blank_sub(int blank_mode, struct fb_info *info,
1939 int op_enable)
1940{
1941 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
1942 int ret = 0;
1943 int cur_power_state, req_power_state = MDSS_PANEL_POWER_OFF;
1944 char trace_buffer[32];
1945
1946 if (!mfd || !op_enable)
1947 return -EPERM;
1948
1949 if (mfd->dcm_state == DCM_ENTER)
1950 return -EPERM;
1951
1952 pr_debug("%pS mode:%d\n", __builtin_return_address(0),
1953 blank_mode);
1954
1955 snprintf(trace_buffer, sizeof(trace_buffer), "fb%d blank %d",
1956 mfd->index, blank_mode);
1957 ATRACE_BEGIN(trace_buffer);
1958
1959 cur_power_state = mfd->panel_power_state;
1960
1961 /*
1962 * Low power (lp) and ultra low power (ulp) modes are currently only
1963 * supported for command mode panels. For all other panel, treat lp
1964 * mode as full unblank and ulp mode as full blank.
1965 */
1966 if (mfd->panel_info->type != MIPI_CMD_PANEL) {
1967 if (blank_mode == BLANK_FLAG_LP) {
1968 pr_debug("lp mode only valid for cmd mode panels\n");
1969 if (mdss_fb_is_power_on_interactive(mfd))
1970 return 0;
1971 blank_mode = FB_BLANK_UNBLANK;
1972 } else if (blank_mode == BLANK_FLAG_ULP) {
1973 pr_debug("ulp mode valid for cmd mode panels\n");
1974 if (mdss_fb_is_power_off(mfd))
1975 return 0;
1976 blank_mode = FB_BLANK_POWERDOWN;
1977 }
1978 }
1979
1980 switch (blank_mode) {
1981 case FB_BLANK_UNBLANK:
1982 pr_debug("unblank called. cur pwr state=%d\n", cur_power_state);
1983 ret = mdss_fb_blank_unblank(mfd);
1984 break;
1985 case BLANK_FLAG_ULP:
1986 req_power_state = MDSS_PANEL_POWER_LP2;
1987 pr_debug("ultra low power mode requested\n");
1988 if (mdss_fb_is_power_off(mfd)) {
1989 pr_debug("Unsupp transition: off --> ulp\n");
1990 return 0;
1991 }
1992
1993 ret = mdss_fb_blank_blank(mfd, req_power_state);
1994 break;
1995 case BLANK_FLAG_LP:
1996 req_power_state = MDSS_PANEL_POWER_LP1;
1997 pr_debug(" power mode requested\n");
1998
1999 /*
2000 * If low power mode is requested when panel is already off,
2001 * then first unblank the panel before entering low power mode
2002 */
2003 if (mdss_fb_is_power_off(mfd) && mfd->mdp.on_fnc) {
2004 pr_debug("off --> lp. switch to on first\n");
2005 ret = mdss_fb_blank_unblank(mfd);
2006 if (ret)
2007 break;
2008 }
2009
2010 ret = mdss_fb_blank_blank(mfd, req_power_state);
2011 break;
2012 case FB_BLANK_HSYNC_SUSPEND:
2013 case FB_BLANK_POWERDOWN:
2014 default:
2015 req_power_state = MDSS_PANEL_POWER_OFF;
2016 pr_debug("blank powerdown called\n");
2017 ret = mdss_fb_blank_blank(mfd, req_power_state);
2018 break;
2019 }
2020
2021 /* Notify listeners */
2022 sysfs_notify(&mfd->fbi->dev->kobj, NULL, "show_blank_event");
2023
2024 ATRACE_END(trace_buffer);
2025
2026 return ret;
2027}
2028
2029static int mdss_fb_blank(int blank_mode, struct fb_info *info)
2030{
2031 int ret;
2032 struct mdss_panel_data *pdata;
2033 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
2034
2035 ret = mdss_fb_pan_idle(mfd);
2036 if (ret) {
2037 pr_warn("mdss_fb_pan_idle for fb%d failed. ret=%d\n",
2038 mfd->index, ret);
2039 return ret;
2040 }
2041 mutex_lock(&mfd->mdss_sysfs_lock);
2042 if (mfd->op_enable == 0) {
2043 if (blank_mode == FB_BLANK_UNBLANK)
2044 mfd->suspend.panel_power_state = MDSS_PANEL_POWER_ON;
2045 else if (blank_mode == BLANK_FLAG_ULP)
2046 mfd->suspend.panel_power_state = MDSS_PANEL_POWER_LP2;
2047 else if (blank_mode == BLANK_FLAG_LP)
2048 mfd->suspend.panel_power_state = MDSS_PANEL_POWER_LP1;
2049 else
2050 mfd->suspend.panel_power_state = MDSS_PANEL_POWER_OFF;
2051 ret = 0;
2052 goto end;
2053 }
2054 pr_debug("mode: %d\n", blank_mode);
2055
2056 pdata = dev_get_platdata(&mfd->pdev->dev);
2057
2058 if (pdata->panel_info.is_lpm_mode &&
2059 blank_mode == FB_BLANK_UNBLANK) {
2060 pr_debug("panel is in lpm mode\n");
2061 mfd->mdp.configure_panel(mfd, 0, 1);
2062 mdss_fb_set_mdp_sync_pt_threshold(mfd, mfd->panel.type);
2063 pdata->panel_info.is_lpm_mode = false;
2064 }
2065
2066 ret = mdss_fb_blank_sub(blank_mode, info, mfd->op_enable);
2067
2068end:
2069 mutex_unlock(&mfd->mdss_sysfs_lock);
2070 return ret;
2071}
2072
2073static inline int mdss_fb_create_ion_client(struct msm_fb_data_type *mfd)
2074{
2075 mfd->fb_ion_client = msm_ion_client_create("mdss_fb_iclient");
2076 if (IS_ERR_OR_NULL(mfd->fb_ion_client)) {
2077 pr_err("Err:client not created, val %d\n",
2078 PTR_RET(mfd->fb_ion_client));
2079 mfd->fb_ion_client = NULL;
2080 return PTR_RET(mfd->fb_ion_client);
2081 }
2082 return 0;
2083}
2084
2085void mdss_fb_free_fb_ion_memory(struct msm_fb_data_type *mfd)
2086{
2087 if (!mfd) {
2088 pr_err("no mfd\n");
2089 return;
2090 }
2091
2092 if (!mfd->fbi->screen_base)
2093 return;
2094
2095 if (!mfd->fb_ion_client || !mfd->fb_ion_handle) {
2096 pr_err("invalid input parameters for fb%d\n", mfd->index);
2097 return;
2098 }
2099
2100 mfd->fbi->screen_base = NULL;
2101 mfd->fbi->fix.smem_start = 0;
2102
2103 ion_unmap_kernel(mfd->fb_ion_client, mfd->fb_ion_handle);
2104
2105 if (mfd->mdp.fb_mem_get_iommu_domain && !(!mfd->fb_attachment ||
2106 !mfd->fb_attachment->dmabuf ||
2107 !mfd->fb_attachment->dmabuf->ops)) {
2108 dma_buf_unmap_attachment(mfd->fb_attachment, mfd->fb_table,
2109 DMA_BIDIRECTIONAL);
2110 dma_buf_detach(mfd->fbmem_buf, mfd->fb_attachment);
2111 dma_buf_put(mfd->fbmem_buf);
2112 }
2113
2114 ion_free(mfd->fb_ion_client, mfd->fb_ion_handle);
2115 mfd->fb_ion_handle = NULL;
2116 mfd->fbmem_buf = NULL;
2117}
2118
2119int mdss_fb_alloc_fb_ion_memory(struct msm_fb_data_type *mfd, size_t fb_size)
2120{
2121 int rc = 0;
2122 void *vaddr;
2123 int domain;
2124
2125 if (!mfd) {
2126 pr_err("Invalid input param - no mfd\n");
2127 return -EINVAL;
2128 }
2129
2130 if (!mfd->fb_ion_client) {
2131 rc = mdss_fb_create_ion_client(mfd);
2132 if (rc < 0) {
2133 pr_err("fb ion client couldn't be created - %d\n", rc);
2134 return rc;
2135 }
2136 }
2137
2138 pr_debug("size for mmap = %zu\n", fb_size);
2139 mfd->fb_ion_handle = ion_alloc(mfd->fb_ion_client, fb_size, SZ_4K,
2140 ION_HEAP(ION_SYSTEM_HEAP_ID), 0);
2141 if (IS_ERR_OR_NULL(mfd->fb_ion_handle)) {
2142 pr_err("unable to alloc fbmem from ion - %ld\n",
2143 PTR_ERR(mfd->fb_ion_handle));
2144 return PTR_ERR(mfd->fb_ion_handle);
2145 }
2146
2147 if (mfd->mdp.fb_mem_get_iommu_domain) {
2148 mfd->fbmem_buf = ion_share_dma_buf(mfd->fb_ion_client,
2149 mfd->fb_ion_handle);
2150 if (IS_ERR(mfd->fbmem_buf)) {
2151 rc = PTR_ERR(mfd->fbmem_buf);
2152 goto fb_mmap_failed;
2153 }
2154
2155 domain = mfd->mdp.fb_mem_get_iommu_domain();
2156
2157 mfd->fb_attachment = mdss_smmu_dma_buf_attach(mfd->fbmem_buf,
2158 &mfd->pdev->dev, domain);
2159 if (IS_ERR(mfd->fb_attachment)) {
2160 rc = PTR_ERR(mfd->fb_attachment);
2161 goto err_put;
2162 }
2163
2164 mfd->fb_table = dma_buf_map_attachment(mfd->fb_attachment,
2165 DMA_BIDIRECTIONAL);
2166 if (IS_ERR(mfd->fb_table)) {
2167 rc = PTR_ERR(mfd->fb_table);
2168 goto err_detach;
2169 }
2170 } else {
2171 pr_err("No IOMMU Domain\n");
2172 rc = -EINVAL;
2173 goto fb_mmap_failed;
2174 }
2175
2176 vaddr = ion_map_kernel(mfd->fb_ion_client, mfd->fb_ion_handle);
2177 if (IS_ERR_OR_NULL(vaddr)) {
2178 pr_err("ION memory mapping failed - %ld\n", PTR_ERR(vaddr));
2179 rc = PTR_ERR(vaddr);
2180 goto err_unmap;
2181 }
2182 pr_debug("alloc 0x%zxB vaddr = %pK for fb%d\n", fb_size,
2183 vaddr, mfd->index);
2184
2185 mfd->fbi->screen_base = (char *) vaddr;
2186 mfd->fbi->fix.smem_len = fb_size;
2187
2188 return rc;
2189
2190err_unmap:
2191 dma_buf_unmap_attachment(mfd->fb_attachment, mfd->fb_table,
2192 DMA_BIDIRECTIONAL);
2193err_detach:
2194 dma_buf_detach(mfd->fbmem_buf, mfd->fb_attachment);
2195err_put:
2196 dma_buf_put(mfd->fbmem_buf);
2197fb_mmap_failed:
2198 ion_free(mfd->fb_ion_client, mfd->fb_ion_handle);
2199 mfd->fb_attachment = NULL;
2200 mfd->fb_table = NULL;
2201 mfd->fb_ion_handle = NULL;
2202 mfd->fbmem_buf = NULL;
2203 return rc;
2204}
2205
2206/**
2207 * mdss_fb_fbmem_ion_mmap() - Custom fb mmap() function for MSM driver.
2208 *
2209 * @info - Framebuffer info.
2210 * @vma - VM area which is part of the process virtual memory.
2211 *
2212 * This framebuffer mmap function differs from standard mmap() function by
2213 * allowing for customized page-protection and dynamically allocate framebuffer
2214 * memory from system heap and map to iommu virtual address.
2215 *
2216 * Return: virtual address is returned through vma
2217 */
2218static int mdss_fb_fbmem_ion_mmap(struct fb_info *info,
2219 struct vm_area_struct *vma)
2220{
2221 int rc = 0;
2222 size_t req_size, fb_size;
2223 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
2224 struct sg_table *table;
2225 unsigned long addr = vma->vm_start;
2226 unsigned long offset = vma->vm_pgoff * PAGE_SIZE;
2227 struct scatterlist *sg;
2228 unsigned int i;
2229 struct page *page;
2230
2231 if (!mfd || !mfd->pdev || !mfd->pdev->dev.of_node) {
2232 pr_err("Invalid device node\n");
2233 return -ENODEV;
2234 }
2235
2236 req_size = vma->vm_end - vma->vm_start;
2237 fb_size = mfd->fbi->fix.smem_len;
2238 if (req_size > fb_size) {
2239 pr_warn("requested map is greater than framebuffer\n");
2240 return -EOVERFLOW;
2241 }
2242
2243 if (!mfd->fbi->screen_base) {
2244 rc = mdss_fb_alloc_fb_ion_memory(mfd, fb_size);
2245 if (rc < 0) {
2246 pr_err("fb mmap failed!!!!\n");
2247 return rc;
2248 }
2249 }
2250
2251 table = mfd->fb_table;
2252 if (IS_ERR(table)) {
2253 pr_err("Unable to get sg_table from ion:%ld\n", PTR_ERR(table));
2254 mfd->fbi->screen_base = NULL;
2255 return PTR_ERR(table);
2256 } else if (!table) {
2257 pr_err("sg_list is NULL\n");
2258 mfd->fbi->screen_base = NULL;
2259 return -EINVAL;
2260 }
2261
2262 page = sg_page(table->sgl);
2263 if (page) {
2264 for_each_sg(table->sgl, sg, table->nents, i) {
2265 unsigned long remainder = vma->vm_end - addr;
2266 unsigned long len = sg->length;
2267
2268 page = sg_page(sg);
2269
2270 if (offset >= sg->length) {
2271 offset -= sg->length;
2272 continue;
2273 } else if (offset) {
2274 page += offset / PAGE_SIZE;
2275 len = sg->length - offset;
2276 offset = 0;
2277 }
2278 len = min(len, remainder);
2279
2280 if (mfd->mdp_fb_page_protection ==
2281 MDP_FB_PAGE_PROTECTION_WRITECOMBINE)
2282 vma->vm_page_prot =
2283 pgprot_writecombine(vma->vm_page_prot);
2284
2285 pr_debug("vma=%pK, addr=%x len=%ld\n",
2286 vma, (unsigned int)addr, len);
2287 pr_debug("vm_start=%x vm_end=%x vm_page_prot=%ld\n",
Sachin Bhayareb6b5a0f2018-03-02 19:50:39 +05302288 (unsigned int)vma->vm_start,
2289 (unsigned int)vma->vm_end,
2290 (unsigned long int)pgprot_val(
2291 vma->vm_page_prot));
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302292
2293 io_remap_pfn_range(vma, addr, page_to_pfn(page), len,
2294 vma->vm_page_prot);
2295 addr += len;
2296 if (addr >= vma->vm_end)
2297 break;
2298 }
2299 } else {
2300 pr_err("PAGE is null\n");
2301 mdss_fb_free_fb_ion_memory(mfd);
2302 return -ENOMEM;
2303 }
2304
2305 return rc;
2306}
2307
2308/*
2309 * mdss_fb_physical_mmap() - Custom fb mmap() function for MSM driver.
2310 *
2311 * @info - Framebuffer info.
2312 * @vma - VM area which is part of the process virtual memory.
2313 *
2314 * This framebuffer mmap function differs from standard mmap() function as
2315 * map to framebuffer memory from the CMA memory which is allocated during
2316 * bootup.
2317 *
2318 * Return: virtual address is returned through vma
2319 */
2320static int mdss_fb_physical_mmap(struct fb_info *info,
2321 struct vm_area_struct *vma)
2322{
2323 /* Get frame buffer memory range. */
2324 unsigned long start = info->fix.smem_start;
2325 u32 len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len);
2326 unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
2327 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
2328
2329 if (!start) {
2330 pr_warn("No framebuffer memory is allocated\n");
2331 return -ENOMEM;
2332 }
2333
2334 /* Set VM flags. */
2335 start &= PAGE_MASK;
2336 if ((vma->vm_end <= vma->vm_start) ||
2337 (off >= len) ||
2338 ((vma->vm_end - vma->vm_start) > (len - off)))
2339 return -EINVAL;
2340 off += start;
2341 if (off < start)
2342 return -EINVAL;
2343 vma->vm_pgoff = off >> PAGE_SHIFT;
2344 /* This is an IO map - tell maydump to skip this VMA */
2345 vma->vm_flags |= VM_IO;
2346
2347 if (mfd->mdp_fb_page_protection == MDP_FB_PAGE_PROTECTION_WRITECOMBINE)
2348 vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
2349
2350 /* Remap the frame buffer I/O range */
2351 if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
2352 vma->vm_end - vma->vm_start,
2353 vma->vm_page_prot))
2354 return -EAGAIN;
2355
2356 return 0;
2357}
2358
2359static int mdss_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
2360{
2361 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
2362 int rc = -EINVAL;
2363
2364 if (mfd->fb_mmap_type == MDP_FB_MMAP_ION_ALLOC) {
2365 rc = mdss_fb_fbmem_ion_mmap(info, vma);
2366 } else if (mfd->fb_mmap_type == MDP_FB_MMAP_PHYSICAL_ALLOC) {
2367 rc = mdss_fb_physical_mmap(info, vma);
2368 } else {
2369 if (!info->fix.smem_start && !mfd->fb_ion_handle) {
2370 rc = mdss_fb_fbmem_ion_mmap(info, vma);
2371 mfd->fb_mmap_type = MDP_FB_MMAP_ION_ALLOC;
2372 } else {
2373 rc = mdss_fb_physical_mmap(info, vma);
2374 mfd->fb_mmap_type = MDP_FB_MMAP_PHYSICAL_ALLOC;
2375 }
2376 }
2377 if (rc < 0)
2378 pr_err("fb mmap failed with rc = %d\n", rc);
2379
2380 return rc;
2381}
2382
2383static struct fb_ops mdss_fb_ops = {
2384 .owner = THIS_MODULE,
2385 .fb_open = mdss_fb_open,
2386 .fb_release = mdss_fb_release,
2387 .fb_check_var = mdss_fb_check_var, /* vinfo check */
2388 .fb_set_par = mdss_fb_set_par, /* set the video mode */
2389 .fb_blank = mdss_fb_blank, /* blank display */
2390 .fb_pan_display = mdss_fb_pan_display, /* pan display */
2391 .fb_ioctl_v2 = mdss_fb_ioctl, /* perform fb specific ioctl */
2392#ifdef CONFIG_COMPAT
2393 .fb_compat_ioctl_v2 = mdss_fb_compat_ioctl,
2394#endif
2395 .fb_mmap = mdss_fb_mmap,
2396};
2397
2398static int mdss_fb_alloc_fbmem_iommu(struct msm_fb_data_type *mfd, int dom)
2399{
2400 void *virt = NULL;
2401 phys_addr_t phys = 0;
2402 size_t size = 0;
2403 struct platform_device *pdev = mfd->pdev;
2404 int rc = 0;
2405 struct device_node *fbmem_pnode = NULL;
2406
2407 if (!pdev || !pdev->dev.of_node) {
2408 pr_err("Invalid device node\n");
2409 return -ENODEV;
2410 }
2411
2412 fbmem_pnode = of_parse_phandle(pdev->dev.of_node,
2413 "linux,contiguous-region", 0);
2414 if (!fbmem_pnode) {
2415 pr_debug("fbmem is not reserved for %s\n", pdev->name);
2416 mfd->fbi->screen_base = NULL;
2417 mfd->fbi->fix.smem_start = 0;
2418 return 0;
2419 }
2420 {
2421 const u32 *addr;
2422 u64 len;
2423
2424 addr = of_get_address(fbmem_pnode, 0, &len, NULL);
2425 if (!addr) {
2426 pr_err("fbmem size is not specified\n");
2427 of_node_put(fbmem_pnode);
2428 return -EINVAL;
2429 }
2430 size = (size_t)len;
2431 of_node_put(fbmem_pnode);
2432 }
2433
2434 pr_debug("%s frame buffer reserve_size=0x%zx\n", __func__, size);
2435
2436 if (size < PAGE_ALIGN(mfd->fbi->fix.line_length *
2437 mfd->fbi->var.yres_virtual))
2438 pr_warn("reserve size is smaller than framebuffer size\n");
2439
2440 rc = mdss_smmu_dma_alloc_coherent(&pdev->dev, size, &phys, &mfd->iova,
2441 &virt, GFP_KERNEL, dom);
2442 if (rc) {
2443 pr_err("unable to alloc fbmem size=%zx\n", size);
2444 return -ENOMEM;
2445 }
2446
2447 if (MDSS_LPAE_CHECK(phys)) {
2448 pr_warn("fb mem phys %pa > 4GB is not supported.\n", &phys);
2449 mdss_smmu_dma_free_coherent(&pdev->dev, size, &virt,
2450 phys, mfd->iova, dom);
2451 return -ERANGE;
2452 }
2453
2454 pr_debug("alloc 0x%zxB @ (%pa phys) (0x%pK virt) (%pa iova) for fb%d\n",
2455 size, &phys, virt, &mfd->iova, mfd->index);
2456
2457 mfd->fbi->screen_base = virt;
2458 mfd->fbi->fix.smem_start = phys;
2459 mfd->fbi->fix.smem_len = size;
2460
2461 return 0;
2462}
2463
2464static int mdss_fb_alloc_fbmem(struct msm_fb_data_type *mfd)
2465{
2466
2467 if (mfd->mdp.fb_mem_alloc_fnc) {
2468 return mfd->mdp.fb_mem_alloc_fnc(mfd);
2469 } else if (mfd->mdp.fb_mem_get_iommu_domain) {
2470 int dom = mfd->mdp.fb_mem_get_iommu_domain();
2471
2472 if (dom >= 0)
2473 return mdss_fb_alloc_fbmem_iommu(mfd, dom);
2474 else
2475 return -ENOMEM;
2476 } else {
2477 pr_err("no fb memory allocator function defined\n");
2478 return -ENOMEM;
2479 }
2480}
2481
2482static int mdss_fb_register(struct msm_fb_data_type *mfd)
2483{
2484 int ret = -ENODEV;
2485 int bpp;
2486 char panel_name[20];
2487 struct mdss_panel_info *panel_info = mfd->panel_info;
2488 struct fb_info *fbi = mfd->fbi;
2489 struct fb_fix_screeninfo *fix;
2490 struct fb_var_screeninfo *var;
2491 int *id;
2492
2493 /*
2494 * fb info initialization
2495 */
2496 fix = &fbi->fix;
2497 var = &fbi->var;
2498
2499 fix->type_aux = 0; /* if type == FB_TYPE_INTERLEAVED_PLANES */
2500 fix->visual = FB_VISUAL_TRUECOLOR; /* True Color */
2501 fix->ywrapstep = 0; /* No support */
2502 fix->mmio_start = 0; /* No MMIO Address */
2503 fix->mmio_len = 0; /* No MMIO Address */
2504 fix->accel = FB_ACCEL_NONE;/* FB_ACCEL_MSM needes to be added in fb.h */
2505
2506 var->xoffset = 0, /* Offset from virtual to visible */
2507 var->yoffset = 0, /* resolution */
2508 var->grayscale = 0, /* No graylevels */
2509 var->nonstd = 0, /* standard pixel format */
2510 var->activate = FB_ACTIVATE_VBL, /* activate it at vsync */
2511 var->height = -1, /* height of picture in mm */
2512 var->width = -1, /* width of picture in mm */
2513 var->accel_flags = 0, /* acceleration flags */
2514 var->sync = 0, /* see FB_SYNC_* */
2515 var->rotate = 0, /* angle we rotate counter clockwise */
2516 mfd->op_enable = false;
2517
2518 switch (mfd->fb_imgType) {
2519 case MDP_RGB_565:
2520 fix->type = FB_TYPE_PACKED_PIXELS;
2521 fix->xpanstep = 1;
2522 fix->ypanstep = 1;
2523 var->vmode = FB_VMODE_NONINTERLACED;
2524 var->blue.offset = 0;
2525 var->green.offset = 5;
2526 var->red.offset = 11;
2527 var->blue.length = 5;
2528 var->green.length = 6;
2529 var->red.length = 5;
2530 var->blue.msb_right = 0;
2531 var->green.msb_right = 0;
2532 var->red.msb_right = 0;
2533 var->transp.offset = 0;
2534 var->transp.length = 0;
2535 bpp = 2;
2536 break;
2537
2538 case MDP_RGB_888:
2539 fix->type = FB_TYPE_PACKED_PIXELS;
2540 fix->xpanstep = 1;
2541 fix->ypanstep = 1;
2542 var->vmode = FB_VMODE_NONINTERLACED;
2543 var->blue.offset = 0;
2544 var->green.offset = 8;
2545 var->red.offset = 16;
2546 var->blue.length = 8;
2547 var->green.length = 8;
2548 var->red.length = 8;
2549 var->blue.msb_right = 0;
2550 var->green.msb_right = 0;
2551 var->red.msb_right = 0;
2552 var->transp.offset = 0;
2553 var->transp.length = 0;
2554 bpp = 3;
2555 break;
2556
2557 case MDP_ARGB_8888:
2558 fix->type = FB_TYPE_PACKED_PIXELS;
2559 fix->xpanstep = 1;
2560 fix->ypanstep = 1;
2561 var->vmode = FB_VMODE_NONINTERLACED;
2562 var->blue.offset = 24;
2563 var->green.offset = 16;
2564 var->red.offset = 8;
2565 var->blue.length = 8;
2566 var->green.length = 8;
2567 var->red.length = 8;
2568 var->blue.msb_right = 0;
2569 var->green.msb_right = 0;
2570 var->red.msb_right = 0;
2571 var->transp.offset = 0;
2572 var->transp.length = 8;
2573 bpp = 4;
2574 break;
2575
2576 case MDP_RGBA_8888:
2577 fix->type = FB_TYPE_PACKED_PIXELS;
2578 fix->xpanstep = 1;
2579 fix->ypanstep = 1;
2580 var->vmode = FB_VMODE_NONINTERLACED;
2581 var->blue.offset = 16;
2582 var->green.offset = 8;
2583 var->red.offset = 0;
2584 var->blue.length = 8;
2585 var->green.length = 8;
2586 var->red.length = 8;
2587 var->blue.msb_right = 0;
2588 var->green.msb_right = 0;
2589 var->red.msb_right = 0;
2590 var->transp.offset = 24;
2591 var->transp.length = 8;
2592 bpp = 4;
2593 break;
2594
2595 case MDP_YCRYCB_H2V1:
2596 fix->type = FB_TYPE_INTERLEAVED_PLANES;
2597 fix->xpanstep = 2;
2598 fix->ypanstep = 1;
2599 var->vmode = FB_VMODE_NONINTERLACED;
2600
2601 /* how about R/G/B offset? */
2602 var->blue.offset = 0;
2603 var->green.offset = 5;
2604 var->red.offset = 11;
2605 var->blue.length = 5;
2606 var->green.length = 6;
2607 var->red.length = 5;
2608 var->blue.msb_right = 0;
2609 var->green.msb_right = 0;
2610 var->red.msb_right = 0;
2611 var->transp.offset = 0;
2612 var->transp.length = 0;
2613 bpp = 2;
2614 break;
2615
2616 default:
2617 pr_err("msm_fb_init: fb %d unknown image type!\n",
2618 mfd->index);
2619 return ret;
2620 }
2621
2622 mdss_panelinfo_to_fb_var(panel_info, var);
2623
2624 fix->type = panel_info->is_3d_panel;
2625 if (mfd->mdp.fb_stride)
2626 fix->line_length = mfd->mdp.fb_stride(mfd->index, var->xres,
2627 bpp);
2628 else
2629 fix->line_length = var->xres * bpp;
2630
2631 var->xres_virtual = var->xres;
2632 var->yres_virtual = panel_info->yres * mfd->fb_page;
2633 var->bits_per_pixel = bpp * 8; /* FrameBuffer color depth */
2634
2635 /*
2636 * Populate smem length here for uspace to get the
2637 * Framebuffer size when FBIO_FSCREENINFO ioctl is called.
2638 */
2639 fix->smem_len = PAGE_ALIGN(fix->line_length * var->yres) * mfd->fb_page;
2640
2641 /* id field for fb app */
2642 id = (int *)&mfd->panel;
2643
2644 snprintf(fix->id, sizeof(fix->id), "mdssfb_%x", (u32) *id);
2645
2646 fbi->fbops = &mdss_fb_ops;
2647 fbi->flags = FBINFO_FLAG_DEFAULT;
2648 fbi->pseudo_palette = mdss_fb_pseudo_palette;
2649
2650 mfd->ref_cnt = 0;
2651 mfd->panel_power_state = MDSS_PANEL_POWER_OFF;
2652 mfd->dcm_state = DCM_UNINIT;
2653
2654 if (mdss_fb_alloc_fbmem(mfd))
2655 pr_warn("unable to allocate fb memory in fb register\n");
2656
2657 mfd->op_enable = true;
2658
2659 mutex_init(&mfd->update.lock);
2660 mutex_init(&mfd->no_update.lock);
2661 mutex_init(&mfd->mdp_sync_pt_data.sync_mutex);
2662 atomic_set(&mfd->mdp_sync_pt_data.commit_cnt, 0);
2663 atomic_set(&mfd->commits_pending, 0);
2664 atomic_set(&mfd->ioctl_ref_cnt, 0);
2665 atomic_set(&mfd->kickoff_pending, 0);
2666
2667 init_timer(&mfd->no_update.timer);
2668 mfd->no_update.timer.function = mdss_fb_no_update_notify_timer_cb;
2669 mfd->no_update.timer.data = (unsigned long)mfd;
2670 mfd->update.ref_count = 0;
2671 mfd->no_update.ref_count = 0;
2672 mfd->update.init_done = false;
2673 init_completion(&mfd->update.comp);
2674 init_completion(&mfd->no_update.comp);
2675 init_completion(&mfd->power_off_comp);
2676 init_completion(&mfd->power_set_comp);
2677 init_waitqueue_head(&mfd->commit_wait_q);
2678 init_waitqueue_head(&mfd->idle_wait_q);
2679 init_waitqueue_head(&mfd->ioctl_q);
2680 init_waitqueue_head(&mfd->kickoff_wait_q);
2681
2682 ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
2683 if (ret)
2684 pr_err("fb_alloc_cmap() failed!\n");
2685
2686 if (register_framebuffer(fbi) < 0) {
2687 fb_dealloc_cmap(&fbi->cmap);
2688
2689 mfd->op_enable = false;
2690 return -EPERM;
2691 }
2692
2693 snprintf(panel_name, ARRAY_SIZE(panel_name), "mdss_panel_fb%d",
2694 mfd->index);
2695 mdss_panel_debugfs_init(panel_info, panel_name);
2696 pr_info("FrameBuffer[%d] %dx%d registered successfully!\n", mfd->index,
2697 fbi->var.xres, fbi->var.yres);
2698
2699 return 0;
2700}
2701
2702static int mdss_fb_open(struct fb_info *info, int user)
2703{
2704 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
2705 struct mdss_fb_file_info *file_info = NULL;
2706 int result;
2707 struct task_struct *task = current->group_leader;
2708
2709 if (mfd->shutdown_pending) {
2710 pr_err_once("Shutdown pending. Aborting operation. Request from pid:%d name=%s\n",
2711 current->tgid, task->comm);
2712 sysfs_notify(&mfd->fbi->dev->kobj, NULL, "show_blank_event");
2713 return -ESHUTDOWN;
2714 }
2715
2716 file_info = kmalloc(sizeof(*file_info), GFP_KERNEL);
2717 if (!file_info)
2718 return -ENOMEM;
2719
2720 file_info->file = info->file;
2721 list_add(&file_info->list, &mfd->file_list);
2722
2723 result = pm_runtime_get_sync(info->dev);
2724
2725 if (result < 0) {
2726 pr_err("pm_runtime: fail to wake up\n");
2727 goto pm_error;
2728 }
2729
2730 if (!mfd->ref_cnt) {
2731 result = mdss_fb_blank_sub(FB_BLANK_UNBLANK, info,
2732 mfd->op_enable);
2733 if (result) {
2734 pr_err("can't turn on fb%d! rc=%d\n", mfd->index,
2735 result);
2736 goto blank_error;
2737 }
2738 }
2739
2740 mfd->ref_cnt++;
2741 pr_debug("mfd refcount:%d file:%pK\n", mfd->ref_cnt, info->file);
2742
2743 return 0;
2744
2745blank_error:
2746 pm_runtime_put(info->dev);
2747pm_error:
2748 list_del(&file_info->list);
2749 kfree(file_info);
2750 return result;
2751}
2752
2753static int mdss_fb_release_all(struct fb_info *info, bool release_all)
2754{
2755 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
2756 struct mdss_fb_file_info *file_info = NULL, *temp_file_info = NULL;
2757 struct file *file = info->file;
2758 int ret = 0;
2759 bool node_found = false;
2760 struct task_struct *task = current->group_leader;
2761
2762 if (!mfd->ref_cnt) {
2763 pr_info("try to close unopened fb %d! from pid:%d name:%s\n",
2764 mfd->index, current->tgid, task->comm);
2765 return -EINVAL;
2766 }
2767
2768 if (!wait_event_timeout(mfd->ioctl_q,
2769 !atomic_read(&mfd->ioctl_ref_cnt) || !release_all,
2770 msecs_to_jiffies(1000)))
2771 pr_warn("fb%d ioctl could not finish. waited 1 sec.\n",
2772 mfd->index);
2773
2774 /* wait only for the last release */
2775 if (release_all || (mfd->ref_cnt == 1)) {
2776 ret = mdss_fb_pan_idle(mfd);
2777 if (ret && (ret != -ESHUTDOWN))
2778 pr_warn("mdss_fb_pan_idle for fb%d failed. ret=%d ignoring.\n",
2779 mfd->index, ret);
2780 }
2781
2782 pr_debug("release_all = %s\n", release_all ? "true" : "false");
2783
2784 list_for_each_entry_safe(file_info, temp_file_info, &mfd->file_list,
2785 list) {
2786 if (!release_all && file_info->file != file)
2787 continue;
2788
2789 pr_debug("found file node mfd->ref=%d\n", mfd->ref_cnt);
2790 list_del(&file_info->list);
2791 kfree(file_info);
2792
2793 mfd->ref_cnt--;
2794 pm_runtime_put(info->dev);
2795
2796 node_found = true;
2797
2798 if (!release_all)
2799 break;
2800 }
2801
2802 if (!node_found || (release_all && mfd->ref_cnt))
2803 pr_warn("file node not found or wrong ref cnt: release all:%d refcnt:%d\n",
2804 release_all, mfd->ref_cnt);
2805
2806 pr_debug("current process=%s pid=%d mfd->ref=%d file:%pK\n",
2807 task->comm, current->tgid, mfd->ref_cnt, info->file);
2808
2809 if (!mfd->ref_cnt || release_all) {
2810 /* resources (if any) will be released during blank */
2811 if (mfd->mdp.release_fnc)
2812 mfd->mdp.release_fnc(mfd, NULL);
2813
2814 if (mfd->mdp.pp_release_fnc) {
2815 ret = (*mfd->mdp.pp_release_fnc)(mfd);
2816 if (ret)
2817 pr_err("PP release failed ret %d\n", ret);
2818 }
2819
2820 /* reset backlight before blank to prevent backlight from
2821 * enabling ahead of unblank. for some special cases like
2822 * adb shell stop/start.
2823 */
2824 mdss_fb_set_backlight(mfd, 0);
2825
2826 ret = mdss_fb_blank_sub(FB_BLANK_POWERDOWN, info,
2827 mfd->op_enable);
2828 if (ret) {
2829 pr_err("can't turn off fb%d! rc=%d current process=%s pid=%d\n",
2830 mfd->index, ret, task->comm, current->tgid);
2831 return ret;
2832 }
2833 if (mfd->fb_ion_handle)
2834 mdss_fb_free_fb_ion_memory(mfd);
2835
2836 atomic_set(&mfd->ioctl_ref_cnt, 0);
2837 } else {
2838 if (mfd->mdp.release_fnc)
2839 ret = mfd->mdp.release_fnc(mfd, file);
2840
2841 /* display commit is needed to release resources */
2842 if (ret)
2843 mdss_fb_pan_display(&mfd->fbi->var, mfd->fbi);
2844 }
2845
2846 return ret;
2847}
2848
2849static int mdss_fb_release(struct fb_info *info, int user)
2850{
2851 return mdss_fb_release_all(info, false);
2852}
2853
2854static void mdss_fb_power_setting_idle(struct msm_fb_data_type *mfd)
2855{
2856 int ret;
2857
2858 if (mfd->is_power_setting) {
2859 ret = wait_for_completion_timeout(
2860 &mfd->power_set_comp,
2861 msecs_to_jiffies(WAIT_DISP_OP_TIMEOUT));
2862 if (ret < 0)
2863 ret = -ERESTARTSYS;
2864 else if (!ret)
2865 pr_err("%s wait for power_set_comp timeout %d %d",
2866 __func__, ret, mfd->is_power_setting);
2867 if (ret <= 0) {
2868 mfd->is_power_setting = false;
2869 complete_all(&mfd->power_set_comp);
2870 }
2871 }
2872}
2873
2874static void __mdss_fb_copy_fence(struct msm_sync_pt_data *sync_pt_data,
Sachin Bhayare2b6d0042018-01-13 19:38:21 +05302875 struct mdss_fence **fences, u32 *fence_cnt)
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302876{
2877 pr_debug("%s: wait for fences\n", sync_pt_data->fence_name);
2878
2879 mutex_lock(&sync_pt_data->sync_mutex);
2880 /*
2881 * Assuming that acq_fen_cnt is sanitized in bufsync ioctl
2882 * to check for sync_pt_data->acq_fen_cnt <= MDP_MAX_FENCE_FD
2883 */
2884 *fence_cnt = sync_pt_data->acq_fen_cnt;
2885 sync_pt_data->acq_fen_cnt = 0;
2886 if (*fence_cnt)
2887 memcpy(fences, sync_pt_data->acq_fen,
Sachin Bhayare2b6d0042018-01-13 19:38:21 +05302888 *fence_cnt * sizeof(struct mdss_fence *));
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302889 mutex_unlock(&sync_pt_data->sync_mutex);
2890}
2891
2892static int __mdss_fb_wait_for_fence_sub(struct msm_sync_pt_data *sync_pt_data,
Sachin Bhayare2b6d0042018-01-13 19:38:21 +05302893 struct mdss_fence **fences, int fence_cnt)
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302894{
2895 int i, ret = 0;
2896 unsigned long max_wait = msecs_to_jiffies(WAIT_MAX_FENCE_TIMEOUT);
2897 unsigned long timeout = jiffies + max_wait;
2898 long wait_ms, wait_jf;
2899
2900 /* buf sync */
2901 for (i = 0; i < fence_cnt && !ret; i++) {
2902 wait_jf = timeout - jiffies;
2903 wait_ms = jiffies_to_msecs(wait_jf);
2904
2905 /*
2906 * In this loop, if one of the previous fence took long
2907 * time, give a chance for the next fence to check if
2908 * fence is already signalled. If not signalled it breaks
2909 * in the final wait timeout.
2910 */
2911 if (wait_jf < 0)
2912 wait_ms = WAIT_MIN_FENCE_TIMEOUT;
2913 else
2914 wait_ms = min_t(long, WAIT_FENCE_FIRST_TIMEOUT,
2915 wait_ms);
2916
Sachin Bhayare2b6d0042018-01-13 19:38:21 +05302917 ret = mdss_wait_sync_fence(fences[i], wait_ms);
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302918
2919 if (ret == -ETIME) {
2920 wait_jf = timeout - jiffies;
2921 wait_ms = jiffies_to_msecs(wait_jf);
2922 if (wait_jf < 0)
2923 break;
2924
2925 wait_ms = min_t(long, WAIT_FENCE_FINAL_TIMEOUT,
2926 wait_ms);
2927
2928 pr_warn("%s: sync_fence_wait timed out! ",
Sachin Bhayare2b6d0042018-01-13 19:38:21 +05302929 mdss_get_sync_fence_name(fences[i]));
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302930 pr_cont("Waiting %ld.%ld more seconds\n",
2931 (wait_ms/MSEC_PER_SEC), (wait_ms%MSEC_PER_SEC));
2932 MDSS_XLOG(sync_pt_data->timeline_value);
2933 MDSS_XLOG_TOUT_HANDLER("mdp");
Sachin Bhayare2b6d0042018-01-13 19:38:21 +05302934 ret = mdss_wait_sync_fence(fences[i], wait_ms);
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302935
2936 if (ret == -ETIME)
2937 break;
2938 }
Sachin Bhayare2b6d0042018-01-13 19:38:21 +05302939 mdss_put_sync_fence(fences[i]);
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302940 }
2941
2942 if (ret < 0) {
2943 pr_err("%s: sync_fence_wait failed! ret = %x\n",
2944 sync_pt_data->fence_name, ret);
2945 for (; i < fence_cnt; i++)
Sachin Bhayare2b6d0042018-01-13 19:38:21 +05302946 mdss_put_sync_fence(fences[i]);
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302947 }
2948 return ret;
2949}
2950
2951int mdss_fb_wait_for_fence(struct msm_sync_pt_data *sync_pt_data)
2952{
Sachin Bhayare2b6d0042018-01-13 19:38:21 +05302953 struct mdss_fence *fences[MDP_MAX_FENCE_FD];
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302954 int fence_cnt = 0;
2955
2956 __mdss_fb_copy_fence(sync_pt_data, fences, &fence_cnt);
2957
2958 if (fence_cnt)
2959 __mdss_fb_wait_for_fence_sub(sync_pt_data,
2960 fences, fence_cnt);
2961
2962 return fence_cnt;
2963}
2964
2965/**
2966 * mdss_fb_signal_timeline() - signal a single release fence
2967 * @sync_pt_data: Sync point data structure for the timeline which
2968 * should be signaled.
2969 *
2970 * This is called after a frame has been pushed to display. This signals the
2971 * timeline to release the fences associated with this frame.
2972 */
2973void mdss_fb_signal_timeline(struct msm_sync_pt_data *sync_pt_data)
2974{
Krishna Manikandanb296a2b2018-03-21 17:16:31 +05302975 struct msm_fb_data_type *mfd;
2976
2977 mfd = container_of(sync_pt_data, typeof(*mfd), mdp_sync_pt_data);
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302978 mutex_lock(&sync_pt_data->sync_mutex);
Krishna Manikandanb296a2b2018-03-21 17:16:31 +05302979 if (atomic_read(&sync_pt_data->commit_cnt) &&
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302980 sync_pt_data->timeline) {
Sachin Bhayare2b6d0042018-01-13 19:38:21 +05302981 mdss_inc_timeline(sync_pt_data->timeline, 1);
Krishna Manikandanb296a2b2018-03-21 17:16:31 +05302982
2983 /*
2984 * For Command mode panels, the retire timeline is incremented
2985 * whenever we receive a readptr_done. For all other panels,
2986 * the retire fence should be signaled along with the release
2987 * fence once the frame is done.
2988 */
2989 if (mfd->panel.type != MIPI_CMD_PANEL)
2990 mdss_inc_timeline(sync_pt_data->timeline_retire, 1);
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302991 MDSS_XLOG(sync_pt_data->timeline_value);
2992 sync_pt_data->timeline_value++;
2993
Krishna Manikandanb296a2b2018-03-21 17:16:31 +05302994 pr_debug("%s: buffer signaled! timeline val=%d commit_cnt=%d\n",
Sachin Bhayareeeb88892018-01-02 16:36:01 +05302995 sync_pt_data->fence_name, sync_pt_data->timeline_value,
2996 atomic_read(&sync_pt_data->commit_cnt));
2997 } else {
2998 pr_debug("%s timeline signaled without commits val=%d\n",
2999 sync_pt_data->fence_name, sync_pt_data->timeline_value);
3000 }
3001 mutex_unlock(&sync_pt_data->sync_mutex);
3002}
3003
3004/**
3005 * mdss_fb_release_fences() - signal all pending release fences
3006 * @mfd: Framebuffer data structure for display
3007 *
3008 * Release all currently pending release fences, including those that are in
3009 * the process to be commtted.
3010 *
3011 * Note: this should only be called during close or suspend sequence.
3012 */
3013static void mdss_fb_release_fences(struct msm_fb_data_type *mfd)
3014{
3015 struct msm_sync_pt_data *sync_pt_data = &mfd->mdp_sync_pt_data;
3016 int val;
3017
3018 mutex_lock(&sync_pt_data->sync_mutex);
3019 if (sync_pt_data->timeline) {
3020 val = sync_pt_data->threshold +
3021 atomic_read(&sync_pt_data->commit_cnt);
Sachin Bhayare9b5caf22018-02-20 22:05:47 +05303022 mdss_resync_timeline(sync_pt_data->timeline);
Krishna Manikandanb296a2b2018-03-21 17:16:31 +05303023 if (mfd->panel.type != MIPI_CMD_PANEL)
3024 mdss_resync_timeline(sync_pt_data->timeline_retire);
3025 sync_pt_data->timeline_value = val;
3026
Sachin Bhayareeeb88892018-01-02 16:36:01 +05303027 }
3028 mutex_unlock(&sync_pt_data->sync_mutex);
3029}
3030
3031static void mdss_fb_release_kickoff(struct msm_fb_data_type *mfd)
3032{
3033 if (mfd->wait_for_kickoff) {
3034 atomic_set(&mfd->kickoff_pending, 0);
3035 wake_up_all(&mfd->kickoff_wait_q);
3036 }
3037}
3038
3039/**
3040 * __mdss_fb_sync_buf_done_callback() - process async display events
3041 * @p: Notifier block registered for async events.
3042 * @event: Event enum to identify the event.
3043 * @data: Optional argument provided with the event.
3044 *
3045 * See enum mdp_notify_event for events handled.
3046 */
3047static int __mdss_fb_sync_buf_done_callback(struct notifier_block *p,
3048 unsigned long event, void *data)
3049{
3050 struct msm_sync_pt_data *sync_pt_data;
3051 struct msm_fb_data_type *mfd;
3052 int fence_cnt;
3053 int ret = NOTIFY_OK;
3054
3055 sync_pt_data = container_of(p, struct msm_sync_pt_data, notifier);
3056 mfd = container_of(sync_pt_data, struct msm_fb_data_type,
3057 mdp_sync_pt_data);
3058
3059 switch (event) {
3060 case MDP_NOTIFY_FRAME_BEGIN:
3061 if (mfd->idle_time && !mod_delayed_work(system_wq,
3062 &mfd->idle_notify_work,
3063 msecs_to_jiffies(WAIT_DISP_OP_TIMEOUT)))
3064 pr_debug("fb%d: start idle delayed work\n",
3065 mfd->index);
3066
3067 mfd->idle_state = MDSS_FB_NOT_IDLE;
3068 break;
3069 case MDP_NOTIFY_FRAME_READY:
3070 if (sync_pt_data->async_wait_fences &&
3071 sync_pt_data->temp_fen_cnt) {
3072 fence_cnt = sync_pt_data->temp_fen_cnt;
3073 sync_pt_data->temp_fen_cnt = 0;
3074 ret = __mdss_fb_wait_for_fence_sub(sync_pt_data,
3075 sync_pt_data->temp_fen, fence_cnt);
3076 }
3077 if (mfd->idle_time && !mod_delayed_work(system_wq,
3078 &mfd->idle_notify_work,
3079 msecs_to_jiffies(mfd->idle_time)))
3080 pr_debug("fb%d: restarted idle work\n",
3081 mfd->index);
3082 if (ret == -ETIME)
3083 ret = NOTIFY_BAD;
3084 mfd->idle_state = MDSS_FB_IDLE_TIMER_RUNNING;
3085 break;
3086 case MDP_NOTIFY_FRAME_FLUSHED:
3087 pr_debug("%s: frame flushed\n", sync_pt_data->fence_name);
3088 sync_pt_data->flushed = true;
3089 break;
3090 case MDP_NOTIFY_FRAME_TIMEOUT:
3091 pr_err("%s: frame timeout\n", sync_pt_data->fence_name);
3092 mdss_fb_signal_timeline(sync_pt_data);
3093 break;
3094 case MDP_NOTIFY_FRAME_DONE:
3095 pr_debug("%s: frame done\n", sync_pt_data->fence_name);
3096 mdss_fb_signal_timeline(sync_pt_data);
3097 mdss_fb_calc_fps(mfd);
3098 break;
3099 case MDP_NOTIFY_FRAME_CFG_DONE:
3100 if (sync_pt_data->async_wait_fences)
3101 __mdss_fb_copy_fence(sync_pt_data,
3102 sync_pt_data->temp_fen,
3103 &sync_pt_data->temp_fen_cnt);
3104 break;
3105 case MDP_NOTIFY_FRAME_CTX_DONE:
3106 mdss_fb_release_kickoff(mfd);
3107 break;
3108 }
3109
3110 return ret;
3111}
3112
3113/**
3114 * mdss_fb_pan_idle() - wait for panel programming to be idle
3115 * @mfd: Framebuffer data structure for display
3116 *
3117 * Wait for any pending programming to be done if in the process of programming
3118 * hardware configuration. After this function returns it is safe to perform
3119 * software updates for next frame.
3120 */
3121static int mdss_fb_pan_idle(struct msm_fb_data_type *mfd)
3122{
3123 int ret = 0;
3124
3125 ret = wait_event_timeout(mfd->idle_wait_q,
3126 (!atomic_read(&mfd->commits_pending) ||
3127 mfd->shutdown_pending),
3128 msecs_to_jiffies(WAIT_DISP_OP_TIMEOUT));
3129 if (!ret) {
3130 pr_err("%pS: wait for idle timeout commits=%d\n",
3131 __builtin_return_address(0),
3132 atomic_read(&mfd->commits_pending));
3133 MDSS_XLOG_TOUT_HANDLER("mdp", "vbif", "vbif_nrt",
3134 "dbg_bus", "vbif_dbg_bus");
3135 ret = -ETIMEDOUT;
3136 } else if (mfd->shutdown_pending) {
3137 pr_debug("Shutdown signalled\n");
3138 ret = -ESHUTDOWN;
3139 } else {
3140 ret = 0;
3141 }
3142
3143 return ret;
3144}
3145
3146static int mdss_fb_wait_for_kickoff(struct msm_fb_data_type *mfd)
3147{
3148 int ret = 0;
3149
3150 if (!mfd->wait_for_kickoff)
3151 return mdss_fb_pan_idle(mfd);
3152
3153 ret = wait_event_timeout(mfd->kickoff_wait_q,
3154 (!atomic_read(&mfd->kickoff_pending) ||
3155 mfd->shutdown_pending),
3156 msecs_to_jiffies(WAIT_DISP_OP_TIMEOUT));
3157 if (!ret) {
3158 pr_err("%pS: wait for kickoff timeout koff=%d commits=%d\n",
3159 __builtin_return_address(0),
3160 atomic_read(&mfd->kickoff_pending),
3161 atomic_read(&mfd->commits_pending));
3162 MDSS_XLOG_TOUT_HANDLER("mdp", "vbif", "vbif_nrt",
3163 "dbg_bus", "vbif_dbg_bus");
3164 ret = -ETIMEDOUT;
3165 } else if (mfd->shutdown_pending) {
3166 pr_debug("Shutdown signalled\n");
3167 ret = -ESHUTDOWN;
3168 } else {
3169 ret = 0;
3170 }
3171
3172 return ret;
3173}
3174
3175static int mdss_fb_pan_display_ex(struct fb_info *info,
3176 struct mdp_display_commit *disp_commit)
3177{
3178 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
3179 struct fb_var_screeninfo *var = &disp_commit->var;
3180 u32 wait_for_finish = disp_commit->wait_for_finish;
3181 int ret = 0;
3182
3183 if (!mfd || (!mfd->op_enable))
3184 return -EPERM;
3185
3186 if ((mdss_fb_is_power_off(mfd)) &&
3187 !((mfd->dcm_state == DCM_ENTER) &&
3188 (mfd->panel.type == MIPI_CMD_PANEL)))
3189 return -EPERM;
3190
3191 if (var->xoffset > (info->var.xres_virtual - info->var.xres))
3192 return -EINVAL;
3193
3194 if (var->yoffset > (info->var.yres_virtual - info->var.yres))
3195 return -EINVAL;
3196
Sachin Bhayare3d3767e2018-01-02 21:10:57 +05303197 ret = mdss_fb_wait_for_kickoff(mfd);
Sachin Bhayareeeb88892018-01-02 16:36:01 +05303198 if (ret) {
3199 pr_err("wait_for_kick failed. rc=%d\n", ret);
3200 return ret;
3201 }
3202
3203 if (mfd->mdp.pre_commit_fnc) {
3204 ret = mfd->mdp.pre_commit_fnc(mfd);
3205 if (ret) {
3206 pr_err("fb%d: pre commit failed %d\n",
3207 mfd->index, ret);
3208 return ret;
3209 }
3210 }
3211
3212 mutex_lock(&mfd->mdp_sync_pt_data.sync_mutex);
3213 if (info->fix.xpanstep)
3214 info->var.xoffset =
3215 (var->xoffset / info->fix.xpanstep) * info->fix.xpanstep;
3216
3217 if (info->fix.ypanstep)
3218 info->var.yoffset =
3219 (var->yoffset / info->fix.ypanstep) * info->fix.ypanstep;
3220
3221 mfd->msm_fb_backup.info = *info;
3222 mfd->msm_fb_backup.disp_commit = *disp_commit;
3223
Sachin Bhayareeeb88892018-01-02 16:36:01 +05303224 atomic_inc(&mfd->commits_pending);
3225 atomic_inc(&mfd->kickoff_pending);
3226 wake_up_all(&mfd->commit_wait_q);
3227 mutex_unlock(&mfd->mdp_sync_pt_data.sync_mutex);
3228 if (wait_for_finish) {
3229 ret = mdss_fb_pan_idle(mfd);
3230 if (ret)
3231 pr_err("mdss_fb_pan_idle failed. rc=%d\n", ret);
3232 }
3233 return ret;
3234}
3235
3236u32 mdss_fb_get_mode_switch(struct msm_fb_data_type *mfd)
3237{
3238 /* If there is no attached mfd then there is no pending mode switch */
3239 if (!mfd)
3240 return 0;
3241
3242 if (mfd->pending_switch)
3243 return mfd->switch_new_mode;
3244
3245 return 0;
3246}
3247
3248/*
3249 * __ioctl_transition_dyn_mode_state() - State machine for mode switch
3250 * @mfd: Framebuffer data structure for display
3251 * @cmd: ioctl that was called
3252 * @validate: used with atomic commit when doing validate layers
3253 *
3254 * This function assists with dynamic mode switch of DSI panel. States
3255 * are used to make sure that panel mode switch occurs on next
3256 * prepare/sync/commit (for legacy) and validate/pre_commit (for
3257 * atomic commit) pairing. This state machine insure that calculation
3258 * and return values (such as buffer release fences) are based on the
3259 * panel mode being switching into.
3260 */
3261static int __ioctl_transition_dyn_mode_state(struct msm_fb_data_type *mfd,
3262 unsigned int cmd, bool validate, bool null_commit)
3263{
3264 if (mfd->switch_state == MDSS_MDP_NO_UPDATE_REQUESTED)
3265 return 0;
3266
3267 mutex_lock(&mfd->switch_lock);
3268 switch (cmd) {
3269 case MSMFB_ATOMIC_COMMIT:
3270 if ((mfd->switch_state == MDSS_MDP_WAIT_FOR_VALIDATE)
3271 && validate) {
3272 if (mfd->switch_new_mode != SWITCH_RESOLUTION)
3273 mfd->pending_switch = true;
3274 mfd->switch_state = MDSS_MDP_WAIT_FOR_COMMIT;
3275 } else if (mfd->switch_state == MDSS_MDP_WAIT_FOR_COMMIT) {
3276 if (mfd->switch_new_mode != SWITCH_RESOLUTION)
3277 mdss_fb_set_mdp_sync_pt_threshold(mfd,
3278 mfd->switch_new_mode);
3279 mfd->switch_state = MDSS_MDP_WAIT_FOR_KICKOFF;
3280 } else if ((mfd->switch_state == MDSS_MDP_WAIT_FOR_VALIDATE)
3281 && null_commit) {
3282 mfd->switch_state = MDSS_MDP_WAIT_FOR_KICKOFF;
3283 }
3284 break;
3285 }
3286 mutex_unlock(&mfd->switch_lock);
3287 return 0;
3288}
3289
3290static inline bool mdss_fb_is_wb_config_same(struct msm_fb_data_type *mfd,
3291 struct mdp_output_layer *output_layer)
3292{
3293 struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
3294 struct msm_mdp_interface *mdp5_interface = &mfd->mdp;
3295
3296 if (!mdp5_data->wfd
3297 || (mdp5_interface->is_config_same
3298 && !mdp5_interface->is_config_same(mfd, output_layer)))
3299 return false;
3300 return true;
3301}
3302
3303/* update pinfo and var for WB on config change */
3304static void mdss_fb_update_resolution(struct msm_fb_data_type *mfd,
3305 u32 xres, u32 yres, u32 format)
3306{
3307 struct mdss_panel_info *pinfo = mfd->panel_info;
3308 struct fb_var_screeninfo *var = &mfd->fbi->var;
3309 struct fb_fix_screeninfo *fix = &mfd->fbi->fix;
3310 struct mdss_mdp_format_params *fmt = NULL;
3311
3312 pinfo->xres = xres;
3313 pinfo->yres = yres;
3314 mfd->fb_imgType = format;
3315 if (mfd->mdp.get_format_params) {
3316 fmt = mfd->mdp.get_format_params(format);
3317 if (fmt) {
3318 pinfo->bpp = fmt->bpp;
3319 var->bits_per_pixel = fmt->bpp * 8;
3320 }
3321 if (mfd->mdp.fb_stride)
3322 fix->line_length = mfd->mdp.fb_stride(mfd->index,
3323 var->xres,
3324 var->bits_per_pixel / 8);
3325 else
3326 fix->line_length = var->xres * var->bits_per_pixel / 8;
3327
3328 }
3329 var->xres_virtual = var->xres;
3330 var->yres_virtual = pinfo->yres * mfd->fb_page;
3331 mdss_panelinfo_to_fb_var(pinfo, var);
3332}
3333
3334int mdss_fb_atomic_commit(struct fb_info *info,
3335 struct mdp_layer_commit *commit, struct file *file)
3336{
3337 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
3338 struct mdp_layer_commit_v1 *commit_v1;
3339 struct mdp_output_layer *output_layer;
3340 struct mdss_panel_info *pinfo;
3341 bool wait_for_finish, wb_change = false;
3342 int ret = -EPERM;
3343 u32 old_xres, old_yres, old_format;
3344
3345 if (!mfd || (!mfd->op_enable)) {
3346 pr_err("mfd is NULL or operation not permitted\n");
3347 return -EPERM;
3348 }
3349
3350 if ((mdss_fb_is_power_off(mfd)) &&
3351 !((mfd->dcm_state == DCM_ENTER) &&
3352 (mfd->panel.type == MIPI_CMD_PANEL))) {
3353 pr_err("commit is not supported when interface is in off state\n");
3354 goto end;
3355 }
3356 pinfo = mfd->panel_info;
3357
3358 /* only supports version 1.0 */
3359 if (commit->version != MDP_COMMIT_VERSION_1_0) {
3360 pr_err("commit version is not supported\n");
3361 goto end;
3362 }
3363
3364 if (!mfd->mdp.pre_commit || !mfd->mdp.atomic_validate) {
3365 pr_err("commit callback is not registered\n");
3366 goto end;
3367 }
3368
3369 commit_v1 = &commit->commit_v1;
3370 if (commit_v1->flags & MDP_VALIDATE_LAYER) {
3371 ret = mdss_fb_wait_for_kickoff(mfd);
3372 if (ret) {
3373 pr_err("wait for kickoff failed\n");
3374 } else {
3375 __ioctl_transition_dyn_mode_state(mfd,
3376 MSMFB_ATOMIC_COMMIT, true, false);
3377 if (mfd->panel.type == WRITEBACK_PANEL) {
3378 output_layer = commit_v1->output_layer;
3379 if (!output_layer) {
3380 pr_err("Output layer is null\n");
3381 goto end;
3382 }
3383 wb_change = !mdss_fb_is_wb_config_same(mfd,
3384 commit_v1->output_layer);
3385 if (wb_change) {
3386 old_xres = pinfo->xres;
3387 old_yres = pinfo->yres;
3388 old_format = mfd->fb_imgType;
3389 mdss_fb_update_resolution(mfd,
3390 output_layer->buffer.width,
3391 output_layer->buffer.height,
3392 output_layer->buffer.format);
3393 }
3394 }
3395 ret = mfd->mdp.atomic_validate(mfd, file, commit_v1);
3396 if (!ret)
3397 mfd->atomic_commit_pending = true;
3398 }
3399 goto end;
3400 } else {
3401 ret = mdss_fb_pan_idle(mfd);
3402 if (ret) {
3403 pr_err("pan display idle call failed\n");
3404 goto end;
3405 }
3406 __ioctl_transition_dyn_mode_state(mfd,
3407 MSMFB_ATOMIC_COMMIT, false,
3408 (commit_v1->input_layer_cnt ? 0 : 1));
3409
3410 ret = mfd->mdp.pre_commit(mfd, file, commit_v1);
3411 if (ret) {
3412 pr_err("atomic pre commit failed\n");
3413 goto end;
3414 }
3415 }
3416
3417 wait_for_finish = commit_v1->flags & MDP_COMMIT_WAIT_FOR_FINISH;
3418 mfd->msm_fb_backup.atomic_commit = true;
3419 mfd->msm_fb_backup.disp_commit.l_roi = commit_v1->left_roi;
3420 mfd->msm_fb_backup.disp_commit.r_roi = commit_v1->right_roi;
3421
3422 mutex_lock(&mfd->mdp_sync_pt_data.sync_mutex);
3423 atomic_inc(&mfd->mdp_sync_pt_data.commit_cnt);
3424 atomic_inc(&mfd->commits_pending);
3425 atomic_inc(&mfd->kickoff_pending);
3426 wake_up_all(&mfd->commit_wait_q);
3427 mutex_unlock(&mfd->mdp_sync_pt_data.sync_mutex);
3428
3429 if (wait_for_finish)
3430 ret = mdss_fb_pan_idle(mfd);
3431
3432end:
3433 if (ret && (mfd->panel.type == WRITEBACK_PANEL) && wb_change)
3434 mdss_fb_update_resolution(mfd, old_xres, old_yres, old_format);
3435 return ret;
3436}
3437
3438static int mdss_fb_pan_display(struct fb_var_screeninfo *var,
3439 struct fb_info *info)
3440{
3441 struct mdp_display_commit disp_commit;
3442 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
3443
3444 /*
3445 * during mode switch through mode sysfs node, it will trigger a
3446 * pan_display after switch. This assumes that fb has been adjusted,
3447 * however when using overlays we may not have the right size at this
3448 * point, so it needs to go through PREPARE first. Abort pan_display
3449 * operations until that happens
3450 */
3451 if (mfd->switch_state != MDSS_MDP_NO_UPDATE_REQUESTED) {
3452 pr_debug("fb%d: pan_display skipped during switch\n",
3453 mfd->index);
3454 return 0;
3455 }
3456
3457 memset(&disp_commit, 0, sizeof(disp_commit));
3458 disp_commit.wait_for_finish = true;
3459 memcpy(&disp_commit.var, var, sizeof(struct fb_var_screeninfo));
3460 return mdss_fb_pan_display_ex(info, &disp_commit);
3461}
3462
3463static int mdss_fb_pan_display_sub(struct fb_var_screeninfo *var,
3464 struct fb_info *info)
3465{
3466 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
3467
3468 if (!mfd->op_enable)
3469 return -EPERM;
3470
3471 if ((mdss_fb_is_power_off(mfd)) &&
3472 !((mfd->dcm_state == DCM_ENTER) &&
3473 (mfd->panel.type == MIPI_CMD_PANEL)))
3474 return -EPERM;
3475
3476 if (var->xoffset > (info->var.xres_virtual - info->var.xres))
3477 return -EINVAL;
3478
3479 if (var->yoffset > (info->var.yres_virtual - info->var.yres))
3480 return -EINVAL;
3481
3482 if (info->fix.xpanstep)
3483 info->var.xoffset =
3484 (var->xoffset / info->fix.xpanstep) * info->fix.xpanstep;
3485
3486 if (info->fix.ypanstep)
3487 info->var.yoffset =
3488 (var->yoffset / info->fix.ypanstep) * info->fix.ypanstep;
3489
3490 if (mfd->mdp.dma_fnc)
3491 mfd->mdp.dma_fnc(mfd);
3492 else
3493 pr_warn("dma function not set for panel type=%d\n",
3494 mfd->panel.type);
3495
3496 return 0;
3497}
3498
3499static int mdss_grayscale_to_mdp_format(u32 grayscale)
3500{
3501 switch (grayscale) {
3502 case V4L2_PIX_FMT_RGB24:
3503 return MDP_RGB_888;
3504 case V4L2_PIX_FMT_NV12:
3505 return MDP_Y_CBCR_H2V2;
3506 default:
3507 return -EINVAL;
3508 }
3509}
3510
3511static void mdss_fb_var_to_panelinfo(struct fb_var_screeninfo *var,
3512 struct mdss_panel_info *pinfo)
3513{
3514 int format = -EINVAL;
3515
3516 pinfo->xres = var->xres;
3517 pinfo->yres = var->yres;
3518 pinfo->lcdc.v_front_porch = var->lower_margin;
3519 pinfo->lcdc.v_back_porch = var->upper_margin;
3520 pinfo->lcdc.v_pulse_width = var->vsync_len;
3521 pinfo->lcdc.h_front_porch = var->right_margin;
3522 pinfo->lcdc.h_back_porch = var->left_margin;
3523 pinfo->lcdc.h_pulse_width = var->hsync_len;
3524
3525 if (var->grayscale > 1) {
3526 format = mdss_grayscale_to_mdp_format(var->grayscale);
Sachin Bhayare3d3767e2018-01-02 21:10:57 +05303527 if (!IS_ERR_VALUE((unsigned long)format))
Sachin Bhayareeeb88892018-01-02 16:36:01 +05303528 pinfo->out_format = format;
3529 else
3530 pr_warn("Failed to map grayscale value (%d) to an MDP format\n",
3531 var->grayscale);
3532 }
3533
3534 /*
3535 * if greater than 1M, then rate would fall below 1mhz which is not
3536 * even supported. In this case it means clock rate is actually
3537 * passed directly in hz.
3538 */
3539 if (var->pixclock > SZ_1M)
3540 pinfo->clk_rate = var->pixclock;
3541 else
3542 pinfo->clk_rate = PICOS2KHZ(var->pixclock) * 1000;
3543
3544 /*
3545 * if it is a DBA panel i.e. HDMI TV connected through
3546 * DSI interface, then store the pixel clock value in
3547 * DSI specific variable.
3548 */
3549 if (pinfo->is_dba_panel)
3550 pinfo->mipi.dsi_pclk_rate = pinfo->clk_rate;
3551}
3552
3553void mdss_panelinfo_to_fb_var(struct mdss_panel_info *pinfo,
3554 struct fb_var_screeninfo *var)
3555{
3556 u32 frame_rate;
3557
3558 var->xres = mdss_fb_get_panel_xres(pinfo);
3559 var->yres = pinfo->yres;
3560 var->lower_margin = pinfo->lcdc.v_front_porch -
3561 pinfo->prg_fet;
3562 var->upper_margin = pinfo->lcdc.v_back_porch +
3563 pinfo->prg_fet;
3564 var->vsync_len = pinfo->lcdc.v_pulse_width;
3565 var->right_margin = pinfo->lcdc.h_front_porch;
3566 var->left_margin = pinfo->lcdc.h_back_porch;
3567 var->hsync_len = pinfo->lcdc.h_pulse_width;
3568
3569 frame_rate = mdss_panel_get_framerate(pinfo,
3570 FPS_RESOLUTION_HZ);
3571 if (frame_rate) {
3572 unsigned long clk_rate, h_total, v_total;
3573
3574 h_total = var->xres + var->left_margin
3575 + var->right_margin + var->hsync_len;
3576 v_total = var->yres + var->lower_margin
3577 + var->upper_margin + var->vsync_len;
3578 clk_rate = h_total * v_total * frame_rate;
3579 var->pixclock = KHZ2PICOS(clk_rate / 1000);
3580 } else if (pinfo->clk_rate) {
3581 var->pixclock = KHZ2PICOS(
3582 (unsigned long int) pinfo->clk_rate / 1000);
3583 }
3584
3585 if (pinfo->physical_width)
3586 var->width = pinfo->physical_width;
3587 if (pinfo->physical_height)
3588 var->height = pinfo->physical_height;
3589
3590 pr_debug("ScreenInfo: res=%dx%d [%d, %d] [%d, %d]\n",
3591 var->xres, var->yres, var->left_margin,
3592 var->right_margin, var->upper_margin,
3593 var->lower_margin);
3594}
3595
3596/**
3597 * __mdss_fb_perform_commit() - process a frame to display
3598 * @mfd: Framebuffer data structure for display
3599 *
3600 * Processes all layers and buffers programmed and ensures all pending release
3601 * fences are signaled once the buffer is transferred to display.
3602 */
3603static int __mdss_fb_perform_commit(struct msm_fb_data_type *mfd)
3604{
3605 struct msm_sync_pt_data *sync_pt_data = &mfd->mdp_sync_pt_data;
3606 struct msm_fb_backup_type *fb_backup = &mfd->msm_fb_backup;
Sachin Bhayare3d3767e2018-01-02 21:10:57 +05303607 int ret = -ENOTSUPP;
Sachin Bhayareeeb88892018-01-02 16:36:01 +05303608 u32 new_dsi_mode, dynamic_dsi_switch = 0;
3609
3610 if (!sync_pt_data->async_wait_fences)
3611 mdss_fb_wait_for_fence(sync_pt_data);
3612 sync_pt_data->flushed = false;
3613
3614 mutex_lock(&mfd->switch_lock);
3615 if (mfd->switch_state == MDSS_MDP_WAIT_FOR_KICKOFF) {
3616 dynamic_dsi_switch = 1;
3617 new_dsi_mode = mfd->switch_new_mode;
3618 } else if (mfd->switch_state != MDSS_MDP_NO_UPDATE_REQUESTED) {
3619 pr_err("invalid commit on fb%d with state = %d\n",
3620 mfd->index, mfd->switch_state);
3621 mutex_unlock(&mfd->switch_lock);
3622 goto skip_commit;
3623 }
3624 mutex_unlock(&mfd->switch_lock);
3625 if (dynamic_dsi_switch) {
3626 MDSS_XLOG(mfd->index, mfd->split_mode, new_dsi_mode,
3627 XLOG_FUNC_ENTRY);
3628 pr_debug("Triggering dyn mode switch to %d\n", new_dsi_mode);
3629 ret = mfd->mdp.mode_switch(mfd, new_dsi_mode);
3630 if (ret)
3631 pr_err("DSI mode switch has failed");
3632 else
3633 mfd->pending_switch = false;
3634 }
3635 if (fb_backup->disp_commit.flags & MDP_DISPLAY_COMMIT_OVERLAY) {
3636 if (mfd->mdp.kickoff_fnc)
3637 ret = mfd->mdp.kickoff_fnc(mfd,
3638 &fb_backup->disp_commit);
3639 else
3640 pr_warn("no kickoff function setup for fb%d\n",
3641 mfd->index);
3642 } else if (fb_backup->atomic_commit) {
3643 if (mfd->mdp.kickoff_fnc)
3644 ret = mfd->mdp.kickoff_fnc(mfd,
3645 &fb_backup->disp_commit);
3646 else
3647 pr_warn("no kickoff function setup for fb%d\n",
3648 mfd->index);
3649 fb_backup->atomic_commit = false;
3650 } else {
3651 ret = mdss_fb_pan_display_sub(&fb_backup->disp_commit.var,
3652 &fb_backup->info);
3653 if (ret)
3654 pr_err("pan display failed %x on fb%d\n", ret,
3655 mfd->index);
3656 }
3657
3658skip_commit:
3659 if (!ret)
3660 mdss_fb_update_backlight(mfd);
3661
Sachin Bhayare3d3767e2018-01-02 21:10:57 +05303662 if (IS_ERR_VALUE((unsigned long)ret) || !sync_pt_data->flushed) {
Sachin Bhayareeeb88892018-01-02 16:36:01 +05303663 mdss_fb_release_kickoff(mfd);
3664 mdss_fb_signal_timeline(sync_pt_data);
3665 if ((mfd->panel.type == MIPI_CMD_PANEL) &&
3666 (mfd->mdp.signal_retire_fence))
3667 mfd->mdp.signal_retire_fence(mfd, 1);
3668 }
3669
3670 if (dynamic_dsi_switch) {
3671 MDSS_XLOG(mfd->index, mfd->split_mode, new_dsi_mode,
3672 XLOG_FUNC_EXIT);
3673 mfd->mdp.mode_switch_post(mfd, new_dsi_mode);
3674 mutex_lock(&mfd->switch_lock);
3675 mfd->switch_state = MDSS_MDP_NO_UPDATE_REQUESTED;
3676 mutex_unlock(&mfd->switch_lock);
3677 if (new_dsi_mode != SWITCH_RESOLUTION)
3678 mfd->panel.type = new_dsi_mode;
3679 pr_debug("Dynamic mode switch completed\n");
3680 }
3681
3682 return ret;
3683}
3684
3685static int __mdss_fb_display_thread(void *data)
3686{
3687 struct msm_fb_data_type *mfd = data;
3688 int ret;
3689 struct sched_param param;
3690
3691 /*
3692 * this priority was found during empiric testing to have appropriate
3693 * realtime scheduling to process display updates and interact with
3694 * other real time and normal priority tasks
3695 */
3696 param.sched_priority = 16;
3697 ret = sched_setscheduler(current, SCHED_FIFO, &param);
3698 if (ret)
3699 pr_warn("set priority failed for fb%d display thread\n",
3700 mfd->index);
3701
3702 while (1) {
3703 wait_event(mfd->commit_wait_q,
3704 (atomic_read(&mfd->commits_pending) ||
3705 kthread_should_stop()));
3706
3707 if (kthread_should_stop())
3708 break;
3709
3710 MDSS_XLOG(mfd->index, XLOG_FUNC_ENTRY);
3711 ret = __mdss_fb_perform_commit(mfd);
3712 MDSS_XLOG(mfd->index, XLOG_FUNC_EXIT);
3713
3714 atomic_dec(&mfd->commits_pending);
3715 wake_up_all(&mfd->idle_wait_q);
3716 }
3717
3718 mdss_fb_release_kickoff(mfd);
3719 atomic_set(&mfd->commits_pending, 0);
3720 wake_up_all(&mfd->idle_wait_q);
3721
3722 return ret;
3723}
3724
3725static int mdss_fb_check_var(struct fb_var_screeninfo *var,
3726 struct fb_info *info)
3727{
3728 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
3729
3730 if (var->rotate != FB_ROTATE_UR && var->rotate != FB_ROTATE_UD)
3731 return -EINVAL;
3732
3733 switch (var->bits_per_pixel) {
3734 case 16:
3735 if ((var->green.offset != 5) ||
3736 !((var->blue.offset == 11)
3737 || (var->blue.offset == 0)) ||
3738 !((var->red.offset == 11)
3739 || (var->red.offset == 0)) ||
3740 (var->blue.length != 5) ||
3741 (var->green.length != 6) ||
3742 (var->red.length != 5) ||
3743 (var->blue.msb_right != 0) ||
3744 (var->green.msb_right != 0) ||
3745 (var->red.msb_right != 0) ||
3746 (var->transp.offset != 0) ||
3747 (var->transp.length != 0))
3748 return -EINVAL;
3749 break;
3750
3751 case 24:
3752 if ((var->blue.offset != 0) ||
3753 (var->green.offset != 8) ||
3754 (var->red.offset != 16) ||
3755 (var->blue.length != 8) ||
3756 (var->green.length != 8) ||
3757 (var->red.length != 8) ||
3758 (var->blue.msb_right != 0) ||
3759 (var->green.msb_right != 0) ||
3760 (var->red.msb_right != 0) ||
3761 !(((var->transp.offset == 0) &&
3762 (var->transp.length == 0)) ||
3763 ((var->transp.offset == 24) &&
3764 (var->transp.length == 8))))
3765 return -EINVAL;
3766 break;
3767
3768 case 32:
3769 /*
3770 * Check user specified color format BGRA/ARGB/RGBA
3771 * and verify the position of the RGB components
3772 */
3773
3774 if (!((var->transp.offset == 24) &&
3775 (var->blue.offset == 0) &&
3776 (var->green.offset == 8) &&
3777 (var->red.offset == 16)) &&
3778 !((var->transp.offset == 0) &&
3779 (var->blue.offset == 24) &&
3780 (var->green.offset == 16) &&
3781 (var->red.offset == 8)) &&
3782 !((var->transp.offset == 24) &&
3783 (var->blue.offset == 16) &&
3784 (var->green.offset == 8) &&
3785 (var->red.offset == 0)))
3786 return -EINVAL;
3787
3788 /* Check the common values for both RGBA and ARGB */
3789
3790 if ((var->blue.length != 8) ||
3791 (var->green.length != 8) ||
3792 (var->red.length != 8) ||
3793 (var->transp.length != 8) ||
3794 (var->blue.msb_right != 0) ||
3795 (var->green.msb_right != 0) ||
3796 (var->red.msb_right != 0))
3797 return -EINVAL;
3798
3799 break;
3800
3801 default:
3802 return -EINVAL;
3803 }
3804
3805 if ((var->xres_virtual <= 0) || (var->yres_virtual <= 0))
3806 return -EINVAL;
3807
3808 if ((var->xres == 0) || (var->yres == 0))
3809 return -EINVAL;
3810
3811 if (var->xoffset > (var->xres_virtual - var->xres))
3812 return -EINVAL;
3813
3814 if (var->yoffset > (var->yres_virtual - var->yres))
3815 return -EINVAL;
3816
3817 if (info->mode) {
3818 const struct fb_videomode *mode;
3819
3820 mode = fb_match_mode(var, &info->modelist);
3821 if (mode == NULL)
3822 return -EINVAL;
3823 } else if (mfd->panel_info && !(var->activate & FB_ACTIVATE_TEST)) {
3824 struct mdss_panel_info *panel_info;
3825 int rc;
3826
3827 panel_info = kzalloc(sizeof(struct mdss_panel_info),
3828 GFP_KERNEL);
3829 if (!panel_info)
3830 return -ENOMEM;
3831
3832 memcpy(panel_info, mfd->panel_info,
3833 sizeof(struct mdss_panel_info));
3834 mdss_fb_var_to_panelinfo(var, panel_info);
3835 rc = mdss_fb_send_panel_event(mfd, MDSS_EVENT_CHECK_PARAMS,
3836 panel_info);
Sachin Bhayare3d3767e2018-01-02 21:10:57 +05303837 if (IS_ERR_VALUE((unsigned long)rc)) {
Sachin Bhayareeeb88892018-01-02 16:36:01 +05303838 kfree(panel_info);
3839 return rc;
3840 }
3841 mfd->panel_reconfig = rc;
3842 kfree(panel_info);
3843 }
3844
3845 return 0;
3846}
3847
3848static int mdss_fb_videomode_switch(struct msm_fb_data_type *mfd,
3849 const struct fb_videomode *mode)
3850{
3851 int ret = 0;
3852 struct mdss_panel_data *pdata, *tmp;
3853 struct mdss_panel_timing *timing;
3854
3855 pdata = dev_get_platdata(&mfd->pdev->dev);
3856 if (!pdata) {
3857 pr_err("no panel connected\n");
3858 return -ENODEV;
3859 }
3860
3861 /* make sure that we are idle while switching */
3862 mdss_fb_wait_for_kickoff(mfd);
3863
3864 pr_debug("fb%d: changing display mode to %s\n", mfd->index, mode->name);
3865 MDSS_XLOG(mfd->index, mode->name,
3866 mdss_fb_get_panel_xres(mfd->panel_info),
3867 mfd->panel_info->yres, mfd->split_mode,
3868 XLOG_FUNC_ENTRY);
3869 tmp = pdata;
3870 do {
3871 if (!tmp->event_handler) {
3872 pr_warn("no event handler for panel\n");
3873 continue;
3874 }
3875 timing = mdss_panel_get_timing_by_name(tmp, mode->name);
3876 ret = tmp->event_handler(tmp,
3877 MDSS_EVENT_PANEL_TIMING_SWITCH, timing);
3878
3879 tmp->active = timing != NULL;
3880 tmp = tmp->next;
3881 } while (tmp && !ret);
3882
3883 if (!ret)
3884 mdss_fb_set_split_mode(mfd, pdata);
3885
3886 if (!ret && mfd->mdp.configure_panel) {
3887 int dest_ctrl = 1;
3888
3889 /* todo: currently assumes no changes in video/cmd mode */
3890 if (!mdss_fb_is_power_off(mfd)) {
3891 mutex_lock(&mfd->switch_lock);
3892 mfd->switch_state = MDSS_MDP_WAIT_FOR_VALIDATE;
3893 mfd->switch_new_mode = SWITCH_RESOLUTION;
3894 mutex_unlock(&mfd->switch_lock);
3895 dest_ctrl = 0;
3896 }
3897 ret = mfd->mdp.configure_panel(mfd,
3898 pdata->panel_info.mipi.mode, dest_ctrl);
3899 }
3900
3901 MDSS_XLOG(mfd->index, mode->name,
3902 mdss_fb_get_panel_xres(mfd->panel_info),
3903 mfd->panel_info->yres, mfd->split_mode,
3904 XLOG_FUNC_EXIT);
3905 pr_debug("fb%d: %s mode change complete\n", mfd->index, mode->name);
3906
3907 return ret;
3908}
3909
3910static int mdss_fb_set_par(struct fb_info *info)
3911{
3912 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
3913 struct fb_var_screeninfo *var = &info->var;
3914 int old_imgType, old_format;
3915 int ret = 0;
3916
3917 ret = mdss_fb_pan_idle(mfd);
3918 if (ret) {
3919 pr_err("mdss_fb_pan_idle failed. rc=%d\n", ret);
3920 return ret;
3921 }
3922
3923 old_imgType = mfd->fb_imgType;
3924 switch (var->bits_per_pixel) {
3925 case 16:
3926 if (var->red.offset == 0)
3927 mfd->fb_imgType = MDP_BGR_565;
3928 else
3929 mfd->fb_imgType = MDP_RGB_565;
3930 break;
3931
3932 case 24:
3933 if ((var->transp.offset == 0) && (var->transp.length == 0))
3934 mfd->fb_imgType = MDP_RGB_888;
3935 else if ((var->transp.offset == 24) &&
3936 (var->transp.length == 8)) {
3937 mfd->fb_imgType = MDP_ARGB_8888;
3938 info->var.bits_per_pixel = 32;
3939 }
3940 break;
3941
3942 case 32:
3943 if ((var->red.offset == 0) &&
3944 (var->green.offset == 8) &&
3945 (var->blue.offset == 16) &&
3946 (var->transp.offset == 24))
3947 mfd->fb_imgType = MDP_RGBA_8888;
3948 else if ((var->red.offset == 16) &&
3949 (var->green.offset == 8) &&
3950 (var->blue.offset == 0) &&
3951 (var->transp.offset == 24))
3952 mfd->fb_imgType = MDP_BGRA_8888;
3953 else if ((var->red.offset == 8) &&
3954 (var->green.offset == 16) &&
3955 (var->blue.offset == 24) &&
3956 (var->transp.offset == 0))
3957 mfd->fb_imgType = MDP_ARGB_8888;
3958 else
3959 mfd->fb_imgType = MDP_RGBA_8888;
3960 break;
3961
3962 default:
3963 return -EINVAL;
3964 }
3965
3966 if (info->mode) {
3967 const struct fb_videomode *mode;
3968
3969 mode = fb_match_mode(var, &info->modelist);
3970 if (!mode)
3971 return -EINVAL;
3972
3973 pr_debug("found mode: %s\n", mode->name);
3974
3975 if (fb_mode_is_equal(mode, info->mode)) {
3976 pr_debug("mode is equal to current mode\n");
3977 return 0;
3978 }
3979
3980 ret = mdss_fb_videomode_switch(mfd, mode);
3981 if (ret)
3982 return ret;
3983 }
3984
3985 if (mfd->mdp.fb_stride)
3986 mfd->fbi->fix.line_length = mfd->mdp.fb_stride(mfd->index,
3987 var->xres,
3988 var->bits_per_pixel / 8);
3989 else
3990 mfd->fbi->fix.line_length = var->xres * var->bits_per_pixel / 8;
3991
3992 /* if memory is not allocated yet, change memory size for fb */
3993 if (!info->fix.smem_start)
3994 mfd->fbi->fix.smem_len = PAGE_ALIGN(mfd->fbi->fix.line_length *
3995 mfd->fbi->var.yres) * mfd->fb_page;
3996
3997 old_format = mdss_grayscale_to_mdp_format(var->grayscale);
Sachin Bhayare3d3767e2018-01-02 21:10:57 +05303998 if (!IS_ERR_VALUE((unsigned long)old_format)) {
Sachin Bhayareeeb88892018-01-02 16:36:01 +05303999 if (old_format != mfd->panel_info->out_format)
4000 mfd->panel_reconfig = true;
4001 }
4002
4003 if (mfd->panel_reconfig || (mfd->fb_imgType != old_imgType)) {
4004 mdss_fb_blank_sub(FB_BLANK_POWERDOWN, info, mfd->op_enable);
4005 mdss_fb_var_to_panelinfo(var, mfd->panel_info);
4006 if (mfd->panel_info->is_dba_panel &&
4007 mdss_fb_send_panel_event(mfd, MDSS_EVENT_UPDATE_PARAMS,
4008 mfd->panel_info))
4009 pr_debug("Failed to send panel event UPDATE_PARAMS\n");
4010 mdss_fb_blank_sub(FB_BLANK_UNBLANK, info, mfd->op_enable);
4011 mfd->panel_reconfig = false;
4012 }
4013
4014 return ret;
4015}
4016
4017int mdss_fb_dcm(struct msm_fb_data_type *mfd, int req_state)
4018{
4019 int ret = 0;
4020
4021 if (req_state == mfd->dcm_state) {
4022 pr_warn("Already in correct DCM/DTM state\n");
4023 return ret;
4024 }
4025
4026 switch (req_state) {
4027 case DCM_UNBLANK:
4028 if (mfd->dcm_state == DCM_UNINIT &&
4029 mdss_fb_is_power_off(mfd) && mfd->mdp.on_fnc) {
4030 if (mfd->disp_thread == NULL) {
4031 ret = mdss_fb_start_disp_thread(mfd);
4032 if (ret < 0)
4033 return ret;
4034 }
4035 ret = mfd->mdp.on_fnc(mfd);
4036 if (ret == 0) {
4037 mfd->panel_power_state = MDSS_PANEL_POWER_ON;
4038 mfd->dcm_state = DCM_UNBLANK;
4039 }
4040 }
4041 break;
4042 case DCM_ENTER:
4043 if (mfd->dcm_state == DCM_UNBLANK) {
4044 /*
4045 * Keep unblank path available for only
4046 * DCM operation
4047 */
4048 mfd->panel_power_state = MDSS_PANEL_POWER_OFF;
4049 mfd->dcm_state = DCM_ENTER;
4050 }
4051 break;
4052 case DCM_EXIT:
4053 if (mfd->dcm_state == DCM_ENTER) {
4054 /* Release the unblank path for exit */
4055 mfd->panel_power_state = MDSS_PANEL_POWER_ON;
4056 mfd->dcm_state = DCM_EXIT;
4057 }
4058 break;
4059 case DCM_BLANK:
4060 if ((mfd->dcm_state == DCM_EXIT ||
4061 mfd->dcm_state == DCM_UNBLANK) &&
4062 mdss_fb_is_power_on(mfd) && mfd->mdp.off_fnc) {
4063 mfd->panel_power_state = MDSS_PANEL_POWER_OFF;
4064 ret = mfd->mdp.off_fnc(mfd);
4065 if (ret == 0)
4066 mfd->dcm_state = DCM_UNINIT;
4067 else
4068 pr_err("DCM_BLANK failed\n");
4069
4070 if (mfd->disp_thread)
4071 mdss_fb_stop_disp_thread(mfd);
4072 }
4073 break;
4074 case DTM_ENTER:
4075 if (mfd->dcm_state == DCM_UNINIT)
4076 mfd->dcm_state = DTM_ENTER;
4077 break;
4078 case DTM_EXIT:
4079 if (mfd->dcm_state == DTM_ENTER)
4080 mfd->dcm_state = DCM_UNINIT;
4081 break;
4082 }
4083
4084 return ret;
4085}
4086
4087static int mdss_fb_cursor(struct fb_info *info, void __user *p)
4088{
4089 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
4090 struct fb_cursor cursor;
4091 int ret;
4092
4093 if (!mfd->mdp.cursor_update)
4094 return -ENODEV;
4095
4096 ret = copy_from_user(&cursor, p, sizeof(cursor));
4097 if (ret)
4098 return ret;
4099
4100 return mfd->mdp.cursor_update(mfd, &cursor);
4101}
4102
4103int mdss_fb_async_position_update(struct fb_info *info,
4104 struct mdp_position_update *update_pos)
4105{
4106 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
4107
4108 if (!update_pos->input_layer_cnt) {
4109 pr_err("no input layers for position update\n");
4110 return -EINVAL;
4111 }
4112 return mfd->mdp.async_position_update(mfd, update_pos);
4113}
4114
4115static int mdss_fb_async_position_update_ioctl(struct fb_info *info,
4116 unsigned long *argp)
4117{
4118 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
4119 struct mdp_position_update update_pos;
4120 int ret, rc;
4121 u32 buffer_size, layer_cnt;
4122 struct mdp_async_layer *layer_list = NULL;
4123 struct mdp_async_layer __user *input_layer_list;
4124
4125 if (!mfd->mdp.async_position_update)
4126 return -ENODEV;
4127
4128 ret = copy_from_user(&update_pos, argp, sizeof(update_pos));
4129 if (ret) {
4130 pr_err("copy from user failed\n");
4131 return ret;
4132 }
4133 input_layer_list = update_pos.input_layers;
4134
4135 layer_cnt = update_pos.input_layer_cnt;
4136 if ((!layer_cnt) || (layer_cnt > MAX_LAYER_COUNT)) {
4137 pr_err("invalid async layers :%d to update\n", layer_cnt);
4138 return -EINVAL;
4139 }
4140
4141 buffer_size = sizeof(struct mdp_async_layer) * layer_cnt;
4142 layer_list = kmalloc(buffer_size, GFP_KERNEL);
4143 if (!layer_list) {
4144 pr_err("unable to allocate memory for layers\n");
4145 return -ENOMEM;
4146 }
4147
4148 ret = copy_from_user(layer_list, input_layer_list, buffer_size);
4149 if (ret) {
4150 pr_err("layer list copy from user failed\n");
4151 goto end;
4152 }
4153 update_pos.input_layers = layer_list;
4154
4155 ret = mdss_fb_async_position_update(info, &update_pos);
4156 if (ret)
4157 pr_err("async position update failed ret:%d\n", ret);
4158
4159 rc = copy_to_user(input_layer_list, layer_list, buffer_size);
4160 if (rc)
4161 pr_err("layer error code copy to user failed\n");
4162
4163 update_pos.input_layers = input_layer_list;
4164 rc = copy_to_user(argp, &update_pos,
4165 sizeof(struct mdp_position_update));
4166 if (rc)
4167 pr_err("copy to user for layers failed");
4168
4169end:
4170 kfree(layer_list);
4171 return ret;
4172}
4173
4174static int mdss_fb_set_lut(struct fb_info *info, void __user *p)
4175{
4176 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
4177 struct fb_cmap cmap;
4178 int ret;
4179
4180 if (!mfd->mdp.lut_update)
4181 return -ENODEV;
4182
4183 ret = copy_from_user(&cmap, p, sizeof(cmap));
4184 if (ret)
4185 return ret;
4186
4187 mfd->mdp.lut_update(mfd, &cmap);
4188 return 0;
4189}
4190
4191/**
4192 * mdss_fb_sync_get_fence() - get fence from timeline
4193 * @timeline: Timeline to create the fence on
4194 * @fence_name: Name of the fence that will be created for debugging
4195 * @val: Timeline value at which the fence will be signaled
4196 *
4197 * Function returns a fence on the timeline given with the name provided.
4198 * The fence created will be signaled when the timeline is advanced.
4199 */
Sachin Bhayare2b6d0042018-01-13 19:38:21 +05304200struct mdss_fence *mdss_fb_sync_get_fence(struct mdss_timeline *timeline,
Sachin Bhayareeeb88892018-01-02 16:36:01 +05304201 const char *fence_name, int val)
4202{
Sachin Bhayare2b6d0042018-01-13 19:38:21 +05304203 struct mdss_fence *fence;
Sachin Bhayareeeb88892018-01-02 16:36:01 +05304204
Sachin Bhayareeeb88892018-01-02 16:36:01 +05304205
Sachin Bhayare2b6d0042018-01-13 19:38:21 +05304206 fence = mdss_get_sync_fence(timeline, fence_name, NULL, val);
4207 pr_debug("%s: buf sync fence timeline=%d\n",
4208 mdss_get_sync_fence_name(fence), val);
Sachin Bhayareeeb88892018-01-02 16:36:01 +05304209 if (fence == NULL) {
Sachin Bhayareeeb88892018-01-02 16:36:01 +05304210 pr_err("%s: cannot create fence\n", fence_name);
4211 return NULL;
4212 }
4213
4214 return fence;
4215}
4216
4217static int mdss_fb_handle_buf_sync_ioctl(struct msm_sync_pt_data *sync_pt_data,
4218 struct mdp_buf_sync *buf_sync)
4219{
4220 int i, ret = 0;
4221 int acq_fen_fd[MDP_MAX_FENCE_FD];
Sachin Bhayare2b6d0042018-01-13 19:38:21 +05304222 struct mdss_fence *fence, *rel_fence, *retire_fence;
Sachin Bhayareeeb88892018-01-02 16:36:01 +05304223 int rel_fen_fd;
4224 int retire_fen_fd;
4225 int val;
4226
4227 if ((buf_sync->acq_fen_fd_cnt > MDP_MAX_FENCE_FD) ||
4228 (sync_pt_data->timeline == NULL))
4229 return -EINVAL;
4230
4231 if (buf_sync->acq_fen_fd_cnt)
4232 ret = copy_from_user(acq_fen_fd, buf_sync->acq_fen_fd,
4233 buf_sync->acq_fen_fd_cnt * sizeof(int));
4234 if (ret) {
4235 pr_err("%s: copy_from_user failed\n", sync_pt_data->fence_name);
4236 return ret;
4237 }
4238
4239 i = mdss_fb_wait_for_fence(sync_pt_data);
4240 if (i > 0)
4241 pr_warn("%s: waited on %d active fences\n",
4242 sync_pt_data->fence_name, i);
4243
4244 mutex_lock(&sync_pt_data->sync_mutex);
4245 for (i = 0; i < buf_sync->acq_fen_fd_cnt; i++) {
Sachin Bhayare2b6d0042018-01-13 19:38:21 +05304246 fence = mdss_get_fd_sync_fence(acq_fen_fd[i]);
Sachin Bhayareeeb88892018-01-02 16:36:01 +05304247 if (fence == NULL) {
4248 pr_err("%s: null fence! i=%d fd=%d\n",
4249 sync_pt_data->fence_name, i,
4250 acq_fen_fd[i]);
4251 ret = -EINVAL;
4252 break;
4253 }
4254 sync_pt_data->acq_fen[i] = fence;
4255 }
4256 sync_pt_data->acq_fen_cnt = i;
4257 if (ret)
4258 goto buf_sync_err_1;
4259
Sachin Bhayare2b6d0042018-01-13 19:38:21 +05304260 val = sync_pt_data->threshold +
Sachin Bhayareeeb88892018-01-02 16:36:01 +05304261 atomic_read(&sync_pt_data->commit_cnt);
4262
4263 MDSS_XLOG(sync_pt_data->timeline_value, val,
4264 atomic_read(&sync_pt_data->commit_cnt));
4265 pr_debug("%s: fence CTL%d Commit_cnt%d\n", sync_pt_data->fence_name,
4266 sync_pt_data->timeline_value,
4267 atomic_read(&sync_pt_data->commit_cnt));
4268 /* Set release fence */
4269 rel_fence = mdss_fb_sync_get_fence(sync_pt_data->timeline,
4270 sync_pt_data->fence_name, val);
4271 if (IS_ERR_OR_NULL(rel_fence)) {
4272 pr_err("%s: unable to retrieve release fence\n",
4273 sync_pt_data->fence_name);
4274 ret = rel_fence ? PTR_ERR(rel_fence) : -ENOMEM;
4275 goto buf_sync_err_1;
4276 }
4277
4278 /* create fd */
Sachin Bhayare2b6d0042018-01-13 19:38:21 +05304279 rel_fen_fd = mdss_get_sync_fence_fd(rel_fence);
Sachin Bhayareeeb88892018-01-02 16:36:01 +05304280 if (rel_fen_fd < 0) {
4281 pr_err("%s: get_unused_fd_flags failed error:0x%x\n",
4282 sync_pt_data->fence_name, rel_fen_fd);
4283 ret = rel_fen_fd;
4284 goto buf_sync_err_2;
4285 }
4286
4287 ret = copy_to_user(buf_sync->rel_fen_fd, &rel_fen_fd, sizeof(int));
4288 if (ret) {
4289 pr_err("%s: copy_to_user failed\n", sync_pt_data->fence_name);
4290 goto buf_sync_err_3;
4291 }
4292
4293 if (!(buf_sync->flags & MDP_BUF_SYNC_FLAG_RETIRE_FENCE))
4294 goto skip_retire_fence;
4295
4296 if (sync_pt_data->get_retire_fence)
4297 retire_fence = sync_pt_data->get_retire_fence(sync_pt_data);
4298 else
4299 retire_fence = NULL;
4300
4301 if (IS_ERR_OR_NULL(retire_fence)) {
4302 val += sync_pt_data->retire_threshold;
4303 retire_fence = mdss_fb_sync_get_fence(
4304 sync_pt_data->timeline, "mdp-retire", val);
4305 }
4306
4307 if (IS_ERR_OR_NULL(retire_fence)) {
4308 pr_err("%s: unable to retrieve retire fence\n",
4309 sync_pt_data->fence_name);
4310 ret = retire_fence ? PTR_ERR(rel_fence) : -ENOMEM;
4311 goto buf_sync_err_3;
4312 }
Sachin Bhayare2b6d0042018-01-13 19:38:21 +05304313 retire_fen_fd = mdss_get_sync_fence_fd(retire_fence);
Sachin Bhayareeeb88892018-01-02 16:36:01 +05304314
4315 if (retire_fen_fd < 0) {
4316 pr_err("%s: get_unused_fd_flags failed for retire fence error:0x%x\n",
4317 sync_pt_data->fence_name, retire_fen_fd);
4318 ret = retire_fen_fd;
Sachin Bhayare2b6d0042018-01-13 19:38:21 +05304319 mdss_put_sync_fence(retire_fence);
Sachin Bhayareeeb88892018-01-02 16:36:01 +05304320 goto buf_sync_err_3;
4321 }
4322
4323 ret = copy_to_user(buf_sync->retire_fen_fd, &retire_fen_fd,
4324 sizeof(int));
4325 if (ret) {
4326 pr_err("%s: copy_to_user failed for retire fence\n",
4327 sync_pt_data->fence_name);
4328 put_unused_fd(retire_fen_fd);
Sachin Bhayare2b6d0042018-01-13 19:38:21 +05304329 mdss_put_sync_fence(retire_fence);
Sachin Bhayareeeb88892018-01-02 16:36:01 +05304330 goto buf_sync_err_3;
4331 }
4332
Sachin Bhayareeeb88892018-01-02 16:36:01 +05304333skip_retire_fence:
Sachin Bhayare2b6d0042018-01-13 19:38:21 +05304334 mdss_get_sync_fence_fd(rel_fence);
Sachin Bhayareeeb88892018-01-02 16:36:01 +05304335 mutex_unlock(&sync_pt_data->sync_mutex);
4336
4337 if (buf_sync->flags & MDP_BUF_SYNC_FLAG_WAIT)
4338 mdss_fb_wait_for_fence(sync_pt_data);
4339
4340 return ret;
4341buf_sync_err_3:
4342 put_unused_fd(rel_fen_fd);
4343buf_sync_err_2:
Sachin Bhayare2b6d0042018-01-13 19:38:21 +05304344 mdss_put_sync_fence(rel_fence);
Sachin Bhayareeeb88892018-01-02 16:36:01 +05304345buf_sync_err_1:
4346 for (i = 0; i < sync_pt_data->acq_fen_cnt; i++)
Sachin Bhayare2b6d0042018-01-13 19:38:21 +05304347 mdss_put_sync_fence(sync_pt_data->acq_fen[i]);
Sachin Bhayareeeb88892018-01-02 16:36:01 +05304348 sync_pt_data->acq_fen_cnt = 0;
4349 mutex_unlock(&sync_pt_data->sync_mutex);
4350 return ret;
4351}
4352static int mdss_fb_display_commit(struct fb_info *info,
4353 unsigned long *argp)
4354{
4355 int ret;
4356 struct mdp_display_commit disp_commit;
4357
4358 ret = copy_from_user(&disp_commit, argp,
4359 sizeof(disp_commit));
4360 if (ret) {
4361 pr_err("%s:copy_from_user failed\n", __func__);
4362 return ret;
4363 }
4364 ret = mdss_fb_pan_display_ex(info, &disp_commit);
4365 return ret;
4366}
4367
4368/**
4369 * __mdss_fb_copy_pixel_ext() - copy pixel extension payload
4370 * @src: pixel extn structure
4371 * @dest: Qseed3/pixel extn common payload
4372 *
4373 * Function copies the pixel extension parameters into the scale data structure,
4374 * this is required to allow using the scale_v2 data structure for both
4375 * QSEED2 and QSEED3
4376 */
4377static void __mdss_fb_copy_pixel_ext(struct mdp_scale_data *src,
4378 struct mdp_scale_data_v2 *dest)
4379{
4380 if (!src || !dest)
4381 return;
4382 memcpy(dest->init_phase_x, src->init_phase_x,
4383 sizeof(src->init_phase_x));
4384 memcpy(dest->phase_step_x, src->phase_step_x,
4385 sizeof(src->init_phase_x));
4386 memcpy(dest->init_phase_y, src->init_phase_y,
4387 sizeof(src->init_phase_x));
4388 memcpy(dest->phase_step_y, src->phase_step_y,
4389 sizeof(src->init_phase_x));
4390
4391 memcpy(dest->num_ext_pxls_left, src->num_ext_pxls_left,
4392 sizeof(src->num_ext_pxls_left));
4393 memcpy(dest->num_ext_pxls_right, src->num_ext_pxls_right,
4394 sizeof(src->num_ext_pxls_right));
4395 memcpy(dest->num_ext_pxls_top, src->num_ext_pxls_top,
4396 sizeof(src->num_ext_pxls_top));
4397 memcpy(dest->num_ext_pxls_btm, src->num_ext_pxls_btm,
4398 sizeof(src->num_ext_pxls_btm));
4399
4400 memcpy(dest->left_ftch, src->left_ftch, sizeof(src->left_ftch));
4401 memcpy(dest->left_rpt, src->left_rpt, sizeof(src->left_rpt));
4402 memcpy(dest->right_ftch, src->right_ftch, sizeof(src->right_ftch));
4403 memcpy(dest->right_rpt, src->right_rpt, sizeof(src->right_rpt));
4404
4405
4406 memcpy(dest->top_rpt, src->top_rpt, sizeof(src->top_rpt));
4407 memcpy(dest->btm_rpt, src->btm_rpt, sizeof(src->btm_rpt));
4408 memcpy(dest->top_ftch, src->top_ftch, sizeof(src->top_ftch));
4409 memcpy(dest->btm_ftch, src->btm_ftch, sizeof(src->btm_ftch));
4410
4411 memcpy(dest->roi_w, src->roi_w, sizeof(src->roi_w));
4412}
4413
4414static int __mdss_fb_scaler_handler(struct mdp_input_layer *layer)
4415{
4416 int ret = 0;
4417 struct mdp_scale_data *pixel_ext = NULL;
4418 struct mdp_scale_data_v2 *scale = NULL;
4419
4420 if ((layer->flags & MDP_LAYER_ENABLE_PIXEL_EXT) &&
4421 (layer->flags & MDP_LAYER_ENABLE_QSEED3_SCALE)) {
4422 pr_err("Invalid flag configuration for scaler, %x\n",
4423 layer->flags);
4424 ret = -EINVAL;
4425 goto err;
4426 }
4427
4428 if (layer->flags & MDP_LAYER_ENABLE_PIXEL_EXT) {
4429 scale = kzalloc(sizeof(struct mdp_scale_data_v2),
4430 GFP_KERNEL);
4431 pixel_ext = kzalloc(sizeof(struct mdp_scale_data),
4432 GFP_KERNEL);
4433 if (!scale || !pixel_ext) {
4434 mdss_mdp_free_layer_pp_info(layer);
4435 ret = -ENOMEM;
4436 goto err;
4437 }
4438 ret = copy_from_user(pixel_ext, layer->scale,
4439 sizeof(struct mdp_scale_data));
4440 if (ret) {
4441 mdss_mdp_free_layer_pp_info(layer);
4442 ret = -EFAULT;
4443 goto err;
4444 }
4445 __mdss_fb_copy_pixel_ext(pixel_ext, scale);
4446 layer->scale = scale;
4447 } else if (layer->flags & MDP_LAYER_ENABLE_QSEED3_SCALE) {
4448 scale = kzalloc(sizeof(struct mdp_scale_data_v2),
4449 GFP_KERNEL);
4450 if (!scale) {
4451 mdss_mdp_free_layer_pp_info(layer);
4452 ret = -ENOMEM;
4453 goto err;
4454 }
4455
4456 ret = copy_from_user(scale, layer->scale,
4457 sizeof(struct mdp_scale_data_v2));
4458 if (ret) {
4459 mdss_mdp_free_layer_pp_info(layer);
4460 ret = -EFAULT;
4461 goto err;
4462 }
4463 layer->scale = scale;
4464 } else {
4465 layer->scale = NULL;
4466 }
4467 kfree(pixel_ext);
4468 return ret;
4469err:
4470 kfree(pixel_ext);
4471 kfree(scale);
4472 layer->scale = NULL;
4473 return ret;
4474}
4475
4476static int mdss_fb_atomic_commit_ioctl(struct fb_info *info,
4477 unsigned long *argp, struct file *file)
4478{
4479 int ret, i = 0, j = 0, rc;
4480 struct mdp_layer_commit commit;
4481 u32 buffer_size, layer_count;
4482 struct mdp_input_layer *layer, *layer_list = NULL;
4483 struct mdp_input_layer __user *input_layer_list;
4484 struct mdp_output_layer *output_layer = NULL;
4485 struct mdp_output_layer __user *output_layer_user;
4486 struct mdp_frc_info *frc_info = NULL;
4487 struct mdp_frc_info __user *frc_info_user;
4488 struct msm_fb_data_type *mfd;
4489 struct mdss_overlay_private *mdp5_data = NULL;
4490
4491 ret = copy_from_user(&commit, argp, sizeof(struct mdp_layer_commit));
4492 if (ret) {
4493 pr_err("%s:copy_from_user failed\n", __func__);
4494 return ret;
4495 }
4496
4497 mfd = (struct msm_fb_data_type *)info->par;
4498 if (!mfd)
4499 return -EINVAL;
4500
4501 mdp5_data = mfd_to_mdp5_data(mfd);
4502
4503 if (mfd->panel_info->panel_dead) {
4504 pr_debug("early commit return\n");
4505 MDSS_XLOG(mfd->panel_info->panel_dead);
4506 /*
4507 * In case of an ESD attack, since we early return from the
4508 * commits, we need to signal the outstanding fences.
4509 */
4510 mdss_fb_release_fences(mfd);
4511 if ((mfd->panel.type == MIPI_CMD_PANEL) &&
4512 mfd->mdp.signal_retire_fence && mdp5_data)
4513 mfd->mdp.signal_retire_fence(mfd,
4514 mdp5_data->retire_cnt);
4515 return 0;
4516 }
4517
4518 output_layer_user = commit.commit_v1.output_layer;
4519 if (output_layer_user) {
4520 buffer_size = sizeof(struct mdp_output_layer);
4521 output_layer = kzalloc(buffer_size, GFP_KERNEL);
4522 if (!output_layer) {
4523 pr_err("unable to allocate memory for output layer\n");
4524 return -ENOMEM;
4525 }
4526
4527 ret = copy_from_user(output_layer,
4528 output_layer_user, buffer_size);
4529 if (ret) {
4530 pr_err("layer list copy from user failed\n");
4531 goto err;
4532 }
4533 commit.commit_v1.output_layer = output_layer;
4534 }
4535
4536 layer_count = commit.commit_v1.input_layer_cnt;
4537 input_layer_list = commit.commit_v1.input_layers;
4538
4539 if (layer_count > MAX_LAYER_COUNT) {
4540 ret = -EINVAL;
4541 goto err;
4542 } else if (layer_count) {
4543 buffer_size = sizeof(struct mdp_input_layer) * layer_count;
4544 layer_list = kzalloc(buffer_size, GFP_KERNEL);
4545 if (!layer_list) {
4546 pr_err("unable to allocate memory for layers\n");
4547 ret = -ENOMEM;
4548 goto err;
4549 }
4550
4551 ret = copy_from_user(layer_list, input_layer_list, buffer_size);
4552 if (ret) {
4553 pr_err("layer list copy from user failed\n");
4554 goto err;
4555 }
4556
4557 commit.commit_v1.input_layers = layer_list;
4558
4559 for (i = 0; i < layer_count; i++) {
4560 layer = &layer_list[i];
4561
4562 if (!(layer->flags & MDP_LAYER_PP)) {
4563 layer->pp_info = NULL;
4564 } else {
4565 ret = mdss_mdp_copy_layer_pp_info(layer);
4566 if (ret) {
4567 pr_err("failure to copy pp_info data for layer %d, ret = %d\n",
4568 i, ret);
4569 goto err;
4570 }
4571 }
4572
4573 if ((layer->flags & MDP_LAYER_ENABLE_PIXEL_EXT) ||
4574 (layer->flags &
4575 MDP_LAYER_ENABLE_QSEED3_SCALE)) {
4576 ret = __mdss_fb_scaler_handler(layer);
4577 if (ret) {
4578 pr_err("failure to copy scale params for layer %d, ret = %d\n",
4579 i, ret);
4580 goto err;
4581 }
4582 } else {
4583 layer->scale = NULL;
4584 }
4585 }
4586 }
4587
4588 /* Copy Deterministic Frame Rate Control info from userspace */
4589 frc_info_user = commit.commit_v1.frc_info;
4590 if (frc_info_user) {
4591 frc_info = kzalloc(sizeof(struct mdp_frc_info), GFP_KERNEL);
4592 if (!frc_info) {
4593 pr_err("unable to allocate memory for frc\n");
4594 ret = -ENOMEM;
4595 goto err;
4596 }
4597
4598 ret = copy_from_user(frc_info, frc_info_user,
4599 sizeof(struct mdp_frc_info));
4600 if (ret) {
4601 pr_err("frc info copy from user failed\n");
4602 goto frc_err;
4603 }
4604
4605 commit.commit_v1.frc_info = frc_info;
4606 }
4607
4608 ATRACE_BEGIN("ATOMIC_COMMIT");
4609 ret = mdss_fb_atomic_commit(info, &commit, file);
4610 if (ret)
4611 pr_err("atomic commit failed ret:%d\n", ret);
4612 ATRACE_END("ATOMIC_COMMIT");
4613
4614 if (layer_count) {
4615 for (j = 0; j < layer_count; j++) {
4616 rc = copy_to_user(&input_layer_list[j].error_code,
4617 &layer_list[j].error_code, sizeof(int));
4618 if (rc)
4619 pr_err("layer error code copy to user failed\n");
4620 }
4621
4622 commit.commit_v1.input_layers = input_layer_list;
4623 commit.commit_v1.output_layer = output_layer_user;
4624 commit.commit_v1.frc_info = frc_info_user;
4625 rc = copy_to_user(argp, &commit,
4626 sizeof(struct mdp_layer_commit));
4627 if (rc)
4628 pr_err("copy to user for release & retire fence failed\n");
4629 }
4630
4631frc_err:
4632 kfree(frc_info);
4633err:
4634 for (i--; i >= 0; i--) {
4635 kfree(layer_list[i].scale);
4636 layer_list[i].scale = NULL;
4637 mdss_mdp_free_layer_pp_info(&layer_list[i]);
4638 }
4639 kfree(layer_list);
4640 kfree(output_layer);
4641
4642 return ret;
4643}
4644
4645int mdss_fb_switch_check(struct msm_fb_data_type *mfd, u32 mode)
4646{
4647 struct mdss_panel_info *pinfo = NULL;
4648 int panel_type;
4649
4650 if (!mfd || !mfd->panel_info)
4651 return -EINVAL;
4652
4653 pinfo = mfd->panel_info;
4654
4655 if ((!mfd->op_enable) || (mdss_fb_is_power_off(mfd)))
4656 return -EPERM;
4657
4658 if (pinfo->mipi.dms_mode != DYNAMIC_MODE_SWITCH_IMMEDIATE) {
4659 pr_warn("Panel does not support immediate dynamic switch!\n");
4660 return -EPERM;
4661 }
4662
4663 if (mfd->dcm_state != DCM_UNINIT) {
4664 pr_warn("Switch not supported during DCM!\n");
4665 return -EPERM;
4666 }
4667
4668 mutex_lock(&mfd->switch_lock);
4669 if (mode == pinfo->type) {
4670 pr_debug("Already in requested mode!\n");
4671 mutex_unlock(&mfd->switch_lock);
4672 return -EPERM;
4673 }
4674 mutex_unlock(&mfd->switch_lock);
4675
4676 panel_type = mfd->panel.type;
4677 if (panel_type != MIPI_VIDEO_PANEL && panel_type != MIPI_CMD_PANEL) {
4678 pr_debug("Panel not in mipi video or cmd mode, cannot change\n");
4679 return -EPERM;
4680 }
4681
4682 return 0;
4683}
4684
4685static int mdss_fb_immediate_mode_switch(struct msm_fb_data_type *mfd, u32 mode)
4686{
4687 int ret;
4688 u32 tranlated_mode;
4689
4690 if (mode)
4691 tranlated_mode = MIPI_CMD_PANEL;
4692 else
4693 tranlated_mode = MIPI_VIDEO_PANEL;
4694
4695 pr_debug("%s: Request to switch to %d,", __func__, tranlated_mode);
4696
4697 ret = mdss_fb_switch_check(mfd, tranlated_mode);
4698 if (ret)
4699 return ret;
4700
4701 mutex_lock(&mfd->switch_lock);
4702 if (mfd->switch_state != MDSS_MDP_NO_UPDATE_REQUESTED) {
4703 pr_err("%s: Mode switch already in progress\n", __func__);
4704 ret = -EAGAIN;
4705 goto exit;
4706 }
4707 mfd->switch_state = MDSS_MDP_WAIT_FOR_VALIDATE;
4708 mfd->switch_new_mode = tranlated_mode;
4709
4710exit:
4711 mutex_unlock(&mfd->switch_lock);
4712 return ret;
4713}
4714
4715/*
4716 * mdss_fb_mode_switch() - Function to change DSI mode
4717 * @mfd: Framebuffer data structure for display
4718 * @mode: Enabled/Disable LowPowerMode
4719 * 1: Switch to Command Mode
4720 * 0: Switch to video Mode
4721 *
4722 * This function is used to change from DSI mode based on the
4723 * argument @mode on the next frame to be displayed.
4724 */
4725static int mdss_fb_mode_switch(struct msm_fb_data_type *mfd, u32 mode)
4726{
4727 struct mdss_panel_info *pinfo = NULL;
4728 int ret = 0;
4729
4730 if (!mfd || !mfd->panel_info)
4731 return -EINVAL;
4732
Veera Sundaram Sankaran7f87b6d2016-09-12 11:10:30 -07004733 /* make sure that we are idle while switching */
4734 mdss_fb_wait_for_kickoff(mfd);
4735
Sachin Bhayareeeb88892018-01-02 16:36:01 +05304736 pinfo = mfd->panel_info;
4737 if (pinfo->mipi.dms_mode == DYNAMIC_MODE_SWITCH_SUSPEND_RESUME) {
4738 ret = mdss_fb_blanking_mode_switch(mfd, mode);
4739 } else if (pinfo->mipi.dms_mode == DYNAMIC_MODE_SWITCH_IMMEDIATE) {
4740 ret = mdss_fb_immediate_mode_switch(mfd, mode);
4741 } else {
4742 pr_warn("Panel does not support dynamic mode switch!\n");
4743 ret = -EPERM;
4744 }
4745
4746 return ret;
4747}
4748
4749static int __ioctl_wait_idle(struct msm_fb_data_type *mfd, u32 cmd)
4750{
4751 int ret = 0;
4752
4753 if (mfd->wait_for_kickoff &&
4754 ((cmd == MSMFB_OVERLAY_PREPARE) ||
4755 (cmd == MSMFB_BUFFER_SYNC) ||
4756 (cmd == MSMFB_OVERLAY_PLAY) ||
4757 (cmd == MSMFB_CURSOR) ||
4758 (cmd == MSMFB_METADATA_GET) ||
4759 (cmd == MSMFB_METADATA_SET) ||
4760 (cmd == MSMFB_OVERLAY_GET) ||
4761 (cmd == MSMFB_OVERLAY_UNSET) ||
4762 (cmd == MSMFB_OVERLAY_SET))) {
4763 ret = mdss_fb_wait_for_kickoff(mfd);
4764 }
4765
4766 if (ret && (ret != -ESHUTDOWN))
4767 pr_err("wait_idle failed. cmd=0x%x rc=%d\n", cmd, ret);
4768
4769 return ret;
4770}
4771
4772#ifdef TARGET_HW_MDSS_MDP3
4773static bool check_not_supported_ioctl(u32 cmd)
4774{
4775 return false;
4776}
4777#else
4778static bool check_not_supported_ioctl(u32 cmd)
4779{
4780 return((cmd == MSMFB_OVERLAY_SET) || (cmd == MSMFB_OVERLAY_UNSET) ||
4781 (cmd == MSMFB_OVERLAY_GET) || (cmd == MSMFB_OVERLAY_PREPARE) ||
4782 (cmd == MSMFB_DISPLAY_COMMIT) || (cmd == MSMFB_OVERLAY_PLAY) ||
4783 (cmd == MSMFB_BUFFER_SYNC) || (cmd == MSMFB_OVERLAY_QUEUE) ||
4784 (cmd == MSMFB_NOTIFY_UPDATE));
4785}
4786#endif
4787
4788/*
4789 * mdss_fb_do_ioctl() - MDSS Framebuffer ioctl function
4790 * @info: pointer to framebuffer info
4791 * @cmd: ioctl command
4792 * @arg: argument to ioctl
4793 *
4794 * This function provides an architecture agnostic implementation
4795 * of the mdss framebuffer ioctl. This function can be called
4796 * by compat ioctl or regular ioctl to handle the supported commands.
4797 */
4798int mdss_fb_do_ioctl(struct fb_info *info, unsigned int cmd,
4799 unsigned long arg, struct file *file)
4800{
4801 struct msm_fb_data_type *mfd;
4802 void __user *argp = (void __user *)arg;
Sachin Bhayare3d3767e2018-01-02 21:10:57 +05304803 int ret = -ENOTSUPP;
Sachin Bhayareeeb88892018-01-02 16:36:01 +05304804 struct mdp_buf_sync buf_sync;
4805 unsigned int dsi_mode = 0;
4806 struct mdss_panel_data *pdata = NULL;
4807
4808 if (!info || !info->par)
4809 return -EINVAL;
4810
4811 mfd = (struct msm_fb_data_type *)info->par;
4812 if (!mfd)
4813 return -EINVAL;
4814
4815 if (mfd->shutdown_pending)
4816 return -ESHUTDOWN;
4817
4818 pdata = dev_get_platdata(&mfd->pdev->dev);
4819 if (!pdata || pdata->panel_info.dynamic_switch_pending)
4820 return -EPERM;
4821
4822 if (check_not_supported_ioctl(cmd)) {
4823 pr_err("Unsupported ioctl\n");
4824 return -EINVAL;
4825 }
4826
4827 atomic_inc(&mfd->ioctl_ref_cnt);
4828
4829 mdss_fb_power_setting_idle(mfd);
4830
4831 ret = __ioctl_wait_idle(mfd, cmd);
4832 if (ret)
4833 goto exit;
4834
4835 switch (cmd) {
4836 case MSMFB_CURSOR:
4837 ret = mdss_fb_cursor(info, argp);
4838 break;
4839
4840 case MSMFB_SET_LUT:
4841 ret = mdss_fb_set_lut(info, argp);
4842 break;
4843
4844 case MSMFB_BUFFER_SYNC:
4845 ret = copy_from_user(&buf_sync, argp, sizeof(buf_sync));
4846 if (ret)
4847 goto exit;
4848
4849 if ((!mfd->op_enable) || (mdss_fb_is_power_off(mfd))) {
4850 ret = -EPERM;
4851 goto exit;
4852 }
4853
4854 ret = mdss_fb_handle_buf_sync_ioctl(&mfd->mdp_sync_pt_data,
4855 &buf_sync);
4856 if (!ret)
4857 ret = copy_to_user(argp, &buf_sync, sizeof(buf_sync));
4858 break;
4859
4860 case MSMFB_NOTIFY_UPDATE:
4861 ret = mdss_fb_notify_update(mfd, argp);
4862 break;
4863
4864 case MSMFB_DISPLAY_COMMIT:
4865 ret = mdss_fb_display_commit(info, argp);
4866 break;
4867
4868 case MSMFB_LPM_ENABLE:
4869 ret = copy_from_user(&dsi_mode, argp, sizeof(dsi_mode));
4870 if (ret) {
4871 pr_err("%s: MSMFB_LPM_ENABLE ioctl failed\n", __func__);
4872 goto exit;
4873 }
4874
4875 ret = mdss_fb_mode_switch(mfd, dsi_mode);
4876 break;
4877 case MSMFB_ATOMIC_COMMIT:
4878 ret = mdss_fb_atomic_commit_ioctl(info, argp, file);
4879 break;
4880
4881 case MSMFB_ASYNC_POSITION_UPDATE:
4882 ret = mdss_fb_async_position_update_ioctl(info, argp);
4883 break;
4884
4885 default:
4886 if (mfd->mdp.ioctl_handler)
4887 ret = mfd->mdp.ioctl_handler(mfd, cmd, argp);
4888 break;
4889 }
4890
Sachin Bhayare3d3767e2018-01-02 21:10:57 +05304891 if (ret == -ENOTSUPP)
Sachin Bhayareeeb88892018-01-02 16:36:01 +05304892 pr_err("unsupported ioctl (%x)\n", cmd);
4893
4894exit:
4895 if (!atomic_dec_return(&mfd->ioctl_ref_cnt))
4896 wake_up_all(&mfd->ioctl_q);
4897
4898 return ret;
4899}
4900
4901static int mdss_fb_ioctl(struct fb_info *info, unsigned int cmd,
4902 unsigned long arg, struct file *file)
4903{
4904 if (!info || !info->par)
4905 return -EINVAL;
4906
4907 return mdss_fb_do_ioctl(info, cmd, arg, file);
4908}
4909
4910static int mdss_fb_register_extra_panel(struct platform_device *pdev,
4911 struct mdss_panel_data *pdata)
4912{
4913 struct mdss_panel_data *fb_pdata;
4914
4915 fb_pdata = dev_get_platdata(&pdev->dev);
4916 if (!fb_pdata) {
4917 pr_err("framebuffer device %s contains invalid panel data\n",
4918 dev_name(&pdev->dev));
4919 return -EINVAL;
4920 }
4921
4922 if (fb_pdata->next) {
4923 pr_err("split panel already setup for framebuffer device %s\n",
4924 dev_name(&pdev->dev));
4925 return -EEXIST;
4926 }
4927
4928 fb_pdata->next = pdata;
4929
4930 return 0;
4931}
4932
4933int mdss_register_panel(struct platform_device *pdev,
4934 struct mdss_panel_data *pdata)
4935{
4936 struct platform_device *fb_pdev, *mdss_pdev;
4937 struct device_node *node = NULL;
4938 int rc = 0;
4939 bool master_panel = true;
4940
4941 if (!pdev || !pdev->dev.of_node) {
4942 pr_err("Invalid device node\n");
4943 return -ENODEV;
4944 }
4945
4946 if (!mdp_instance) {
4947 pr_err("mdss mdp resource not initialized yet\n");
4948 return -EPROBE_DEFER;
4949 }
4950
4951 if (pdata->get_fb_node)
4952 node = pdata->get_fb_node(pdev);
4953
4954 if (!node) {
4955 node = of_parse_phandle(pdev->dev.of_node,
4956 "qcom,mdss-fb-map", 0);
4957 if (!node) {
4958 pr_err("Unable to find fb node for device: %s\n",
4959 pdev->name);
4960 return -ENODEV;
4961 }
4962 }
4963 mdss_pdev = of_find_device_by_node(node->parent);
4964 if (!mdss_pdev) {
4965 pr_err("Unable to find mdss for node: %s\n", node->full_name);
4966 rc = -ENODEV;
4967 goto mdss_notfound;
4968 }
4969
4970 pdata->active = true;
4971 fb_pdev = of_find_device_by_node(node);
4972 if (fb_pdev) {
4973 rc = mdss_fb_register_extra_panel(fb_pdev, pdata);
4974 if (rc == 0)
4975 master_panel = false;
4976 } else {
4977 pr_info("adding framebuffer device %s\n", dev_name(&pdev->dev));
4978 fb_pdev = of_platform_device_create(node, NULL,
4979 &mdss_pdev->dev);
4980 if (fb_pdev)
4981 fb_pdev->dev.platform_data = pdata;
4982 }
4983
4984 if (master_panel && mdp_instance->panel_register_done)
4985 mdp_instance->panel_register_done(pdata);
4986
4987mdss_notfound:
4988 of_node_put(node);
4989 return rc;
4990}
4991EXPORT_SYMBOL(mdss_register_panel);
4992
4993int mdss_fb_register_mdp_instance(struct msm_mdp_interface *mdp)
4994{
4995 if (mdp_instance) {
4996 pr_err("multiple MDP instance registration\n");
4997 return -EINVAL;
4998 }
4999
5000 mdp_instance = mdp;
5001 return 0;
5002}
5003EXPORT_SYMBOL(mdss_fb_register_mdp_instance);
5004
5005int mdss_fb_get_phys_info(dma_addr_t *start, unsigned long *len, int fb_num)
5006{
5007 struct fb_info *info;
5008 struct msm_fb_data_type *mfd;
5009
5010 if (fb_num >= MAX_FBI_LIST)
5011 return -EINVAL;
5012
5013 info = fbi_list[fb_num];
5014 if (!info)
5015 return -ENOENT;
5016
5017 mfd = (struct msm_fb_data_type *)info->par;
5018 if (!mfd)
5019 return -ENODEV;
5020
5021 if (mfd->iova)
5022 *start = mfd->iova;
5023 else
5024 *start = info->fix.smem_start;
5025 *len = info->fix.smem_len;
5026
5027 return 0;
5028}
5029EXPORT_SYMBOL(mdss_fb_get_phys_info);
5030
5031int __init mdss_fb_init(void)
5032{
5033 int rc = -ENODEV;
5034
5035 if (fb_get_options("msmfb", NULL))
5036 return rc;
5037
5038 if (platform_driver_register(&mdss_fb_driver))
5039 return rc;
5040
5041 return 0;
5042}
5043
5044module_init(mdss_fb_init);
5045
5046int mdss_fb_suspres_panel(struct device *dev, void *data)
5047{
5048 struct msm_fb_data_type *mfd;
5049 int rc = 0;
5050 u32 event;
5051
5052 if (!data) {
5053 pr_err("Device state not defined\n");
5054 return -EINVAL;
5055 }
5056 mfd = dev_get_drvdata(dev);
5057 if (!mfd)
5058 return 0;
5059
5060 event = *((bool *) data) ? MDSS_EVENT_RESUME : MDSS_EVENT_SUSPEND;
5061
5062 /* Do not send runtime suspend/resume for HDMI primary */
5063 if (!mdss_fb_is_hdmi_primary(mfd)) {
5064 rc = mdss_fb_send_panel_event(mfd, event, NULL);
5065 if (rc)
5066 pr_warn("unable to %s fb%d (%d)\n",
5067 event == MDSS_EVENT_RESUME ?
5068 "resume" : "suspend",
5069 mfd->index, rc);
5070 }
5071 return rc;
5072}
5073
5074/*
5075 * mdss_fb_report_panel_dead() - Sends the PANEL_ALIVE=0 status to HAL layer.
5076 * @mfd : frame buffer structure associated with fb device.
5077 *
5078 * This function is called if the panel fails to respond as expected to
5079 * the register read/BTA or if the TE signal is not coming as expected
5080 * from the panel. The function sends the PANEL_ALIVE=0 status to HAL
5081 * layer.
5082 */
5083void mdss_fb_report_panel_dead(struct msm_fb_data_type *mfd)
5084{
5085 char *envp[2] = {"PANEL_ALIVE=0", NULL};
5086 struct mdss_panel_data *pdata =
5087 dev_get_platdata(&mfd->pdev->dev);
5088 if (!pdata) {
5089 pr_err("Panel data not available\n");
5090 return;
5091 }
5092
5093 pdata->panel_info.panel_dead = true;
5094 kobject_uevent_env(&mfd->fbi->dev->kobj,
5095 KOBJ_CHANGE, envp);
5096 pr_err("Panel has gone bad, sending uevent - %s\n", envp[0]);
5097}
5098
5099
5100/*
5101 * mdss_fb_calc_fps() - Calculates fps value.
5102 * @mfd : frame buffer structure associated with fb device.
5103 *
5104 * This function is called at frame done. It counts the number
5105 * of frames done for every 1 sec. Stores the value in measured_fps.
5106 * measured_fps value is 10 times the calculated fps value.
5107 * For example, measured_fps= 594 for calculated fps of 59.4
5108 */
5109void mdss_fb_calc_fps(struct msm_fb_data_type *mfd)
5110{
5111 ktime_t current_time_us;
5112 u64 fps, diff_us;
5113
5114 current_time_us = ktime_get();
5115 diff_us = (u64)ktime_us_delta(current_time_us,
5116 mfd->fps_info.last_sampled_time_us);
5117 mfd->fps_info.frame_count++;
5118
5119 if (diff_us >= MDP_TIME_PERIOD_CALC_FPS_US) {
5120 fps = ((u64)mfd->fps_info.frame_count) * 10000000;
5121 do_div(fps, diff_us);
5122 mfd->fps_info.measured_fps = (unsigned int)fps;
5123 pr_debug(" MDP_FPS for fb%d is %d.%d\n",
5124 mfd->index, (unsigned int)fps/10, (unsigned int)fps%10);
5125 mfd->fps_info.last_sampled_time_us = current_time_us;
5126 mfd->fps_info.frame_count = 0;
5127 }
5128}