Merge "msm: mdss: allow assertive display on write back framebuffer"
diff --git a/drivers/video/msm/mdss/mdss.h b/drivers/video/msm/mdss/mdss.h
index ecc07cf..dd1a95b 100644
--- a/drivers/video/msm/mdss/mdss.h
+++ b/drivers/video/msm/mdss/mdss.h
@@ -82,6 +82,7 @@
u32 has_bwc;
u32 has_decimation;
u8 has_wfd_blk;
+ u8 has_wb_ad;
u32 mdp_irq_mask;
u32 mdp_hist_irq_mask;
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index 6a12b6b..3107e38 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -1821,6 +1821,9 @@
if (mdata->nad_cfgs > mdata->nmixers_intf)
return -EINVAL;
+ mdata->has_wb_ad = of_property_read_bool(pdev->dev.of_node,
+ "qcom,mdss-has-wb-ad");
+
ad_offsets = kzalloc(sizeof(u32) * mdata->nad_cfgs, GFP_KERNEL);
if (!ad_offsets) {
pr_err("no mem assigned: kzalloc fail\n");
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 70d9107..7a8f3bc 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -384,6 +384,7 @@
struct mdss_mdp_data free_list[MAX_FREE_LIST_SIZE];
int free_list_size;
+ int ad_state;
};
struct mdss_mdp_perf_params {
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index 176d0df..7b36f2c 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -420,6 +420,7 @@
ctl->read_line_cnt_fnc = NULL;
ctl->add_vsync_handler = NULL;
ctl->remove_vsync_handler = NULL;
+ ctl->panel_data = NULL;
mutex_unlock(&mdss_mdp_ctl_lock);
return 0;
@@ -428,7 +429,7 @@
static struct mdss_mdp_mixer *mdss_mdp_mixer_alloc(
struct mdss_mdp_ctl *ctl, u32 type, int mux)
{
- struct mdss_mdp_mixer *mixer = NULL;
+ struct mdss_mdp_mixer *mixer = NULL, *alt_mixer = NULL;
u32 nmixers_intf;
u32 nmixers_wb;
u32 i;
@@ -446,6 +447,16 @@
case MDSS_MDP_MIXER_TYPE_INTF:
mixer_pool = ctl->mdata->mixer_intf;
nmixers = nmixers_intf;
+
+ /*
+ * try to reserve first layer mixer for write back if
+ * assertive display needs to be supported through wfd
+ */
+ if (ctl->mdata->has_wb_ad && ctl->intf_num) {
+ alt_mixer = mixer_pool;
+ mixer_pool++;
+ nmixers--;
+ }
break;
case MDSS_MDP_MIXER_TYPE_WRITEBACK:
@@ -484,6 +495,9 @@
}
mixer = NULL;
}
+
+ if (!mixer && alt_mixer && (alt_mixer->ref_cnt == 0))
+ mixer = alt_mixer;
mutex_unlock(&mdss_mdp_ctl_lock);
return mixer;
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index ba59c4f..1adba15 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -1499,15 +1499,81 @@
return ret;
}
-static DEVICE_ATTR(vsync_event, S_IRUGO, mdss_mdp_vsync_show_event, NULL);
+static inline int mdss_mdp_ad_is_supported(struct msm_fb_data_type *mfd)
+{
+ struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
+ struct mdss_mdp_mixer *mixer;
-static struct attribute *vsync_fs_attrs[] = {
+ if (!ctl) {
+ pr_debug("there is no ctl attached to fb\n");
+ return 0;
+ }
+
+ mixer = mdss_mdp_mixer_get(ctl, MDSS_MDP_MIXER_MUX_LEFT);
+ if (mixer && (mixer->num > ctl->mdata->nad_cfgs)) {
+ if (!mixer)
+ pr_warn("there is no mixer attached to fb\n");
+ else
+ pr_debug("mixer attached (%d) doesnt support ad\n",
+ mixer->num);
+ return 0;
+ }
+
+ mixer = mdss_mdp_mixer_get(ctl, MDSS_MDP_MIXER_MUX_RIGHT);
+ if (mixer && (mixer->num > ctl->mdata->nad_cfgs))
+ return 0;
+
+ return 1;
+}
+
+static ssize_t mdss_mdp_ad_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fb_info *fbi = dev_get_drvdata(dev);
+ struct msm_fb_data_type *mfd = fbi->par;
+ struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
+ int ret, state;
+
+ state = mdss_mdp_ad_is_supported(mfd) ? mdp5_data->ad_state : -1;
+
+ ret = scnprintf(buf, PAGE_SIZE, "%d", state);
+
+ return ret;
+}
+
+static ssize_t mdss_mdp_ad_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct fb_info *fbi = dev_get_drvdata(dev);
+ struct msm_fb_data_type *mfd = fbi->par;
+ struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
+ int ret, ad;
+
+ ret = kstrtoint(buf, 10, &ad);
+ if (ret) {
+ pr_err("Invalid input for ad\n");
+ return -EINVAL;
+ }
+
+ mdp5_data->ad_state = ad;
+ sysfs_notify(&dev->kobj, NULL, "ad");
+
+ return count;
+}
+
+
+static DEVICE_ATTR(vsync_event, S_IRUGO, mdss_mdp_vsync_show_event, NULL);
+static DEVICE_ATTR(ad, S_IRUGO | S_IWUSR | S_IWGRP, mdss_mdp_ad_show,
+ mdss_mdp_ad_store);
+
+static struct attribute *mdp_overlay_sysfs_attrs[] = {
&dev_attr_vsync_event.attr,
+ &dev_attr_ad.attr,
NULL,
};
-static struct attribute_group vsync_fs_attr_group = {
- .attrs = vsync_fs_attrs,
+static struct attribute_group mdp_overlay_sysfs_group = {
+ .attrs = mdp_overlay_sysfs_attrs,
};
static int mdss_mdp_hw_cursor_update(struct msm_fb_data_type *mfd,
@@ -2224,7 +2290,7 @@
if (rc)
return rc;
- rc = sysfs_create_group(&dev->kobj, &vsync_fs_attr_group);
+ rc = sysfs_create_group(&dev->kobj, &mdp_overlay_sysfs_group);
if (rc) {
pr_err("vsync sysfs group creation failed, ret=%d\n", rc);
goto init_fail;