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: Ie17c84ee3c1092ea65804566bdf05326a34a6d4d

video: mdss: Report PCC values from pp registers

Other drivers write to these regs (KCAL, Sony) and other developers may
implement more than one driver. Make sure we are always reporting the correct
PCC values.

Change-Id: Id4a28602d6678d8032f1328c49163b52c15d52b1
This commit is contained in:
Steve Kondik 2015-02-08 18:06:04 -08:00 committed by Luca Stefani
parent 03c7f2babb
commit 2006fd744d
1 changed files with 86 additions and 0 deletions

View File

@ -55,6 +55,8 @@
#include "mdss_mdp_splash_logo.h"
#define CREATE_TRACE_POINTS
#include "mdss_debug.h"
#include "mdss_mdp.h"
#if defined(CONFIG_FB_MSM_MDSS_SAMSUNG)
#include "samsung/ss_dsi_panel_common.h" /* UTIL HEADER */
#endif
@ -421,6 +423,89 @@ static ssize_t mdss_fb_store_split(struct device *dev,
return len;
}
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)
{
u32 copyback = 0;
struct mdp_pcc_cfg_data pcc_cfg;
memset(&pcc_cfg, 0, sizeof(struct mdp_pcc_cfg_data));
pcc_cfg.block = MDP_LOGICAL_BLOCK_DISP_0;
pcc_cfg.ops = MDP_PP_OPS_READ;
mdss_mdp_pcc_config(&pcc_cfg, &copyback);
/* We disable pcc when using default values and reg
* are zeroed on pp resume, so ignore empty values.
*/
if (pcc_cfg.r.r && pcc_cfg.g.g && pcc_cfg.b.b) {
pcc_r = pcc_cfg.r.r;
pcc_g = pcc_cfg.g.g;
pcc_b = pcc_cfg.b.b;
}
return scnprintf(buf, PAGE_SIZE, "%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, &copyback) == 0) {
pcc_r = r;
pcc_g = g;
pcc_b = b;
return count;
}
return -EINVAL;
}
static DEVICE_ATTR(rgb, S_IRUGO | S_IWUSR | S_IWGRP, mdss_get_rgb, mdss_set_rgb);
static ssize_t mdss_fb_show_split(struct device *dev,
struct device_attribute *attr, char *buf)
{
@ -805,6 +890,7 @@ static struct attribute *mdss_fb_attrs[] = {
&dev_attr_msm_fb_thermal_level.attr,
&dev_attr_msm_fb_panel_status.attr,
&dev_attr_msm_fb_dfps_mode.attr,
&dev_attr_rgb.attr,
NULL,
};