]> git.karo-electronics.de Git - linux-beck.git/blobdiff - drivers/gpu/drm/exynos/exynos_mixer.c
drm/exynos: remove struct *_win_data abstraction on planes
[linux-beck.git] / drivers / gpu / drm / exynos / exynos_mixer.c
index 2e3bc57ea50e594dcdf739042c39169428ecbda1..d181cb1ce71ab5d037d99064e97a094d48ec8aaa 100644 (file)
 
 #include "exynos_drm_drv.h"
 #include "exynos_drm_crtc.h"
+#include "exynos_drm_plane.h"
 #include "exynos_drm_iommu.h"
 #include "exynos_mixer.h"
 
 #define MIXER_WIN_NR           3
 #define MIXER_DEFAULT_WIN      0
 
-struct hdmi_win_data {
-       dma_addr_t              dma_addr;
-       dma_addr_t              chroma_dma_addr;
-       uint32_t                pixel_format;
-       unsigned int            bpp;
-       unsigned int            crtc_x;
-       unsigned int            crtc_y;
-       unsigned int            crtc_width;
-       unsigned int            crtc_height;
-       unsigned int            fb_x;
-       unsigned int            fb_y;
-       unsigned int            fb_width;
-       unsigned int            fb_pitch;
-       unsigned int            fb_height;
-       unsigned int            src_width;
-       unsigned int            src_height;
-       unsigned int            mode_width;
-       unsigned int            mode_height;
-       unsigned int            scan_flags;
-       bool                    enabled;
-       bool                    resume;
-};
-
 struct mixer_resources {
        int                     irq;
        void __iomem            *mixer_regs;
@@ -90,6 +68,7 @@ struct mixer_context {
        struct device           *dev;
        struct drm_device       *drm_dev;
        struct exynos_drm_crtc  *crtc;
+       struct exynos_drm_plane planes[MIXER_WIN_NR];
        int                     pipe;
        bool                    interlace;
        bool                    powered;
@@ -99,7 +78,6 @@ struct mixer_context {
 
        struct mutex            mixer_mutex;
        struct mixer_resources  mixer_res;
-       struct hdmi_win_data    win_data[MIXER_WIN_NR];
        enum mixer_version_id   mxr_ver;
        wait_queue_head_t       wait_vsync_queue;
        atomic_t                wait_vsync_event;
@@ -403,7 +381,7 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
 {
        struct mixer_resources *res = &ctx->mixer_res;
        unsigned long flags;
-       struct hdmi_win_data *win_data;
+       struct exynos_drm_plane *plane;
        unsigned int x_ratio, y_ratio;
        unsigned int buf_num = 1;
        dma_addr_t luma_addr[2], chroma_addr[2];
@@ -411,9 +389,9 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
        bool crcb_mode = false;
        u32 val;
 
-       win_data = &ctx->win_data[win];
+       plane = &ctx->planes[win];
 
-       switch (win_data->pixel_format) {
+       switch (plane->pixel_format) {
        case DRM_FORMAT_NV12:
                crcb_mode = false;
                buf_num = 2;
@@ -421,35 +399,35 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
        /* TODO: single buffer format NV12, NV21 */
        default:
                /* ignore pixel format at disable time */
-               if (!win_data->dma_addr)
+               if (!plane->dma_addr[0])
                        break;
 
                DRM_ERROR("pixel format for vp is wrong [%d].\n",
-                               win_data->pixel_format);
+                               plane->pixel_format);
                return;
        }
 
        /* scaling feature: (src << 16) / dst */
-       x_ratio = (win_data->src_width << 16) / win_data->crtc_width;
-       y_ratio = (win_data->src_height << 16) / win_data->crtc_height;
+       x_ratio = (plane->src_width << 16) / plane->crtc_width;
+       y_ratio = (plane->src_height << 16) / plane->crtc_height;
 
        if (buf_num == 2) {
-               luma_addr[0] = win_data->dma_addr;
-               chroma_addr[0] = win_data->chroma_dma_addr;
+               luma_addr[0] = plane->dma_addr[0];
+               chroma_addr[0] = plane->dma_addr[1];
        } else {
-               luma_addr[0] = win_data->dma_addr;
-               chroma_addr[0] = win_data->dma_addr
-                       + (win_data->fb_pitch * win_data->fb_height);
+               luma_addr[0] = plane->dma_addr[0];
+               chroma_addr[0] = plane->dma_addr[0]
+                       + (plane->pitch * plane->fb_height);
        }
 
-       if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE) {
+       if (plane->scan_flag & DRM_MODE_FLAG_INTERLACE) {
                ctx->interlace = true;
                if (tiled_mode) {
                        luma_addr[1] = luma_addr[0] + 0x40;
                        chroma_addr[1] = chroma_addr[0] + 0x40;
                } else {
-                       luma_addr[1] = luma_addr[0] + win_data->fb_pitch;
-                       chroma_addr[1] = chroma_addr[0] + win_data->fb_pitch;
+                       luma_addr[1] = luma_addr[0] + plane->pitch;
+                       chroma_addr[1] = chroma_addr[0] + plane->pitch;
                }
        } else {
                ctx->interlace = false;
@@ -470,26 +448,26 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
        vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK);
 
        /* setting size of input image */
-       vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(win_data->fb_pitch) |
-               VP_IMG_VSIZE(win_data->fb_height));
+       vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(plane->pitch) |
+               VP_IMG_VSIZE(plane->fb_height));
        /* chroma height has to reduced by 2 to avoid chroma distorions */
-       vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(win_data->fb_pitch) |
-               VP_IMG_VSIZE(win_data->fb_height / 2));
+       vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(plane->pitch) |
+               VP_IMG_VSIZE(plane->fb_height / 2));
 
-       vp_reg_write(res, VP_SRC_WIDTH, win_data->src_width);
-       vp_reg_write(res, VP_SRC_HEIGHT, win_data->src_height);
+       vp_reg_write(res, VP_SRC_WIDTH, plane->src_width);
+       vp_reg_write(res, VP_SRC_HEIGHT, plane->src_height);
        vp_reg_write(res, VP_SRC_H_POSITION,
-                       VP_SRC_H_POSITION_VAL(win_data->fb_x));
-       vp_reg_write(res, VP_SRC_V_POSITION, win_data->fb_y);
+                       VP_SRC_H_POSITION_VAL(plane->fb_x));
+       vp_reg_write(res, VP_SRC_V_POSITION, plane->fb_y);
 
-       vp_reg_write(res, VP_DST_WIDTH, win_data->crtc_width);
-       vp_reg_write(res, VP_DST_H_POSITION, win_data->crtc_x);
+       vp_reg_write(res, VP_DST_WIDTH, plane->crtc_width);
+       vp_reg_write(res, VP_DST_H_POSITION, plane->crtc_x);
        if (ctx->interlace) {
-               vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height / 2);
-               vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y / 2);
+               vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_height / 2);
+               vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y / 2);
        } else {
-               vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height);
-               vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y);
+               vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_height);
+               vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y);
        }
 
        vp_reg_write(res, VP_H_RATIO, x_ratio);
@@ -503,8 +481,8 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
        vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]);
        vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]);
 
-       mixer_cfg_scan(ctx, win_data->mode_height);
-       mixer_cfg_rgb_fmt(ctx, win_data->mode_height);
+       mixer_cfg_scan(ctx, plane->mode_height);
+       mixer_cfg_rgb_fmt(ctx, plane->mode_height);
        mixer_cfg_layer(ctx, win, true);
        mixer_run(ctx);
 
@@ -525,21 +503,21 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win)
 {
        struct mixer_resources *res = &ctx->mixer_res;
        unsigned long flags;
-       struct hdmi_win_data *win_data;
+       struct exynos_drm_plane *plane;
        unsigned int x_ratio, y_ratio;
        unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
        dma_addr_t dma_addr;
        unsigned int fmt;
        u32 val;
 
-       win_data = &ctx->win_data[win];
+       plane = &ctx->planes[win];
 
        #define RGB565 4
        #define ARGB1555 5
        #define ARGB4444 6
        #define ARGB8888 7
 
-       switch (win_data->bpp) {
+       switch (plane->bpp) {
        case 16:
                fmt = ARGB4444;
                break;
@@ -554,17 +532,17 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win)
        x_ratio = 0;
        y_ratio = 0;
 
-       dst_x_offset = win_data->crtc_x;
-       dst_y_offset = win_data->crtc_y;
+       dst_x_offset = plane->crtc_x;
+       dst_y_offset = plane->crtc_y;
 
        /* converting dma address base and source offset */
-       dma_addr = win_data->dma_addr
-               + (win_data->fb_x * win_data->bpp >> 3)
-               + (win_data->fb_y * win_data->fb_pitch);
+       dma_addr = plane->dma_addr[0]
+               + (plane->fb_x * plane->bpp >> 3)
+               + (plane->fb_y * plane->pitch);
        src_x_offset = 0;
        src_y_offset = 0;
 
-       if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE)
+       if (plane->scan_flag & DRM_MODE_FLAG_INTERLACE)
                ctx->interlace = true;
        else
                ctx->interlace = false;
@@ -578,18 +556,18 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win)
 
        /* setup geometry */
        mixer_reg_write(res, MXR_GRAPHIC_SPAN(win),
-                       win_data->fb_pitch / (win_data->bpp >> 3));
+                       plane->pitch / (plane->bpp >> 3));
 
        /* setup display size */
        if (ctx->mxr_ver == MXR_VER_128_0_0_184 &&
                win == MIXER_DEFAULT_WIN) {
-               val  = MXR_MXR_RES_HEIGHT(win_data->mode_height);
-               val |= MXR_MXR_RES_WIDTH(win_data->mode_width);
+               val  = MXR_MXR_RES_HEIGHT(plane->mode_height);
+               val |= MXR_MXR_RES_WIDTH(plane->mode_width);
                mixer_reg_write(res, MXR_RESOLUTION, val);
        }
 
-       val  = MXR_GRP_WH_WIDTH(win_data->crtc_width);
-       val |= MXR_GRP_WH_HEIGHT(win_data->crtc_height);
+       val  = MXR_GRP_WH_WIDTH(plane->crtc_width);
+       val |= MXR_GRP_WH_HEIGHT(plane->crtc_height);
        val |= MXR_GRP_WH_H_SCALE(x_ratio);
        val |= MXR_GRP_WH_V_SCALE(y_ratio);
        mixer_reg_write(res, MXR_GRAPHIC_WH(win), val);
@@ -607,8 +585,8 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win)
        /* set buffer address to mixer */
        mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr);
 
-       mixer_cfg_scan(ctx, win_data->mode_height);
-       mixer_cfg_rgb_fmt(ctx, win_data->mode_height);
+       mixer_cfg_scan(ctx, plane->mode_height);
+       mixer_cfg_rgb_fmt(ctx, plane->mode_height);
        mixer_cfg_layer(ctx, win, true);
 
        /* layer update mandatory for mixer 16.0.33.0 */
@@ -920,59 +898,6 @@ static void mixer_disable_vblank(struct exynos_drm_crtc *crtc)
        mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
 }
 
-static void mixer_win_mode_set(struct exynos_drm_crtc *crtc,
-                       struct exynos_drm_plane *plane)
-{
-       struct mixer_context *mixer_ctx = crtc->ctx;
-       struct hdmi_win_data *win_data;
-       int win;
-
-       if (!plane) {
-               DRM_ERROR("plane is NULL\n");
-               return;
-       }
-
-       DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n",
-                                plane->fb_width, plane->fb_height,
-                                plane->fb_x, plane->fb_y,
-                                plane->crtc_width, plane->crtc_height,
-                                plane->crtc_x, plane->crtc_y);
-
-       win = plane->zpos;
-       if (win == DEFAULT_ZPOS)
-               win = MIXER_DEFAULT_WIN;
-
-       if (win < 0 || win >= MIXER_WIN_NR) {
-               DRM_ERROR("mixer window[%d] is wrong\n", win);
-               return;
-       }
-
-       win_data = &mixer_ctx->win_data[win];
-
-       win_data->dma_addr = plane->dma_addr[0];
-       win_data->chroma_dma_addr = plane->dma_addr[1];
-       win_data->pixel_format = plane->pixel_format;
-       win_data->bpp = plane->bpp;
-
-       win_data->crtc_x = plane->crtc_x;
-       win_data->crtc_y = plane->crtc_y;
-       win_data->crtc_width = plane->crtc_width;
-       win_data->crtc_height = plane->crtc_height;
-
-       win_data->fb_x = plane->fb_x;
-       win_data->fb_y = plane->fb_y;
-       win_data->fb_width = plane->fb_width;
-       win_data->fb_height = plane->fb_height;
-       win_data->fb_pitch = plane->pitch;
-       win_data->src_width = plane->src_width;
-       win_data->src_height = plane->src_height;
-
-       win_data->mode_width = plane->mode_width;
-       win_data->mode_height = plane->mode_height;
-
-       win_data->scan_flags = plane->scan_flag;
-}
-
 static void mixer_win_commit(struct exynos_drm_crtc *crtc, int zpos)
 {
        struct mixer_context *mixer_ctx = crtc->ctx;
@@ -992,7 +917,7 @@ static void mixer_win_commit(struct exynos_drm_crtc *crtc, int zpos)
        else
                mixer_graph_buffer(mixer_ctx, win);
 
-       mixer_ctx->win_data[win].enabled = true;
+       mixer_ctx->planes[win].enabled = true;
 }
 
 static void mixer_win_disable(struct exynos_drm_crtc *crtc, int zpos)
@@ -1007,7 +932,7 @@ static void mixer_win_disable(struct exynos_drm_crtc *crtc, int zpos)
        mutex_lock(&mixer_ctx->mixer_mutex);
        if (!mixer_ctx->powered) {
                mutex_unlock(&mixer_ctx->mixer_mutex);
-               mixer_ctx->win_data[win].resume = false;
+               mixer_ctx->planes[win].resume = false;
                return;
        }
        mutex_unlock(&mixer_ctx->mixer_mutex);
@@ -1020,7 +945,7 @@ static void mixer_win_disable(struct exynos_drm_crtc *crtc, int zpos)
        mixer_vsync_set_update(mixer_ctx, true);
        spin_unlock_irqrestore(&res->reg_slock, flags);
 
-       mixer_ctx->win_data[win].enabled = false;
+       mixer_ctx->planes[win].enabled = false;
 }
 
 static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc)
@@ -1057,12 +982,12 @@ static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc)
 
 static void mixer_window_suspend(struct mixer_context *ctx)
 {
-       struct hdmi_win_data *win_data;
+       struct exynos_drm_plane *plane;
        int i;
 
        for (i = 0; i < MIXER_WIN_NR; i++) {
-               win_data = &ctx->win_data[i];
-               win_data->resume = win_data->enabled;
+               plane = &ctx->planes[i];
+               plane->resume = plane->enabled;
                mixer_win_disable(ctx->crtc, i);
        }
        mixer_wait_for_vblank(ctx->crtc);
@@ -1070,14 +995,14 @@ static void mixer_window_suspend(struct mixer_context *ctx)
 
 static void mixer_window_resume(struct mixer_context *ctx)
 {
-       struct hdmi_win_data *win_data;
+       struct exynos_drm_plane *plane;
        int i;
 
        for (i = 0; i < MIXER_WIN_NR; i++) {
-               win_data = &ctx->win_data[i];
-               win_data->enabled = win_data->resume;
-               win_data->resume = false;
-               if (win_data->enabled)
+               plane = &ctx->planes[i];
+               plane->enabled = plane->resume;
+               plane->resume = false;
+               if (plane->enabled)
                        mixer_win_commit(ctx->crtc, i);
        }
 }
@@ -1189,7 +1114,6 @@ static struct exynos_drm_crtc_ops mixer_crtc_ops = {
        .enable_vblank          = mixer_enable_vblank,
        .disable_vblank         = mixer_disable_vblank,
        .wait_for_vblank        = mixer_wait_for_vblank,
-       .win_mode_set           = mixer_win_mode_set,
        .win_commit             = mixer_win_commit,
        .win_disable            = mixer_win_disable,
 };
@@ -1253,15 +1177,27 @@ static int mixer_bind(struct device *dev, struct device *manager, void *data)
 {
        struct mixer_context *ctx = dev_get_drvdata(dev);
        struct drm_device *drm_dev = data;
-       int ret;
+       struct exynos_drm_plane *exynos_plane;
+       enum drm_plane_type type;
+       int zpos, ret;
 
        ret = mixer_initialize(ctx, drm_dev);
        if (ret)
                return ret;
 
-       ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe,
-                                    EXYNOS_DISPLAY_TYPE_HDMI,
-                                    &mixer_crtc_ops, ctx);
+       for (zpos = 0; zpos < MIXER_WIN_NR; zpos++) {
+               type = (zpos == MIXER_DEFAULT_WIN) ? DRM_PLANE_TYPE_PRIMARY :
+                                               DRM_PLANE_TYPE_OVERLAY;
+               ret = exynos_plane_init(drm_dev, &ctx->planes[zpos],
+                                       1 << ctx->pipe, type);
+               if (ret)
+                       return ret;
+       }
+
+       exynos_plane = &ctx->planes[MIXER_DEFAULT_WIN];
+       ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
+                                          ctx->pipe, EXYNOS_DISPLAY_TYPE_HDMI,
+                                          &mixer_crtc_ops, ctx);
        if (IS_ERR(ctx->crtc)) {
                mixer_ctx_remove(ctx);
                ret = PTR_ERR(ctx->crtc);