rk3288 lcdc: add support BCSH func

This commit is contained in:
hjc
2014-05-27 16:03:59 +08:00
parent ba679313e6
commit af1283a6fd
3 changed files with 190 additions and 91 deletions

View File

@@ -3166,56 +3166,53 @@ static int rk3288_lcdc_set_dsp_cabc(struct rk_lcdc_driver *dev_drv,int mode)
return 0;
}
/*
Sin0=*0.000???????? Cos0=*1.000
Sin5=*0.087???????C Cos5=*0.996
Sin10=*0.174 Cos10=*0.985
Sin15=*0.259 ???????CCos15=*0.966
Sin20=*0.342????????Cos20=*0.940
Sin25=*0.422????????Cos25=*0.906
Sin30=*0.500????????Cos30=*0.866
a:[-30~0]:
sin_hue = sin(a)*256 +0x100;
cos_hue = cos(a)*256;
a:[0~30]
sin_hue = sin(a)*256;
cos_hue = cos(a)*256;
*/
static int rk3288_lcdc_set_hue(struct rk_lcdc_driver *dev_drv,int hue)
static int rk3288_lcdc_get_bcsh_hue(struct rk_lcdc_driver *dev_drv,bcsh_hue_mode mode)
{
struct lcdc_device *lcdc_dev =
container_of(dev_drv, struct lcdc_device, driver);
u32 val;
spin_lock(&lcdc_dev->reg_lock);
if (lcdc_dev->clk_on) {
val = lcdc_readl(lcdc_dev, BCSH_H);
switch(mode){
case H_SIN:
val &= m_BCSH_SIN_HUE;
break;
case H_COS:
val &= m_BCSH_COS_HUE;
val >>= 16;
break;
default:
break;
}
}
spin_unlock(&lcdc_dev->reg_lock);
return val;
}
static int rk3288_lcdc_set_bcsh_hue(struct rk_lcdc_driver *dev_drv,int sin_hue, int cos_hue)
{
struct lcdc_device *lcdc_dev =
container_of(dev_drv, struct lcdc_device, driver);
int sin_hue_val,cos_hue_val;
u32 mask, val;
int sin_hue[7]={0,22, 44, 66, 87, 108, 128};
int cos_hue[7]={256,254,252,247,240,231,221};
if((hue > 0)&&(hue <= 30)){
/*sin_hue_val = (int)sin_hue[hue] * 256;
cos_hue_val = (int)cos_hue[hue] * 256;*/
hue /= 5;
sin_hue_val = sin_hue[hue];
cos_hue_val = cos_hue[hue];
}else if((hue > 30)&&(hue <= 60)){
hue -= 30;
hue /= 5;
/*sin_hue_val = (int)sin_hue[hue] * 256 + 0x100;
cos_hue_val = (int)cos_hue[hue] * 256 + 0x100;*/
sin_hue_val = sin_hue[hue] + 0x100;
cos_hue_val = cos_hue[hue] + 0x100;
}else{
dev_warn(lcdc_dev->dev,"hue=%d should be [0:60]\n",hue);
}
spin_lock(&lcdc_dev->reg_lock);
if(lcdc_dev->clk_on){
mask = m_BCSH_OUT_MODE;
val = v_BCSH_OUT_MODE(3);
lcdc_msk_reg(lcdc_dev, BCSH_BCS, mask, val);
spin_lock(&lcdc_dev->reg_lock);
if (lcdc_dev->clk_on) {
mask = m_BCSH_SIN_HUE | m_BCSH_COS_HUE;
val = v_BCSH_SIN_HUE(sin_hue_val) | v_BCSH_COS_HUE(cos_hue_val);
val = v_BCSH_SIN_HUE(sin_hue) | v_BCSH_COS_HUE(cos_hue);
lcdc_msk_reg(lcdc_dev, BCSH_H, mask, val);
mask = m_BCSH_EN;
val = v_BCSH_EN(1);
lcdc_msk_reg(lcdc_dev, BCSH_COLOR_BAR, mask, val);
lcdc_cfg_done(lcdc_dev);
}
spin_unlock(&lcdc_dev->reg_lock);
@@ -3223,30 +3220,101 @@ static int rk3288_lcdc_set_hue(struct rk_lcdc_driver *dev_drv,int hue)
return 0;
}
static int rk3288_lcdc_set_bcsh_bcs(struct rk_lcdc_driver *dev_drv,int bri,int con,int sat)
static int rk3288_lcdc_set_bcsh_bcs(struct rk_lcdc_driver *dev_drv,bcsh_bcs_mode mode,int value)
{
struct lcdc_device *lcdc_dev =
container_of(dev_drv, struct lcdc_device, driver);
u32 mask, val;
spin_lock(&lcdc_dev->reg_lock);
if(lcdc_dev->clk_on){
mask = m_BCSH_OUT_MODE | m_BCSH_BRIGHTNESS |
m_BCSH_CONTRAST | m_BCSH_SAT_CON;
val = v_BCSH_OUT_MODE(3) | v_BCSH_BRIGHTNESS(bri) |
v_BCSH_CONTRAST(con) | v_BCSH_SAT_CON(sat);
if(lcdc_dev->clk_on) {
switch (mode) {
case BRIGHTNESS:
/*from 0 to 255,typical is 128*/
if (value < 0x80)
value += 0x80;
else if (value >= 0x80)
value = value - 0x80;
mask = m_BCSH_BRIGHTNESS;
val = v_BCSH_BRIGHTNESS(value);
break;
case CONTRAST:
/*from 0 to 510,typical is 256*/
mask = m_BCSH_CONTRAST;
val = v_BCSH_CONTRAST(value);
break;
case SAT_CON:
/*from 0 to 1015,typical is 256*/
mask = m_BCSH_SAT_CON;
val = v_BCSH_SAT_CON(value);
break;
default:
break;
}
lcdc_msk_reg(lcdc_dev, BCSH_BCS, mask, val);
lcdc_cfg_done(lcdc_dev);
}
spin_unlock(&lcdc_dev->reg_lock);
return val;
}
mask = m_BCSH_EN;
val = v_BCSH_EN(1);
lcdc_msk_reg(lcdc_dev, BCSH_COLOR_BAR, mask, val);
static int rk3288_lcdc_get_bcsh_bcs(struct rk_lcdc_driver *dev_drv,bcsh_bcs_mode mode)
{
struct lcdc_device *lcdc_dev =
container_of(dev_drv, struct lcdc_device, driver);
u32 val;
spin_lock(&lcdc_dev->reg_lock);
if(lcdc_dev->clk_on) {
val = lcdc_readl(lcdc_dev, BCSH_BCS);
switch (mode) {
case BRIGHTNESS:
val &= m_BCSH_BRIGHTNESS;
if(val > 0x80)
val -= 0x80;
else
val += 0x80;
break;
case CONTRAST:
val &= m_BCSH_CONTRAST;
val >>= 8;
break;
case SAT_CON:
val &= m_BCSH_SAT_CON;
val >>= 20;
break;
default:
break;
}
}
spin_unlock(&lcdc_dev->reg_lock);
return val;
}
static int rk3288_lcdc_open_bcsh(struct rk_lcdc_driver *dev_drv, bool open)
{
struct lcdc_device *lcdc_dev =
container_of(dev_drv, struct lcdc_device, driver);
u32 mask, val;
spin_lock(&lcdc_dev->reg_lock);
if (lcdc_dev->clk_on) {
if (open) {
lcdc_writel(lcdc_dev,BCSH_COLOR_BAR,0x1);
lcdc_writel(lcdc_dev,BCSH_BCS,0xd0010000);
lcdc_writel(lcdc_dev,BCSH_H,0x01000000);
} else {
mask = m_BCSH_EN;
val = v_BCSH_EN(0);
lcdc_msk_reg(lcdc_dev, BCSH_COLOR_BAR, mask, val);
}
lcdc_cfg_done(lcdc_dev);
}
spin_unlock(&lcdc_dev->reg_lock);
return 0;
}
static struct rk_lcdc_win lcdc_win[] = {
[0] = {
.name = "win0",
@@ -3295,8 +3363,11 @@ static struct rk_lcdc_drv_ops lcdc_drv_ops = {
.dpi_status = rk3288_lcdc_dpi_status,
.get_dsp_addr = rk3288_lcdc_get_dsp_addr,
.set_dsp_cabc = rk3288_lcdc_set_dsp_cabc,
.set_dsp_hue = rk3288_lcdc_set_hue,
.set_dsp_bcsh_hue = rk3288_lcdc_set_bcsh_hue,
.set_dsp_bcsh_bcs = rk3288_lcdc_set_bcsh_bcs,
.get_dsp_bcsh_hue = rk3288_lcdc_get_bcsh_hue,
.get_dsp_bcsh_bcs = rk3288_lcdc_get_bcsh_bcs,
.open_bcsh = rk3288_lcdc_open_bcsh,
.dump_reg = rk3288_lcdc_reg_dump,
.cfg_done = rk3288_lcdc_config_done,
.set_irq_to_cpu = rk3288_lcdc_set_irq_to_cpu,

View File

@@ -318,53 +318,68 @@ static ssize_t set_dsp_cabc(struct device *dev, struct device_attribute *attr,
}
static ssize_t show_hue(struct device *dev,
static ssize_t show_dsp_bcsh(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct fb_info *fbi = dev_get_drvdata(dev);
struct rk_lcdc_driver *dev_drv =
(struct rk_lcdc_driver *)fbi->par;
int brightness, contrast, sat_con, sin_hue, cos_hue;
brightness = dev_drv->ops->get_dsp_bcsh_bcs(dev_drv, BRIGHTNESS);
contrast = dev_drv->ops->get_dsp_bcsh_bcs(dev_drv, CONTRAST);
sat_con = dev_drv->ops->get_dsp_bcsh_bcs(dev_drv, SAT_CON);
sin_hue = dev_drv->ops->get_dsp_bcsh_hue(dev_drv,H_SIN);
cos_hue = dev_drv->ops->get_dsp_bcsh_hue(dev_drv,H_COS);
snprintf(buf, PAGE_SIZE, "brightness:%4d,contrast:%4d,sat_con:%4d,"
"sin_hue:%4d,cos_hue:%4d\n",
brightness, contrast,sat_con,sin_hue,cos_hue);
return 0;
}
static ssize_t set_hue(struct device *dev, struct device_attribute *attr,
static ssize_t set_dsp_bcsh(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct fb_info *fbi = dev_get_drvdata(dev);
struct rk_lcdc_driver *dev_drv =
(struct rk_lcdc_driver *)fbi->par;
int ret,hue;
ret = kstrtoint(buf, 0, &hue);
if (ret)
return ret;
int brightness, contrast, sat_con, hue, ret, open, sin_hue, cos_hue;
if (!strncmp(buf, "open", 4)) {
ret = dev_drv->ops->open_bcsh(dev_drv, 1);
} else if (!strncmp(buf, "close", 5)) {
ret = dev_drv->ops->open_bcsh(dev_drv, 0);
} else if (!strncmp(buf, "brightness", 10)) {
sscanf(buf, "brightness %d", &brightness);
if (unlikely(brightness > 255)) {
dev_err(fbi->dev,"brightness should be [0:255],now=%d\n\n",brightness);
brightness = 255;
}
ret = dev_drv->ops->set_dsp_bcsh_bcs(dev_drv, BRIGHTNESS,brightness);
} else if (!strncmp(buf, "contrast", 8)) {
sscanf(buf, "contrast %d", &contrast);
if (unlikely(contrast > 510)) {
dev_err(fbi->dev,"contrast should be [0:510],now=%d\n",contrast);
contrast = 510;
}
ret = dev_drv->ops->set_dsp_bcsh_bcs(dev_drv, CONTRAST,contrast);
} else if (!strncmp(buf, "sat_con", 7)) {
sscanf(buf, "sat_con %d", &sat_con);
if (unlikely(sat_con > 1015)) {
dev_err(fbi->dev,"sat_con should be [0:1015],now=%d\n",sat_con);
sat_con = 1015;
}
ret = dev_drv->ops->set_dsp_bcsh_bcs(dev_drv, SAT_CON,sat_con);
} else if (!strncmp(buf, "hue", 3)) {
sscanf(buf, "hue %d %d", &sin_hue,&cos_hue);
if (unlikely(sin_hue > 511 || cos_hue > 511)) {
dev_err(fbi->dev,"sin_hue=%d,cos_hue=%d\n",sin_hue,cos_hue);
}
ret = dev_drv->ops->set_dsp_bcsh_hue(dev_drv,sin_hue,cos_hue);
} else {
printk("format error\n");
}
ret = dev_drv->ops->set_dsp_hue(dev_drv, hue);
if(ret < 0)
return ret;
return count;
}
static ssize_t show_dsp_bcs(struct device *dev,
struct device_attribute *attr, char *buf)
{
return 0;
}
static ssize_t set_dsp_bcs(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct fb_info *fbi = dev_get_drvdata(dev);
struct rk_lcdc_driver *dev_drv =
(struct rk_lcdc_driver *)fbi->par;
int ret,bri,con,sat;
ret = kstrtoint(buf, 0, &bri);
if (ret)
return ret;
ret = dev_drv->ops->set_dsp_bcsh_bcs(dev_drv, bri,con,sat);
if(ret < 0)
return ret;
@@ -459,8 +474,7 @@ static struct device_attribute rkfb_attrs[] = {
__ATTR(map, S_IRUGO | S_IWUSR, show_fb_win_map, set_fb_win_map),
__ATTR(dsp_lut, S_IRUGO | S_IWUSR, show_dsp_lut, set_dsp_lut),
__ATTR(cabc, S_IRUGO | S_IWUSR, show_dsp_cabc, set_dsp_cabc),
__ATTR(hue, S_IRUGO | S_IWUSR, show_hue, set_hue),
__ATTR(bcs, S_IRUGO | S_IWUSR, show_dsp_bcs, set_dsp_bcs),
__ATTR(bcsh, S_IRUGO | S_IWUSR, show_dsp_bcsh, set_dsp_bcsh),
__ATTR(scale, S_IRUGO | S_IWUSR, show_scale, set_scale),
};

View File

@@ -223,6 +223,17 @@ enum
SCALE_DOWN = 0x2
};
typedef enum {
BRIGHTNESS = 0x0,
CONTRAST = 0x1,
SAT_CON = 0x2
} bcsh_bcs_mode;
typedef enum {
H_SIN = 0x0,
H_COS = 0x1
} bcsh_hue_mode;
struct rk_fb_rgb {
struct fb_bitfield red;
@@ -396,8 +407,11 @@ struct rk_lcdc_drv_ops {
int (*dpi_status) (struct rk_lcdc_driver * dev_drv);
int (*get_dsp_addr)(struct rk_lcdc_driver * dev_drv,unsigned int *dsp_addr);
int (*set_dsp_cabc) (struct rk_lcdc_driver * dev_drv, int mode);
int (*set_dsp_hue) (struct rk_lcdc_driver *dev_drv,int hue);
int (*set_dsp_bcsh_bcs)(struct rk_lcdc_driver *dev_drv,int bri,int con,int sat);
int (*set_dsp_bcsh_hue) (struct rk_lcdc_driver *dev_drv,int sin_hue, int cos_hue);
int (*set_dsp_bcsh_bcs)(struct rk_lcdc_driver *dev_drv,bcsh_bcs_mode mode,int value);
int (*get_dsp_bcsh_hue) (struct rk_lcdc_driver *dev_drv,bcsh_hue_mode mode);
int (*get_dsp_bcsh_bcs)(struct rk_lcdc_driver *dev_drv,bcsh_bcs_mode mode);
int (*open_bcsh)(struct rk_lcdc_driver *dev_drv, bool open);
int (*dump_reg) (struct rk_lcdc_driver * dev_drv);
int (*mmu_en) (struct rk_lcdc_driver * dev_drv);
int (*cfg_done) (struct rk_lcdc_driver * dev_drv);