diff options
| author | Steve Kondik <steve@cyngn.com> | 2015-03-08 01:25:52 -0500 |
|---|---|---|
| committer | Tony Layher <layhertony@gmail.com> | 2015-03-08 01:26:10 -0500 |
| commit | edb6d4aa6b70479664b240c494b6b4e429fd3481 (patch) | |
| tree | 5b914d6add01ae58427d0a1a8feb2d72ba83d99d | |
| parent | bfcb3e34aa3156e146c65a6baf00bcfcdf455e33 (diff) | |
video: mdss: Color temperature interface using PCC
* 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: Icc497dafff7d25560f0e4e9597d52c78d5ab9178
| -rw-r--r-- | drivers/video/msm/mdss/mdss_fb.c | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c index 7b544582b08..83b824aa17a 100644 --- a/drivers/video/msm/mdss/mdss_fb.c +++ b/drivers/video/msm/mdss/mdss_fb.c @@ -499,6 +499,68 @@ static ssize_t mdss_fb_get_doze_mode(struct device *dev, return scnprintf(buf, PAGE_SIZE, "%d\n", mfd->doze_mode); } +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; + + 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; + + if (mdss_mdp_pcc_config(&pcc_cfg, ©back) == 0) { + pcc_r = r; + pcc_g = g; + pcc_b = b; + return count; + } + + return -EINVAL; +} + static DEVICE_ATTR(msm_fb_type, S_IRUGO, mdss_fb_get_type, NULL); static DEVICE_ATTR(msm_fb_split, S_IRUGO | S_IWUSR, mdss_fb_show_split, mdss_fb_store_split); @@ -511,6 +573,7 @@ static DEVICE_ATTR(msm_fb_src_split_info, S_IRUGO, mdss_fb_get_src_split_info, NULL); static DEVICE_ATTR(always_on, S_IRUGO | S_IWUSR | S_IWGRP, mdss_fb_get_doze_mode, mdss_fb_set_doze_mode); +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, @@ -521,6 +584,7 @@ static struct attribute *mdss_fb_attrs[] = { &dev_attr_msm_fb_panel_info.attr, &dev_attr_msm_fb_src_split_info.attr, &dev_attr_always_on.attr, + &dev_attr_rgb.attr, NULL, }; |
