2019-05-19 15:51:43 +02:00
// SPDX-License-Identifier: GPL-2.0-or-later
2016-11-10 15:29:37 +01:00
/*
* Copyright ( C ) 2016 BayLibre , SAS
* Author : Neil Armstrong < narmstrong @ baylibre . com >
* Copyright ( C ) 2015 Amlogic , Inc . All rights reserved .
* Copyright ( C ) 2014 Endless Mobile
*
* Written by :
* Jasper St . Pierre < jstpierre @ mecheye . net >
*/
2018-11-06 10:40:00 +01:00
# include <linux/bitfield.h>
2019-07-16 08:42:02 +02:00
# include <linux/soc/amlogic/meson-canvas.h>
2016-11-10 15:29:37 +01:00
# include <drm/drm_atomic_helper.h>
2019-07-16 08:42:02 +02:00
# include <drm/drm_device.h>
# include <drm/drm_print.h>
2019-01-17 22:03:34 +01:00
# include <drm/drm_probe_helper.h>
2019-07-16 08:42:02 +02:00
# include <drm/drm_vblank.h>
2016-11-10 15:29:37 +01:00
# include "meson_crtc.h"
# include "meson_plane.h"
2019-07-16 08:42:02 +02:00
# include "meson_registers.h"
2017-02-07 17:16:26 +08:00
# include "meson_venc.h"
2016-11-10 15:29:37 +01:00
# include "meson_viu.h"
2019-10-21 11:15:09 +02:00
# include "meson_rdma.h"
2019-07-16 08:42:02 +02:00
# include "meson_vpp.h"
2019-10-21 11:15:09 +02:00
# include "meson_osd_afbcd.h"
2016-11-10 15:29:37 +01:00
2019-03-25 15:18:20 +01:00
# define MESON_G12A_VIU_OFFSET 0x5ec0
2016-11-10 15:29:37 +01:00
/* CRTC definition */
struct meson_crtc {
struct drm_crtc base ;
struct drm_pending_vblank_event * event ;
struct meson_drm * priv ;
2019-03-25 15:18:20 +01:00
void ( * enable_osd1 ) ( struct meson_drm * priv ) ;
void ( * enable_vd1 ) ( struct meson_drm * priv ) ;
2019-10-21 11:15:09 +02:00
void ( * enable_osd1_afbc ) ( struct meson_drm * priv ) ;
void ( * disable_osd1_afbc ) ( struct meson_drm * priv ) ;
2019-03-25 15:18:20 +01:00
unsigned int viu_offset ;
2019-10-21 11:15:09 +02:00
bool vsync_forced ;
bool vsync_disabled ;
2016-11-10 15:29:37 +01:00
} ;
# define to_meson_crtc(x) container_of(x, struct meson_crtc, base)
/* CRTC */
2017-02-07 17:16:26 +08:00
static int meson_crtc_enable_vblank ( struct drm_crtc * crtc )
{
struct meson_crtc * meson_crtc = to_meson_crtc ( crtc ) ;
struct meson_drm * priv = meson_crtc - > priv ;
2019-10-21 11:15:09 +02:00
meson_crtc - > vsync_disabled = false ;
2017-02-07 17:16:26 +08:00
meson_venc_enable_vsync ( priv ) ;
return 0 ;
}
static void meson_crtc_disable_vblank ( struct drm_crtc * crtc )
{
struct meson_crtc * meson_crtc = to_meson_crtc ( crtc ) ;
struct meson_drm * priv = meson_crtc - > priv ;
2019-10-21 11:15:09 +02:00
if ( ! meson_crtc - > vsync_forced ) {
meson_crtc - > vsync_disabled = true ;
meson_venc_disable_vsync ( priv ) ;
}
2017-02-07 17:16:26 +08:00
}
2016-11-10 15:29:37 +01:00
static const struct drm_crtc_funcs meson_crtc_funcs = {
. atomic_destroy_state = drm_atomic_helper_crtc_destroy_state ,
. atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state ,
. destroy = drm_crtc_cleanup ,
. page_flip = drm_atomic_helper_page_flip ,
. reset = drm_atomic_helper_crtc_reset ,
. set_config = drm_atomic_helper_set_config ,
2017-02-07 17:16:26 +08:00
. enable_vblank = meson_crtc_enable_vblank ,
. disable_vblank = meson_crtc_disable_vblank ,
2016-11-10 15:29:37 +01:00
} ;
2019-03-25 15:18:20 +01:00
static void meson_g12a_crtc_atomic_enable ( struct drm_crtc * crtc ,
struct drm_crtc_state * old_state )
{
struct meson_crtc * meson_crtc = to_meson_crtc ( crtc ) ;
struct drm_crtc_state * crtc_state = crtc - > state ;
struct meson_drm * priv = meson_crtc - > priv ;
DRM_DEBUG_DRIVER ( " \n " ) ;
if ( ! crtc_state ) {
DRM_ERROR ( " Invalid crtc_state \n " ) ;
return ;
}
/* VD1 Preblend vertical start/end */
writel ( FIELD_PREP ( GENMASK ( 11 , 0 ) , 2303 ) ,
priv - > io_base + _REG ( VPP_PREBLEND_VD1_V_START_END ) ) ;
/* Setup Blender */
writel ( crtc_state - > mode . hdisplay |
crtc_state - > mode . vdisplay < < 16 ,
priv - > io_base + _REG ( VPP_POSTBLEND_H_SIZE ) ) ;
writel_relaxed ( 0 < < 16 |
( crtc_state - > mode . hdisplay - 1 ) ,
priv - > io_base + _REG ( VPP_OSD1_BLD_H_SCOPE ) ) ;
writel_relaxed ( 0 < < 16 |
( crtc_state - > mode . vdisplay - 1 ) ,
priv - > io_base + _REG ( VPP_OSD1_BLD_V_SCOPE ) ) ;
writel_relaxed ( crtc_state - > mode . hdisplay < < 16 |
crtc_state - > mode . vdisplay ,
priv - > io_base + _REG ( VPP_OUT_H_V_SIZE ) ) ;
drm_crtc_vblank_on ( crtc ) ;
}
2019-01-14 16:31:18 +01:00
static void meson_crtc_atomic_enable ( struct drm_crtc * crtc ,
struct drm_crtc_state * old_state )
2016-11-10 15:29:37 +01:00
{
struct meson_crtc * meson_crtc = to_meson_crtc ( crtc ) ;
2017-04-04 14:15:21 +02:00
struct drm_crtc_state * crtc_state = crtc - > state ;
2016-11-10 15:29:37 +01:00
struct meson_drm * priv = meson_crtc - > priv ;
2017-04-04 14:15:21 +02:00
DRM_DEBUG_DRIVER ( " \n " ) ;
if ( ! crtc_state ) {
DRM_ERROR ( " Invalid crtc_state \n " ) ;
return ;
}
2016-11-10 15:29:37 +01:00
/* Enable VPP Postblend */
2017-04-04 14:15:21 +02:00
writel ( crtc_state - > mode . hdisplay ,
2016-11-10 15:29:37 +01:00
priv - > io_base + _REG ( VPP_POSTBLEND_H_SIZE ) ) ;
2018-11-06 10:40:00 +01:00
/* VD1 Preblend vertical start/end */
writel ( FIELD_PREP ( GENMASK ( 11 , 0 ) , 2303 ) ,
priv - > io_base + _REG ( VPP_PREBLEND_VD1_V_START_END ) ) ;
2016-11-10 15:29:37 +01:00
writel_bits_relaxed ( VPP_POSTBLEND_ENABLE , VPP_POSTBLEND_ENABLE ,
priv - > io_base + _REG ( VPP_MISC ) ) ;
2018-11-22 17:01:03 +01:00
drm_crtc_vblank_on ( crtc ) ;
2016-11-10 15:29:37 +01:00
}
2019-03-25 15:18:20 +01:00
static void meson_g12a_crtc_atomic_disable ( struct drm_crtc * crtc ,
struct drm_crtc_state * old_state )
{
struct meson_crtc * meson_crtc = to_meson_crtc ( crtc ) ;
struct meson_drm * priv = meson_crtc - > priv ;
DRM_DEBUG_DRIVER ( " \n " ) ;
drm_crtc_vblank_off ( crtc ) ;
priv - > viu . osd1_enabled = false ;
priv - > viu . osd1_commit = false ;
priv - > viu . vd1_enabled = false ;
priv - > viu . vd1_commit = false ;
if ( crtc - > state - > event & & ! crtc - > state - > active ) {
spin_lock_irq ( & crtc - > dev - > event_lock ) ;
drm_crtc_send_vblank_event ( crtc , crtc - > state - > event ) ;
spin_unlock_irq ( & crtc - > dev - > event_lock ) ;
crtc - > state - > event = NULL ;
}
}
2017-06-30 12:36:45 +03:00
static void meson_crtc_atomic_disable ( struct drm_crtc * crtc ,
struct drm_crtc_state * old_state )
2016-11-10 15:29:37 +01:00
{
struct meson_crtc * meson_crtc = to_meson_crtc ( crtc ) ;
struct meson_drm * priv = meson_crtc - > priv ;
2018-11-06 10:40:00 +01:00
DRM_DEBUG_DRIVER ( " \n " ) ;
2018-11-22 17:01:03 +01:00
drm_crtc_vblank_off ( crtc ) ;
2016-11-10 15:29:37 +01:00
priv - > viu . osd1_enabled = false ;
2017-04-04 14:15:21 +02:00
priv - > viu . osd1_commit = false ;
2016-11-10 15:29:37 +01:00
2018-11-06 10:40:00 +01:00
priv - > viu . vd1_enabled = false ;
priv - > viu . vd1_commit = false ;
2016-11-10 15:29:37 +01:00
/* Disable VPP Postblend */
2018-11-06 10:40:00 +01:00
writel_bits_relaxed ( VPP_OSD1_POSTBLEND | VPP_VD1_POSTBLEND |
VPP_VD1_PREBLEND | VPP_POSTBLEND_ENABLE , 0 ,
2016-11-10 15:29:37 +01:00
priv - > io_base + _REG ( VPP_MISC ) ) ;
if ( crtc - > state - > event & & ! crtc - > state - > active ) {
spin_lock_irq ( & crtc - > dev - > event_lock ) ;
drm_crtc_send_vblank_event ( crtc , crtc - > state - > event ) ;
spin_unlock_irq ( & crtc - > dev - > event_lock ) ;
crtc - > state - > event = NULL ;
}
}
static void meson_crtc_atomic_begin ( struct drm_crtc * crtc ,
struct drm_crtc_state * state )
{
struct meson_crtc * meson_crtc = to_meson_crtc ( crtc ) ;
unsigned long flags ;
if ( crtc - > state - > event ) {
WARN_ON ( drm_crtc_vblank_get ( crtc ) ! = 0 ) ;
spin_lock_irqsave ( & crtc - > dev - > event_lock , flags ) ;
meson_crtc - > event = crtc - > state - > event ;
spin_unlock_irqrestore ( & crtc - > dev - > event_lock , flags ) ;
crtc - > state - > event = NULL ;
}
}
static void meson_crtc_atomic_flush ( struct drm_crtc * crtc ,
struct drm_crtc_state * old_crtc_state )
{
struct meson_crtc * meson_crtc = to_meson_crtc ( crtc ) ;
struct meson_drm * priv = meson_crtc - > priv ;
2017-04-04 14:15:21 +02:00
priv - > viu . osd1_commit = true ;
2018-11-06 10:40:00 +01:00
priv - > viu . vd1_commit = true ;
2016-11-10 15:29:37 +01:00
}
static const struct drm_crtc_helper_funcs meson_crtc_helper_funcs = {
. atomic_begin = meson_crtc_atomic_begin ,
. atomic_flush = meson_crtc_atomic_flush ,
2017-06-30 12:36:44 +03:00
. atomic_enable = meson_crtc_atomic_enable ,
2017-06-30 12:36:45 +03:00
. atomic_disable = meson_crtc_atomic_disable ,
2016-11-10 15:29:37 +01:00
} ;
2019-03-25 15:18:20 +01:00
static const struct drm_crtc_helper_funcs meson_g12a_crtc_helper_funcs = {
. atomic_begin = meson_crtc_atomic_begin ,
. atomic_flush = meson_crtc_atomic_flush ,
. atomic_enable = meson_g12a_crtc_atomic_enable ,
. atomic_disable = meson_g12a_crtc_atomic_disable ,
} ;
static void meson_crtc_enable_osd1 ( struct meson_drm * priv )
{
writel_bits_relaxed ( VPP_OSD1_POSTBLEND , VPP_OSD1_POSTBLEND ,
priv - > io_base + _REG ( VPP_MISC ) ) ;
}
2019-10-21 11:15:09 +02:00
static void meson_crtc_g12a_enable_osd1_afbc ( struct meson_drm * priv )
{
writel_relaxed ( priv - > viu . osd1_blk2_cfg4 ,
priv - > io_base + _REG ( VIU_OSD1_BLK2_CFG_W4 ) ) ;
writel_bits_relaxed ( OSD_MEM_LINEAR_ADDR , OSD_MEM_LINEAR_ADDR ,
priv - > io_base + _REG ( VIU_OSD1_CTRL_STAT ) ) ;
writel_relaxed ( priv - > viu . osd1_blk1_cfg4 ,
priv - > io_base + _REG ( VIU_OSD1_BLK1_CFG_W4 ) ) ;
meson_viu_g12a_enable_osd1_afbc ( priv ) ;
writel_bits_relaxed ( OSD_MEM_LINEAR_ADDR , OSD_MEM_LINEAR_ADDR ,
priv - > io_base + _REG ( VIU_OSD1_CTRL_STAT ) ) ;
writel_bits_relaxed ( OSD_MALI_SRC_EN , OSD_MALI_SRC_EN ,
priv - > io_base + _REG ( VIU_OSD1_BLK0_CFG_W0 ) ) ;
}
2019-03-25 15:18:20 +01:00
static void meson_g12a_crtc_enable_osd1 ( struct meson_drm * priv )
{
writel_relaxed ( priv - > viu . osd_blend_din0_scope_h ,
priv - > io_base +
_REG ( VIU_OSD_BLEND_DIN0_SCOPE_H ) ) ;
writel_relaxed ( priv - > viu . osd_blend_din0_scope_v ,
priv - > io_base +
_REG ( VIU_OSD_BLEND_DIN0_SCOPE_V ) ) ;
writel_relaxed ( priv - > viu . osb_blend0_size ,
priv - > io_base +
_REG ( VIU_OSD_BLEND_BLEND0_SIZE ) ) ;
writel_relaxed ( priv - > viu . osb_blend1_size ,
priv - > io_base +
_REG ( VIU_OSD_BLEND_BLEND1_SIZE ) ) ;
2019-06-05 16:12:53 +02:00
writel_bits_relaxed ( 3 < < 8 , 3 < < 8 ,
priv - > io_base + _REG ( OSD1_BLEND_SRC_CTRL ) ) ;
2019-03-25 15:18:20 +01:00
}
static void meson_crtc_enable_vd1 ( struct meson_drm * priv )
{
writel_bits_relaxed ( VPP_VD1_PREBLEND | VPP_VD1_POSTBLEND |
VPP_COLOR_MNG_ENABLE ,
VPP_VD1_PREBLEND | VPP_VD1_POSTBLEND |
VPP_COLOR_MNG_ENABLE ,
priv - > io_base + _REG ( VPP_MISC ) ) ;
}
static void meson_g12a_crtc_enable_vd1 ( struct meson_drm * priv )
{
2019-06-24 16:48:12 +02:00
writel_relaxed ( VD_BLEND_PREBLD_SRC_VD1 |
VD_BLEND_PREBLD_PREMULT_EN |
VD_BLEND_POSTBLD_SRC_VD1 |
VD_BLEND_POSTBLD_PREMULT_EN ,
priv - > io_base + _REG ( VD1_BLEND_SRC_CTRL ) ) ;
2019-03-25 15:18:20 +01:00
}
2016-11-10 15:29:37 +01:00
void meson_crtc_irq ( struct meson_drm * priv )
{
struct meson_crtc * meson_crtc = to_meson_crtc ( priv - > crtc ) ;
unsigned long flags ;
/* Update the OSD registers */
if ( priv - > viu . osd1_enabled & & priv - > viu . osd1_commit ) {
writel_relaxed ( priv - > viu . osd1_ctrl_stat ,
priv - > io_base + _REG ( VIU_OSD1_CTRL_STAT ) ) ;
2019-10-21 11:15:06 +02:00
writel_relaxed ( priv - > viu . osd1_ctrl_stat2 ,
priv - > io_base + _REG ( VIU_OSD1_CTRL_STAT2 ) ) ;
2016-11-10 15:29:37 +01:00
writel_relaxed ( priv - > viu . osd1_blk0_cfg [ 0 ] ,
priv - > io_base + _REG ( VIU_OSD1_BLK0_CFG_W0 ) ) ;
writel_relaxed ( priv - > viu . osd1_blk0_cfg [ 1 ] ,
priv - > io_base + _REG ( VIU_OSD1_BLK0_CFG_W1 ) ) ;
writel_relaxed ( priv - > viu . osd1_blk0_cfg [ 2 ] ,
priv - > io_base + _REG ( VIU_OSD1_BLK0_CFG_W2 ) ) ;
writel_relaxed ( priv - > viu . osd1_blk0_cfg [ 3 ] ,
priv - > io_base + _REG ( VIU_OSD1_BLK0_CFG_W3 ) ) ;
writel_relaxed ( priv - > viu . osd1_blk0_cfg [ 4 ] ,
priv - > io_base + _REG ( VIU_OSD1_BLK0_CFG_W4 ) ) ;
2019-10-21 11:15:09 +02:00
if ( priv - > viu . osd1_afbcd ) {
if ( meson_crtc - > enable_osd1_afbc )
meson_crtc - > enable_osd1_afbc ( priv ) ;
} else {
if ( meson_crtc - > disable_osd1_afbc )
meson_crtc - > disable_osd1_afbc ( priv ) ;
if ( priv - > afbcd . ops ) {
priv - > afbcd . ops - > reset ( priv ) ;
priv - > afbcd . ops - > disable ( priv ) ;
}
meson_crtc - > vsync_forced = false ;
}
2018-11-06 10:40:01 +01:00
writel_relaxed ( priv - > viu . osd_sc_ctrl0 ,
priv - > io_base + _REG ( VPP_OSD_SC_CTRL0 ) ) ;
writel_relaxed ( priv - > viu . osd_sc_i_wh_m1 ,
priv - > io_base + _REG ( VPP_OSD_SCI_WH_M1 ) ) ;
writel_relaxed ( priv - > viu . osd_sc_o_h_start_end ,
priv - > io_base + _REG ( VPP_OSD_SCO_H_START_END ) ) ;
writel_relaxed ( priv - > viu . osd_sc_o_v_start_end ,
priv - > io_base + _REG ( VPP_OSD_SCO_V_START_END ) ) ;
writel_relaxed ( priv - > viu . osd_sc_v_ini_phase ,
priv - > io_base + _REG ( VPP_OSD_VSC_INI_PHASE ) ) ;
writel_relaxed ( priv - > viu . osd_sc_v_phase_step ,
priv - > io_base + _REG ( VPP_OSD_VSC_PHASE_STEP ) ) ;
writel_relaxed ( priv - > viu . osd_sc_h_ini_phase ,
priv - > io_base + _REG ( VPP_OSD_HSC_INI_PHASE ) ) ;
writel_relaxed ( priv - > viu . osd_sc_h_phase_step ,
priv - > io_base + _REG ( VPP_OSD_HSC_PHASE_STEP ) ) ;
writel_relaxed ( priv - > viu . osd_sc_h_ctrl0 ,
priv - > io_base + _REG ( VPP_OSD_HSC_CTRL0 ) ) ;
writel_relaxed ( priv - > viu . osd_sc_v_ctrl0 ,
priv - > io_base + _REG ( VPP_OSD_VSC_CTRL0 ) ) ;
2016-11-10 15:29:37 +01:00
2019-10-21 11:15:09 +02:00
if ( ! priv - > viu . osd1_afbcd )
meson_canvas_config ( priv - > canvas , priv - > canvas_id_osd1 ,
priv - > viu . osd1_addr ,
priv - > viu . osd1_stride ,
priv - > viu . osd1_height ,
MESON_CANVAS_WRAP_NONE ,
MESON_CANVAS_BLKMODE_LINEAR , 0 ) ;
2018-02-15 11:19:36 +01:00
2016-11-10 15:29:37 +01:00
/* Enable OSD1 */
2019-03-25 15:18:20 +01:00
if ( meson_crtc - > enable_osd1 )
meson_crtc - > enable_osd1 ( priv ) ;
2016-11-10 15:29:37 +01:00
2019-10-21 11:15:09 +02:00
if ( priv - > viu . osd1_afbcd ) {
priv - > afbcd . ops - > reset ( priv ) ;
priv - > afbcd . ops - > setup ( priv ) ;
priv - > afbcd . ops - > enable ( priv ) ;
meson_crtc - > vsync_forced = true ;
}
2016-11-10 15:29:37 +01:00
priv - > viu . osd1_commit = false ;
}
2018-11-06 10:40:00 +01:00
/* Update the VD1 registers */
if ( priv - > viu . vd1_enabled & & priv - > viu . vd1_commit ) {
switch ( priv - > viu . vd1_planes ) {
case 3 :
2019-03-11 11:51:44 +01:00
meson_canvas_config ( priv - > canvas ,
priv - > canvas_id_vd1_2 ,
priv - > viu . vd1_addr2 ,
priv - > viu . vd1_stride2 ,
priv - > viu . vd1_height2 ,
MESON_CANVAS_WRAP_NONE ,
MESON_CANVAS_BLKMODE_LINEAR ,
MESON_CANVAS_ENDIAN_SWAP64 ) ;
2018-11-06 10:40:00 +01:00
/* fallthrough */
case 2 :
2019-03-11 11:51:44 +01:00
meson_canvas_config ( priv - > canvas ,
priv - > canvas_id_vd1_1 ,
priv - > viu . vd1_addr1 ,
priv - > viu . vd1_stride1 ,
priv - > viu . vd1_height1 ,
MESON_CANVAS_WRAP_NONE ,
MESON_CANVAS_BLKMODE_LINEAR ,
MESON_CANVAS_ENDIAN_SWAP64 ) ;
2018-11-06 10:40:00 +01:00
/* fallthrough */
case 1 :
2019-03-11 11:51:44 +01:00
meson_canvas_config ( priv - > canvas ,
priv - > canvas_id_vd1_0 ,
priv - > viu . vd1_addr0 ,
priv - > viu . vd1_stride0 ,
priv - > viu . vd1_height0 ,
MESON_CANVAS_WRAP_NONE ,
MESON_CANVAS_BLKMODE_LINEAR ,
MESON_CANVAS_ENDIAN_SWAP64 ) ;
2019-12-16 11:58:21 +08:00
}
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . vd1_if0_gen_reg ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD1_IF0_GEN_REG ) ) ;
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . vd1_if0_gen_reg ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD2_IF0_GEN_REG ) ) ;
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . vd1_if0_gen_reg2 ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD1_IF0_GEN_REG2 ) ) ;
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . viu_vd1_fmt_ctrl ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VIU_VD1_FMT_CTRL ) ) ;
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . viu_vd1_fmt_ctrl ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VIU_VD2_FMT_CTRL ) ) ;
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . viu_vd1_fmt_w ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VIU_VD1_FMT_W ) ) ;
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . viu_vd1_fmt_w ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VIU_VD2_FMT_W ) ) ;
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . vd1_if0_canvas0 ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD1_IF0_CANVAS0 ) ) ;
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . vd1_if0_canvas0 ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD1_IF0_CANVAS1 ) ) ;
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . vd1_if0_canvas0 ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD2_IF0_CANVAS0 ) ) ;
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . vd1_if0_canvas0 ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD2_IF0_CANVAS1 ) ) ;
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . vd1_if0_luma_x0 ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD1_IF0_LUMA_X0 ) ) ;
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . vd1_if0_luma_x0 ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD1_IF0_LUMA_X1 ) ) ;
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . vd1_if0_luma_x0 ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD2_IF0_LUMA_X0 ) ) ;
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . vd1_if0_luma_x0 ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD2_IF0_LUMA_X1 ) ) ;
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . vd1_if0_luma_y0 ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD1_IF0_LUMA_Y0 ) ) ;
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . vd1_if0_luma_y0 ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD1_IF0_LUMA_Y1 ) ) ;
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . vd1_if0_luma_y0 ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD2_IF0_LUMA_Y0 ) ) ;
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . vd1_if0_luma_y0 ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD2_IF0_LUMA_Y1 ) ) ;
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . vd1_if0_chroma_x0 ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD1_IF0_CHROMA_X0 ) ) ;
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . vd1_if0_chroma_x0 ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD1_IF0_CHROMA_X1 ) ) ;
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . vd1_if0_chroma_x0 ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD2_IF0_CHROMA_X0 ) ) ;
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . vd1_if0_chroma_x0 ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD2_IF0_CHROMA_X1 ) ) ;
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . vd1_if0_chroma_y0 ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD1_IF0_CHROMA_Y0 ) ) ;
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . vd1_if0_chroma_y0 ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD1_IF0_CHROMA_Y1 ) ) ;
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . vd1_if0_chroma_y0 ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD2_IF0_CHROMA_Y0 ) ) ;
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . vd1_if0_chroma_y0 ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD2_IF0_CHROMA_Y1 ) ) ;
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . vd1_if0_repeat_loop ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD1_IF0_RPT_LOOP ) ) ;
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . vd1_if0_repeat_loop ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD2_IF0_RPT_LOOP ) ) ;
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . vd1_if0_luma0_rpt_pat ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD1_IF0_LUMA0_RPT_PAT ) ) ;
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . vd1_if0_luma0_rpt_pat ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD2_IF0_LUMA0_RPT_PAT ) ) ;
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . vd1_if0_luma0_rpt_pat ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD1_IF0_LUMA1_RPT_PAT ) ) ;
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . vd1_if0_luma0_rpt_pat ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD2_IF0_LUMA1_RPT_PAT ) ) ;
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . vd1_if0_chroma0_rpt_pat ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD1_IF0_CHROMA0_RPT_PAT ) ) ;
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . vd1_if0_chroma0_rpt_pat ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD2_IF0_CHROMA0_RPT_PAT ) ) ;
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . vd1_if0_chroma0_rpt_pat ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD1_IF0_CHROMA1_RPT_PAT ) ) ;
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . vd1_if0_chroma0_rpt_pat ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD2_IF0_CHROMA1_RPT_PAT ) ) ;
writel_relaxed ( 0 , priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD1_IF0_LUMA_PSEL ) ) ;
writel_relaxed ( 0 , priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD1_IF0_CHROMA_PSEL ) ) ;
writel_relaxed ( 0 , priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD2_IF0_LUMA_PSEL ) ) ;
writel_relaxed ( 0 , priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD2_IF0_CHROMA_PSEL ) ) ;
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . vd1_range_map_y ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD1_IF0_RANGE_MAP_Y ) ) ;
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . vd1_range_map_cb ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD1_IF0_RANGE_MAP_CB ) ) ;
2018-11-06 10:40:00 +01:00
writel_relaxed ( priv - > viu . vd1_range_map_cr ,
2019-03-25 15:18:20 +01:00
priv - > io_base + meson_crtc - > viu_offset +
_REG ( VD1_IF0_RANGE_MAP_CR ) ) ;
2019-06-24 16:48:12 +02:00
writel_relaxed ( VPP_VSC_BANK_LENGTH ( 4 ) |
VPP_HSC_BANK_LENGTH ( 4 ) |
VPP_SC_VD_EN_ENABLE |
VPP_SC_TOP_EN_ENABLE |
VPP_SC_HSC_EN_ENABLE |
VPP_SC_VSC_EN_ENABLE ,
2018-11-06 10:40:00 +01:00
priv - > io_base + _REG ( VPP_SC_MISC ) ) ;
writel_relaxed ( priv - > viu . vpp_pic_in_height ,
priv - > io_base + _REG ( VPP_PIC_IN_HEIGHT ) ) ;
writel_relaxed ( priv - > viu . vpp_postblend_vd1_h_start_end ,
priv - > io_base + _REG ( VPP_POSTBLEND_VD1_H_START_END ) ) ;
writel_relaxed ( priv - > viu . vpp_blend_vd2_h_start_end ,
priv - > io_base + _REG ( VPP_BLEND_VD2_H_START_END ) ) ;
writel_relaxed ( priv - > viu . vpp_postblend_vd1_v_start_end ,
priv - > io_base + _REG ( VPP_POSTBLEND_VD1_V_START_END ) ) ;
writel_relaxed ( priv - > viu . vpp_blend_vd2_v_start_end ,
priv - > io_base + _REG ( VPP_BLEND_VD2_V_START_END ) ) ;
writel_relaxed ( priv - > viu . vpp_hsc_region12_startp ,
priv - > io_base + _REG ( VPP_HSC_REGION12_STARTP ) ) ;
writel_relaxed ( priv - > viu . vpp_hsc_region34_startp ,
priv - > io_base + _REG ( VPP_HSC_REGION34_STARTP ) ) ;
writel_relaxed ( priv - > viu . vpp_hsc_region4_endp ,
priv - > io_base + _REG ( VPP_HSC_REGION4_ENDP ) ) ;
writel_relaxed ( priv - > viu . vpp_hsc_start_phase_step ,
priv - > io_base + _REG ( VPP_HSC_START_PHASE_STEP ) ) ;
writel_relaxed ( priv - > viu . vpp_hsc_region1_phase_slope ,
priv - > io_base + _REG ( VPP_HSC_REGION1_PHASE_SLOPE ) ) ;
writel_relaxed ( priv - > viu . vpp_hsc_region3_phase_slope ,
priv - > io_base + _REG ( VPP_HSC_REGION3_PHASE_SLOPE ) ) ;
writel_relaxed ( priv - > viu . vpp_line_in_length ,
priv - > io_base + _REG ( VPP_LINE_IN_LENGTH ) ) ;
writel_relaxed ( priv - > viu . vpp_preblend_h_size ,
priv - > io_base + _REG ( VPP_PREBLEND_H_SIZE ) ) ;
writel_relaxed ( priv - > viu . vpp_vsc_region12_startp ,
priv - > io_base + _REG ( VPP_VSC_REGION12_STARTP ) ) ;
writel_relaxed ( priv - > viu . vpp_vsc_region34_startp ,
priv - > io_base + _REG ( VPP_VSC_REGION34_STARTP ) ) ;
writel_relaxed ( priv - > viu . vpp_vsc_region4_endp ,
priv - > io_base + _REG ( VPP_VSC_REGION4_ENDP ) ) ;
writel_relaxed ( priv - > viu . vpp_vsc_start_phase_step ,
priv - > io_base + _REG ( VPP_VSC_START_PHASE_STEP ) ) ;
writel_relaxed ( priv - > viu . vpp_vsc_ini_phase ,
priv - > io_base + _REG ( VPP_VSC_INI_PHASE ) ) ;
writel_relaxed ( priv - > viu . vpp_vsc_phase_ctrl ,
priv - > io_base + _REG ( VPP_VSC_PHASE_CTRL ) ) ;
writel_relaxed ( priv - > viu . vpp_hsc_phase_ctrl ,
priv - > io_base + _REG ( VPP_HSC_PHASE_CTRL ) ) ;
writel_relaxed ( 0x42 , priv - > io_base + _REG ( VPP_SCALE_COEF_IDX ) ) ;
/* Enable VD1 */
2019-03-25 15:18:20 +01:00
if ( meson_crtc - > enable_vd1 )
meson_crtc - > enable_vd1 ( priv ) ;
2018-11-06 10:40:00 +01:00
priv - > viu . vd1_commit = false ;
}
2019-10-21 11:15:09 +02:00
if ( meson_crtc - > vsync_disabled )
return ;
2016-11-10 15:29:37 +01:00
drm_crtc_handle_vblank ( priv - > crtc ) ;
spin_lock_irqsave ( & priv - > drm - > event_lock , flags ) ;
if ( meson_crtc - > event ) {
drm_crtc_send_vblank_event ( priv - > crtc , meson_crtc - > event ) ;
drm_crtc_vblank_put ( priv - > crtc ) ;
meson_crtc - > event = NULL ;
}
spin_unlock_irqrestore ( & priv - > drm - > event_lock , flags ) ;
}
int meson_crtc_create ( struct meson_drm * priv )
{
struct meson_crtc * meson_crtc ;
struct drm_crtc * crtc ;
int ret ;
meson_crtc = devm_kzalloc ( priv - > drm - > dev , sizeof ( * meson_crtc ) ,
GFP_KERNEL ) ;
if ( ! meson_crtc )
return - ENOMEM ;
meson_crtc - > priv = priv ;
crtc = & meson_crtc - > base ;
ret = drm_crtc_init_with_planes ( priv - > drm , crtc ,
priv - > primary_plane , NULL ,
& meson_crtc_funcs , " meson_crtc " ) ;
if ( ret ) {
dev_err ( priv - > drm - > dev , " Failed to init CRTC \n " ) ;
return ret ;
}
2019-08-22 16:43:41 +02:00
if ( meson_vpu_is_compatible ( priv , VPU_COMPATIBLE_G12A ) ) {
2019-03-25 15:18:20 +01:00
meson_crtc - > enable_osd1 = meson_g12a_crtc_enable_osd1 ;
meson_crtc - > enable_vd1 = meson_g12a_crtc_enable_vd1 ;
meson_crtc - > viu_offset = MESON_G12A_VIU_OFFSET ;
2019-10-21 11:15:09 +02:00
meson_crtc - > enable_osd1_afbc =
meson_crtc_g12a_enable_osd1_afbc ;
meson_crtc - > disable_osd1_afbc =
meson_viu_g12a_disable_osd1_afbc ;
2019-03-25 15:18:20 +01:00
drm_crtc_helper_add ( crtc , & meson_g12a_crtc_helper_funcs ) ;
} else {
meson_crtc - > enable_osd1 = meson_crtc_enable_osd1 ;
meson_crtc - > enable_vd1 = meson_crtc_enable_vd1 ;
2019-10-21 11:15:09 +02:00
if ( meson_vpu_is_compatible ( priv , VPU_COMPATIBLE_GXM ) ) {
meson_crtc - > enable_osd1_afbc =
meson_viu_gxm_enable_osd1_afbc ;
meson_crtc - > disable_osd1_afbc =
meson_viu_gxm_disable_osd1_afbc ;
}
2019-03-25 15:18:20 +01:00
drm_crtc_helper_add ( crtc , & meson_crtc_helper_funcs ) ;
}
2016-11-10 15:29:37 +01:00
priv - > crtc = crtc ;
return 0 ;
}