drm/rockchip: vop: add BCSH support for full vops

The full name of BCSH is Brightness, Contrast, Saturation and Hue.
BCSH is supported on all full vop designed.

Change-Id: I17bcd5a07b93b3c68aa892606f886bcd3a7673a0
Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
This commit is contained in:
Mark Yao 2017-08-14 09:47:28 +08:00 committed by Huang, Tao
parent 2272eb5d62
commit e268caad71
11 changed files with 128 additions and 0 deletions

View File

@ -213,6 +213,7 @@ rockchip_dp_drm_encoder_atomic_check(struct drm_encoder *encoder,
s->output_type = DRM_MODE_CONNECTOR_eDP;
if (info->num_bus_formats)
s->bus_format = info->bus_formats[0];
s->tv_state = &conn_state->tv;
return 0;
}

View File

@ -743,6 +743,7 @@ static int cdn_dp_encoder_atomic_check(struct drm_encoder *encoder,
s->output_mode = ROCKCHIP_OUT_MODE_AAAA;
s->output_type = DRM_MODE_CONNECTOR_DisplayPort;
s->tv_state = &conn_state->tv;
return 0;
}

View File

@ -1220,6 +1220,7 @@ dw_mipi_dsi_encoder_atomic_check(struct drm_encoder *encoder,
s->output_type = DRM_MODE_CONNECTOR_DSI;
if (info->num_bus_formats)
s->bus_format = info->bus_formats[0];
s->tv_state = &conn_state->tv;
if (dsi->slave)
s->output_flags = ROCKCHIP_OUTPUT_DSI_DUAL_CHANNEL;

View File

@ -543,6 +543,7 @@ dw_hdmi_rockchip_encoder_atomic_check(struct drm_encoder *encoder,
s->bus_format = MEDIA_BUS_FMT_RGB888_1X24;
}
s->output_type = DRM_MODE_CONNECTOR_HDMIA;
s->tv_state = &conn_state->tv;
return 0;
}

View File

@ -1122,6 +1122,26 @@ static void rockchip_gem_pool_destroy(struct drm_device *drm)
gen_pool_destroy(private->secure_buffer_pool);
}
static void rockchip_attach_connector_property(struct drm_device *drm)
{
struct drm_connector *connector;
struct drm_mode_config *conf = &drm->mode_config;
mutex_lock(&drm->mode_config.mutex);
drm_for_each_connector(connector, drm) {
#define ROCKCHIP_PROP_ATTACH(prop, v) \
drm_object_attach_property(&connector->base, prop, v)
ROCKCHIP_PROP_ATTACH(conf->tv_brightness_property, 100);
ROCKCHIP_PROP_ATTACH(conf->tv_contrast_property, 100);
ROCKCHIP_PROP_ATTACH(conf->tv_saturation_property, 100);
ROCKCHIP_PROP_ATTACH(conf->tv_hue_property, 100);
}
mutex_unlock(&drm->mode_config.mutex);
}
static int rockchip_drm_bind(struct device *dev)
{
struct drm_device *drm_dev;
@ -1192,6 +1212,8 @@ static int rockchip_drm_bind(struct device *dev)
if (ret)
goto err_mode_config_cleanup;
rockchip_attach_connector_property(drm_dev);
ret = drm_vblank_init(drm_dev, drm_dev->mode_config.num_crtc);
if (ret)
goto err_unbind_all;

View File

@ -76,6 +76,7 @@ struct rockchip_dclk_pll {
struct rockchip_crtc_state {
struct drm_crtc_state base;
struct drm_property_blob *cabc_lut;
struct drm_tv_connector_state *tv_state;
int left_margin;
int right_margin;
int top_margin;

View File

@ -21,6 +21,7 @@
#include <drm/drm_plane_helper.h>
#include <linux/devfreq.h>
#include <linux/fixp-arith.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/module.h>
@ -2192,6 +2193,67 @@ static void vop_update_cabc(struct drm_crtc *crtc,
}
}
static void vop_tv_config_update(struct drm_crtc *crtc,
struct drm_crtc_state *old_crtc_state)
{
struct rockchip_crtc_state *s =
to_rockchip_crtc_state(crtc->state);
struct rockchip_crtc_state *old_s =
to_rockchip_crtc_state(old_crtc_state);
int brightness, contrast, saturation, hue, sin_hue, cos_hue;
struct vop *vop = to_vop(crtc);
const struct vop_data *vop_data = vop->data;
if (!s->tv_state)
return;
if (old_s->tv_state &&
!memcmp(s->tv_state, old_s->tv_state, sizeof(*s->tv_state)))
return;
if (s->tv_state->brightness == 50 &&
s->tv_state->contrast == 50 &&
s->tv_state->saturation == 50 &&
s->tv_state->hue == 50) {
VOP_CTRL_SET(vop, bcsh_en, 0);
return;
}
if (vop_data->feature & VOP_FEATURE_OUTPUT_10BIT)
brightness = interpolate(0, -128, 100, 127,
s->tv_state->brightness);
else
brightness = interpolate(0, -32, 100, 31,
s->tv_state->brightness);
contrast = interpolate(0, 0, 100, 511, s->tv_state->contrast);
saturation = interpolate(0, 0, 100, 511, s->tv_state->saturation);
hue = interpolate(0, -30, 100, 30, s->tv_state->hue);
/*
* a:[-30~0]:
* sin_hue = 0x100 - sin(a)*256;
* cos_hue = cos(a)*256;
* a:[0~30]
* sin_hue = sin(a)*256;
* cos_hue = cos(a)*256;
*/
sin_hue = fixp_sin32(hue) >> 23;
cos_hue = fixp_cos32(hue) >> 23;
VOP_CTRL_SET(vop, bcsh_brightness, brightness);
VOP_CTRL_SET(vop, bcsh_contrast, contrast);
VOP_CTRL_SET(vop, bcsh_sat_con, saturation * contrast / 0x100);
VOP_CTRL_SET(vop, bcsh_sin_hue, sin_hue);
VOP_CTRL_SET(vop, bcsh_cos_hue, cos_hue);
VOP_CTRL_SET(vop, bcsh_en, 1);
if (!is_yuv_output(s->bus_format)) {
VOP_CTRL_SET(vop, bcsh_r2y_en, 1);
VOP_CTRL_SET(vop, bcsh_y2r_en, 1);
} else {
VOP_CTRL_SET(vop, bcsh_r2y_en, 0);
VOP_CTRL_SET(vop, bcsh_y2r_en, 0);
}
}
static void vop_cfg_update(struct drm_crtc *crtc,
struct drm_crtc_state *old_crtc_state)
{
@ -2201,6 +2263,8 @@ static void vop_cfg_update(struct drm_crtc *crtc,
spin_lock(&vop->reg_lock);
vop_tv_config_update(crtc, old_crtc_state);
if (s->afbdc_en) {
uint32_t pic_size;

View File

@ -179,6 +179,20 @@ struct vop_ctrl {
struct vop_reg cabc_global_dn;
struct vop_reg cabc_calc_pixel_num;
/* BCSH */
struct vop_reg bcsh_brightness;
struct vop_reg bcsh_contrast;
struct vop_reg bcsh_sat_con;
struct vop_reg bcsh_sin_hue;
struct vop_reg bcsh_cos_hue;
struct vop_reg bcsh_r2y_csc_mode;
struct vop_reg bcsh_r2y_en;
struct vop_reg bcsh_y2r_csc_mode;
struct vop_reg bcsh_y2r_en;
struct vop_reg bcsh_color_bar;
struct vop_reg bcsh_out_mode;
struct vop_reg bcsh_en;
struct vop_reg cfg_done;
};
@ -544,5 +558,10 @@ static inline int us_to_vertical_line(struct drm_display_mode *mode, int us)
return us * mode->clock / mode->htotal / 1000;
}
static inline int interpolate(int x1, int y1, int x2, int y2, int x)
{
return y1 + (y2 - y1) * (x - x1) / (x2 - x1);
}
extern const struct component_ops vop_component_ops;
#endif /* _ROCKCHIP_DRM_VOP_H */

View File

@ -621,6 +621,7 @@ rockchip_lvds_encoder_atomic_check(struct drm_encoder *encoder,
s->output_type = DRM_MODE_CONNECTOR_LVDS;
if (info->num_bus_formats)
s->bus_format = info->bus_formats[0];
s->tv_state = &conn_state->tv;
return 0;
}

View File

@ -247,6 +247,19 @@ static const struct vop_ctrl rk3288_ctrl_data = {
.cabc_global_dn_limit_en = VOP_REG_VER(RK3399_CABC_CTRL3, 0x1, 8,
3, 5, -1),
.bcsh_brightness = VOP_REG(RK3288_BCSH_BCS, 0xff, 0),
.bcsh_contrast = VOP_REG(RK3288_BCSH_BCS, 0x1ff, 8),
.bcsh_sat_con = VOP_REG(RK3288_BCSH_BCS, 0x3ff, 20),
.bcsh_out_mode = VOP_REG(RK3288_BCSH_BCS, 0x3, 0),
.bcsh_sin_hue = VOP_REG(RK3288_BCSH_H, 0x1ff, 0),
.bcsh_cos_hue = VOP_REG(RK3288_BCSH_H, 0x1ff, 16),
.bcsh_r2y_csc_mode = VOP_REG_VER(RK3368_BCSH_CTRL, 0x1, 6, 3, 2, -1),
.bcsh_r2y_en = VOP_REG_VER(RK3368_BCSH_CTRL, 0x1, 4, 3, 2, -1),
.bcsh_y2r_csc_mode = VOP_REG_VER(RK3368_BCSH_CTRL, 0x3, 2, 3, 2, -1),
.bcsh_y2r_en = VOP_REG_VER(RK3368_BCSH_CTRL, 0x1, 0, 3, 2, -1),
.bcsh_color_bar = VOP_REG(RK3288_BCSH_COLOR_BAR, 0xffffff, 8),
.bcsh_en = VOP_REG(RK3288_BCSH_COLOR_BAR, 0x1, 0),
.xmirror = VOP_REG(RK3288_DSP_CTRL0, 0x1, 22),
.ymirror = VOP_REG(RK3288_DSP_CTRL0, 0x1, 23),

View File

@ -121,6 +121,10 @@
#define RK3288_DSP_VACT_ST_END 0x0194
#define RK3288_DSP_VS_ST_END_F1 0x0198
#define RK3288_DSP_VACT_ST_END_F1 0x019c
#define RK3288_BCSH_COLOR_BAR 0x01b0
#define RK3288_BCSH_BCS 0x01b4
#define RK3288_BCSH_H 0x01b8
/* register definition end */
/* rk3368 register definition */