Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * i.MX IPUv3 Graphics driver
0004  *
0005  * Copyright (C) 2011 Sascha Hauer, Pengutronix
0006  */
0007 
0008 #include <linux/clk.h>
0009 #include <linux/component.h>
0010 #include <linux/device.h>
0011 #include <linux/dma-mapping.h>
0012 #include <linux/errno.h>
0013 #include <linux/export.h>
0014 #include <linux/module.h>
0015 #include <linux/platform_device.h>
0016 
0017 #include <video/imx-ipu-v3.h>
0018 
0019 #include <drm/drm_atomic.h>
0020 #include <drm/drm_atomic_helper.h>
0021 #include <drm/drm_fb_cma_helper.h>
0022 #include <drm/drm_gem_cma_helper.h>
0023 #include <drm/drm_managed.h>
0024 #include <drm/drm_probe_helper.h>
0025 #include <drm/drm_vblank.h>
0026 
0027 #include "imx-drm.h"
0028 #include "ipuv3-plane.h"
0029 
0030 #define DRIVER_DESC     "i.MX IPUv3 Graphics"
0031 
0032 struct ipu_crtc {
0033     struct device       *dev;
0034     struct drm_crtc     base;
0035 
0036     /* plane[0] is the full plane, plane[1] is the partial plane */
0037     struct ipu_plane    *plane[2];
0038 
0039     struct ipu_dc       *dc;
0040     struct ipu_di       *di;
0041     int         irq;
0042     struct drm_pending_vblank_event *event;
0043 };
0044 
0045 static inline struct ipu_crtc *to_ipu_crtc(struct drm_crtc *crtc)
0046 {
0047     return container_of(crtc, struct ipu_crtc, base);
0048 }
0049 
0050 static void ipu_crtc_atomic_enable(struct drm_crtc *crtc,
0051                    struct drm_atomic_state *state)
0052 {
0053     struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
0054     struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
0055 
0056     ipu_prg_enable(ipu);
0057     ipu_dc_enable(ipu);
0058     ipu_dc_enable_channel(ipu_crtc->dc);
0059     ipu_di_enable(ipu_crtc->di);
0060 }
0061 
0062 static void ipu_crtc_disable_planes(struct ipu_crtc *ipu_crtc,
0063                     struct drm_crtc_state *old_crtc_state)
0064 {
0065     bool disable_partial = false;
0066     bool disable_full = false;
0067     struct drm_plane *plane;
0068 
0069     drm_atomic_crtc_state_for_each_plane(plane, old_crtc_state) {
0070         if (plane == &ipu_crtc->plane[0]->base)
0071             disable_full = true;
0072         if (ipu_crtc->plane[1] && plane == &ipu_crtc->plane[1]->base)
0073             disable_partial = true;
0074     }
0075 
0076     if (disable_partial)
0077         ipu_plane_disable(ipu_crtc->plane[1], true);
0078     if (disable_full)
0079         ipu_plane_disable(ipu_crtc->plane[0], true);
0080 }
0081 
0082 static void ipu_crtc_atomic_disable(struct drm_crtc *crtc,
0083                     struct drm_atomic_state *state)
0084 {
0085     struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(state,
0086                                           crtc);
0087     struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
0088     struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
0089 
0090     ipu_dc_disable_channel(ipu_crtc->dc);
0091     ipu_di_disable(ipu_crtc->di);
0092     /*
0093      * Planes must be disabled before DC clock is removed, as otherwise the
0094      * attached IDMACs will be left in undefined state, possibly hanging
0095      * the IPU or even system.
0096      */
0097     ipu_crtc_disable_planes(ipu_crtc, old_crtc_state);
0098     ipu_dc_disable(ipu);
0099     ipu_prg_disable(ipu);
0100 
0101     drm_crtc_vblank_off(crtc);
0102 
0103     spin_lock_irq(&crtc->dev->event_lock);
0104     if (crtc->state->event && !crtc->state->active) {
0105         drm_crtc_send_vblank_event(crtc, crtc->state->event);
0106         crtc->state->event = NULL;
0107     }
0108     spin_unlock_irq(&crtc->dev->event_lock);
0109 }
0110 
0111 static void imx_drm_crtc_reset(struct drm_crtc *crtc)
0112 {
0113     struct imx_crtc_state *state;
0114 
0115     if (crtc->state)
0116         __drm_atomic_helper_crtc_destroy_state(crtc->state);
0117 
0118     kfree(to_imx_crtc_state(crtc->state));
0119     crtc->state = NULL;
0120 
0121     state = kzalloc(sizeof(*state), GFP_KERNEL);
0122     if (state)
0123         __drm_atomic_helper_crtc_reset(crtc, &state->base);
0124 }
0125 
0126 static struct drm_crtc_state *imx_drm_crtc_duplicate_state(struct drm_crtc *crtc)
0127 {
0128     struct imx_crtc_state *state;
0129 
0130     state = kzalloc(sizeof(*state), GFP_KERNEL);
0131     if (!state)
0132         return NULL;
0133 
0134     __drm_atomic_helper_crtc_duplicate_state(crtc, &state->base);
0135 
0136     WARN_ON(state->base.crtc != crtc);
0137     state->base.crtc = crtc;
0138 
0139     return &state->base;
0140 }
0141 
0142 static void imx_drm_crtc_destroy_state(struct drm_crtc *crtc,
0143                        struct drm_crtc_state *state)
0144 {
0145     __drm_atomic_helper_crtc_destroy_state(state);
0146     kfree(to_imx_crtc_state(state));
0147 }
0148 
0149 static int ipu_enable_vblank(struct drm_crtc *crtc)
0150 {
0151     struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
0152 
0153     enable_irq(ipu_crtc->irq);
0154 
0155     return 0;
0156 }
0157 
0158 static void ipu_disable_vblank(struct drm_crtc *crtc)
0159 {
0160     struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
0161 
0162     disable_irq_nosync(ipu_crtc->irq);
0163 }
0164 
0165 static const struct drm_crtc_funcs ipu_crtc_funcs = {
0166     .set_config = drm_atomic_helper_set_config,
0167     .page_flip = drm_atomic_helper_page_flip,
0168     .reset = imx_drm_crtc_reset,
0169     .atomic_duplicate_state = imx_drm_crtc_duplicate_state,
0170     .atomic_destroy_state = imx_drm_crtc_destroy_state,
0171     .enable_vblank = ipu_enable_vblank,
0172     .disable_vblank = ipu_disable_vblank,
0173 };
0174 
0175 static irqreturn_t ipu_irq_handler(int irq, void *dev_id)
0176 {
0177     struct ipu_crtc *ipu_crtc = dev_id;
0178     struct drm_crtc *crtc = &ipu_crtc->base;
0179     unsigned long flags;
0180     int i;
0181 
0182     drm_crtc_handle_vblank(crtc);
0183 
0184     if (ipu_crtc->event) {
0185         for (i = 0; i < ARRAY_SIZE(ipu_crtc->plane); i++) {
0186             struct ipu_plane *plane = ipu_crtc->plane[i];
0187 
0188             if (!plane)
0189                 continue;
0190 
0191             if (ipu_plane_atomic_update_pending(&plane->base))
0192                 break;
0193         }
0194 
0195         if (i == ARRAY_SIZE(ipu_crtc->plane)) {
0196             spin_lock_irqsave(&crtc->dev->event_lock, flags);
0197             drm_crtc_send_vblank_event(crtc, ipu_crtc->event);
0198             ipu_crtc->event = NULL;
0199             drm_crtc_vblank_put(crtc);
0200             spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
0201         }
0202     }
0203 
0204     return IRQ_HANDLED;
0205 }
0206 
0207 static bool ipu_crtc_mode_fixup(struct drm_crtc *crtc,
0208                   const struct drm_display_mode *mode,
0209                   struct drm_display_mode *adjusted_mode)
0210 {
0211     struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
0212     struct videomode vm;
0213     int ret;
0214 
0215     drm_display_mode_to_videomode(adjusted_mode, &vm);
0216 
0217     ret = ipu_di_adjust_videomode(ipu_crtc->di, &vm);
0218     if (ret)
0219         return false;
0220 
0221     if ((vm.vsync_len == 0) || (vm.hsync_len == 0))
0222         return false;
0223 
0224     drm_display_mode_from_videomode(&vm, adjusted_mode);
0225 
0226     return true;
0227 }
0228 
0229 static int ipu_crtc_atomic_check(struct drm_crtc *crtc,
0230                  struct drm_atomic_state *state)
0231 {
0232     struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,
0233                                       crtc);
0234     u32 primary_plane_mask = drm_plane_mask(crtc->primary);
0235 
0236     if (crtc_state->active && (primary_plane_mask & crtc_state->plane_mask) == 0)
0237         return -EINVAL;
0238 
0239     return 0;
0240 }
0241 
0242 static void ipu_crtc_atomic_begin(struct drm_crtc *crtc,
0243                   struct drm_atomic_state *state)
0244 {
0245     drm_crtc_vblank_on(crtc);
0246 }
0247 
0248 static void ipu_crtc_atomic_flush(struct drm_crtc *crtc,
0249                   struct drm_atomic_state *state)
0250 {
0251     spin_lock_irq(&crtc->dev->event_lock);
0252     if (crtc->state->event) {
0253         struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
0254 
0255         WARN_ON(drm_crtc_vblank_get(crtc));
0256         ipu_crtc->event = crtc->state->event;
0257         crtc->state->event = NULL;
0258     }
0259     spin_unlock_irq(&crtc->dev->event_lock);
0260 }
0261 
0262 static void ipu_crtc_mode_set_nofb(struct drm_crtc *crtc)
0263 {
0264     struct drm_device *dev = crtc->dev;
0265     struct drm_encoder *encoder;
0266     struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
0267     struct drm_display_mode *mode = &crtc->state->adjusted_mode;
0268     struct imx_crtc_state *imx_crtc_state = to_imx_crtc_state(crtc->state);
0269     struct ipu_di_signal_cfg sig_cfg = {};
0270     unsigned long encoder_types = 0;
0271 
0272     dev_dbg(ipu_crtc->dev, "%s: mode->hdisplay: %d\n", __func__,
0273             mode->hdisplay);
0274     dev_dbg(ipu_crtc->dev, "%s: mode->vdisplay: %d\n", __func__,
0275             mode->vdisplay);
0276 
0277     list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
0278         if (encoder->crtc == crtc)
0279             encoder_types |= BIT(encoder->encoder_type);
0280     }
0281 
0282     dev_dbg(ipu_crtc->dev, "%s: attached to encoder types 0x%lx\n",
0283         __func__, encoder_types);
0284 
0285     /*
0286      * If we have DAC or LDB, then we need the IPU DI clock to be
0287      * the same as the LDB DI clock. For TVDAC, derive the IPU DI
0288      * clock from 27 MHz TVE_DI clock, but allow to divide it.
0289      */
0290     if (encoder_types & (BIT(DRM_MODE_ENCODER_DAC) |
0291                  BIT(DRM_MODE_ENCODER_LVDS)))
0292         sig_cfg.clkflags = IPU_DI_CLKMODE_SYNC | IPU_DI_CLKMODE_EXT;
0293     else if (encoder_types & BIT(DRM_MODE_ENCODER_TVDAC))
0294         sig_cfg.clkflags = IPU_DI_CLKMODE_EXT;
0295     else
0296         sig_cfg.clkflags = 0;
0297 
0298     sig_cfg.enable_pol = !(imx_crtc_state->bus_flags & DRM_BUS_FLAG_DE_LOW);
0299     /* Default to driving pixel data on negative clock edges */
0300     sig_cfg.clk_pol = !!(imx_crtc_state->bus_flags &
0301                  DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE);
0302     sig_cfg.bus_format = imx_crtc_state->bus_format;
0303     sig_cfg.v_to_h_sync = 0;
0304     sig_cfg.hsync_pin = imx_crtc_state->di_hsync_pin;
0305     sig_cfg.vsync_pin = imx_crtc_state->di_vsync_pin;
0306 
0307     drm_display_mode_to_videomode(mode, &sig_cfg.mode);
0308     if (!IS_ALIGNED(sig_cfg.mode.hactive, 8)) {
0309         unsigned int new_hactive = ALIGN(sig_cfg.mode.hactive, 8);
0310 
0311         dev_warn(ipu_crtc->dev, "8-pixel align hactive %d -> %d\n",
0312              sig_cfg.mode.hactive, new_hactive);
0313 
0314         sig_cfg.mode.hfront_porch = new_hactive - sig_cfg.mode.hactive;
0315         sig_cfg.mode.hactive = new_hactive;
0316     }
0317 
0318     ipu_dc_init_sync(ipu_crtc->dc, ipu_crtc->di,
0319              mode->flags & DRM_MODE_FLAG_INTERLACE,
0320              imx_crtc_state->bus_format, sig_cfg.mode.hactive);
0321     ipu_di_init_sync_panel(ipu_crtc->di, &sig_cfg);
0322 }
0323 
0324 static const struct drm_crtc_helper_funcs ipu_helper_funcs = {
0325     .mode_fixup = ipu_crtc_mode_fixup,
0326     .mode_set_nofb = ipu_crtc_mode_set_nofb,
0327     .atomic_check = ipu_crtc_atomic_check,
0328     .atomic_begin = ipu_crtc_atomic_begin,
0329     .atomic_flush = ipu_crtc_atomic_flush,
0330     .atomic_disable = ipu_crtc_atomic_disable,
0331     .atomic_enable = ipu_crtc_atomic_enable,
0332 };
0333 
0334 static void ipu_put_resources(struct drm_device *dev, void *ptr)
0335 {
0336     struct ipu_crtc *ipu_crtc = ptr;
0337 
0338     if (!IS_ERR_OR_NULL(ipu_crtc->dc))
0339         ipu_dc_put(ipu_crtc->dc);
0340     if (!IS_ERR_OR_NULL(ipu_crtc->di))
0341         ipu_di_put(ipu_crtc->di);
0342 }
0343 
0344 static int ipu_get_resources(struct drm_device *dev, struct ipu_crtc *ipu_crtc,
0345                  struct ipu_client_platformdata *pdata)
0346 {
0347     struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
0348     int ret;
0349 
0350     ipu_crtc->dc = ipu_dc_get(ipu, pdata->dc);
0351     if (IS_ERR(ipu_crtc->dc))
0352         return PTR_ERR(ipu_crtc->dc);
0353 
0354     ret = drmm_add_action_or_reset(dev, ipu_put_resources, ipu_crtc);
0355     if (ret)
0356         return ret;
0357 
0358     ipu_crtc->di = ipu_di_get(ipu, pdata->di);
0359     if (IS_ERR(ipu_crtc->di))
0360         return PTR_ERR(ipu_crtc->di);
0361 
0362     return 0;
0363 }
0364 
0365 static int ipu_drm_bind(struct device *dev, struct device *master, void *data)
0366 {
0367     struct ipu_client_platformdata *pdata = dev->platform_data;
0368     struct ipu_soc *ipu = dev_get_drvdata(dev->parent);
0369     struct drm_device *drm = data;
0370     struct ipu_plane *primary_plane;
0371     struct ipu_crtc *ipu_crtc;
0372     struct drm_crtc *crtc;
0373     int dp = -EINVAL;
0374     int ret;
0375 
0376     if (pdata->dp >= 0)
0377         dp = IPU_DP_FLOW_SYNC_BG;
0378     primary_plane = ipu_plane_init(drm, ipu, pdata->dma[0], dp, 0,
0379                        DRM_PLANE_TYPE_PRIMARY);
0380     if (IS_ERR(primary_plane))
0381         return PTR_ERR(primary_plane);
0382 
0383     ipu_crtc = drmm_crtc_alloc_with_planes(drm, struct ipu_crtc, base,
0384                            &primary_plane->base, NULL,
0385                            &ipu_crtc_funcs, NULL);
0386     if (IS_ERR(ipu_crtc))
0387         return PTR_ERR(ipu_crtc);
0388 
0389     ipu_crtc->dev = dev;
0390     ipu_crtc->plane[0] = primary_plane;
0391 
0392     crtc = &ipu_crtc->base;
0393     crtc->port = pdata->of_node;
0394     drm_crtc_helper_add(crtc, &ipu_helper_funcs);
0395 
0396     ret = ipu_get_resources(drm, ipu_crtc, pdata);
0397     if (ret) {
0398         dev_err(ipu_crtc->dev, "getting resources failed with %d.\n",
0399             ret);
0400         return ret;
0401     }
0402 
0403     /* If this crtc is using the DP, add an overlay plane */
0404     if (pdata->dp >= 0 && pdata->dma[1] > 0) {
0405         ipu_crtc->plane[1] = ipu_plane_init(drm, ipu, pdata->dma[1],
0406                         IPU_DP_FLOW_SYNC_FG,
0407                         drm_crtc_mask(&ipu_crtc->base),
0408                         DRM_PLANE_TYPE_OVERLAY);
0409         if (IS_ERR(ipu_crtc->plane[1]))
0410             ipu_crtc->plane[1] = NULL;
0411     }
0412 
0413     ipu_crtc->irq = ipu_plane_irq(ipu_crtc->plane[0]);
0414     ret = devm_request_irq(ipu_crtc->dev, ipu_crtc->irq, ipu_irq_handler, 0,
0415             "imx_drm", ipu_crtc);
0416     if (ret < 0) {
0417         dev_err(ipu_crtc->dev, "irq request failed with %d.\n", ret);
0418         return ret;
0419     }
0420     /* Only enable IRQ when we actually need it to trigger work. */
0421     disable_irq(ipu_crtc->irq);
0422 
0423     return 0;
0424 }
0425 
0426 static const struct component_ops ipu_crtc_ops = {
0427     .bind = ipu_drm_bind,
0428 };
0429 
0430 static int ipu_drm_probe(struct platform_device *pdev)
0431 {
0432     struct device *dev = &pdev->dev;
0433     int ret;
0434 
0435     if (!dev->platform_data)
0436         return -EINVAL;
0437 
0438     ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
0439     if (ret)
0440         return ret;
0441 
0442     return component_add(dev, &ipu_crtc_ops);
0443 }
0444 
0445 static int ipu_drm_remove(struct platform_device *pdev)
0446 {
0447     component_del(&pdev->dev, &ipu_crtc_ops);
0448     return 0;
0449 }
0450 
0451 struct platform_driver ipu_drm_driver = {
0452     .driver = {
0453         .name = "imx-ipuv3-crtc",
0454     },
0455     .probe = ipu_drm_probe,
0456     .remove = ipu_drm_remove,
0457 };