Hi Piotr, At 2024-11-02 03:01:17, "Piotr Zalewski" <pz010001011...@proton.me> wrote: >Add support for gamma LUT in VOP2 driver. The implementation was inspired >by one found in VOP1 driver. Blue and red channels in gamma LUT register >write were swapped with respect to how gamma LUT values are written in >VOP1. Gamma LUT port selection was added before the write of new gamma LUT >table. > >If the current SoC is rk356x, check if no other CRTC has gamma LUT enabled >in atomic_check (only one video port can use gamma LUT at a time) and >disable gamma LUT before the LUT table write. > >If the current SoC isn't rk356x, "seamless" gamma lut update is performed >similarly to how it was done in the case of RK3399 in VOP1[1]. In seamless >update gamma LUT disable before the write isn't necessary, check if no >other CRTC has gamma LUT enabled is also not necessary, different register >is being used to select gamma LUT port[2] and after setting DSP_LUT_EN bit, >GAMMA_UPDATE_EN bit is set[3]. > >Gamma size is set and drm color management is enabled for each video port's >CRTC except ones which have no associated device. > >Patch was tested on RK3566 (Pinetab2). When using userspace tools >which set eg. constant color temperature no issues were noticed. When >using userspace tools which adjust eg. color temperature the slight screen >flicker is visible probably because of gamma LUT disable needed in the >case of RK356x before gamma LUT write. > >Compare behaviour of eg.: >``` >gammastep -O 3000 >``` > >To eg.: >``` >gammastep -l 53:23 -t 6000:3000 >``` > >In latter case color temperature is slowly adjusted at the beginning which >causes screen to slighly flicker. Then it adjusts every few seconds which >also causes slight screen flicker. > >[1] >https://lists.infradead.org/pipermail/linux-rockchip/2021-October/028132.html >[2] >https://lore.kernel.org/linux-rockchip/48249708-8c05-40d2-a5d8-23de960c5...@rock-chips.com/ >[3] >https://github.com/radxa/kernel/blob/linux-6.1-stan-rkr1/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c#L3437 > >Helped-by: Daniel Stone <dan...@fooishbar.org> >Helped-by: Dragan Simic <dsi...@manjaro.org> >Helped-by: Diederik de Haas <didi.deb...@cknow.org> >Helped-by: Andy Yan <andy....@rock-chips.com> >Signed-off-by: Piotr Zalewski <pz010001011...@proton.me>
Reviewed-by: Andy Yan <andys...@163.com> >--- > >Notes: > Changes in v7: > - Code styling changes only [6]. > > Changes in v6: > - Move gamma lut write to atomic_flush[4]. > - In atomic_check if any other than the currently updated CRTC has > gamma lut enabled, return -EINVAL [5] (perform a check only if > device is rk356x). > - Instead of checking for rk3588 to determine seamless gamma > update availability check for rk3566/rk3568. > - remove null check in vop2_create_crtcs > - Move some code to separate functions to increase readability. > > Changes in v5: > - Do not trigger full modeset in case seamless gamma lut update > isn't possible (eg. rk356x case). It was discovered that with > full modeset, userspace tools which adjust color temperature with > high frequency cause screen to go black and reduce overall > performance. Instead, revert to previous behaviour of lut update > happening in atomic_begin or (in case there is a modeset) in > atomic_enable. Also, add unrelated to modeset trigger > changes/improvements from v4 on top. Improve code readability > too. > > Changes in v4: > - rework the implementation to better utilize DRM atomic updates[2] > - handle the RK3588 case[2][3] > > Changes in v3: > - v3 is patch v2 "resend", by mistake the incremental patch was > sent in v2 > > Changes in v2: > - Apply code styling corrections[1] > - Move gamma LUT write inside the vop2 lock > > Link to v6: > https://lore.kernel.org/linux-rockchip/20241016223558.673145-2-pz010001011...@proton.me/ > Link to v5: > https://lore.kernel.org/linux-rockchip/20241014222022.571819-4-pz010001011...@proton.me/ > Link to v4: > https://lore.kernel.org/linux-rockchip/20240815124306.189282-2-pz010001011...@proton.me/ > Link to v3: > https://lore.kernel.org/linux-rockchip/TkgKVivuaLFLILPY-n3iZo_8KF-daKdqdu-0_e0HP-5Ar_8DAL >DeNWog2suwWKjX7eomcbGET0KZe7DlzdhK2YM6CbLbeKeFZr-MJzJMtw0=@proton.me/ > Link to v2: > https://lore.kernel.org/linux-rockchip/Hk03HDb6wSSHWtEFZHUye06HR0-9YzP5nCHx9A8_kHzWSZawDr >U1o1pjEGkCOJFoRg0nTB4BWEv6V0XBOjF4-0Mj44lp2TrjaQfnytzp-Pk=@proton.me/ > Link to v1: > https://lore.kernel.org/linux-rockchip/ZVMxgcrtgHui9fJpnhbN6TSPhofHbbXElh241lImrzzTUl-8We >jGpaR8CPzYhBgoqe_xj7N6En8Ny7Z-gsCr0kaFs7apwjYV1MBJJLmLHxs=@proton.me/ > > [1] > https://lore.kernel.org/linux-rockchip/d019761504b540600d9fc7a585d6f...@manjaro.org > [2] > https://lore.kernel.org/linux-rockchip/CAPj87rOM=j0zmuWL9frGKV1xzPbJrk=Q9ip7F_HAPYnbCqPouw@mail.g >mail.com > [3] > https://lore.kernel.org/linux-rockchip/7d998e4c-e1d3-4e8b-af76-c5bc83b43...@rock-chips.com > [4] > https://lore.kernel.org/linux-rockchip/7b45f190.452f.1928e41b746.coremail.andys...@163.com/ > [5] > https://lore.kernel.org/linux-rockchip/CAPj87rOdQPsuH9qB_ZLfC9S=cO2noNi1mOGW0ZmQ6SHCugb9=w@mail.g >mail.com/ > [6] > https://lore.kernel.org/linux-rockchip/6a92e23a.56c.192d5ae32d5.coremail.andys...@163.com/ > > drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 190 +++++++++++++++++++ > drivers/gpu/drm/rockchip/rockchip_drm_vop2.h | 5 + > 2 files changed, 195 insertions(+) > >diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c >b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c >index 9873172e3fd3..58439ee8a52c 100644 >--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c >+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c >@@ -278,6 +278,15 @@ static u32 vop2_readl(struct vop2 *vop2, u32 offset) > return val; > } > >+static u32 vop2_vp_read(struct vop2_video_port *vp, u32 offset) >+{ >+ u32 val; >+ >+ regmap_read(vp->vop2->map, vp->data->offset + offset, &val); >+ >+ return val; >+} >+ > static void vop2_win_write(const struct vop2_win *win, unsigned int reg, u32 > v) > { > regmap_field_write(win->reg[reg], v); >@@ -998,6 +1007,67 @@ static void vop2_disable(struct vop2 *vop2) > clk_disable_unprepare(vop2->hclk); > } > >+static bool vop2_vp_dsp_lut_is_enabled(struct vop2_video_port *vp) >+{ >+ u32 dsp_ctrl = vop2_vp_read(vp, RK3568_VP_DSP_CTRL); >+ >+ return dsp_ctrl & RK3568_VP_DSP_CTRL__DSP_LUT_EN; >+} >+ >+static void vop2_vp_dsp_lut_disable(struct vop2_video_port *vp) >+{ >+ u32 dsp_ctrl = vop2_vp_read(vp, RK3568_VP_DSP_CTRL); >+ >+ dsp_ctrl &= ~RK3568_VP_DSP_CTRL__DSP_LUT_EN; >+ vop2_vp_write(vp, RK3568_VP_DSP_CTRL, dsp_ctrl); >+} >+ >+static bool vop2_vp_dsp_lut_poll_disabled(struct vop2_video_port *vp) >+{ >+ u32 dsp_ctrl; >+ int ret = readx_poll_timeout(vop2_vp_dsp_lut_is_enabled, vp, dsp_ctrl, >+ !dsp_ctrl, 5, 30 * 1000); >+ if (ret) { >+ drm_err(vp->vop2->drm, "display LUT RAM enable timeout!\n"); >+ return false; >+ } >+ >+ return true; >+} >+ >+static void vop2_vp_dsp_lut_enable(struct vop2_video_port *vp) >+{ >+ u32 dsp_ctrl = vop2_vp_read(vp, RK3568_VP_DSP_CTRL); >+ >+ dsp_ctrl |= RK3568_VP_DSP_CTRL__DSP_LUT_EN; >+ vop2_vp_write(vp, RK3568_VP_DSP_CTRL, dsp_ctrl); >+} >+ >+static void vop2_vp_dsp_lut_update_enable(struct vop2_video_port *vp) >+{ >+ u32 dsp_ctrl = vop2_vp_read(vp, RK3568_VP_DSP_CTRL); >+ >+ dsp_ctrl |= RK3588_VP_DSP_CTRL__GAMMA_UPDATE_EN; >+ vop2_vp_write(vp, RK3568_VP_DSP_CTRL, dsp_ctrl); >+} >+