aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Kondik <steve@cyngn.com>2015-02-08 20:06:00 -0600
committereboye <eboyee@gmail.com>2015-03-30 01:05:15 +0200
commit3db1b12f17102df945a443a898415c5a30231f99 (patch)
tree3b1f4ac4dcec98db33dd611b0b5a0715fb2833e9
parent6ee077c87ab471dc420a44047532a3b22239fc26 (diff)
video: mdss: Color temperature interface using PCClp5.0
* MDSS5 supports Polynomial Color Correction. Use this to implement a simple sysfs API for adjusting RGB scaling values. This can be used to implement color temperature and other controls. * Why use this when we have KCAL? This code is dead simple, the interface is in the right place, and it allows for 128X accuracy. Change-Id: Ib848d6c9dbdf41f61cc7539a61138d6632ceba94
-rw-r--r--drivers/video/msm/mdss/mdss_fb.c66
1 files changed, 66 insertions, 0 deletions
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index 0cfe9787c7f..18e57f76fed 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -394,12 +394,77 @@ static ssize_t mdss_fb_get_idle_notify(struct device *dev,
return ret;
}
+static int pcc_r = 32768, pcc_g = 32768, pcc_b = 32768;
+static ssize_t mdss_get_rgb(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d %d %d\n", pcc_r, pcc_g, pcc_b);
+}
+
+/*
+ * simple color temperature interface using polynomial color correction
+ *
+ * input values are r/g/b adjustments from 0-32768 representing 0 -> 1
+ *
+ * example adjustment @ 3500K:
+ * 1.0000 / 0.5515 / 0.2520 = 32768 / 25828 / 17347
+ *
+ * reference chart:
+ * http://www.vendian.org/mncharity/dir3/blackbody/UnstableURLs/bbr_color.html
+ */
+static ssize_t mdss_set_rgb(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ uint32_t r = 0, g = 0, b = 0;
+ struct mdp_pcc_cfg_data pcc_cfg;
+ u32 copyback = 0;
+ int ret;
+
+ if (count > 19)
+ return -EINVAL;
+
+ sscanf(buf, "%d %d %d", &r, &g, &b);
+
+ if (r < 0 || r > 32768)
+ return -EINVAL;
+ if (g < 0 || g > 32768)
+ return -EINVAL;
+ if (b < 0 || b > 32768)
+ return -EINVAL;
+
+ pr_info("%s: r=%d g=%d b=%d", __func__, r, g, b);
+
+ memset(&pcc_cfg, 0, sizeof(struct mdp_pcc_cfg_data));
+
+ pcc_cfg.block = MDP_LOGICAL_BLOCK_DISP_0;
+ if (r == 32768 && g == 32768 && b == 32768)
+ pcc_cfg.ops = MDP_PP_OPS_DISABLE;
+ else
+ pcc_cfg.ops = MDP_PP_OPS_ENABLE;
+ pcc_cfg.ops |= MDP_PP_OPS_WRITE;
+ pcc_cfg.r.r = r;
+ pcc_cfg.g.g = g;
+ pcc_cfg.b.b = b;
+
+ ret = mdss_mdp_pcc_config(&pcc_cfg, &copyback);
+ if (ret != 0)
+ return ret;
+
+ pcc_r = r;
+ pcc_g = g;
+ pcc_b = b;
+
+ return count;
+}
+
static DEVICE_ATTR(msm_fb_type, S_IRUGO, mdss_fb_get_type, NULL);
static DEVICE_ATTR(msm_fb_split, S_IRUGO, mdss_fb_get_split, NULL);
static DEVICE_ATTR(show_blank_event, S_IRUGO, mdss_mdp_show_blank_event, NULL);
static DEVICE_ATTR(idle_time, S_IRUGO | S_IWUSR | S_IWGRP,
mdss_fb_get_idle_time, mdss_fb_set_idle_time);
static DEVICE_ATTR(idle_notify, S_IRUGO, mdss_fb_get_idle_notify, NULL);
+static DEVICE_ATTR(rgb, S_IRUGO | S_IWUSR | S_IWGRP, mdss_get_rgb, mdss_set_rgb);
static struct attribute *mdss_fb_attrs[] = {
&dev_attr_msm_fb_type.attr,
@@ -407,6 +472,7 @@ static struct attribute *mdss_fb_attrs[] = {
&dev_attr_show_blank_event.attr,
&dev_attr_idle_time.attr,
&dev_attr_idle_notify.attr,
+ &dev_attr_rgb.attr,
NULL,
};