Merge tag 'drm-msm-next-2017-08-22' of git://people.freedesktop.org/~robclark/linux...
authorDave Airlie <airlied@redhat.com>
Thu, 24 Aug 2017 23:29:45 +0000 (09:29 +1000)
committerDave Airlie <airlied@redhat.com>
Thu, 24 Aug 2017 23:29:45 +0000 (09:29 +1000)
Updates for 4.14..  I have some further patches from Jordan to add
multiple priority levels and pre-emption, but those will probably be
for 4.15 to give me time for the mesa parts.

* tag 'drm-msm-next-2017-08-22' of git://people.freedesktop.org/~robclark/linux:
  drm/msm/mdp5: mark runtime_pm functions as __maybe_unused
  drm/msm: remove unused variable
  drm/msm/mdp5: make helper function static
  drm/msm: make msm_framebuffer_init() static
  drm/msm: add helper to allocate stolen fb
  drm/msm: don't track fbdev's gem object separately
  drm/msm: add modeset module param
  drm/msm/mdp5: add tracking for clk enable-count
  drm/msm: remove unused define
  drm/msm: Add a helper function for in-kernel buffer allocations
  drm/msm: Attach the GPU MMU when it is created
  drm/msm: Add A5XX hardware fault detection
  drm/msm: Remove uneeded platform dev members
  drm/msm/mdp5: Set up runtime PM for MDSS
  drm/msm/mdp5: Write to SMP registers even if allocations don't change
  drm/msm/mdp5: Don't use mode_set helper funcs for encoders and CRTCs
  drm/msm/dsi: Implement RPM suspend/resume callbacks
  drm/msm/dsi: Set up runtime PM for DSI
  drm/msm/hdmi: Set up runtime PM for HDMI
  drm/msm/mdp5: Use runtime PM get/put API instead of toggling clocks

1  2 
drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
drivers/gpu/drm/msm/hdmi/hdmi_connector.c
drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
drivers/gpu/drm/msm/msm_drv.c
drivers/gpu/drm/msm/msm_fbdev.c

index 13ac822dee5d89c7cc47411ea2f7b517223c0b65,e9b5e886e7476bebff43a87b31c4faf421b70adc..7e357077ed2634dadb2436c6c5abfb0d6625583b
@@@ -35,6 -35,8 +35,8 @@@ static void msm_hdmi_power_on(struct dr
        const struct hdmi_platform_config *config = hdmi->config;
        int i, ret;
  
+       pm_runtime_get_sync(&hdmi->pdev->dev);
        for (i = 0; i < config->pwr_reg_cnt; i++) {
                ret = regulator_enable(hdmi->pwr_regs[i]);
                if (ret) {
@@@ -84,6 -86,8 +86,8 @@@ static void power_off(struct drm_bridg
                                        config->pwr_reg_names[i], ret);
                }
        }
+       pm_runtime_put_autosuspend(&hdmi->pdev->dev);
  }
  
  #define AVI_IFRAME_LINE_NUMBER 1
@@@ -97,7 -101,7 +101,7 @@@ static void msm_hdmi_config_avi_infofra
        u32 val;
        int len;
  
 -      drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
 +      drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
  
        len = hdmi_infoframe_pack(&frame, buffer, sizeof(buffer));
        if (len < 0) {
index 71536d9c7fe8c89d37b0061ae97e962e446ff536,c0e117179ecb3b9970bc0d6b2084c0d1e98bb07c..c0848dfedd50648de59be95cdd389f81bde29edf
@@@ -137,6 -137,36 +137,36 @@@ err
        return ret;
  }
  
+ static void enable_hpd_clocks(struct hdmi *hdmi, bool enable)
+ {
+       const struct hdmi_platform_config *config = hdmi->config;
+       struct device *dev = &hdmi->pdev->dev;
+       int i, ret;
+       if (enable) {
+               for (i = 0; i < config->hpd_clk_cnt; i++) {
+                       if (config->hpd_freq && config->hpd_freq[i]) {
+                               ret = clk_set_rate(hdmi->hpd_clks[i],
+                                                  config->hpd_freq[i]);
+                               if (ret)
+                                       dev_warn(dev,
+                                                "failed to set clk %s (%d)\n",
+                                                config->hpd_clk_names[i], ret);
+                       }
+                       ret = clk_prepare_enable(hdmi->hpd_clks[i]);
+                       if (ret) {
+                               dev_err(dev,
+                                       "failed to enable hpd clk: %s (%d)\n",
+                                       config->hpd_clk_names[i], ret);
+                       }
+               }
+       } else {
+               for (i = config->hpd_clk_cnt - 1; i >= 0; i--)
+                       clk_disable_unprepare(hdmi->hpd_clks[i]);
+       }
+ }
  static int hpd_enable(struct hdmi_connector *hdmi_connector)
  {
        struct hdmi *hdmi = hdmi_connector->hdmi;
                goto fail;
        }
  
-       for (i = 0; i < config->hpd_clk_cnt; i++) {
-               if (config->hpd_freq && config->hpd_freq[i]) {
-                       ret = clk_set_rate(hdmi->hpd_clks[i],
-                                       config->hpd_freq[i]);
-                       if (ret)
-                               dev_warn(dev, "failed to set clk %s (%d)\n",
-                                               config->hpd_clk_names[i], ret);
-               }
-               ret = clk_prepare_enable(hdmi->hpd_clks[i]);
-               if (ret) {
-                       dev_err(dev, "failed to enable hpd clk: %s (%d)\n",
-                                       config->hpd_clk_names[i], ret);
-                       goto fail;
-               }
-       }
+       pm_runtime_get_sync(dev);
+       enable_hpd_clocks(hdmi, true);
  
        msm_hdmi_set_mode(hdmi, false);
        msm_hdmi_phy_reset(hdmi);
@@@ -225,8 -241,8 +241,8 @@@ static void hdp_disable(struct hdmi_con
  
        msm_hdmi_set_mode(hdmi, false);
  
-       for (i = 0; i < config->hpd_clk_cnt; i++)
-               clk_disable_unprepare(hdmi->hpd_clks[i]);
+       enable_hpd_clocks(hdmi, false);
+       pm_runtime_put_autosuspend(dev);
  
        ret = gpio_config(hdmi, false);
        if (ret)
@@@ -285,7 -301,16 +301,16 @@@ void msm_hdmi_connector_irq(struct drm_
  
  static enum drm_connector_status detect_reg(struct hdmi *hdmi)
  {
-       uint32_t hpd_int_status = hdmi_read(hdmi, REG_HDMI_HPD_INT_STATUS);
+       uint32_t hpd_int_status;
+       pm_runtime_get_sync(&hdmi->pdev->dev);
+       enable_hpd_clocks(hdmi, true);
+       hpd_int_status = hdmi_read(hdmi, REG_HDMI_HPD_INT_STATUS);
+       enable_hpd_clocks(hdmi, false);
+       pm_runtime_put_autosuspend(&hdmi->pdev->dev);
        return (hpd_int_status & HDMI_HPD_INT_STATUS_CABLE_DETECTED) ?
                        connector_status_connected : connector_status_disconnected;
  }
@@@ -407,6 -432,7 +432,6 @@@ static int msm_hdmi_connector_mode_vali
  }
  
  static const struct drm_connector_funcs hdmi_connector_funcs = {
 -      .dpms = drm_atomic_helper_connector_dpms,
        .detect = hdmi_connector_detect,
        .fill_modes = drm_helper_probe_single_connector_modes,
        .destroy = hdmi_connector_destroy,
index 3a81e26629c7dc001fd9fa6bfd2bd26cf72848d6,aefe6d2cfa948c841a3c115cca59c1771e5094e6..6fcb58ab718cd9c986155f50eb55cccf07c22c32
@@@ -409,12 -409,12 +409,13 @@@ static void mdp5_crtc_mode_set_nofb(str
        spin_unlock_irqrestore(&mdp5_crtc->lm_lock, flags);
  }
  
 -static void mdp5_crtc_disable(struct drm_crtc *crtc)
 +static void mdp5_crtc_atomic_disable(struct drm_crtc *crtc,
 +                                   struct drm_crtc_state *old_state)
  {
        struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
        struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
        struct mdp5_kms *mdp5_kms = get_kms(crtc);
+       struct device *dev = &mdp5_kms->pdev->dev;
  
        DBG("%s", crtc->name);
  
                mdp_irq_unregister(&mdp5_kms->base, &mdp5_crtc->pp_done);
  
        mdp_irq_unregister(&mdp5_kms->base, &mdp5_crtc->err);
-       mdp5_disable(mdp5_kms);
+       pm_runtime_put_autosuspend(dev);
  
        mdp5_crtc->enabled = false;
  }
  
 -static void mdp5_crtc_enable(struct drm_crtc *crtc)
 +static void mdp5_crtc_atomic_enable(struct drm_crtc *crtc,
 +                                  struct drm_crtc_state *old_state)
  {
        struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
        struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
        struct mdp5_kms *mdp5_kms = get_kms(crtc);
+       struct device *dev = &mdp5_kms->pdev->dev;
  
        DBG("%s", crtc->name);
  
        if (WARN_ON(mdp5_crtc->enabled))
                return;
  
-       mdp5_enable(mdp5_kms);
+       pm_runtime_get_sync(dev);
+       mdp5_crtc_mode_set_nofb(crtc);
        mdp_irq_register(&mdp5_kms->base, &mdp5_crtc->err);
  
        if (mdp5_cstate->cmd_mode)
@@@ -533,7 -536,7 +538,7 @@@ static bool is_fullscreen(struct drm_cr
                ((pstate->crtc_y + pstate->crtc_h) >= cstate->mode.vdisplay);
  }
  
- enum mdp_mixer_stage_id get_start_stage(struct drm_crtc *crtc,
static enum mdp_mixer_stage_id get_start_stage(struct drm_crtc *crtc,
                                        struct drm_crtc_state *new_crtc_state,
                                        struct drm_plane_state *bpstate)
  {
@@@ -727,6 -730,7 +732,7 @@@ static int mdp5_crtc_cursor_set(struct 
        struct mdp5_pipeline *pipeline = &mdp5_cstate->pipeline;
        struct drm_device *dev = crtc->dev;
        struct mdp5_kms *mdp5_kms = get_kms(crtc);
+       struct platform_device *pdev = mdp5_kms->pdev;
        struct msm_kms *kms = &mdp5_kms->base.base;
        struct drm_gem_object *cursor_bo, *old_bo = NULL;
        uint32_t blendcfg, stride;
        if (!handle) {
                DBG("Cursor off");
                cursor_enable = false;
-               mdp5_enable(mdp5_kms);
+               pm_runtime_get_sync(&pdev->dev);
                goto set_cursor;
        }
  
        lm = mdp5_cstate->pipeline.mixer->lm;
        stride = width * drm_format_plane_cpp(DRM_FORMAT_ARGB8888, 0);
  
+       pm_runtime_get_sync(&pdev->dev);
        spin_lock_irqsave(&mdp5_crtc->cursor.lock, flags);
        old_bo = mdp5_crtc->cursor.scanout_bo;
  
  
        get_roi(crtc, &roi_w, &roi_h);
  
-       mdp5_enable(mdp5_kms);
        mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_STRIDE(lm), stride);
        mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_FORMAT(lm),
                        MDP5_LM_CURSOR_FORMAT_FORMAT(CURSOR_FMT_ARGB8888));
  
        spin_unlock_irqrestore(&mdp5_crtc->cursor.lock, flags);
  
+       pm_runtime_put_autosuspend(&pdev->dev);
  set_cursor:
        ret = mdp5_ctl_set_cursor(ctl, pipeline, 0, cursor_enable);
        if (ret) {
        crtc_flush(crtc, flush_mask);
  
  end:
-       mdp5_disable(mdp5_kms);
+       pm_runtime_put_autosuspend(&pdev->dev);
        if (old_bo) {
                drm_flip_work_queue(&mdp5_crtc->unref_cursor_work, old_bo);
                /* enable vblank to complete cursor work: */
@@@ -842,7 -848,7 +850,7 @@@ static int mdp5_crtc_cursor_move(struc
  
        get_roi(crtc, &roi_w, &roi_h);
  
-       mdp5_enable(mdp5_kms);
+       pm_runtime_get_sync(&mdp5_kms->pdev->dev);
  
        spin_lock_irqsave(&mdp5_crtc->cursor.lock, flags);
        mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_SIZE(lm),
  
        crtc_flush(crtc, flush_mask);
  
-       mdp5_disable(mdp5_kms);
+       pm_runtime_put_autosuspend(&mdp5_kms->pdev->dev);
  
        return 0;
  }
@@@ -927,6 -933,7 +935,6 @@@ static const struct drm_crtc_funcs mdp5
        .set_config = drm_atomic_helper_set_config,
        .destroy = mdp5_crtc_destroy,
        .page_flip = drm_atomic_helper_page_flip,
 -      .set_property = drm_atomic_helper_crtc_set_property,
        .reset = mdp5_crtc_reset,
        .atomic_duplicate_state = mdp5_crtc_duplicate_state,
        .atomic_destroy_state = mdp5_crtc_destroy_state,
@@@ -939,6 -946,7 +947,6 @@@ static const struct drm_crtc_funcs mdp5
        .set_config = drm_atomic_helper_set_config,
        .destroy = mdp5_crtc_destroy,
        .page_flip = drm_atomic_helper_page_flip,
 -      .set_property = drm_atomic_helper_crtc_set_property,
        .reset = mdp5_crtc_reset,
        .atomic_duplicate_state = mdp5_crtc_duplicate_state,
        .atomic_destroy_state = mdp5_crtc_destroy_state,
  };
  
  static const struct drm_crtc_helper_funcs mdp5_crtc_helper_funcs = {
 -      .disable = mdp5_crtc_disable,
 -      .enable = mdp5_crtc_enable,
 +      .mode_set_nofb = mdp5_crtc_mode_set_nofb,
        .atomic_check = mdp5_crtc_atomic_check,
        .atomic_begin = mdp5_crtc_atomic_begin,
        .atomic_flush = mdp5_crtc_atomic_flush,
 +      .atomic_enable = mdp5_crtc_atomic_enable,
 +      .atomic_disable = mdp5_crtc_atomic_disable,
  };
  
  static void mdp5_crtc_vblank_irq(struct mdp_irq *irq, uint32_t irqstatus)
index b0129e7b29e3067e9f00dfa578da8d13e1b4c7fa,dda55b6103e2440d0a52ac8e2fcb7d81439313d1..606df7bea97bff05691b41993ee741088c3d86dd
@@@ -73,6 -73,10 +73,10 @@@ bool dumpstate = false
  MODULE_PARM_DESC(dumpstate, "Dump KMS state on errors");
  module_param(dumpstate, bool, 0600);
  
+ static bool modeset = true;
+ MODULE_PARM_DESC(modeset, "Use kernel modesetting [KMS] (1=on (default), 0=disable)");
+ module_param(modeset, bool, 0600);
  /*
   * Util/helpers:
   */
@@@ -832,6 -836,7 +836,6 @@@ static struct drm_driver msm_driver = 
        .gem_vm_ops         = &vm_ops,
        .dumb_create        = msm_gem_dumb_create,
        .dumb_map_offset    = msm_gem_dumb_map_offset,
 -      .dumb_destroy       = drm_gem_dumb_destroy,
        .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
        .gem_prime_export   = drm_gem_prime_export,
@@@ -878,8 -883,37 +882,37 @@@ static int msm_pm_resume(struct device 
  }
  #endif
  
+ #ifdef CONFIG_PM
+ static int msm_runtime_suspend(struct device *dev)
+ {
+       struct drm_device *ddev = dev_get_drvdata(dev);
+       struct msm_drm_private *priv = ddev->dev_private;
+       DBG("");
+       if (priv->mdss)
+               return msm_mdss_disable(priv->mdss);
+       return 0;
+ }
+ static int msm_runtime_resume(struct device *dev)
+ {
+       struct drm_device *ddev = dev_get_drvdata(dev);
+       struct msm_drm_private *priv = ddev->dev_private;
+       DBG("");
+       if (priv->mdss)
+               return msm_mdss_enable(priv->mdss);
+       return 0;
+ }
+ #endif
  static const struct dev_pm_ops msm_pm_ops = {
        SET_SYSTEM_SLEEP_PM_OPS(msm_pm_suspend, msm_pm_resume)
+       SET_RUNTIME_PM_OPS(msm_runtime_suspend, msm_runtime_resume, NULL)
  };
  
  /*
@@@ -1103,6 -1137,9 +1136,9 @@@ static struct platform_driver msm_platf
  
  static int __init msm_drm_register(void)
  {
+       if (!modeset)
+               return -EINVAL;
        DBG("init");
        msm_mdp_register();
        msm_dsi_register();
index 9c00fedfc741614632d25fa29235d367f3763408,5dc0ae3089354f3451b8bb91d1108aa91c3159cf..c178563fcd4dc56a2d1fbdaf4197c847b5c11904
@@@ -19,7 -19,6 +19,6 @@@
  #include <drm/drm_fb_helper.h>
  
  #include "msm_drv.h"
- #include "msm_gem.h"
  #include "msm_kms.h"
  
  extern int msm_gem_mmap_obj(struct drm_gem_object *obj,
@@@ -35,7 -34,6 +34,6 @@@ static int msm_fbdev_mmap(struct fb_inf
  struct msm_fbdev {
        struct drm_fb_helper base;
        struct drm_framebuffer *fb;
-       struct drm_gem_object *bo;
  };
  
  static struct fb_ops msm_fb_ops = {
@@@ -57,16 -55,16 +55,16 @@@ static int msm_fbdev_mmap(struct fb_inf
  {
        struct drm_fb_helper *helper = (struct drm_fb_helper *)info->par;
        struct msm_fbdev *fbdev = to_msm_fbdev(helper);
-       struct drm_gem_object *drm_obj = fbdev->bo;
+       struct drm_gem_object *bo = msm_framebuffer_bo(fbdev->fb, 0);
        int ret = 0;
  
-       ret = drm_gem_mmap_obj(drm_obj, drm_obj->size, vma);
+       ret = drm_gem_mmap_obj(bo, bo->size, vma);
        if (ret) {
                pr_err("%s:drm_gem_mmap_obj fail\n", __func__);
                return ret;
        }
  
-       return msm_gem_mmap_obj(drm_obj, vma);
+       return msm_gem_mmap_obj(bo, vma);
  }
  
  static int msm_fbdev_create(struct drm_fb_helper *helper,
        struct drm_device *dev = helper->dev;
        struct msm_drm_private *priv = dev->dev_private;
        struct drm_framebuffer *fb = NULL;
+       struct drm_gem_object *bo;
        struct fb_info *fbi = NULL;
-       struct drm_mode_fb_cmd2 mode_cmd = {0};
        uint64_t paddr;
-       int ret, size;
+       uint32_t format;
+       int ret, pitch;
+       format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth);
  
        DBG("create fbdev: %dx%d@%d (%dx%d)", sizes->surface_width,
                        sizes->surface_height, sizes->surface_bpp,
                        sizes->fb_width, sizes->fb_height);
  
-       mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
-                       sizes->surface_depth);
-       mode_cmd.width = sizes->surface_width;
-       mode_cmd.height = sizes->surface_height;
-       mode_cmd.pitches[0] = align_pitch(
-                       mode_cmd.width, sizes->surface_bpp);
+       pitch = align_pitch(sizes->surface_width, sizes->surface_bpp);
+       fb = msm_alloc_stolen_fb(dev, sizes->surface_width,
+                       sizes->surface_height, pitch, format);
  
-       /* allocate backing bo */
-       size = mode_cmd.pitches[0] * mode_cmd.height;
-       DBG("allocating %d bytes for fb %d", size, dev->primary->index);
-       fbdev->bo = msm_gem_new(dev, size, MSM_BO_SCANOUT |
-                       MSM_BO_WC | MSM_BO_STOLEN);
-       if (IS_ERR(fbdev->bo)) {
-               ret = PTR_ERR(fbdev->bo);
-               fbdev->bo = NULL;
-               dev_err(dev->dev, "failed to allocate buffer object: %d\n", ret);
-               goto fail;
-       }
-       fb = msm_framebuffer_init(dev, &mode_cmd, &fbdev->bo);
        if (IS_ERR(fb)) {
                dev_err(dev->dev, "failed to allocate fb\n");
-               /* note: if fb creation failed, we can't rely on fb destroy
-                * to unref the bo:
-                */
-               drm_gem_object_unreference_unlocked(fbdev->bo);
                ret = PTR_ERR(fb);
                goto fail;
        }
  
+       bo = msm_framebuffer_bo(fb, 0);
        mutex_lock(&dev->struct_mutex);
  
        /*
         * in panic (ie. lock-safe, etc) we could avoid pinning the
         * buffer now:
         */
-       ret = msm_gem_get_iova(fbdev->bo, priv->kms->aspace, &paddr);
+       ret = msm_gem_get_iova(bo, priv->kms->aspace, &paddr);
        if (ret) {
                dev_err(dev->dev, "failed to get buffer obj iova: %d\n", ret);
                goto fail_unlock;
        helper->fb = fb;
  
        fbi->par = helper;
 -      fbi->flags = FBINFO_DEFAULT;
        fbi->fbops = &msm_fb_ops;
  
        strcpy(fbi->fix.id, "msm");
  
        dev->mode_config.fb_base = paddr;
  
-       fbi->screen_base = msm_gem_get_vaddr(fbdev->bo);
+       fbi->screen_base = msm_gem_get_vaddr(bo);
        if (IS_ERR(fbi->screen_base)) {
                ret = PTR_ERR(fbi->screen_base);
                goto fail_unlock;
        }
-       fbi->screen_size = fbdev->bo->size;
+       fbi->screen_size = bo->size;
        fbi->fix.smem_start = paddr;
-       fbi->fix.smem_len = fbdev->bo->size;
+       fbi->fix.smem_len = bo->size;
  
        DBG("par=%p, %dx%d", fbi->par, fbi->var.xres, fbi->var.yres);
        DBG("allocated %dx%d fb", fbdev->fb->width, fbdev->fb->height);
@@@ -241,7 -223,9 +222,9 @@@ void msm_fbdev_free(struct drm_device *
  
        /* this will free the backing object */
        if (fbdev->fb) {
-               msm_gem_put_vaddr(fbdev->bo);
+               struct drm_gem_object *bo =
+                       msm_framebuffer_bo(fbdev->fb, 0);
+               msm_gem_put_vaddr(bo);
                drm_framebuffer_remove(fbdev->fb);
        }