From: Bencheng Jing Date: Sat, 28 Apr 2018 11:10:10 +0000 (+0800) Subject: drm: pq: G12A DRM support gamma and ctm setting [1/1] X-Git-Tag: khadas-vims-v0.9.6-release~1136 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=d146035908727359ecd45a5d65f5c6ad666385ba;p=platform%2Fkernel%2Flinux-amlogic.git drm: pq: G12A DRM support gamma and ctm setting [1/1] PD#165492 Problem: G12A DRM add gamma and ctm setting support Solution: 1. amvecm: add gamma apis for drm 2. drm: add gamma and ctm setting Verify: Verified on customer platfor Change-Id: Iff5204ae7f719542463ac15140e471cd762c9c27 Signed-off-by: Bencheng Jing --- diff --git a/MAINTAINERS b/MAINTAINERS index a13c47b..4cc87a4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14175,6 +14175,7 @@ F: driver/amlogic/drm/am_meson_drv.c F: driver/amlogic/drm/am_meson_drv.h F: driver/amlogic/drm/am_meson_vpu.c F: driver/amlogic/drm/am_meson_vpu.h +F: drivers/amlogic/media/enhancement/amvecm/amvecm_drm.c AMLOGIC ADD S400EMMC DTS M: Yue Gui diff --git a/drivers/amlogic/drm/am_meson_vpu.c b/drivers/amlogic/drm/am_meson_vpu.c index 69372bf..fccfdc2 100644 --- a/drivers/amlogic/drm/am_meson_vpu.c +++ b/drivers/amlogic/drm/am_meson_vpu.c @@ -34,6 +34,7 @@ /* Amlogic Headers */ #include +#include #include "osd.h" #include "osd_drm.h" @@ -255,7 +256,6 @@ int am_meson_crtc_dts_info_set(const void *dt_match_data) return 0; } - static const struct drm_plane_funcs am_osd_plane_funs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, @@ -667,6 +667,26 @@ void am_meson_crtc_atomic_begin(struct drm_crtc *crtc, void am_meson_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state) { + struct drm_color_ctm *ctm; + struct drm_color_lut *lut; + int gamma_lut_size = 0; + + if (crtc->state->color_mgmt_changed) { + DRM_INFO("%s color_mgmt_changed!\n", __func__); + if (crtc->state->ctm) { + DRM_INFO("%s color_mgmt_changed 1!\n", __func__); + ctm = (struct drm_color_ctm *) + crtc->state->ctm->data; + am_meson_ctm_set(0, ctm); + } + if (crtc->state->gamma_lut) { + DRM_INFO("%s color_mgmt_changed 2!\n", __func__); + lut = (struct drm_color_lut *) + crtc->state->gamma_lut->data; + gamma_lut_size = amvecm_drm_get_gamma_size(0); + amvecm_drm_gamma_set(0, lut, gamma_lut_size); + } + } } static const struct drm_crtc_helper_funcs am_crtc_helper_funcs = { @@ -682,6 +702,7 @@ int am_meson_crtc_create(struct am_meson_crtc *amcrtc) { struct meson_drm *priv = amcrtc->priv; struct drm_crtc *crtc = &amcrtc->base; + int gamma_lut_size = 0; int ret; DRM_INFO("%s\n", __func__); @@ -696,6 +717,12 @@ int am_meson_crtc_create(struct am_meson_crtc *amcrtc) drm_crtc_helper_add(crtc, &am_crtc_helper_funcs); osd_drm_init(&osd_meson_dev); + amvecm_drm_init(0); + amvecm_drm_gamma_enable(0); + gamma_lut_size = amvecm_drm_get_gamma_size(0); + drm_mode_crtc_set_gamma_size(crtc, gamma_lut_size); + drm_crtc_enable_color_mgmt(crtc, 0, true, gamma_lut_size); + priv->crtc = crtc; return 0; } @@ -830,6 +857,8 @@ static void am_meson_vpu_unbind(struct device *dev, struct meson_drm *private = drm_dev->dev_private; am_meson_unregister_crtc_funcs(private->crtc); + amvecm_drm_gamma_disable(0); + am_meson_ctm_disable(); osd_drm_debugfs_exit(); } diff --git a/drivers/amlogic/media/enhancement/amvecm/Makefile b/drivers/amlogic/media/enhancement/amvecm/Makefile index 42f1595..894e057 100644 --- a/drivers/amlogic/media/enhancement/amvecm/Makefile +++ b/drivers/amlogic/media/enhancement/amvecm/Makefile @@ -15,3 +15,4 @@ am_vecm-objs += cm2_adj.o am_vecm-objs += vlock.o am_vecm-objs += hdr/am_hdr10_plus.o am_vecm-objs += local_contrast.o +am_vecm-objs += amvecm_drm.o diff --git a/drivers/amlogic/media/enhancement/amvecm/amve.c b/drivers/amlogic/media/enhancement/amvecm/amve.c index b8f91ef..8d6323b 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amve.c +++ b/drivers/amlogic/media/enhancement/amvecm/amve.c @@ -338,12 +338,12 @@ void ve_on_vs(struct vframe_s *vf) void vpp_enable_lcd_gamma_table(void) { - WRITE_VPP_REG_BITS(L_GAMMA_CNTL_PORT, 1, GAMMA_EN, 1); + VSYNC_WR_MPEG_REG_BITS(L_GAMMA_CNTL_PORT, 1, GAMMA_EN, 1); } void vpp_disable_lcd_gamma_table(void) { - WRITE_VPP_REG_BITS(L_GAMMA_CNTL_PORT, 0, GAMMA_EN, 1); + VSYNC_WR_MPEG_REG_BITS(L_GAMMA_CNTL_PORT, 0, GAMMA_EN, 1); } void vpp_set_lcd_gamma_table(u16 *data, u32 rgb_mask) @@ -387,7 +387,7 @@ void vpp_set_lcd_gamma_table(u16 *data, u32 rgb_mask) (0x1 << rgb_mask) | (0x23 << HADR)); - WRITE_VPP_REG_BITS(L_GAMMA_CNTL_PORT, + VSYNC_WR_MPEG_REG_BITS(L_GAMMA_CNTL_PORT, gamma_en, GAMMA_EN, 1); spin_unlock_irqrestore(&vpp_lcd_gamma_lock, flags); diff --git a/drivers/amlogic/media/enhancement/amvecm/amve.h b/drivers/amlogic/media/enhancement/amvecm/amve.h index f2d9785..d90c1e0 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amve.h +++ b/drivers/amlogic/media/enhancement/amvecm/amve.h @@ -143,6 +143,9 @@ extern int VSYNC_WR_MPEG_REG(u32 adr, u32 val); /* unsigned long long ve_get_vs_cnt(void); */ /* #endif */ extern int video_rgb_ogo_xvy_mtx; + +#define GAMMA_SIZE 256 + extern unsigned int dnlp_sel; extern void ve_dnlp_load_reg(void); @@ -161,5 +164,8 @@ extern int vpp_set_lut3d(int enable, int bLut3DLoad, extern void vpp_lut3d_table_init(int *pLut3D, int bitdepth); extern void dump_plut3d_table(void); extern void dump_plut3d_reg_table(void); + +extern void amvecm_gamma_init(bool en); + #endif diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm.c b/drivers/amlogic/media/enhancement/amvecm/amvecm.c index 92e95b5..6475b1c 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm.c @@ -5198,7 +5198,7 @@ void init_pq_setting(void) } /* #endif*/ -static void amvecm_gamma_init(bool en) +void amvecm_gamma_init(bool en) { unsigned int i; unsigned short data[256]; diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm_drm.c b/drivers/amlogic/media/enhancement/amvecm/amvecm_drm.c new file mode 100644 index 0000000..602ca96 --- /dev/null +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm_drm.c @@ -0,0 +1,133 @@ +/* + * drivers/amlogic/media/enhancement/amvecm/amvecm_drm.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include "arch/ve_regs.h" +#include "arch/vpp_regs.h" +#include "amve.h" + +void amvecm_drm_init(u32 index) +{ + amvecm_gamma_init(1); +} +EXPORT_SYMBOL(amvecm_drm_init); + +/*gamam size*/ +int amvecm_drm_get_gamma_size(u32 index) +{ + return GAMMA_SIZE; +} +EXPORT_SYMBOL(amvecm_drm_get_gamma_size); + +/*get gamma table*/ +int amvecm_drm_gamma_get(u32 index, u16 *red, u16 *green, u16 *blue) +{ + int i = 0; + + for (i = 0; i < GAMMA_SIZE; i++) { + red[i] = video_gamma_table_r.data[i] << 6; + green[i] = video_gamma_table_g.data[i] << 6; + blue[i] = video_gamma_table_b.data[i] << 6; + } + return 0; +} +EXPORT_SYMBOL(amvecm_drm_gamma_get); + +/*set gamma table*/ +int amvecm_drm_gamma_set(u32 index, struct drm_color_lut *lut, int lut_size) +{ + + int i = 0; + + if (lut_size != GAMMA_SIZE) { + pr_info("AMGAMMA_DRM: %s: lutsize is unsuitable\n", __func__); + return -1; + } + + for (i = 0; i < GAMMA_SIZE; i++) { + video_gamma_table_r.data[i] = ((lut[i].red >> 6) & 0x3ff); + video_gamma_table_g.data[i] = ((lut[i].green >> 6) & 0x3ff); + video_gamma_table_b.data[i] = ((lut[i].blue >> 6) & 0x3ff); + } + + vecm_latch_flag |= FLAG_GAMMA_TABLE_R; + vecm_latch_flag |= FLAG_GAMMA_TABLE_G; + vecm_latch_flag |= FLAG_GAMMA_TABLE_B; + + return 0; +} +EXPORT_SYMBOL(amvecm_drm_gamma_set); + +/*gamma enable*/ +int amvecm_drm_gamma_enable(u32 index) +{ + vecm_latch_flag |= FLAG_GAMMA_TABLE_EN; + return 0; +} +EXPORT_SYMBOL(amvecm_drm_gamma_enable); + +/*gamma disable*/ +int amvecm_drm_gamma_disable(u32 index) +{ + vecm_latch_flag |= FLAG_GAMMA_TABLE_DIS; + return 0; +} +EXPORT_SYMBOL(amvecm_drm_gamma_disable); + +int am_meson_ctm_set(u32 index, struct drm_color_ctm *ctm) +{ + int64_t m[9]; + int i = 0; + + for (i = 0; i < 9; i++) { + m[i] = ctm->matrix[i]; + // DRM uses signed 32.32 fixed point while Meson expects signed + // 3.10 fixed point. The following operations are performed to + // transform the numbers: + // - shift the sign bit from bit 63 to bit 12, + // - shift the 2 integer bits from from starting bit 21 to 10, + // - shift the fractional part and take the 10 significant bits. + m[i] = ((m[i] >> 51) & 0x1000) | ((m[i] >> 22) & 0xfff); + } + VSYNC_WR_MPEG_REG_BITS(VPP_POST_MATRIX_EN_CTRL, 1, 0, 1); + + VSYNC_WR_MPEG_REG(VPP_POST_MATRIX_COEF00_01, ((m[0] & 0xfff) << 16) + | (m[1] & 0xfff)); + VSYNC_WR_MPEG_REG(VPP_POST_MATRIX_COEF02_10, ((m[2] & 0xfff) << 16) + | (m[3] & 0xfff)); + VSYNC_WR_MPEG_REG(VPP_POST_MATRIX_COEF11_12, ((m[4] & 0xfff) << 16) + | (m[5] & 0xfff)); + VSYNC_WR_MPEG_REG(VPP_POST_MATRIX_COEF20_21, ((m[6] & 0xfff) << 16) + | (m[7] & 0xfff)); + VSYNC_WR_MPEG_REG(VPP_POST_MATRIX_COEF22, (m[8] & 0xfff)); + VSYNC_WR_MPEG_REG(VPP_POST_MATRIX_OFFSET0_1, 0x0); + VSYNC_WR_MPEG_REG(VPP_POST_MATRIX_OFFSET2, 0x0); + VSYNC_WR_MPEG_REG(VPP_POST_MATRIX_PRE_OFFSET0_1, 0x0); + VSYNC_WR_MPEG_REG(VPP_POST_MATRIX_PRE_OFFSET2, 0x0); + return 0; +} +EXPORT_SYMBOL(am_meson_ctm_set); + +int am_meson_ctm_disable(void) +{ + VSYNC_WR_MPEG_REG_BITS(VPP_POST_MATRIX_EN_CTRL, 0, 0, 1); + return 0; +} +EXPORT_SYMBOL(am_meson_ctm_disable); diff --git a/include/linux/amlogic/media/amvecm/amvecm.h b/include/linux/amlogic/media/amvecm/amvecm.h index ba81bd2..59e88fe 100644 --- a/include/linux/amlogic/media/amvecm/amvecm.h +++ b/include/linux/amlogic/media/amvecm/amvecm.h @@ -23,6 +23,8 @@ #include #include #include +#include + /* struct ve_dnlp_s video_ve_dnlp; */ @@ -429,5 +431,15 @@ extern int VSYNC_WR_MPEG_REG_BITS(u32 adr, u32 val, u32 start, u32 len); extern u32 VSYNC_RD_MPEG_REG(u32 adr); extern int VSYNC_WR_MPEG_REG(u32 adr, u32 val); #endif +extern int amvecm_drm_get_gamma_size(u32 index); +extern void amvecm_drm_init(u32 index); +extern int amvecm_drm_gamma_set(u32 index, + struct drm_color_lut *lut, int lut_size); +extern int amvecm_drm_gamma_get(u32 index, u16 *red, u16 *green, u16 *blue); +extern int amvecm_drm_gamma_enable(u32 index); +extern int amvecm_drm_gamma_disable(u32 index); +extern int am_meson_ctm_set(u32 index, struct drm_color_ctm *ctm); +extern int am_meson_ctm_disable(void); + #endif /* AMVECM_H */