]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/sun4i: layer: replace mixer with layer struct
authorJernej Skrabec <jernej.skrabec@gmail.com>
Tue, 4 Nov 2025 18:09:40 +0000 (19:09 +0100)
committerChen-Yu Tsai <wens@kernel.org>
Wed, 12 Nov 2025 09:18:25 +0000 (17:18 +0800)
This allows to almost completely decouple layer code from mixer. This is
important for DE33.

Reviewed-by: Chen-Yu Tsai <wens@kernel.org>
Tested-by: Ryan Walklin <ryan@testtoast.com>
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
Link: https://patch.msgid.link/20251104180942.61538-29-jernej.skrabec@gmail.com
Signed-off-by: Chen-Yu Tsai <wens@kernel.org>
drivers/gpu/drm/sun4i/sun8i_csc.c
drivers/gpu/drm/sun4i/sun8i_mixer.c
drivers/gpu/drm/sun4i/sun8i_mixer.h
drivers/gpu/drm/sun4i/sun8i_ui_layer.c
drivers/gpu/drm/sun4i/sun8i_ui_layer.h
drivers/gpu/drm/sun4i/sun8i_ui_scaler.c
drivers/gpu/drm/sun4i/sun8i_vi_layer.c
drivers/gpu/drm/sun4i/sun8i_vi_layer.h
drivers/gpu/drm/sun4i/sun8i_vi_scaler.c

index 30779db2f9b2a2c95235fc1e6f7126592143a8b0..ce81c12f511d564b47fbfe6186887a9e8c2485e6 100644 (file)
@@ -233,14 +233,14 @@ void sun8i_csc_config(struct sun8i_layer *layer,
        u32 mode = sun8i_csc_get_mode(state);
        u32 base;
 
-       if (layer->mixer->cfg->de_type == SUN8I_MIXER_DE3) {
+       if (layer->cfg->de_type == SUN8I_MIXER_DE3) {
                sun8i_de3_ccsc_setup(layer->regs, layer->channel,
                                     mode, state->color_encoding,
                                     state->color_range);
                return;
        }
 
-       base = ccsc_base[layer->mixer->cfg->lay_cfg.ccsc][layer->channel];
+       base = ccsc_base[layer->cfg->ccsc][layer->channel];
 
        sun8i_csc_setup(layer->regs, base,
                        mode, state->color_encoding,
index b515204c815ee9ee43c7dcb2563f5a67ac0a854b..5fd5781d4b1351e543a7a72b6eaa7b5cfbb74cdd 100644 (file)
@@ -339,7 +339,8 @@ static struct drm_plane **sun8i_layers_init(struct drm_device *drm,
 
                layer = sun8i_vi_layer_init_one(drm, mixer, type,
                                                mixer->engine.regs, i,
-                                               phy_index, plane_cnt);
+                                               phy_index, plane_cnt,
+                                               &mixer->cfg->lay_cfg);
                if (IS_ERR(layer)) {
                        dev_err(drm->dev,
                                "Couldn't initialize overlay plane\n");
@@ -364,7 +365,8 @@ static struct drm_plane **sun8i_layers_init(struct drm_device *drm,
 
                layer = sun8i_ui_layer_init_one(drm, mixer, type,
                                                mixer->engine.regs, index,
-                                               phy_index, plane_cnt);
+                                               phy_index, plane_cnt,
+                                               &mixer->cfg->lay_cfg);
                if (IS_ERR(layer)) {
                        dev_err(drm->dev, "Couldn't initialize %s plane\n",
                                i ? "overlay" : "primary");
index 5b6068755ad1a811fd20d8e9fa8961a7b6d26f29..3948023e095b1a7dac017fc1bf11f642f934f7b8 100644 (file)
@@ -225,13 +225,14 @@ enum {
 };
 
 struct sun8i_layer {
-       struct drm_plane        plane;
-       struct sun8i_mixer      *mixer;
-       int                     type;
-       int                     index;
-       int                     channel;
-       int                     overlay;
-       struct regmap           *regs;
+       struct drm_plane                plane;
+       struct sun8i_mixer              *mixer;
+       int                             type;
+       int                             index;
+       int                             channel;
+       int                             overlay;
+       struct regmap                   *regs;
+       const struct sun8i_layer_cfg    *cfg;
 };
 
 static inline struct sun8i_layer *
@@ -260,14 +261,14 @@ sun8i_blender_regmap(struct sun8i_mixer *mixer)
 }
 
 static inline u32
-sun8i_channel_base(struct sun8i_mixer *mixer, int channel)
+sun8i_channel_base(struct sun8i_layer *layer)
 {
-       if (mixer->cfg->de_type == SUN8I_MIXER_DE33)
-               return DE33_CH_BASE + channel * DE33_CH_SIZE;
-       else if (mixer->cfg->de_type == SUN8I_MIXER_DE3)
-               return DE3_CH_BASE + channel * DE3_CH_SIZE;
+       if (layer->cfg->de_type == SUN8I_MIXER_DE33)
+               return DE33_CH_BASE + layer->channel * DE33_CH_SIZE;
+       else if (layer->cfg->de_type == SUN8I_MIXER_DE3)
+               return DE3_CH_BASE + layer->channel * DE3_CH_SIZE;
        else
-               return DE2_CH_BASE + channel * DE2_CH_SIZE;
+               return DE2_CH_BASE + layer->channel * DE2_CH_SIZE;
 }
 
 int sun8i_mixer_drm_format_to_hw(u32 format, u32 *hw_format);
index cd19e40aefdc1f156dd6c3b31e8b122c4d541d7a..a8a67241c822cbdb119f856342533a239297529e 100644 (file)
 
 static void sun8i_ui_layer_disable(struct sun8i_layer *layer)
 {
-       struct sun8i_mixer *mixer = layer->mixer;
-       u32 ch_base = sun8i_channel_base(mixer, layer->channel);
+       u32 ch_base = sun8i_channel_base(layer);
 
-       regmap_write(mixer->engine.regs,
+       regmap_write(layer->regs,
                     SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ch_base, layer->overlay), 0);
 }
 
@@ -39,11 +38,10 @@ static void sun8i_ui_layer_update_attributes(struct sun8i_layer *layer,
                                             struct drm_plane *plane)
 {
        struct drm_plane_state *state = plane->state;
-       struct sun8i_mixer *mixer = layer->mixer;
        const struct drm_format_info *fmt;
        u32 val, ch_base, hw_fmt;
 
-       ch_base = sun8i_channel_base(mixer, layer->channel);
+       ch_base = sun8i_channel_base(layer);
        fmt = state->fb->format;
        sun8i_mixer_drm_format_to_hw(fmt->format, &hw_fmt);
 
@@ -62,7 +60,6 @@ static void sun8i_ui_layer_update_coord(struct sun8i_layer *layer,
                                        struct drm_plane *plane)
 {
        struct drm_plane_state *state = plane->state;
-       struct sun8i_mixer *mixer = layer->mixer;
        u32 src_w, src_h, dst_w, dst_h;
        u32 outsize, insize;
        u32 hphase, vphase;
@@ -71,7 +68,7 @@ static void sun8i_ui_layer_update_coord(struct sun8i_layer *layer,
        DRM_DEBUG_DRIVER("Updating UI channel %d overlay %d\n",
                         layer->channel, layer->overlay);
 
-       ch_base = sun8i_channel_base(mixer, layer->channel);
+       ch_base = sun8i_channel_base(layer);
 
        src_w = drm_rect_width(&state->src) >> 16;
        src_h = drm_rect_height(&state->src) >> 16;
@@ -103,7 +100,7 @@ static void sun8i_ui_layer_update_coord(struct sun8i_layer *layer,
                hscale = state->src_w / state->crtc_w;
                vscale = state->src_h / state->crtc_h;
 
-               if (mixer->cfg->de_type == SUN8I_MIXER_DE33) {
+               if (layer->cfg->de_type == SUN8I_MIXER_DE33) {
                        sun8i_vi_scaler_setup(layer, src_w, src_h, dst_w, dst_h,
                                              hscale, vscale, hphase, vphase,
                                              state->fb->format);
@@ -115,7 +112,7 @@ static void sun8i_ui_layer_update_coord(struct sun8i_layer *layer,
                }
        } else {
                DRM_DEBUG_DRIVER("HW scaling is not needed\n");
-               if (mixer->cfg->de_type == SUN8I_MIXER_DE33)
+               if (layer->cfg->de_type == SUN8I_MIXER_DE33)
                        sun8i_vi_scaler_enable(layer, false);
                else
                        sun8i_ui_scaler_enable(layer, false);
@@ -126,14 +123,13 @@ static void sun8i_ui_layer_update_buffer(struct sun8i_layer *layer,
                                         struct drm_plane *plane)
 {
        struct drm_plane_state *state = plane->state;
-       struct sun8i_mixer *mixer = layer->mixer;
        struct drm_framebuffer *fb = state->fb;
        struct drm_gem_dma_object *gem;
        dma_addr_t dma_addr;
        u32 ch_base;
        int bpp;
 
-       ch_base = sun8i_channel_base(mixer, layer->channel);
+       ch_base = sun8i_channel_base(layer);
 
        /* Get the physical address of the buffer in memory */
        gem = drm_fb_dma_get_gem_obj(fb, 0);
@@ -190,7 +186,7 @@ static int sun8i_ui_layer_atomic_check(struct drm_plane *plane,
        min_scale = DRM_PLANE_NO_SCALING;
        max_scale = DRM_PLANE_NO_SCALING;
 
-       if (layer->mixer->cfg->lay_cfg.scaler_mask & BIT(layer->channel)) {
+       if (layer->cfg->scaler_mask & BIT(layer->channel)) {
                min_scale = SUN8I_UI_SCALER_SCALE_MIN;
                max_scale = SUN8I_UI_SCALER_SCALE_MAX;
        }
@@ -266,7 +262,8 @@ struct sun8i_layer *sun8i_ui_layer_init_one(struct drm_device *drm,
                                            enum drm_plane_type type,
                                            struct regmap *regs,
                                            int index, int phy_index,
-                                           int plane_cnt)
+                                           int plane_cnt,
+                                           const struct sun8i_layer_cfg *cfg)
 {
        struct sun8i_layer *layer;
        int ret;
@@ -281,6 +278,7 @@ struct sun8i_layer *sun8i_ui_layer_init_one(struct drm_device *drm,
        layer->channel = phy_index;
        layer->overlay = 0;
        layer->regs = regs;
+       layer->cfg = cfg;
 
        /* possible crtcs are set later */
        ret = drm_universal_plane_init(drm, &layer->plane, 0,
index 9383c3364df3dd3b64f6d7edc017c471d5998ac6..c357b39999ff2ec3efd10abdf9d7f406cd29c876 100644 (file)
@@ -54,5 +54,6 @@ struct sun8i_layer *sun8i_ui_layer_init_one(struct drm_device *drm,
                                            enum drm_plane_type type,
                                            struct regmap *regs,
                                            int index, int phy_index,
-                                           int plane_cnt);
+                                           int plane_cnt,
+                                           const struct sun8i_layer_cfg *cfg);
 #endif /* _SUN8I_UI_LAYER_H_ */
index 4d06c366de7faeae3678710740359cdd024eaa1c..a178da8f532addab4e1737c7cad5d064fda99204 100644 (file)
@@ -89,18 +89,18 @@ static const u32 lan2coefftab16[240] = {
        0x0b1c1603, 0x0d1c1502, 0x0e1d1401, 0x0f1d1301,
 };
 
-static u32 sun8i_ui_scaler_base(struct sun8i_mixer *mixer, int channel)
+static u32 sun8i_ui_scaler_base(struct sun8i_layer *layer)
 {
-       int offset = mixer->cfg->lay_cfg.vi_scaler_num;
+       int offset = layer->cfg->vi_scaler_num;
 
-       if (mixer->cfg->de_type == SUN8I_MIXER_DE3)
+       if (layer->cfg->de_type == SUN8I_MIXER_DE3)
                return DE3_VI_SCALER_UNIT_BASE +
                       DE3_VI_SCALER_UNIT_SIZE * offset +
-                      DE3_UI_SCALER_UNIT_SIZE * (channel - offset);
+                      DE3_UI_SCALER_UNIT_SIZE * (layer->channel - offset);
        else
                return DE2_VI_SCALER_UNIT_BASE +
                       DE2_VI_SCALER_UNIT_SIZE * offset +
-                      DE2_UI_SCALER_UNIT_SIZE * (channel - offset);
+                      DE2_UI_SCALER_UNIT_SIZE * (layer->channel - offset);
 }
 
 static int sun8i_ui_scaler_coef_index(unsigned int step)
@@ -129,10 +129,9 @@ static int sun8i_ui_scaler_coef_index(unsigned int step)
 
 void sun8i_ui_scaler_enable(struct sun8i_layer *layer, bool enable)
 {
-       struct sun8i_mixer *mixer = layer->mixer;
        u32 val, base;
 
-       base = sun8i_ui_scaler_base(mixer, layer->channel);
+       base = sun8i_ui_scaler_base(layer);
 
        if (enable)
                val = SUN8I_SCALER_GSU_CTRL_EN |
@@ -147,12 +146,11 @@ void sun8i_ui_scaler_setup(struct sun8i_layer *layer,
                           u32 src_w, u32 src_h, u32 dst_w, u32 dst_h,
                           u32 hscale, u32 vscale, u32 hphase, u32 vphase)
 {
-       struct sun8i_mixer *mixer = layer->mixer;
        u32 insize, outsize;
        int i, offset;
        u32 base;
 
-       base = sun8i_ui_scaler_base(mixer, layer->channel);
+       base = sun8i_ui_scaler_base(layer);
 
        hphase <<= SUN8I_UI_SCALER_PHASE_FRAC - 16;
        vphase <<= SUN8I_UI_SCALER_PHASE_FRAC - 16;
index 84ca7a37f14c5c2594d114f9f20b07b8315296f1..5f91011425bf4a9329b63020e4053138ed0b5daa 100644 (file)
 
 static void sun8i_vi_layer_disable(struct sun8i_layer *layer)
 {
-       struct sun8i_mixer *mixer = layer->mixer;
-       u32 ch_base = sun8i_channel_base(mixer, layer->channel);
+       u32 ch_base = sun8i_channel_base(layer);
 
-       regmap_write(mixer->engine.regs,
+       regmap_write(layer->regs,
                     SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch_base, layer->overlay), 0);
 }
 
@@ -32,11 +31,10 @@ static void sun8i_vi_layer_update_attributes(struct sun8i_layer *layer,
                                             struct drm_plane *plane)
 {
        struct drm_plane_state *state = plane->state;
-       struct sun8i_mixer *mixer = layer->mixer;
        const struct drm_format_info *fmt;
        u32 val, ch_base, hw_fmt;
 
-       ch_base = sun8i_channel_base(mixer, layer->channel);
+       ch_base = sun8i_channel_base(layer);
        fmt = state->fb->format;
        sun8i_mixer_drm_format_to_hw(fmt->format, &hw_fmt);
 
@@ -44,7 +42,7 @@ static void sun8i_vi_layer_update_attributes(struct sun8i_layer *layer,
        if (!fmt->is_yuv)
                val |= SUN8I_MIXER_CHAN_VI_LAYER_ATTR_RGB_MODE;
        val |= SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN;
-       if (mixer->cfg->de_type >= SUN8I_MIXER_DE3) {
+       if (layer->cfg->de_type >= SUN8I_MIXER_DE3) {
                val |= SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA(state->alpha >> 8);
                val |= (state->alpha == DRM_BLEND_ALPHA_OPAQUE) ?
                        SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA_MODE_PIXEL :
@@ -54,7 +52,7 @@ static void sun8i_vi_layer_update_attributes(struct sun8i_layer *layer,
        regmap_write(layer->regs,
                     SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch_base, layer->overlay), val);
 
-       if (mixer->cfg->lay_cfg.de2_fcc_alpha) {
+       if (layer->cfg->de2_fcc_alpha) {
                regmap_write(layer->regs,
                             SUN8I_MIXER_FCC_GLOBAL_ALPHA_REG,
                             SUN8I_MIXER_FCC_GLOBAL_ALPHA(state->alpha >> 8));
@@ -78,7 +76,7 @@ static void sun8i_vi_layer_update_coord(struct sun8i_layer *layer,
        DRM_DEBUG_DRIVER("Updating VI channel %d overlay %d\n",
                         layer->channel, layer->overlay);
 
-       ch_base = sun8i_channel_base(mixer, layer->channel);
+       ch_base = sun8i_channel_base(layer);
 
        src_w = drm_rect_width(&state->src) >> 16;
        src_h = drm_rect_height(&state->src) >> 16;
@@ -153,7 +151,7 @@ static void sun8i_vi_layer_update_coord(struct sun8i_layer *layer,
                }
 
                /* it seems that every RGB scaler has buffer for 2048 pixels */
-               scanline = subsampled ? mixer->cfg->lay_cfg.scanline_yuv : 2048;
+               scanline = subsampled ? layer->cfg->scanline_yuv : 2048;
 
                if (src_w > scanline) {
                        DRM_DEBUG_DRIVER("Using horizontal coarse scaling\n");
@@ -195,7 +193,6 @@ static void sun8i_vi_layer_update_buffer(struct sun8i_layer *layer,
                                         struct drm_plane *plane)
 {
        struct drm_plane_state *state = plane->state;
-       struct sun8i_mixer *mixer = layer->mixer;
        struct drm_framebuffer *fb = state->fb;
        const struct drm_format_info *format = fb->format;
        struct drm_gem_dma_object *gem;
@@ -204,7 +201,7 @@ static void sun8i_vi_layer_update_buffer(struct sun8i_layer *layer,
        u32 ch_base;
        int i;
 
-       ch_base = sun8i_channel_base(mixer, layer->channel);
+       ch_base = sun8i_channel_base(layer);
 
        /* Adjust x and y to be dividable by subsampling factor */
        src_x = (state->src.x1 >> 16) & ~(format->hsub - 1);
@@ -278,7 +275,7 @@ static int sun8i_vi_layer_atomic_check(struct drm_plane *plane,
        min_scale = DRM_PLANE_NO_SCALING;
        max_scale = DRM_PLANE_NO_SCALING;
 
-       if (layer->mixer->cfg->lay_cfg.scaler_mask & BIT(layer->channel)) {
+       if (layer->cfg->scaler_mask & BIT(layer->channel)) {
                min_scale = SUN8I_VI_SCALER_SCALE_MIN;
                max_scale = SUN8I_VI_SCALER_SCALE_MAX;
        }
@@ -414,7 +411,8 @@ struct sun8i_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
                                            enum drm_plane_type type,
                                            struct regmap *regs,
                                            int index, int phy_index,
-                                           int plane_cnt)
+                                           int plane_cnt,
+                                           const struct sun8i_layer_cfg *cfg)
 {
        u32 supported_encodings, supported_ranges;
        unsigned int format_count;
@@ -432,8 +430,9 @@ struct sun8i_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
        layer->channel = phy_index;
        layer->overlay = 0;
        layer->regs = regs;
+       layer->cfg = cfg;
 
-       if (mixer->cfg->de_type >= SUN8I_MIXER_DE3) {
+       if (layer->cfg->de_type >= SUN8I_MIXER_DE3) {
                formats = sun8i_vi_layer_de3_formats;
                format_count = ARRAY_SIZE(sun8i_vi_layer_de3_formats);
        } else {
@@ -452,7 +451,7 @@ struct sun8i_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
                return ERR_PTR(ret);
        }
 
-       if (mixer->cfg->lay_cfg.de2_fcc_alpha || mixer->cfg->de_type >= SUN8I_MIXER_DE3) {
+       if (layer->cfg->de2_fcc_alpha || layer->cfg->de_type >= SUN8I_MIXER_DE3) {
                ret = drm_plane_create_alpha_property(&layer->plane);
                if (ret) {
                        dev_err(drm->dev, "Couldn't add alpha property\n");
@@ -469,7 +468,7 @@ struct sun8i_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
 
        supported_encodings = BIT(DRM_COLOR_YCBCR_BT601) |
                              BIT(DRM_COLOR_YCBCR_BT709);
-       if (mixer->cfg->de_type >= SUN8I_MIXER_DE3)
+       if (layer->cfg->de_type >= SUN8I_MIXER_DE3)
                supported_encodings |= BIT(DRM_COLOR_YCBCR_BT2020);
 
        supported_ranges = BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
index 89d0c32e63cf8f0eb7f1cf17b146741e53d4969d..6ec68baa2409459dfa864dd932b3e05743b99c6b 100644 (file)
@@ -59,5 +59,6 @@ struct sun8i_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
                                            enum drm_plane_type type,
                                            struct regmap *regs,
                                            int index, int phy_index,
-                                           int plane_cnt);
+                                           int plane_cnt,
+                                           const struct sun8i_layer_cfg *cfg);
 #endif /* _SUN8I_VI_LAYER_H_ */
index fe0bb1de6f08cdc0eee8c67eafaee6ef6a690317..3dec4eeb1ba21df4ba3bef670cd0801c5a0d4624 100644 (file)
@@ -833,17 +833,17 @@ static const u32 bicubic4coefftab32[480] = {
        0x1012110d, 0x1012110d, 0x1013110c, 0x1013110c,
 };
 
-static u32 sun8i_vi_scaler_base(struct sun8i_mixer *mixer, int channel)
+static u32 sun8i_vi_scaler_base(struct sun8i_layer *layer)
 {
-       if (mixer->cfg->de_type == SUN8I_MIXER_DE33)
+       if (layer->cfg->de_type == SUN8I_MIXER_DE33)
                return DE33_VI_SCALER_UNIT_BASE +
-                      DE33_CH_SIZE * channel;
-       else if (mixer->cfg->de_type == SUN8I_MIXER_DE3)
+                      DE33_CH_SIZE * layer->channel;
+       else if (layer->cfg->de_type == SUN8I_MIXER_DE3)
                return DE3_VI_SCALER_UNIT_BASE +
-                      DE3_VI_SCALER_UNIT_SIZE * channel;
+                      DE3_VI_SCALER_UNIT_SIZE * layer->channel;
        else
                return DE2_VI_SCALER_UNIT_BASE +
-                      DE2_VI_SCALER_UNIT_SIZE * channel;
+                      DE2_VI_SCALER_UNIT_SIZE * layer->channel;
 }
 
 static int sun8i_vi_scaler_coef_index(unsigned int step)
@@ -914,7 +914,7 @@ void sun8i_vi_scaler_enable(struct sun8i_layer *layer, bool enable)
 {
        u32 val, base;
 
-       base = sun8i_vi_scaler_base(layer->mixer, layer->channel);
+       base = sun8i_vi_scaler_base(layer);
 
        if (enable)
                val = SUN8I_SCALER_VSU_CTRL_EN |
@@ -931,12 +931,11 @@ void sun8i_vi_scaler_setup(struct sun8i_layer *layer,
                           u32 hscale, u32 vscale, u32 hphase, u32 vphase,
                           const struct drm_format_info *format)
 {
-       struct sun8i_mixer *mixer = layer->mixer;
        u32 chphase, cvphase;
        u32 insize, outsize;
        u32 base;
 
-       base = sun8i_vi_scaler_base(mixer, layer->channel);
+       base = sun8i_vi_scaler_base(layer);
 
        hphase <<= SUN8I_VI_SCALER_PHASE_FRAC - 16;
        vphase <<= SUN8I_VI_SCALER_PHASE_FRAC - 16;
@@ -960,7 +959,7 @@ void sun8i_vi_scaler_setup(struct sun8i_layer *layer,
                cvphase = vphase;
        }
 
-       if (mixer->cfg->de_type >= SUN8I_MIXER_DE3) {
+       if (layer->cfg->de_type >= SUN8I_MIXER_DE3) {
                u32 val;
 
                if (format->hsub == 1 && format->vsub == 1)