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        void (*set_encoder_mode)(struct msm_kms *kms,
 121                                 struct drm_encoder *encoder,
 122                                 bool cmd_mode);
 123        /* cleanup: */
 124        void (*destroy)(struct msm_kms *kms);
 125#ifdef CONFIG_DEBUG_FS
 126        /* debugfs: */
 127        int (*debugfs_init)(struct msm_kms *kms, struct drm_minor *minor);
 128#endif
 129};
 130
 131struct msm_kms;
 132
 133/*
 134 * A per-crtc timer for pending async atomic flushes.  Scheduled to expire
 135 * shortly before vblank to flush pending async updates.
 136 */
 137struct msm_pending_timer {
 138        struct hrtimer timer;
 139        struct kthread_work work;
 140        struct kthread_worker *worker;
 141        struct msm_kms *kms;
 142        unsigned crtc_idx;
 143};
 144
 145struct msm_kms {
 146        const struct msm_kms_funcs *funcs;
 147        struct drm_device *dev;
 148
 149        /* irq number to be passed on to drm_irq_install */
 150        int irq;
 151
 152        /* mapper-id used to request GEM buffer mapped for scanout: */
 153        struct msm_gem_address_space *aspace;
 154
 155        /*
 156         * For async commit, where ->flush_commit() and later happens
 157         * from the crtc's pending_timer close to end of the frame:
 158         */
 159        struct mutex commit_lock[MAX_CRTCS];
 160        unsigned pending_crtc_mask;
 161        struct msm_pending_timer pending_timers[MAX_CRTCS];
 162};
 163
 164static inline int msm_kms_init(struct msm_kms *kms,
 165                const struct msm_kms_funcs *funcs)
 166{
 167        unsigned i, ret;
 168
 169        for (i = 0; i < ARRAY_SIZE(kms->commit_lock); i++)
 170                mutex_init(&kms->commit_lock[i]);
 171
 172        kms->funcs = funcs;
 173
 174        for (i = 0; i < ARRAY_SIZE(kms->pending_timers); i++) {
 175                ret = msm_atomic_init_pending_timer(&kms->pending_timers[i], kms, i);
 176                if (ret) {
 177                        return ret;
 178                }
 179        }
 180
 181        return 0;
 182}
 183
 184static inline void msm_kms_destroy(struct msm_kms *kms)
 185{
 186        unsigned i;
 187
 188        for (i = 0; i < ARRAY_SIZE(kms->pending_timers); i++)
 189                msm_atomic_destroy_pending_timer(&kms->pending_timers[i]);
 190}
 191
 192struct msm_kms *mdp4_kms_init(struct drm_device *dev);
 193struct msm_kms *mdp5_kms_init(struct drm_device *dev);
 194struct msm_kms *dpu_kms_init(struct drm_device *dev);
 195
 196struct msm_mdss_funcs {
 197        int (*enable)(struct msm_mdss *mdss);
 198        int (*disable)(struct msm_mdss *mdss);
 199        void (*destroy)(struct drm_device *dev);
 200};
 201
 202struct msm_mdss {
 203        struct drm_device *dev;
 204        const struct msm_mdss_funcs *funcs;
 205};
 206
 207int mdp5_mdss_init(struct drm_device *dev);
 208int dpu_mdss_init(struct drm_device *dev);
 209
 210#define for_each_crtc_mask(dev, crtc, crtc_mask) \
 211        drm_for_each_crtc(crtc, dev) \
 212                for_each_if (drm_crtc_mask(crtc) & (crtc_mask))
 213
 214#define for_each_crtc_mask_reverse(dev, crtc, crtc_mask) \
 215        drm_for_each_crtc_reverse(crtc, dev) \
 216                for_each_if (drm_crtc_mask(crtc) & (crtc_mask))
 217
 218#endif /* __MSM_KMS_H__ */
 219