linux/drivers/gpu/drm/msm/msm_kms.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0-only */
   2/*
   3 * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
   4 * Copyright (C) 2013 Red Hat
   5 * Author: Rob Clark <robdclark@gmail.com>
   6 */
   7
   8#ifndef __MSM_KMS_H__
   9#define __MSM_KMS_H__
  10
  11#include <linux/clk.h>
  12#include <linux/regulator/consumer.h>
  13
  14#include "msm_drv.h"
  15
  16#define MAX_PLANE       4
  17
  18/* As there are different display controller blocks depending on the
  19 * snapdragon version, the kms support is split out and the appropriate
  20 * implementation is loaded at runtime.  The kms module is responsible
  21 * for constructing the appropriate planes/crtcs/encoders/connectors.
  22 */
  23struct msm_kms_funcs {
  24        /* hw initialization: */
  25        int (*hw_init)(struct msm_kms *kms);
  26        /* irq handling: */
  27        void (*irq_preinstall)(struct msm_kms *kms);
  28        int (*irq_postinstall)(struct msm_kms *kms);
  29        void (*irq_uninstall)(struct msm_kms *kms);
  30        irqreturn_t (*irq)(struct msm_kms *kms);
  31        int (*enable_vblank)(struct msm_kms *kms, struct drm_crtc *crtc);
  32        void (*disable_vblank)(struct msm_kms *kms, struct drm_crtc *crtc);
  33
  34        /*
  35         * Atomic commit handling:
  36         *
  37         * Note that in the case of async commits, the funcs which take
  38         * a crtc_mask (ie. ->flush_commit(), and ->complete_commit())
  39         * might not be evenly balanced with ->prepare_commit(), however
  40         * each crtc that effected by a ->prepare_commit() (potentially
  41         * multiple times) will eventually (at end of vsync period) be
  42         * flushed and completed.
  43         *
  44         * This has some implications about tracking of cleanup state,
  45         * for example SMP blocks to release after commit completes.  Ie.
  46         * cleanup state should be also duplicated in the various
  47         * duplicate_state() methods, as the current cleanup state at
  48         * ->complete_commit() time may have accumulated cleanup work
  49         * from multiple commits.
  50         */
  51
  52        /**
  53         * Enable/disable power/clks needed for hw access done in other
  54         * commit related methods.
  55         *
  56         * If mdp4 is migrated to runpm, we could probably drop these
  57         * and use runpm directly.
  58         */
  59        void (*enable_commit)(struct msm_kms *kms);
  60        void (*disable_commit)(struct msm_kms *kms);
  61
  62        /**
  63         * If the kms backend supports async commit, it should implement
  64         * this method to return the time of the next vsync.  This is
  65         * used to determine a time slightly before vsync, for the async
  66         * commit timer to run and complete an async commit.
  67         */
  68        ktime_t (*vsync_time)(struct msm_kms *kms, struct drm_crtc *crtc);
  69
  70        /**
  71         * Prepare for atomic commit.  This is called after any previous
  72         * (async or otherwise) commit has completed.
  73         */
  74        void (*prepare_commit)(struct msm_kms *kms, struct drm_atomic_state *state);
  75
  76        /**
  77         * Flush an atomic commit.  This is called after the hardware
  78         * updates have already been pushed down to effected planes/
  79         * crtcs/encoders/connectors.
  80         */
  81        void (*flush_commit)(struct msm_kms *kms, unsigned crtc_mask);
  82
  83        /**
  84         * Wait for any in-progress flush to complete on the specified
  85         * crtcs.  This should not block if there is no in-progress
  86         * commit (ie. don't just wait for a vblank), as it will also
  87         * be called before ->prepare_commit() to ensure any potential
  88         * "async" commit has completed.
  89         */
  90        void (*wait_flush)(struct msm_kms *kms, unsigned crtc_mask);
  91
  92        /**
  93         * Clean up after commit is completed.  This is called after
  94         * ->wait_flush(), to give the backend a chance to do any
  95         * post-commit cleanup.
  96         */
  97        void (*complete_commit)(struct msm_kms *kms, unsigned crtc_mask);
  98
  99        /*
 100         * Format handling:
 101         */
 102
 103        /* get msm_format w/ optional format modifiers from drm_mode_fb_cmd2 */
 104        const struct msm_format *(*get_format)(struct msm_kms *kms,
 105                                        const uint32_t format,
 106                                        const uint64_t modifiers);
 107        /* do format checking on format modified through fb_cmd2 modifiers */
 108        int (*check_modified_format)(const struct msm_kms *kms,
 109                        const struct msm_format *msm_fmt,
 110                        const struct drm_mode_fb_cmd2 *cmd,
 111                        struct drm_gem_object **bos);
 112
 113        /* misc: */
 114        long (*round_pixclk)(struct msm_kms *kms, unsigned long rate,
 115                        struct drm_encoder *encoder);
 116        int (*set_split_display)(struct msm_kms *kms,
 117                        struct drm_encoder *encoder,
 118                        struct drm_encoder *slave_encoder,
 119                        bool is_cmd_mode);
 120        /* cleanup: */
 121        void (*destroy)(struct msm_kms *kms);
 122
 123        /* snapshot: */
 124        void (*snapshot)(struct msm_disp_state *disp_state, struct msm_kms *kms);
 125
 126#ifdef CONFIG_DEBUG_FS
 127        /* debugfs: */
 128        int (*debugfs_init)(struct msm_kms *kms, struct drm_minor *minor);
 129#endif
 130};
 131
 132struct msm_kms;
 133
 134/*
 135 * A per-crtc timer for pending async atomic flushes.  Scheduled to expire
 136 * shortly before vblank to flush pending async updates.
 137 */
 138struct msm_pending_timer {
 139        struct hrtimer timer;
 140        struct kthread_work work;
 141        struct kthread_worker *worker;
 142        struct msm_kms *kms;
 143        unsigned crtc_idx;
 144};
 145
 146struct msm_kms {
 147        const struct msm_kms_funcs *funcs;
 148        struct drm_device *dev;
 149
 150        /* irq number to be passed on to msm_irq_install */
 151        int irq;
 152
 153        /* mapper-id used to request GEM buffer mapped for scanout: */
 154        struct msm_gem_address_space *aspace;
 155
 156        /* disp snapshot support */
 157        struct kthread_worker *dump_worker;
 158        struct kthread_work dump_work;
 159        struct mutex dump_mutex;
 160
 161        /*
 162         * For async commit, where ->flush_commit() and later happens
 163         * from the crtc's pending_timer close to end of the frame:
 164         */
 165        struct mutex commit_lock[MAX_CRTCS];
 166        unsigned pending_crtc_mask;
 167        struct msm_pending_timer pending_timers[MAX_CRTCS];
 168};
 169
 170static inline int msm_kms_init(struct msm_kms *kms,
 171                const struct msm_kms_funcs *funcs)
 172{
 173        unsigned i, ret;
 174
 175        for (i = 0; i < ARRAY_SIZE(kms->commit_lock); i++)
 176                mutex_init(&kms->commit_lock[i]);
 177
 178        kms->funcs = funcs;
 179
 180        for (i = 0; i < ARRAY_SIZE(kms->pending_timers); i++) {
 181                ret = msm_atomic_init_pending_timer(&kms->pending_timers[i], kms, i);
 182                if (ret) {
 183                        return ret;
 184                }
 185        }
 186
 187        return 0;
 188}
 189
 190static inline void msm_kms_destroy(struct msm_kms *kms)
 191{
 192        unsigned i;
 193
 194        for (i = 0; i < ARRAY_SIZE(kms->pending_timers); i++)
 195                msm_atomic_destroy_pending_timer(&kms->pending_timers[i]);
 196}
 197
 198struct msm_kms *mdp4_kms_init(struct drm_device *dev);
 199struct msm_kms *mdp5_kms_init(struct drm_device *dev);
 200struct msm_kms *dpu_kms_init(struct drm_device *dev);
 201
 202struct msm_mdss_funcs {
 203        int (*enable)(struct msm_mdss *mdss);
 204        int (*disable)(struct msm_mdss *mdss);
 205        void (*destroy)(struct drm_device *dev);
 206};
 207
 208struct msm_mdss {
 209        struct drm_device *dev;
 210        const struct msm_mdss_funcs *funcs;
 211};
 212
 213int mdp5_mdss_init(struct drm_device *dev);
 214int dpu_mdss_init(struct drm_device *dev);
 215
 216#define for_each_crtc_mask(dev, crtc, crtc_mask) \
 217        drm_for_each_crtc(crtc, dev) \
 218                for_each_if (drm_crtc_mask(crtc) & (crtc_mask))
 219
 220#define for_each_crtc_mask_reverse(dev, crtc, crtc_mask) \
 221        drm_for_each_crtc_reverse(crtc, dev) \
 222                for_each_if (drm_crtc_mask(crtc) & (crtc_mask))
 223
 224#endif /* __MSM_KMS_H__ */
 225