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:02 +01:00
# include <linux/bitfield.h>
2019-07-16 08:42:02 +02:00
2016-11-10 15:29:37 +01:00
# include <drm/drm_atomic.h>
# include <drm/drm_atomic_helper.h>
2022-06-13 23:03:12 +03:00
# include <drm/drm_blend.h>
2019-07-16 08:42:02 +02:00
# include <drm/drm_device.h>
2022-08-02 02:04:02 +02:00
# include <drm/drm_fb_dma_helper.h>
2019-07-16 08:42:02 +02:00
# include <drm/drm_fourcc.h>
2022-06-14 12:54:49 +03:00
# include <drm/drm_framebuffer.h>
2021-02-22 15:17:56 +01:00
# include <drm/drm_gem_atomic_helper.h>
2022-08-02 02:04:03 +02:00
# include <drm/drm_gem_dma_helper.h>
2016-11-10 15:29:37 +01:00
# include "meson_plane.h"
# include "meson_registers.h"
2019-07-16 08:42:02 +02:00
# include "meson_viu.h"
2019-10-21 11:15:06 +02:00
# include "meson_osd_afbcd.h"
2016-11-10 15:29:37 +01:00
2018-11-06 10:40:02 +01:00
/* OSD_SCI_WH_M1 */
# define SCI_WH_M1_W(w) FIELD_PREP(GENMASK(28, 16), w)
# define SCI_WH_M1_H(h) FIELD_PREP(GENMASK(12, 0), h)
/* OSD_SCO_H_START_END */
/* OSD_SCO_V_START_END */
# define SCO_HV_START(start) FIELD_PREP(GENMASK(27, 16), start)
# define SCO_HV_END(end) FIELD_PREP(GENMASK(11, 0), end)
/* OSD_SC_CTRL0 */
# define SC_CTRL0_PATH_EN BIT(3)
# define SC_CTRL0_SEL_OSD1 BIT(2)
/* OSD_VSC_CTRL0 */
# define VSC_BANK_LEN(value) FIELD_PREP(GENMASK(2, 0), value)
# define VSC_TOP_INI_RCV_NUM(value) FIELD_PREP(GENMASK(6, 3), value)
# define VSC_TOP_RPT_L0_NUM(value) FIELD_PREP(GENMASK(9, 8), value)
# define VSC_BOT_INI_RCV_NUM(value) FIELD_PREP(GENMASK(14, 11), value)
# define VSC_BOT_RPT_L0_NUM(value) FIELD_PREP(GENMASK(17, 16), value)
# define VSC_PROG_INTERLACE BIT(23)
# define VSC_VERTICAL_SCALER_EN BIT(24)
/* OSD_VSC_INI_PHASE */
# define VSC_INI_PHASE_BOT(bottom) FIELD_PREP(GENMASK(31, 16), bottom)
# define VSC_INI_PHASE_TOP(top) FIELD_PREP(GENMASK(15, 0), top)
/* OSD_HSC_CTRL0 */
# define HSC_BANK_LENGTH(value) FIELD_PREP(GENMASK(2, 0), value)
# define HSC_INI_RCV_NUM0(value) FIELD_PREP(GENMASK(6, 3), value)
# define HSC_RPT_P0_NUM0(value) FIELD_PREP(GENMASK(9, 8), value)
# define HSC_HORIZ_SCALER_EN BIT(22)
/* VPP_OSD_VSC_PHASE_STEP */
/* VPP_OSD_HSC_PHASE_STEP */
# define SC_PHASE_STEP(value) FIELD_PREP(GENMASK(27, 0), value)
2016-11-10 15:29:37 +01:00
struct meson_plane {
struct drm_plane base ;
struct meson_drm * priv ;
2018-11-28 11:07:34 +01:00
bool enabled ;
2016-11-10 15:29:37 +01:00
} ;
# define to_meson_plane(x) container_of(x, struct meson_plane, base)
2018-11-06 10:40:02 +01:00
# define FRAC_16_16(mult, div) (((mult) << 16) / (div))
2016-11-10 15:29:37 +01:00
static int meson_plane_atomic_check ( struct drm_plane * plane ,
drm/atomic: Pass the full state to planes atomic_check
The current atomic helpers have either their object state being passed as
an argument or the full atomic state.
The former is the pattern that was done at first, before switching to the
latter for new hooks or when it was needed.
Let's convert all the remaining helpers to provide a consistent
interface, starting with the planes atomic_check.
The conversion was done using the coccinelle script below plus some
manual changes for vmwgfx, built tested on all the drivers.
@@
identifier plane, plane_state;
symbol state;
@@
struct drm_plane_helper_funcs {
...
int (*atomic_check)(struct drm_plane *plane,
- struct drm_plane_state *plane_state);
+ struct drm_atomic_state *state);
...
}
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_check = func,
...,
};
@@
struct drm_plane_helper_funcs *FUNCS;
identifier f;
identifier dev;
identifier plane, plane_state, state;
@@
f(struct drm_device *dev, struct drm_atomic_state *state)
{
<+...
- FUNCS->atomic_check(plane, plane_state)
+ FUNCS->atomic_check(plane, state)
...+>
}
@ ignores_new_state @
identifier plane_atomic_func.func;
identifier plane, new_plane_state;
@@
func(struct drm_plane *plane, struct drm_plane_state *new_plane_state)
{
... when != new_plane_state
}
@ adds_new_state depends on plane_atomic_func && !ignores_new_state @
identifier plane_atomic_func.func;
identifier plane, new_plane_state;
@@
func(struct drm_plane *plane, struct drm_plane_state *new_plane_state)
{
+ struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
...
}
@ depends on plane_atomic_func @
identifier plane_atomic_func.func;
identifier plane, new_plane_state;
@@
func(struct drm_plane *plane,
- struct drm_plane_state *new_plane_state
+ struct drm_atomic_state *state
)
{ ... }
@ include depends on adds_new_state @
@@
#include <drm/drm_atomic.h>
@ no_include depends on !include && adds_new_state @
@@
+ #include <drm/drm_atomic.h>
#include <drm/...>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-4-maxime@cerno.tech
2021-02-19 13:00:24 +01:00
struct drm_atomic_state * state )
2016-11-10 15:29:37 +01:00
{
drm/atomic: Pass the full state to planes atomic_check
The current atomic helpers have either their object state being passed as
an argument or the full atomic state.
The former is the pattern that was done at first, before switching to the
latter for new hooks or when it was needed.
Let's convert all the remaining helpers to provide a consistent
interface, starting with the planes atomic_check.
The conversion was done using the coccinelle script below plus some
manual changes for vmwgfx, built tested on all the drivers.
@@
identifier plane, plane_state;
symbol state;
@@
struct drm_plane_helper_funcs {
...
int (*atomic_check)(struct drm_plane *plane,
- struct drm_plane_state *plane_state);
+ struct drm_atomic_state *state);
...
}
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_check = func,
...,
};
@@
struct drm_plane_helper_funcs *FUNCS;
identifier f;
identifier dev;
identifier plane, plane_state, state;
@@
f(struct drm_device *dev, struct drm_atomic_state *state)
{
<+...
- FUNCS->atomic_check(plane, plane_state)
+ FUNCS->atomic_check(plane, state)
...+>
}
@ ignores_new_state @
identifier plane_atomic_func.func;
identifier plane, new_plane_state;
@@
func(struct drm_plane *plane, struct drm_plane_state *new_plane_state)
{
... when != new_plane_state
}
@ adds_new_state depends on plane_atomic_func && !ignores_new_state @
identifier plane_atomic_func.func;
identifier plane, new_plane_state;
@@
func(struct drm_plane *plane, struct drm_plane_state *new_plane_state)
{
+ struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
...
}
@ depends on plane_atomic_func @
identifier plane_atomic_func.func;
identifier plane, new_plane_state;
@@
func(struct drm_plane *plane,
- struct drm_plane_state *new_plane_state
+ struct drm_atomic_state *state
)
{ ... }
@ include depends on adds_new_state @
@@
#include <drm/drm_atomic.h>
@ no_include depends on !include && adds_new_state @
@@
+ #include <drm/drm_atomic.h>
#include <drm/...>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-4-maxime@cerno.tech
2021-02-19 13:00:24 +01:00
struct drm_plane_state * new_plane_state = drm_atomic_get_new_plane_state ( state ,
plane ) ;
2016-11-10 15:29:37 +01:00
struct drm_crtc_state * crtc_state ;
2021-02-19 13:00:22 +01:00
if ( ! new_plane_state - > crtc )
2017-01-02 16:09:59 +01:00
return 0 ;
drm: Use the state pointer directly in planes atomic_check
Now that atomic_check takes the global atomic state as a parameter, we
don't need to go through the pointer in the plane state.
This was done using the following coccinelle script:
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
static struct drm_plane_helper_funcs helpers = {
...,
.atomic_check = func,
...,
};
@@
identifier plane_atomic_func.func;
identifier plane, state;
identifier plane_state;
@@
func(struct drm_plane *plane, struct drm_atomic_state *state) {
...
- struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
<... when != plane_state
- plane_state->state
+ state
...>
}
@@
identifier plane_atomic_func.func;
identifier plane, state;
identifier plane_state;
@@
func(struct drm_plane *plane, struct drm_atomic_state *state) {
...
struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
<...
- plane_state->state
+ state
...>
}
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-5-maxime@cerno.tech
2021-02-19 13:00:25 +01:00
crtc_state = drm_atomic_get_crtc_state ( state ,
2021-02-19 13:00:22 +01:00
new_plane_state - > crtc ) ;
2016-11-10 15:29:37 +01:00
if ( IS_ERR ( crtc_state ) )
return PTR_ERR ( crtc_state ) ;
2018-11-06 10:40:02 +01:00
/*
* Only allow :
* - Upscaling up to 5 x , vertical and horizontal
* - Final coordinates must match crtc size
*/
2021-02-19 13:00:22 +01:00
return drm_atomic_helper_check_plane_state ( new_plane_state ,
crtc_state ,
2018-11-06 10:40:02 +01:00
FRAC_16_16 ( 1 , 5 ) ,
2022-07-20 10:30:54 +02:00
DRM_PLANE_NO_SCALING ,
2018-11-06 10:40:02 +01:00
false , true ) ;
2016-11-10 15:29:37 +01:00
}
2019-10-21 11:15:06 +02:00
# define MESON_MOD_AFBC_VALID_BITS (AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | \
AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 | \
AFBC_FORMAT_MOD_YTR | \
AFBC_FORMAT_MOD_SPARSE | \
AFBC_FORMAT_MOD_SPLIT )
2016-11-10 15:29:37 +01:00
/* Takes a fixed 16.16 number and converts it to integer. */
static inline int64_t fixed16_to_int ( int64_t value )
{
return value > > 16 ;
}
2019-10-21 11:15:06 +02:00
static u32 meson_g12a_afbcd_line_stride ( struct meson_drm * priv )
{
u32 line_stride = 0 ;
switch ( priv - > afbcd . format ) {
case DRM_FORMAT_RGB565 :
line_stride = ( ( priv - > viu . osd1_width < < 4 ) + 127 ) > > 7 ;
break ;
case DRM_FORMAT_RGB888 :
case DRM_FORMAT_XRGB8888 :
case DRM_FORMAT_ARGB8888 :
case DRM_FORMAT_XBGR8888 :
case DRM_FORMAT_ABGR8888 :
line_stride = ( ( priv - > viu . osd1_width < < 5 ) + 127 ) > > 7 ;
break ;
}
return ( ( line_stride + 1 ) > > 1 ) < < 1 ;
}
2016-11-10 15:29:37 +01:00
static void meson_plane_atomic_update ( struct drm_plane * plane ,
drm/atomic: Pass the full state to planes atomic disable and update
The current atomic helpers have either their object state being passed as
an argument or the full atomic state.
The former is the pattern that was done at first, before switching to the
latter for new hooks or when it was needed.
Let's convert the remaining helpers to provide a consistent interface,
this time with the planes atomic_update and atomic_disable.
The conversion was done using the coccinelle script below, built tested on
all the drivers.
@@
identifier plane, plane_state;
symbol state;
@@
struct drm_plane_helper_funcs {
...
void (*atomic_update)(struct drm_plane *plane,
- struct drm_plane_state *plane_state);
+ struct drm_atomic_state *state);
...
}
@@
identifier plane, plane_state;
symbol state;
@@
struct drm_plane_helper_funcs {
...
void (*atomic_disable)(struct drm_plane *plane,
- struct drm_plane_state *plane_state);
+ struct drm_atomic_state *state);
...
}
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
(
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_update = func,
...,
};
|
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_disable = func,
...,
};
)
@@
struct drm_plane_helper_funcs *FUNCS;
identifier f;
identifier crtc_state;
identifier plane, plane_state, state;
expression e;
@@
f(struct drm_crtc_state *crtc_state)
{
...
struct drm_atomic_state *state = e;
<+...
(
- FUNCS->atomic_disable(plane, plane_state)
+ FUNCS->atomic_disable(plane, state)
|
- FUNCS->atomic_update(plane, plane_state)
+ FUNCS->atomic_update(plane, state)
)
...+>
}
@@
identifier plane_atomic_func.func;
identifier plane;
symbol state;
@@
func(struct drm_plane *plane,
- struct drm_plane_state *state)
+ struct drm_plane_state *old_plane_state)
{
<...
- state
+ old_plane_state
...>
}
@ ignores_old_state @
identifier plane_atomic_func.func;
identifier plane, old_state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
... when != old_state
}
@ adds_old_state depends on plane_atomic_func && !ignores_old_state @
identifier plane_atomic_func.func;
identifier plane, plane_state;
@@
func(struct drm_plane *plane, struct drm_plane_state *plane_state)
{
+ struct drm_plane_state *plane_state = drm_atomic_get_old_plane_state(state, plane);
...
}
@ depends on plane_atomic_func @
identifier plane_atomic_func.func;
identifier plane, plane_state;
@@
func(struct drm_plane *plane,
- struct drm_plane_state *plane_state
+ struct drm_atomic_state *state
)
{ ... }
@ include depends on adds_old_state @
@@
#include <drm/drm_atomic.h>
@ no_include depends on !include && adds_old_state @
@@
+ #include <drm/drm_atomic.h>
#include <drm/...>
@@
identifier plane_atomic_func.func;
identifier plane, state;
identifier plane_state;
@@
func(struct drm_plane *plane, struct drm_atomic_state *state) {
...
struct drm_plane_state *plane_state = drm_atomic_get_old_plane_state(state, plane);
<+...
- plane_state->state
+ state
...+>
}
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-9-maxime@cerno.tech
2021-02-19 13:00:29 +01:00
struct drm_atomic_state * state )
2016-11-10 15:29:37 +01:00
{
struct meson_plane * meson_plane = to_meson_plane ( plane ) ;
drm: Use state helper instead of the plane state pointer
Many drivers reference the plane->state pointer in order to get the
current plane state in their atomic_update or atomic_disable hooks,
which would be the new plane state in the global atomic state since
_swap_state happened when those hooks are run.
Use the drm_atomic_get_new_plane_state helper to get that state to make it
more obvious.
This was made using the coccinelle script below:
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
(
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_disable = func,
...,
};
|
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_update = func,
...,
};
)
@ adds_new_state @
identifier plane_atomic_func.func;
identifier plane, state;
identifier new_state;
@@
func(struct drm_plane *plane, struct drm_atomic_state *state)
{
...
- struct drm_plane_state *new_state = plane->state;
+ struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, plane);
...
}
@ include depends on adds_new_state @
@@
#include <drm/drm_atomic.h>
@ no_include depends on !include && adds_new_state @
@@
+ #include <drm/drm_atomic.h>
#include <drm/...>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://lore.kernel.org/r/20210219120032.260676-1-maxime@cerno.tech
2021-02-19 13:00:30 +01:00
struct drm_plane_state * new_state = drm_atomic_get_new_plane_state ( state ,
plane ) ;
drm: Rename plane->state variables in atomic update and disable
Some drivers are storing the plane->state pointer in atomic_update and
atomic_disable in a variable simply called state, while the state passed
as an argument is called old_state.
In order to ease subsequent reworks and to avoid confusing or
inconsistent names, let's rename those variables to new_state.
This was done using the following coccinelle script, plus some manual
changes for mtk and tegra.
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
(
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_disable = func,
...,
};
|
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_update = func,
...,
};
)
@ moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
symbol old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_state = plane->state;
...
}
@ depends on moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ new_state
...>
}
@ moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
symbol oldstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *oldstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *newstate = plane->state;
...
}
@ depends on moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ newstate
...>
}
@ moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
symbol old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_pstate = plane->state;
...
}
@ depends on moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
<...
- state
+ new_pstate
...>
}
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-8-maxime@cerno.tech
2021-02-19 13:00:28 +01:00
struct drm_rect dest = drm_plane_state_dest ( new_state ) ;
2016-11-10 15:29:37 +01:00
struct meson_drm * priv = meson_plane - > priv ;
drm: Rename plane->state variables in atomic update and disable
Some drivers are storing the plane->state pointer in atomic_update and
atomic_disable in a variable simply called state, while the state passed
as an argument is called old_state.
In order to ease subsequent reworks and to avoid confusing or
inconsistent names, let's rename those variables to new_state.
This was done using the following coccinelle script, plus some manual
changes for mtk and tegra.
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
(
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_disable = func,
...,
};
|
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_update = func,
...,
};
)
@ moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
symbol old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_state = plane->state;
...
}
@ depends on moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ new_state
...>
}
@ moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
symbol oldstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *oldstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *newstate = plane->state;
...
}
@ depends on moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ newstate
...>
}
@ moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
symbol old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_pstate = plane->state;
...
}
@ depends on moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
<...
- state
+ new_pstate
...>
}
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-8-maxime@cerno.tech
2021-02-19 13:00:28 +01:00
struct drm_framebuffer * fb = new_state - > fb ;
2022-08-02 02:04:03 +02:00
struct drm_gem_dma_object * gem ;
2016-11-10 15:29:37 +01:00
unsigned long flags ;
2018-11-06 10:40:02 +01:00
int vsc_ini_rcv_num , vsc_ini_rpt_p0_num ;
int vsc_bot_rcv_num , vsc_bot_rpt_p0_num ;
int hsc_ini_rcv_num , hsc_ini_rpt_p0_num ;
int hf_phase_step , vf_phase_step ;
int src_w , src_h , dst_w , dst_h ;
int bot_ini_phase ;
int hf_bank_len ;
int vf_bank_len ;
2018-11-05 11:45:08 +01:00
u8 canvas_id_osd1 ;
2016-11-10 15:29:37 +01:00
/*
* Update Coordinates
* Update Formats
* Update Buffer
* Enable Plane
*/
spin_lock_irqsave ( & priv - > drm - > event_lock , flags ) ;
2019-10-21 11:15:06 +02:00
/* Check if AFBC decoder is required for this buffer */
if ( ( meson_vpu_is_compatible ( priv , VPU_COMPATIBLE_GXM ) | |
meson_vpu_is_compatible ( priv , VPU_COMPATIBLE_G12A ) ) & &
fb - > modifier & DRM_FORMAT_MOD_ARM_AFBC ( MESON_MOD_AFBC_VALID_BITS ) )
priv - > viu . osd1_afbcd = true ;
else
priv - > viu . osd1_afbcd = false ;
2016-11-10 15:29:37 +01:00
/* Enable OSD and BLK0, set max global alpha */
priv - > viu . osd1_ctrl_stat = OSD_ENABLE |
2022-09-08 16:51:03 +01:00
( 0x100 < < OSD_GLOBAL_ALPHA_SHIFT ) |
2016-11-10 15:29:37 +01:00
OSD_BLK0_ENABLE ;
2019-10-21 11:15:06 +02:00
priv - > viu . osd1_ctrl_stat2 = readl ( priv - > io_base +
_REG ( VIU_OSD1_CTRL_STAT2 ) ) ;
2019-03-11 11:51:44 +01:00
canvas_id_osd1 = priv - > canvas_id_osd1 ;
2018-11-05 11:45:08 +01:00
2016-11-10 15:29:37 +01:00
/* Set up BLK0 to point to the right canvas */
2019-10-21 11:15:06 +02:00
priv - > viu . osd1_blk0_cfg [ 0 ] = canvas_id_osd1 < < OSD_CANVAS_SEL ;
if ( priv - > viu . osd1_afbcd ) {
if ( meson_vpu_is_compatible ( priv , VPU_COMPATIBLE_G12A ) ) {
/* This is the internal decoding memory address */
priv - > viu . osd1_blk1_cfg4 = MESON_G12A_AFBCD_OUT_ADDR ;
priv - > viu . osd1_blk0_cfg [ 0 ] | = OSD_ENDIANNESS_BE ;
priv - > viu . osd1_ctrl_stat2 | = OSD_PENDING_STAT_CLEAN ;
priv - > viu . osd1_ctrl_stat | = VIU_OSD1_CFG_SYN_EN ;
}
if ( meson_vpu_is_compatible ( priv , VPU_COMPATIBLE_GXM ) ) {
priv - > viu . osd1_blk0_cfg [ 0 ] | = OSD_ENDIANNESS_LE ;
priv - > viu . osd1_ctrl_stat2 | = OSD_DPATH_MALI_AFBCD ;
}
} else {
priv - > viu . osd1_blk0_cfg [ 0 ] | = OSD_ENDIANNESS_LE ;
if ( meson_vpu_is_compatible ( priv , VPU_COMPATIBLE_GXM ) )
priv - > viu . osd1_ctrl_stat2 & = ~ OSD_DPATH_MALI_AFBCD ;
}
2016-11-10 15:29:37 +01:00
/* On GXBB, Use the old non-HDR RGB2YUV converter */
2019-08-22 16:43:41 +02:00
if ( meson_vpu_is_compatible ( priv , VPU_COMPATIBLE_GXBB ) )
2016-11-10 15:29:37 +01:00
priv - > viu . osd1_blk0_cfg [ 0 ] | = OSD_OUTPUT_COLOR_RGB ;
2019-10-21 11:15:06 +02:00
if ( priv - > viu . osd1_afbcd & &
meson_vpu_is_compatible ( priv , VPU_COMPATIBLE_G12A ) ) {
priv - > viu . osd1_blk0_cfg [ 0 ] | = OSD_MALI_SRC_EN |
priv - > afbcd . ops - > fmt_to_blk_mode ( fb - > modifier ,
fb - > format - > format ) ;
} else {
switch ( fb - > format - > format ) {
case DRM_FORMAT_XRGB8888 :
case DRM_FORMAT_ARGB8888 :
priv - > viu . osd1_blk0_cfg [ 0 ] | = OSD_BLK_MODE_32 |
OSD_COLOR_MATRIX_32_ARGB ;
break ;
case DRM_FORMAT_XBGR8888 :
case DRM_FORMAT_ABGR8888 :
priv - > viu . osd1_blk0_cfg [ 0 ] | = OSD_BLK_MODE_32 |
OSD_COLOR_MATRIX_32_ABGR ;
break ;
case DRM_FORMAT_RGB888 :
priv - > viu . osd1_blk0_cfg [ 0 ] | = OSD_BLK_MODE_24 |
OSD_COLOR_MATRIX_24_RGB ;
break ;
case DRM_FORMAT_RGB565 :
priv - > viu . osd1_blk0_cfg [ 0 ] | = OSD_BLK_MODE_16 |
OSD_COLOR_MATRIX_16_RGB565 ;
break ;
2020-04-24 15:49:49 +08:00
}
2019-10-21 11:15:06 +02:00
}
2016-12-14 23:32:55 +02:00
switch ( fb - > format - > format ) {
2016-11-10 15:29:37 +01:00
case DRM_FORMAT_XRGB8888 :
2019-04-29 09:52:38 +02:00
case DRM_FORMAT_XBGR8888 :
/* For XRGB, replace the pixel's alpha by 0xFF */
2019-10-21 11:15:06 +02:00
priv - > viu . osd1_ctrl_stat2 | = OSD_REPLACE_EN ;
2019-04-29 09:52:38 +02:00
break ;
2016-11-10 15:29:37 +01:00
case DRM_FORMAT_ARGB8888 :
2019-04-29 09:52:38 +02:00
case DRM_FORMAT_ABGR8888 :
/* For ARGB, use the pixel's alpha */
2019-10-21 11:15:06 +02:00
priv - > viu . osd1_ctrl_stat2 & = ~ OSD_REPLACE_EN ;
2016-11-10 15:29:37 +01:00
break ;
2019-12-16 11:58:21 +08:00
}
2016-11-10 15:29:37 +01:00
2018-11-06 10:40:02 +01:00
/* Default scaler parameters */
vsc_bot_rcv_num = 0 ;
vsc_bot_rpt_p0_num = 0 ;
hf_bank_len = 4 ;
vf_bank_len = 4 ;
drm: Rename plane->state variables in atomic update and disable
Some drivers are storing the plane->state pointer in atomic_update and
atomic_disable in a variable simply called state, while the state passed
as an argument is called old_state.
In order to ease subsequent reworks and to avoid confusing or
inconsistent names, let's rename those variables to new_state.
This was done using the following coccinelle script, plus some manual
changes for mtk and tegra.
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
(
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_disable = func,
...,
};
|
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_update = func,
...,
};
)
@ moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
symbol old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_state = plane->state;
...
}
@ depends on moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ new_state
...>
}
@ moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
symbol oldstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *oldstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *newstate = plane->state;
...
}
@ depends on moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ newstate
...>
}
@ moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
symbol old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_pstate = plane->state;
...
}
@ depends on moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
<...
- state
+ new_pstate
...>
}
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-8-maxime@cerno.tech
2021-02-19 13:00:28 +01:00
if ( new_state - > crtc - > mode . flags & DRM_MODE_FLAG_INTERLACE ) {
2018-11-06 10:40:02 +01:00
vsc_bot_rcv_num = 6 ;
vsc_bot_rpt_p0_num = 2 ;
}
hsc_ini_rcv_num = hf_bank_len ;
vsc_ini_rcv_num = vf_bank_len ;
hsc_ini_rpt_p0_num = ( hf_bank_len / 2 ) - 1 ;
vsc_ini_rpt_p0_num = ( vf_bank_len / 2 ) - 1 ;
drm: Rename plane->state variables in atomic update and disable
Some drivers are storing the plane->state pointer in atomic_update and
atomic_disable in a variable simply called state, while the state passed
as an argument is called old_state.
In order to ease subsequent reworks and to avoid confusing or
inconsistent names, let's rename those variables to new_state.
This was done using the following coccinelle script, plus some manual
changes for mtk and tegra.
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
(
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_disable = func,
...,
};
|
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_update = func,
...,
};
)
@ moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
symbol old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_state = plane->state;
...
}
@ depends on moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ new_state
...>
}
@ moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
symbol oldstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *oldstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *newstate = plane->state;
...
}
@ depends on moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ newstate
...>
}
@ moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
symbol old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_pstate = plane->state;
...
}
@ depends on moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
<...
- state
+ new_pstate
...>
}
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-8-maxime@cerno.tech
2021-02-19 13:00:28 +01:00
src_w = fixed16_to_int ( new_state - > src_w ) ;
src_h = fixed16_to_int ( new_state - > src_h ) ;
dst_w = new_state - > crtc_w ;
dst_h = new_state - > crtc_h ;
2018-11-06 10:40:02 +01:00
2018-11-06 10:40:01 +01:00
/*
* When the output is interlaced , the OSD must switch between
* each field using the INTERLACE_SEL_ODD ( 0 ) of VIU_OSD1_BLK0_CFG_W0
* at each vsync .
* But the vertical scaler can provide such funtionnality if
* is configured for 2 : 1 scaling with interlace options enabled .
*/
drm: Rename plane->state variables in atomic update and disable
Some drivers are storing the plane->state pointer in atomic_update and
atomic_disable in a variable simply called state, while the state passed
as an argument is called old_state.
In order to ease subsequent reworks and to avoid confusing or
inconsistent names, let's rename those variables to new_state.
This was done using the following coccinelle script, plus some manual
changes for mtk and tegra.
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
(
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_disable = func,
...,
};
|
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_update = func,
...,
};
)
@ moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
symbol old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_state = plane->state;
...
}
@ depends on moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ new_state
...>
}
@ moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
symbol oldstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *oldstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *newstate = plane->state;
...
}
@ depends on moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ newstate
...>
}
@ moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
symbol old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_pstate = plane->state;
...
}
@ depends on moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
<...
- state
+ new_pstate
...>
}
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-8-maxime@cerno.tech
2021-02-19 13:00:28 +01:00
if ( new_state - > crtc - > mode . flags & DRM_MODE_FLAG_INTERLACE ) {
2016-11-10 15:29:37 +01:00
dest . y1 / = 2 ;
dest . y2 / = 2 ;
2018-11-06 10:40:02 +01:00
dst_h / = 2 ;
}
hf_phase_step = ( ( src_w < < 18 ) / dst_w ) < < 6 ;
vf_phase_step = ( src_h < < 20 ) / dst_h ;
drm: Rename plane->state variables in atomic update and disable
Some drivers are storing the plane->state pointer in atomic_update and
atomic_disable in a variable simply called state, while the state passed
as an argument is called old_state.
In order to ease subsequent reworks and to avoid confusing or
inconsistent names, let's rename those variables to new_state.
This was done using the following coccinelle script, plus some manual
changes for mtk and tegra.
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
(
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_disable = func,
...,
};
|
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_update = func,
...,
};
)
@ moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
symbol old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_state = plane->state;
...
}
@ depends on moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ new_state
...>
}
@ moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
symbol oldstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *oldstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *newstate = plane->state;
...
}
@ depends on moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ newstate
...>
}
@ moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
symbol old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_pstate = plane->state;
...
}
@ depends on moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
<...
- state
+ new_pstate
...>
}
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-8-maxime@cerno.tech
2021-02-19 13:00:28 +01:00
if ( new_state - > crtc - > mode . flags & DRM_MODE_FLAG_INTERLACE )
2018-11-06 10:40:02 +01:00
bot_ini_phase = ( ( vf_phase_step / 2 ) > > 4 ) ;
else
bot_ini_phase = 0 ;
2018-11-06 10:40:01 +01:00
2018-11-06 10:40:02 +01:00
vf_phase_step = ( vf_phase_step < < 4 ) ;
2018-11-06 10:40:01 +01:00
2018-11-06 10:40:02 +01:00
/* In interlaced mode, scaler is always active */
if ( src_h ! = dst_h | | src_w ! = dst_w ) {
priv - > viu . osd_sc_i_wh_m1 = SCI_WH_M1_W ( src_w - 1 ) |
SCI_WH_M1_H ( src_h - 1 ) ;
priv - > viu . osd_sc_o_h_start_end = SCO_HV_START ( dest . x1 ) |
SCO_HV_END ( dest . x2 - 1 ) ;
priv - > viu . osd_sc_o_v_start_end = SCO_HV_START ( dest . y1 ) |
SCO_HV_END ( dest . y2 - 1 ) ;
/* Enable OSD Scaler */
priv - > viu . osd_sc_ctrl0 = SC_CTRL0_PATH_EN | SC_CTRL0_SEL_OSD1 ;
} else {
priv - > viu . osd_sc_i_wh_m1 = 0 ;
priv - > viu . osd_sc_o_h_start_end = 0 ;
priv - > viu . osd_sc_o_v_start_end = 0 ;
priv - > viu . osd_sc_ctrl0 = 0 ;
}
2018-11-06 10:40:01 +01:00
2018-11-06 10:40:02 +01:00
/* In interlaced mode, vertical scaler is always active */
if ( src_h ! = dst_h ) {
2018-11-06 10:40:01 +01:00
priv - > viu . osd_sc_v_ctrl0 =
2018-11-06 10:40:02 +01:00
VSC_BANK_LEN ( vf_bank_len ) |
VSC_TOP_INI_RCV_NUM ( vsc_ini_rcv_num ) |
VSC_TOP_RPT_L0_NUM ( vsc_ini_rpt_p0_num ) |
VSC_VERTICAL_SCALER_EN ;
drm: Rename plane->state variables in atomic update and disable
Some drivers are storing the plane->state pointer in atomic_update and
atomic_disable in a variable simply called state, while the state passed
as an argument is called old_state.
In order to ease subsequent reworks and to avoid confusing or
inconsistent names, let's rename those variables to new_state.
This was done using the following coccinelle script, plus some manual
changes for mtk and tegra.
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
(
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_disable = func,
...,
};
|
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_update = func,
...,
};
)
@ moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
symbol old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_state = plane->state;
...
}
@ depends on moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ new_state
...>
}
@ moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
symbol oldstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *oldstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *newstate = plane->state;
...
}
@ depends on moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ newstate
...>
}
@ moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
symbol old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_pstate = plane->state;
...
}
@ depends on moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
<...
- state
+ new_pstate
...>
}
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-8-maxime@cerno.tech
2021-02-19 13:00:28 +01:00
if ( new_state - > crtc - > mode . flags & DRM_MODE_FLAG_INTERLACE )
2018-11-06 10:40:02 +01:00
priv - > viu . osd_sc_v_ctrl0 | =
VSC_BOT_INI_RCV_NUM ( vsc_bot_rcv_num ) |
VSC_BOT_RPT_L0_NUM ( vsc_bot_rpt_p0_num ) |
VSC_PROG_INTERLACE ;
priv - > viu . osd_sc_v_phase_step = SC_PHASE_STEP ( vf_phase_step ) ;
priv - > viu . osd_sc_v_ini_phase = VSC_INI_PHASE_BOT ( bot_ini_phase ) ;
} else {
priv - > viu . osd_sc_v_ctrl0 = 0 ;
priv - > viu . osd_sc_v_phase_step = 0 ;
priv - > viu . osd_sc_v_ini_phase = 0 ;
}
/* Horizontal scaler is only used if width does not match */
if ( src_w ! = dst_w ) {
priv - > viu . osd_sc_h_ctrl0 =
HSC_BANK_LENGTH ( hf_bank_len ) |
HSC_INI_RCV_NUM0 ( hsc_ini_rcv_num ) |
HSC_RPT_P0_NUM0 ( hsc_ini_rpt_p0_num ) |
HSC_HORIZ_SCALER_EN ;
priv - > viu . osd_sc_h_phase_step = SC_PHASE_STEP ( hf_phase_step ) ;
2018-11-06 10:40:01 +01:00
priv - > viu . osd_sc_h_ini_phase = 0 ;
} else {
priv - > viu . osd_sc_h_ctrl0 = 0 ;
2018-11-06 10:40:02 +01:00
priv - > viu . osd_sc_h_phase_step = 0 ;
priv - > viu . osd_sc_h_ini_phase = 0 ;
2018-11-06 10:40:01 +01:00
}
2016-11-10 15:29:37 +01:00
/*
* The format of these registers is ( x2 < < 16 | x1 ) ,
* where x2 is exclusive .
* e . g . + 30 x1920 would be ( 1919 < < 16 ) | 30
*/
2018-11-06 10:40:02 +01:00
priv - > viu . osd1_blk0_cfg [ 1 ] =
drm: Rename plane->state variables in atomic update and disable
Some drivers are storing the plane->state pointer in atomic_update and
atomic_disable in a variable simply called state, while the state passed
as an argument is called old_state.
In order to ease subsequent reworks and to avoid confusing or
inconsistent names, let's rename those variables to new_state.
This was done using the following coccinelle script, plus some manual
changes for mtk and tegra.
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
(
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_disable = func,
...,
};
|
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_update = func,
...,
};
)
@ moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
symbol old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_state = plane->state;
...
}
@ depends on moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ new_state
...>
}
@ moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
symbol oldstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *oldstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *newstate = plane->state;
...
}
@ depends on moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ newstate
...>
}
@ moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
symbol old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_pstate = plane->state;
...
}
@ depends on moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
<...
- state
+ new_pstate
...>
}
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-8-maxime@cerno.tech
2021-02-19 13:00:28 +01:00
( ( fixed16_to_int ( new_state - > src . x2 ) - 1 ) < < 16 ) |
fixed16_to_int ( new_state - > src . x1 ) ;
2018-11-06 10:40:02 +01:00
priv - > viu . osd1_blk0_cfg [ 2 ] =
drm: Rename plane->state variables in atomic update and disable
Some drivers are storing the plane->state pointer in atomic_update and
atomic_disable in a variable simply called state, while the state passed
as an argument is called old_state.
In order to ease subsequent reworks and to avoid confusing or
inconsistent names, let's rename those variables to new_state.
This was done using the following coccinelle script, plus some manual
changes for mtk and tegra.
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
(
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_disable = func,
...,
};
|
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_update = func,
...,
};
)
@ moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
symbol old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_state = plane->state;
...
}
@ depends on moves_new_state_old_state @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ new_state
...>
}
@ moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
symbol oldstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *oldstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *newstate = plane->state;
...
}
@ depends on moves_new_state_oldstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_state;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
<...
- state
+ newstate
...>
}
@ moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
symbol old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
...
- struct drm_plane_state *state = plane->state;
+ struct drm_plane_state *new_pstate = plane->state;
...
}
@ depends on moves_new_state_old_pstate @
identifier plane_atomic_func.func;
identifier plane;
identifier old_pstate;
symbol state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_pstate)
{
<...
- state
+ new_pstate
...>
}
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-8-maxime@cerno.tech
2021-02-19 13:00:28 +01:00
( ( fixed16_to_int ( new_state - > src . y2 ) - 1 ) < < 16 ) |
fixed16_to_int ( new_state - > src . y1 ) ;
2016-11-10 15:29:37 +01:00
priv - > viu . osd1_blk0_cfg [ 3 ] = ( ( dest . x2 - 1 ) < < 16 ) | dest . x1 ;
priv - > viu . osd1_blk0_cfg [ 4 ] = ( ( dest . y2 - 1 ) < < 16 ) | dest . y1 ;
2019-08-22 16:43:41 +02:00
if ( meson_vpu_is_compatible ( priv , VPU_COMPATIBLE_G12A ) ) {
2019-03-25 15:18:18 +01:00
priv - > viu . osd_blend_din0_scope_h = ( ( dest . x2 - 1 ) < < 16 ) | dest . x1 ;
priv - > viu . osd_blend_din0_scope_v = ( ( dest . y2 - 1 ) < < 16 ) | dest . y1 ;
priv - > viu . osb_blend0_size = dst_h < < 16 | dst_w ;
priv - > viu . osb_blend1_size = dst_h < < 16 | dst_w ;
}
2016-11-10 15:29:37 +01:00
/* Update Canvas with buffer address */
2022-08-02 02:04:02 +02:00
gem = drm_fb_dma_get_gem_obj ( fb , 0 ) ;
2016-11-10 15:29:37 +01:00
2022-08-02 02:04:04 +02:00
priv - > viu . osd1_addr = gem - > dma_addr ;
2018-02-15 11:19:36 +01:00
priv - > viu . osd1_stride = fb - > pitches [ 0 ] ;
priv - > viu . osd1_height = fb - > height ;
2019-10-21 11:15:03 +02:00
priv - > viu . osd1_width = fb - > width ;
2016-11-10 15:29:37 +01:00
2019-10-21 11:15:06 +02:00
if ( priv - > viu . osd1_afbcd ) {
priv - > afbcd . modifier = fb - > modifier ;
priv - > afbcd . format = fb - > format - > format ;
/* Calculate decoder write stride */
if ( meson_vpu_is_compatible ( priv , VPU_COMPATIBLE_G12A ) )
priv - > viu . osd1_blk2_cfg4 =
meson_g12a_afbcd_line_stride ( priv ) ;
}
2018-11-28 11:07:34 +01:00
if ( ! meson_plane - > enabled ) {
/* Reset OSD1 before enabling it on GXL+ SoCs */
2019-08-22 16:43:41 +02:00
if ( meson_vpu_is_compatible ( priv , VPU_COMPATIBLE_GXM ) | |
meson_vpu_is_compatible ( priv , VPU_COMPATIBLE_GXL ) )
2018-11-28 11:07:34 +01:00
meson_viu_osd1_reset ( priv ) ;
meson_plane - > enabled = true ;
}
2019-06-05 16:12:52 +02:00
priv - > viu . osd1_enabled = true ;
2016-11-10 15:29:37 +01:00
spin_unlock_irqrestore ( & priv - > drm - > event_lock , flags ) ;
}
static void meson_plane_atomic_disable ( struct drm_plane * plane ,
drm/atomic: Pass the full state to planes atomic disable and update
The current atomic helpers have either their object state being passed as
an argument or the full atomic state.
The former is the pattern that was done at first, before switching to the
latter for new hooks or when it was needed.
Let's convert the remaining helpers to provide a consistent interface,
this time with the planes atomic_update and atomic_disable.
The conversion was done using the coccinelle script below, built tested on
all the drivers.
@@
identifier plane, plane_state;
symbol state;
@@
struct drm_plane_helper_funcs {
...
void (*atomic_update)(struct drm_plane *plane,
- struct drm_plane_state *plane_state);
+ struct drm_atomic_state *state);
...
}
@@
identifier plane, plane_state;
symbol state;
@@
struct drm_plane_helper_funcs {
...
void (*atomic_disable)(struct drm_plane *plane,
- struct drm_plane_state *plane_state);
+ struct drm_atomic_state *state);
...
}
@ plane_atomic_func @
identifier helpers;
identifier func;
@@
(
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_update = func,
...,
};
|
static const struct drm_plane_helper_funcs helpers = {
...,
.atomic_disable = func,
...,
};
)
@@
struct drm_plane_helper_funcs *FUNCS;
identifier f;
identifier crtc_state;
identifier plane, plane_state, state;
expression e;
@@
f(struct drm_crtc_state *crtc_state)
{
...
struct drm_atomic_state *state = e;
<+...
(
- FUNCS->atomic_disable(plane, plane_state)
+ FUNCS->atomic_disable(plane, state)
|
- FUNCS->atomic_update(plane, plane_state)
+ FUNCS->atomic_update(plane, state)
)
...+>
}
@@
identifier plane_atomic_func.func;
identifier plane;
symbol state;
@@
func(struct drm_plane *plane,
- struct drm_plane_state *state)
+ struct drm_plane_state *old_plane_state)
{
<...
- state
+ old_plane_state
...>
}
@ ignores_old_state @
identifier plane_atomic_func.func;
identifier plane, old_state;
@@
func(struct drm_plane *plane, struct drm_plane_state *old_state)
{
... when != old_state
}
@ adds_old_state depends on plane_atomic_func && !ignores_old_state @
identifier plane_atomic_func.func;
identifier plane, plane_state;
@@
func(struct drm_plane *plane, struct drm_plane_state *plane_state)
{
+ struct drm_plane_state *plane_state = drm_atomic_get_old_plane_state(state, plane);
...
}
@ depends on plane_atomic_func @
identifier plane_atomic_func.func;
identifier plane, plane_state;
@@
func(struct drm_plane *plane,
- struct drm_plane_state *plane_state
+ struct drm_atomic_state *state
)
{ ... }
@ include depends on adds_old_state @
@@
#include <drm/drm_atomic.h>
@ no_include depends on !include && adds_old_state @
@@
+ #include <drm/drm_atomic.h>
#include <drm/...>
@@
identifier plane_atomic_func.func;
identifier plane, state;
identifier plane_state;
@@
func(struct drm_plane *plane, struct drm_atomic_state *state) {
...
struct drm_plane_state *plane_state = drm_atomic_get_old_plane_state(state, plane);
<+...
- plane_state->state
+ state
...+>
}
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20210219120032.260676-9-maxime@cerno.tech
2021-02-19 13:00:29 +01:00
struct drm_atomic_state * state )
2016-11-10 15:29:37 +01:00
{
struct meson_plane * meson_plane = to_meson_plane ( plane ) ;
struct meson_drm * priv = meson_plane - > priv ;
2019-10-21 11:15:06 +02:00
if ( priv - > afbcd . ops ) {
priv - > afbcd . ops - > reset ( priv ) ;
priv - > afbcd . ops - > disable ( priv ) ;
}
2016-11-10 15:29:37 +01:00
/* Disable OSD1 */
2019-08-22 16:43:41 +02:00
if ( meson_vpu_is_compatible ( priv , VPU_COMPATIBLE_G12A ) )
2019-06-24 16:48:43 +02:00
writel_bits_relaxed ( VIU_OSD1_POSTBLD_SRC_OSD1 , 0 ,
2019-06-05 16:12:53 +02:00
priv - > io_base + _REG ( OSD1_BLEND_SRC_CTRL ) ) ;
2019-03-25 15:18:18 +01:00
else
writel_bits_relaxed ( VPP_OSD1_POSTBLEND , 0 ,
priv - > io_base + _REG ( VPP_MISC ) ) ;
2016-11-10 15:29:37 +01:00
2018-11-28 11:07:34 +01:00
meson_plane - > enabled = false ;
2019-06-05 16:12:52 +02:00
priv - > viu . osd1_enabled = false ;
2016-11-10 15:29:37 +01:00
}
static const struct drm_plane_helper_funcs meson_plane_helper_funcs = {
. atomic_check = meson_plane_atomic_check ,
. atomic_disable = meson_plane_atomic_disable ,
. atomic_update = meson_plane_atomic_update ,
} ;
2019-10-21 11:15:06 +02:00
static bool meson_plane_format_mod_supported ( struct drm_plane * plane ,
u32 format , u64 modifier )
{
struct meson_plane * meson_plane = to_meson_plane ( plane ) ;
struct meson_drm * priv = meson_plane - > priv ;
int i ;
if ( modifier = = DRM_FORMAT_MOD_INVALID )
return false ;
if ( modifier = = DRM_FORMAT_MOD_LINEAR )
return true ;
if ( ! meson_vpu_is_compatible ( priv , VPU_COMPATIBLE_GXM ) & &
! meson_vpu_is_compatible ( priv , VPU_COMPATIBLE_G12A ) )
return false ;
if ( modifier & ~ DRM_FORMAT_MOD_ARM_AFBC ( MESON_MOD_AFBC_VALID_BITS ) )
return false ;
for ( i = 0 ; i < plane - > modifier_count ; + + i )
if ( plane - > modifiers [ i ] = = modifier )
break ;
if ( i = = plane - > modifier_count ) {
DRM_DEBUG_KMS ( " Unsupported modifier \n " ) ;
return false ;
}
if ( priv - > afbcd . ops & & priv - > afbcd . ops - > supported_fmt )
return priv - > afbcd . ops - > supported_fmt ( modifier , format ) ;
DRM_DEBUG_KMS ( " AFBC Unsupported \n " ) ;
return false ;
}
2016-11-10 15:29:37 +01:00
static const struct drm_plane_funcs meson_plane_funcs = {
. update_plane = drm_atomic_helper_update_plane ,
. disable_plane = drm_atomic_helper_disable_plane ,
. destroy = drm_plane_cleanup ,
. reset = drm_atomic_helper_plane_reset ,
. atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state ,
. atomic_destroy_state = drm_atomic_helper_plane_destroy_state ,
2019-10-21 11:15:06 +02:00
. format_mod_supported = meson_plane_format_mod_supported ,
2016-11-10 15:29:37 +01:00
} ;
static const uint32_t supported_drm_formats [ ] = {
DRM_FORMAT_ARGB8888 ,
2019-04-29 09:52:38 +02:00
DRM_FORMAT_ABGR8888 ,
2016-11-10 15:29:37 +01:00
DRM_FORMAT_XRGB8888 ,
2019-04-29 09:52:38 +02:00
DRM_FORMAT_XBGR8888 ,
2016-11-10 15:29:37 +01:00
DRM_FORMAT_RGB888 ,
DRM_FORMAT_RGB565 ,
} ;
2019-10-21 11:15:06 +02:00
static const uint64_t format_modifiers_afbc_gxm [ ] = {
DRM_FORMAT_MOD_ARM_AFBC ( AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
AFBC_FORMAT_MOD_SPARSE |
AFBC_FORMAT_MOD_YTR ) ,
/* SPLIT mandates SPARSE, RGB modes mandates YTR */
DRM_FORMAT_MOD_ARM_AFBC ( AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
AFBC_FORMAT_MOD_YTR |
AFBC_FORMAT_MOD_SPARSE |
AFBC_FORMAT_MOD_SPLIT ) ,
DRM_FORMAT_MOD_LINEAR ,
DRM_FORMAT_MOD_INVALID ,
} ;
static const uint64_t format_modifiers_afbc_g12a [ ] = {
/*
* - TOFIX Support AFBC modifiers for YUV formats ( 16 x16 + TILED )
* - SPLIT is mandatory for performances reasons when in 16 x16
* block size
* - 32 x8 block size + SPLIT is mandatory with 4 K frame size
* for performances reasons
*/
DRM_FORMAT_MOD_ARM_AFBC ( AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
AFBC_FORMAT_MOD_SPARSE |
AFBC_FORMAT_MOD_SPLIT ) ,
DRM_FORMAT_MOD_ARM_AFBC ( AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
AFBC_FORMAT_MOD_YTR |
AFBC_FORMAT_MOD_SPARSE |
AFBC_FORMAT_MOD_SPLIT ) ,
DRM_FORMAT_MOD_ARM_AFBC ( AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
AFBC_FORMAT_MOD_SPARSE ) ,
DRM_FORMAT_MOD_ARM_AFBC ( AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
AFBC_FORMAT_MOD_YTR |
AFBC_FORMAT_MOD_SPARSE ) ,
DRM_FORMAT_MOD_ARM_AFBC ( AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
AFBC_FORMAT_MOD_SPARSE |
AFBC_FORMAT_MOD_SPLIT ) ,
DRM_FORMAT_MOD_ARM_AFBC ( AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
AFBC_FORMAT_MOD_YTR |
AFBC_FORMAT_MOD_SPARSE |
AFBC_FORMAT_MOD_SPLIT ) ,
DRM_FORMAT_MOD_LINEAR ,
DRM_FORMAT_MOD_INVALID ,
} ;
static const uint64_t format_modifiers_default [ ] = {
DRM_FORMAT_MOD_LINEAR ,
DRM_FORMAT_MOD_INVALID ,
} ;
2016-11-10 15:29:37 +01:00
int meson_plane_create ( struct meson_drm * priv )
{
struct meson_plane * meson_plane ;
struct drm_plane * plane ;
2019-10-21 11:15:06 +02:00
const uint64_t * format_modifiers = format_modifiers_default ;
2023-11-29 03:34:05 -08:00
int ret ;
2016-11-10 15:29:37 +01:00
meson_plane = devm_kzalloc ( priv - > drm - > dev , sizeof ( * meson_plane ) ,
GFP_KERNEL ) ;
if ( ! meson_plane )
return - ENOMEM ;
meson_plane - > priv = priv ;
plane = & meson_plane - > base ;
2019-10-21 11:15:06 +02:00
if ( meson_vpu_is_compatible ( priv , VPU_COMPATIBLE_GXM ) )
format_modifiers = format_modifiers_afbc_gxm ;
else if ( meson_vpu_is_compatible ( priv , VPU_COMPATIBLE_G12A ) )
format_modifiers = format_modifiers_afbc_g12a ;
2023-11-29 03:34:05 -08:00
ret = drm_universal_plane_init ( priv - > drm , plane , 0xFF ,
& meson_plane_funcs ,
supported_drm_formats ,
ARRAY_SIZE ( supported_drm_formats ) ,
format_modifiers ,
DRM_PLANE_TYPE_PRIMARY , " meson_primary_plane " ) ;
if ( ret ) {
devm_kfree ( priv - > drm - > dev , meson_plane ) ;
return ret ;
}
2016-11-10 15:29:37 +01:00
drm_plane_helper_add ( plane , & meson_plane_helper_funcs ) ;
2019-04-29 09:52:47 +02:00
/* For now, OSD Primary plane is always on the front */
drm_plane_create_zpos_immutable_property ( plane , 1 ) ;
2016-11-10 15:29:37 +01:00
priv - > primary_plane = plane ;
return 0 ;
}