brintos

brintos / linux-shallow public Read only

0
0
Text · 16.2 KiB · 2e28a13 Raw
573 lines · c
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 Hat5 * Author: Rob Clark <robdclark@gmail.com>6 */7 8#ifndef __MSM_DRV_H__9#define __MSM_DRV_H__10 11#include <linux/kernel.h>12#include <linux/clk.h>13#include <linux/cpufreq.h>14#include <linux/devfreq.h>15#include <linux/module.h>16#include <linux/component.h>17#include <linux/platform_device.h>18#include <linux/pm.h>19#include <linux/pm_runtime.h>20#include <linux/slab.h>21#include <linux/list.h>22#include <linux/iommu.h>23#include <linux/types.h>24#include <linux/of_graph.h>25#include <linux/of_device.h>26#include <linux/sizes.h>27#include <linux/kthread.h>28 29#include <drm/drm_atomic.h>30#include <drm/drm_atomic_helper.h>31#include <drm/drm_probe_helper.h>32#include <drm/display/drm_dsc.h>33#include <drm/msm_drm.h>34#include <drm/drm_gem.h>35 36extern struct fault_attr fail_gem_alloc;37extern struct fault_attr fail_gem_iova;38 39struct msm_kms;40struct msm_gpu;41struct msm_mmu;42struct msm_mdss;43struct msm_rd_state;44struct msm_perf_state;45struct msm_gem_submit;46struct msm_fence_context;47struct msm_gem_address_space;48struct msm_gem_vma;49struct msm_disp_state;50 51#define MAX_CRTCS      852#define MAX_BRIDGES    853 54#define FRAC_16_16(mult, div)    (((mult) << 16) / (div))55 56enum msm_dp_controller {57	MSM_DP_CONTROLLER_0,58	MSM_DP_CONTROLLER_1,59	MSM_DP_CONTROLLER_2,60	MSM_DP_CONTROLLER_3,61	MSM_DP_CONTROLLER_COUNT,62};63 64enum msm_dsi_controller {65	MSM_DSI_CONTROLLER_0,66	MSM_DSI_CONTROLLER_1,67	MSM_DSI_CONTROLLER_COUNT,68};69 70#define MSM_GPU_MAX_RINGS 471#define MAX_H_TILES_PER_DISPLAY 272 73/**74 * struct msm_display_topology - defines a display topology pipeline75 * @num_lm:       number of layer mixers used76 * @num_intf:     number of interfaces the panel is mounted on77 * @num_dspp:     number of dspp blocks used78 * @num_dsc:      number of Display Stream Compression (DSC) blocks used79 * @needs_cdm:    indicates whether cdm block is needed for this display topology80 */81struct msm_display_topology {82	u32 num_lm;83	u32 num_intf;84	u32 num_dspp;85	u32 num_dsc;86	bool needs_cdm;87};88 89/* Commit/Event thread specific structure */90struct msm_drm_thread {91	struct drm_device *dev;92	struct kthread_worker *worker;93};94 95struct msm_drm_private {96 97	struct drm_device *dev;98 99	struct msm_kms *kms;100	int (*kms_init)(struct drm_device *dev);101 102	/* subordinate devices, if present: */103	struct platform_device *gpu_pdev;104 105	/* possibly this should be in the kms component, but it is106	 * shared by both mdp4 and mdp5..107	 */108	struct hdmi *hdmi;109 110	/* DSI is shared by mdp4 and mdp5 */111	struct msm_dsi *dsi[MSM_DSI_CONTROLLER_COUNT];112 113	struct msm_dp *dp[MSM_DP_CONTROLLER_COUNT];114 115	/* when we have more than one 'msm_gpu' these need to be an array: */116	struct msm_gpu *gpu;117 118	/* gpu is only set on open(), but we need this info earlier */119	bool is_a2xx;120	bool has_cached_coherent;121 122	struct msm_rd_state *rd;       /* debugfs to dump all submits */123	struct msm_rd_state *hangrd;   /* debugfs to dump hanging submits */124	struct msm_perf_state *perf;125 126	/**127	 * total_mem: Total/global amount of memory backing GEM objects.128	 */129	atomic64_t total_mem;130 131	/**132	 * List of all GEM objects (mainly for debugfs, protected by obj_lock133	 * (acquire before per GEM object lock)134	 */135	struct list_head objects;136	struct mutex obj_lock;137 138	/**139	 * lru:140	 *141	 * The various LRU's that a GEM object is in at various stages of142	 * it's lifetime.  Objects start out in the unbacked LRU.  When143	 * pinned (for scannout or permanently mapped GPU buffers, like144	 * ringbuffer, memptr, fw, etc) it moves to the pinned LRU.  When145	 * unpinned, it moves into willneed or dontneed LRU depending on146	 * madvise state.  When backing pages are evicted (willneed) or147	 * purged (dontneed) it moves back into the unbacked LRU.148	 *149	 * The dontneed LRU is considered by the shrinker for objects150	 * that are candidate for purging, and the willneed LRU is151	 * considered for objects that could be evicted.152	 */153	struct {154		/**155		 * unbacked:156		 *157		 * The LRU for GEM objects without backing pages allocated.158		 * This mostly exists so that objects are always is one159		 * LRU.160		 */161		struct drm_gem_lru unbacked;162 163		/**164		 * pinned:165		 *166		 * The LRU for pinned GEM objects167		 */168		struct drm_gem_lru pinned;169 170		/**171		 * willneed:172		 *173		 * The LRU for unpinned GEM objects which are in madvise174		 * WILLNEED state (ie. can be evicted)175		 */176		struct drm_gem_lru willneed;177 178		/**179		 * dontneed:180		 *181		 * The LRU for unpinned GEM objects which are in madvise182		 * DONTNEED state (ie. can be purged)183		 */184		struct drm_gem_lru dontneed;185 186		/**187		 * lock:188		 *189		 * Protects manipulation of all of the LRUs.190		 */191		struct mutex lock;192	} lru;193 194	struct workqueue_struct *wq;195 196	unsigned int num_crtcs;197 198	struct msm_drm_thread event_thread[MAX_CRTCS];199 200	/* VRAM carveout, used when no IOMMU: */201	struct {202		unsigned long size;203		dma_addr_t paddr;204		/* NOTE: mm managed at the page level, size is in # of pages205		 * and position mm_node->start is in # of pages:206		 */207		struct drm_mm mm;208		spinlock_t lock; /* Protects drm_mm node allocation/removal */209	} vram;210 211	struct notifier_block vmap_notifier;212	struct shrinker *shrinker;213 214	/**215	 * hangcheck_period: For hang detection, in ms216	 *217	 * Note that in practice, a submit/job will get at least two hangcheck218	 * periods, due to checking for progress being implemented as simply219	 * "have the CP position registers changed since last time?"220	 */221	unsigned int hangcheck_period;222 223	/** gpu_devfreq_config: Devfreq tuning config for the GPU. */224	struct devfreq_simple_ondemand_data gpu_devfreq_config;225 226	/**227	 * gpu_clamp_to_idle: Enable clamping to idle freq when inactive228	 */229	bool gpu_clamp_to_idle;230 231	/**232	 * disable_err_irq:233	 *234	 * Disable handling of GPU hw error interrupts, to force fallback to235	 * sw hangcheck timer.  Written (via debugfs) by igt tests to test236	 * the sw hangcheck mechanism.237	 */238	bool disable_err_irq;239};240 241const struct msm_format *mdp_get_format(struct msm_kms *kms, uint32_t format, uint64_t modifier);242 243struct msm_pending_timer;244 245int msm_atomic_init_pending_timer(struct msm_pending_timer *timer,246		struct msm_kms *kms, int crtc_idx);247void msm_atomic_destroy_pending_timer(struct msm_pending_timer *timer);248void msm_atomic_commit_tail(struct drm_atomic_state *state);249int msm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state);250struct drm_atomic_state *msm_atomic_state_alloc(struct drm_device *dev);251 252int msm_crtc_enable_vblank(struct drm_crtc *crtc);253void msm_crtc_disable_vblank(struct drm_crtc *crtc);254 255int msm_register_mmu(struct drm_device *dev, struct msm_mmu *mmu);256void msm_unregister_mmu(struct drm_device *dev, struct msm_mmu *mmu);257 258struct msm_gem_address_space *msm_kms_init_aspace(struct drm_device *dev);259bool msm_use_mmu(struct drm_device *dev);260 261int msm_ioctl_gem_submit(struct drm_device *dev, void *data,262		struct drm_file *file);263 264#ifdef CONFIG_DEBUG_FS265unsigned long msm_gem_shrinker_shrink(struct drm_device *dev, unsigned long nr_to_scan);266#endif267 268int msm_gem_shrinker_init(struct drm_device *dev);269void msm_gem_shrinker_cleanup(struct drm_device *dev);270 271struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj);272int msm_gem_prime_vmap(struct drm_gem_object *obj, struct iosys_map *map);273void msm_gem_prime_vunmap(struct drm_gem_object *obj, struct iosys_map *map);274struct drm_gem_object *msm_gem_prime_import_sg_table(struct drm_device *dev,275		struct dma_buf_attachment *attach, struct sg_table *sg);276int msm_gem_prime_pin(struct drm_gem_object *obj);277void msm_gem_prime_unpin(struct drm_gem_object *obj);278 279int msm_framebuffer_prepare(struct drm_framebuffer *fb,280		struct msm_gem_address_space *aspace, bool needs_dirtyfb);281void msm_framebuffer_cleanup(struct drm_framebuffer *fb,282		struct msm_gem_address_space *aspace, bool needed_dirtyfb);283uint32_t msm_framebuffer_iova(struct drm_framebuffer *fb,284		struct msm_gem_address_space *aspace, int plane);285struct drm_gem_object *msm_framebuffer_bo(struct drm_framebuffer *fb, int plane);286const struct msm_format *msm_framebuffer_format(struct drm_framebuffer *fb);287struct drm_framebuffer *msm_framebuffer_create(struct drm_device *dev,288		struct drm_file *file, const struct drm_mode_fb_cmd2 *mode_cmd);289struct drm_framebuffer * msm_alloc_stolen_fb(struct drm_device *dev,290		int w, int h, int p, uint32_t format);291 292#ifdef CONFIG_DRM_FBDEV_EMULATION293void msm_fbdev_setup(struct drm_device *dev);294#else295static inline void msm_fbdev_setup(struct drm_device *dev)296{297}298#endif299 300struct hdmi;301#ifdef CONFIG_DRM_MSM_HDMI302int msm_hdmi_modeset_init(struct hdmi *hdmi, struct drm_device *dev,303		struct drm_encoder *encoder);304void __init msm_hdmi_register(void);305void __exit msm_hdmi_unregister(void);306#else307static inline int msm_hdmi_modeset_init(struct hdmi *hdmi, struct drm_device *dev,308		struct drm_encoder *encoder)309{310	return -EINVAL;311}312static inline void __init msm_hdmi_register(void) {}313static inline void __exit msm_hdmi_unregister(void) {}314#endif315 316struct msm_dsi;317#ifdef CONFIG_DRM_MSM_DSI318int dsi_dev_attach(struct platform_device *pdev);319void dsi_dev_detach(struct platform_device *pdev);320void __init msm_dsi_register(void);321void __exit msm_dsi_unregister(void);322int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev,323			 struct drm_encoder *encoder);324void msm_dsi_snapshot(struct msm_disp_state *disp_state, struct msm_dsi *msm_dsi);325bool msm_dsi_is_cmd_mode(struct msm_dsi *msm_dsi);326bool msm_dsi_is_bonded_dsi(struct msm_dsi *msm_dsi);327bool msm_dsi_is_master_dsi(struct msm_dsi *msm_dsi);328bool msm_dsi_wide_bus_enabled(struct msm_dsi *msm_dsi);329struct drm_dsc_config *msm_dsi_get_dsc_config(struct msm_dsi *msm_dsi);330const char *msm_dsi_get_te_source(struct msm_dsi *msm_dsi);331#else332static inline void __init msm_dsi_register(void)333{334}335static inline void __exit msm_dsi_unregister(void)336{337}338static inline int msm_dsi_modeset_init(struct msm_dsi *msm_dsi,339				       struct drm_device *dev,340				       struct drm_encoder *encoder)341{342	return -EINVAL;343}344static inline void msm_dsi_snapshot(struct msm_disp_state *disp_state, struct msm_dsi *msm_dsi)345{346}347static inline bool msm_dsi_is_cmd_mode(struct msm_dsi *msm_dsi)348{349	return false;350}351static inline bool msm_dsi_is_bonded_dsi(struct msm_dsi *msm_dsi)352{353	return false;354}355static inline bool msm_dsi_is_master_dsi(struct msm_dsi *msm_dsi)356{357	return false;358}359static inline bool msm_dsi_wide_bus_enabled(struct msm_dsi *msm_dsi)360{361	return false;362}363 364static inline struct drm_dsc_config *msm_dsi_get_dsc_config(struct msm_dsi *msm_dsi)365{366	return NULL;367}368 369static inline const char *msm_dsi_get_te_source(struct msm_dsi *msm_dsi)370{371	return NULL;372}373#endif374 375#ifdef CONFIG_DRM_MSM_DP376int __init msm_dp_register(void);377void __exit msm_dp_unregister(void);378int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev,379			 struct drm_encoder *encoder, bool yuv_supported);380void msm_dp_snapshot(struct msm_disp_state *disp_state, struct msm_dp *dp_display);381bool msm_dp_is_yuv_420_enabled(const struct msm_dp *dp_display,382			       const struct drm_display_mode *mode);383bool msm_dp_needs_periph_flush(const struct msm_dp *dp_display,384			       const struct drm_display_mode *mode);385bool msm_dp_wide_bus_available(const struct msm_dp *dp_display);386 387#else388static inline int __init msm_dp_register(void)389{390	return -EINVAL;391}392static inline void __exit msm_dp_unregister(void)393{394}395static inline int msm_dp_modeset_init(struct msm_dp *dp_display,396				       struct drm_device *dev,397				       struct drm_encoder *encoder,398				       bool yuv_supported)399{400	return -EINVAL;401}402 403static inline void msm_dp_snapshot(struct msm_disp_state *disp_state, struct msm_dp *dp_display)404{405}406 407static inline bool msm_dp_is_yuv_420_enabled(const struct msm_dp *dp_display,408					     const struct drm_display_mode *mode)409{410	return false;411}412 413static inline bool msm_dp_needs_periph_flush(const struct msm_dp *dp_display,414					     const struct drm_display_mode *mode)415{416	return false;417}418 419static inline bool msm_dp_wide_bus_available(const struct msm_dp *dp_display)420{421	return false;422}423 424#endif425 426#ifdef CONFIG_DRM_MSM_MDP4427void msm_mdp4_register(void);428void msm_mdp4_unregister(void);429#else430static inline void msm_mdp4_register(void) {}431static inline void msm_mdp4_unregister(void) {}432#endif433 434#ifdef CONFIG_DRM_MSM_MDP5435void msm_mdp_register(void);436void msm_mdp_unregister(void);437#else438static inline void msm_mdp_register(void) {}439static inline void msm_mdp_unregister(void) {}440#endif441 442#ifdef CONFIG_DRM_MSM_DPU443void msm_dpu_register(void);444void msm_dpu_unregister(void);445#else446static inline void msm_dpu_register(void) {}447static inline void msm_dpu_unregister(void) {}448#endif449 450#ifdef CONFIG_DRM_MSM_MDSS451void msm_mdss_register(void);452void msm_mdss_unregister(void);453#else454static inline void msm_mdss_register(void) {}455static inline void msm_mdss_unregister(void) {}456#endif457 458#ifdef CONFIG_DEBUG_FS459void msm_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m);460int msm_debugfs_late_init(struct drm_device *dev);461int msm_rd_debugfs_init(struct drm_minor *minor);462void msm_rd_debugfs_cleanup(struct msm_drm_private *priv);463__printf(3, 4)464void msm_rd_dump_submit(struct msm_rd_state *rd, struct msm_gem_submit *submit,465		const char *fmt, ...);466int msm_perf_debugfs_init(struct drm_minor *minor);467void msm_perf_debugfs_cleanup(struct msm_drm_private *priv);468#else469static inline int msm_debugfs_late_init(struct drm_device *dev) { return 0; }470__printf(3, 4)471static inline void msm_rd_dump_submit(struct msm_rd_state *rd,472			struct msm_gem_submit *submit,473			const char *fmt, ...) {}474static inline void msm_rd_debugfs_cleanup(struct msm_drm_private *priv) {}475static inline void msm_perf_debugfs_cleanup(struct msm_drm_private *priv) {}476#endif477 478struct clk *msm_clk_get(struct platform_device *pdev, const char *name);479 480struct clk *msm_clk_bulk_get_clock(struct clk_bulk_data *bulk, int count,481	const char *name);482void __iomem *msm_ioremap(struct platform_device *pdev, const char *name);483void __iomem *msm_ioremap_size(struct platform_device *pdev, const char *name,484		phys_addr_t *size);485void __iomem *msm_ioremap_quiet(struct platform_device *pdev, const char *name);486void __iomem *msm_ioremap_mdss(struct platform_device *mdss_pdev,487			       struct platform_device *dev,488			       const char *name);489 490struct icc_path *msm_icc_get(struct device *dev, const char *name);491 492static inline void msm_rmw(void __iomem *addr, u32 mask, u32 or)493{494	u32 val = readl(addr);495 496	val &= ~mask;497	writel(val | or, addr);498}499 500/**501 * struct msm_hrtimer_work - a helper to combine an hrtimer with kthread_work502 *503 * @timer: hrtimer to control when the kthread work is triggered504 * @work:  the kthread work505 * @worker: the kthread worker the work will be scheduled on506 */507struct msm_hrtimer_work {508	struct hrtimer timer;509	struct kthread_work work;510	struct kthread_worker *worker;511};512 513void msm_hrtimer_queue_work(struct msm_hrtimer_work *work,514			    ktime_t wakeup_time,515			    enum hrtimer_mode mode);516void msm_hrtimer_work_init(struct msm_hrtimer_work *work,517			   struct kthread_worker *worker,518			   kthread_work_func_t fn,519			   clockid_t clock_id,520			   enum hrtimer_mode mode);521 522#define DBG(fmt, ...) DRM_DEBUG_DRIVER(fmt"\n", ##__VA_ARGS__)523#define VERB(fmt, ...) if (0) DRM_DEBUG_DRIVER(fmt"\n", ##__VA_ARGS__)524 525static inline int align_pitch(int width, int bpp)526{527	int bytespp = (bpp + 7) / 8;528	/* adreno needs pitch aligned to 32 pixels: */529	return bytespp * ALIGN(width, 32);530}531 532/* for the generated headers: */533#define INVALID_IDX(idx) ({BUG(); 0;})534#define fui(x)                ({BUG(); 0;})535#define _mesa_float_to_half(x) ({BUG(); 0;})536 537 538#define FIELD(val, name) (((val) & name ## __MASK) >> name ## __SHIFT)539 540/* for conditionally setting boolean flag(s): */541#define COND(bool, val) ((bool) ? (val) : 0)542 543static inline unsigned long timeout_to_jiffies(const ktime_t *timeout)544{545	ktime_t now = ktime_get();546	s64 remaining_jiffies;547 548	if (ktime_compare(*timeout, now) < 0) {549		remaining_jiffies = 0;550	} else {551		ktime_t rem = ktime_sub(*timeout, now);552		remaining_jiffies = ktime_divns(rem, NSEC_PER_SEC / HZ);553	}554 555	return clamp(remaining_jiffies, 1LL, (s64)INT_MAX);556}557 558/* Driver helpers */559 560extern const struct component_master_ops msm_drm_ops;561 562int msm_kms_pm_prepare(struct device *dev);563void msm_kms_pm_complete(struct device *dev);564 565int msm_drv_probe(struct device *dev,566	int (*kms_init)(struct drm_device *dev),567	struct msm_kms *kms);568void msm_kms_shutdown(struct platform_device *pdev);569 570bool msm_disp_drv_should_bind(struct device *dev, bool dpu_driver);571 572#endif /* __MSM_DRV_H__ */573