diff options
| author | Steve Kondik <steve@cyngn.com> | 2015-02-08 20:06:00 -0600 |
|---|---|---|
| committer | eboye <eboyee@gmail.com> | 2015-03-30 01:05:15 +0200 |
| commit | 3db1b12f17102df945a443a898415c5a30231f99 (patch) | |
| tree | 3b1f4ac4dcec98db33dd611b0b5a0715fb2833e9 | |
| parent | 6ee077c87ab471dc420a44047532a3b22239fc26 (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.c | 66 |
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, ©back); + 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, }; |
