mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
226 lines
6.7 KiB
226 lines
6.7 KiB
/* SPDX-License-Identifier: GPL-2.0-only */ |
|
/* |
|
* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. |
|
* Copyright (C) 2013 Red Hat |
|
* Author: Rob Clark <[email protected]> |
|
*/ |
|
|
|
#ifndef __MSM_KMS_H__ |
|
#define __MSM_KMS_H__ |
|
|
|
#include <linux/clk.h> |
|
#include <linux/regulator/consumer.h> |
|
|
|
#include "msm_drv.h" |
|
|
|
#define MAX_PLANE 4 |
|
|
|
/* As there are different display controller blocks depending on the |
|
* snapdragon version, the kms support is split out and the appropriate |
|
* implementation is loaded at runtime. The kms module is responsible |
|
* for constructing the appropriate planes/crtcs/encoders/connectors. |
|
*/ |
|
struct msm_kms_funcs { |
|
/* hw initialization: */ |
|
int (*hw_init)(struct msm_kms *kms); |
|
/* irq handling: */ |
|
void (*irq_preinstall)(struct msm_kms *kms); |
|
int (*irq_postinstall)(struct msm_kms *kms); |
|
void (*irq_uninstall)(struct msm_kms *kms); |
|
irqreturn_t (*irq)(struct msm_kms *kms); |
|
int (*enable_vblank)(struct msm_kms *kms, struct drm_crtc *crtc); |
|
void (*disable_vblank)(struct msm_kms *kms, struct drm_crtc *crtc); |
|
|
|
/* |
|
* Atomic commit handling: |
|
* |
|
* Note that in the case of async commits, the funcs which take |
|
* a crtc_mask (ie. ->flush_commit(), and ->complete_commit()) |
|
* might not be evenly balanced with ->prepare_commit(), however |
|
* each crtc that effected by a ->prepare_commit() (potentially |
|
* multiple times) will eventually (at end of vsync period) be |
|
* flushed and completed. |
|
* |
|
* This has some implications about tracking of cleanup state, |
|
* for example SMP blocks to release after commit completes. Ie. |
|
* cleanup state should be also duplicated in the various |
|
* duplicate_state() methods, as the current cleanup state at |
|
* ->complete_commit() time may have accumulated cleanup work |
|
* from multiple commits. |
|
*/ |
|
|
|
/** |
|
* Enable/disable power/clks needed for hw access done in other |
|
* commit related methods. |
|
* |
|
* If mdp4 is migrated to runpm, we could probably drop these |
|
* and use runpm directly. |
|
*/ |
|
void (*enable_commit)(struct msm_kms *kms); |
|
void (*disable_commit)(struct msm_kms *kms); |
|
|
|
/** |
|
* If the kms backend supports async commit, it should implement |
|
* this method to return the time of the next vsync. This is |
|
* used to determine a time slightly before vsync, for the async |
|
* commit timer to run and complete an async commit. |
|
*/ |
|
ktime_t (*vsync_time)(struct msm_kms *kms, struct drm_crtc *crtc); |
|
|
|
/** |
|
* Prepare for atomic commit. This is called after any previous |
|
* (async or otherwise) commit has completed. |
|
*/ |
|
void (*prepare_commit)(struct msm_kms *kms, struct drm_atomic_state *state); |
|
|
|
/** |
|
* Flush an atomic commit. This is called after the hardware |
|
* updates have already been pushed down to effected planes/ |
|
* crtcs/encoders/connectors. |
|
*/ |
|
void (*flush_commit)(struct msm_kms *kms, unsigned crtc_mask); |
|
|
|
/** |
|
* Wait for any in-progress flush to complete on the specified |
|
* crtcs. This should not block if there is no in-progress |
|
* commit (ie. don't just wait for a vblank), as it will also |
|
* be called before ->prepare_commit() to ensure any potential |
|
* "async" commit has completed. |
|
*/ |
|
void (*wait_flush)(struct msm_kms *kms, unsigned crtc_mask); |
|
|
|
/** |
|
* Clean up after commit is completed. This is called after |
|
* ->wait_flush(), to give the backend a chance to do any |
|
* post-commit cleanup. |
|
*/ |
|
void (*complete_commit)(struct msm_kms *kms, unsigned crtc_mask); |
|
|
|
/* |
|
* Format handling: |
|
*/ |
|
|
|
/* get msm_format w/ optional format modifiers from drm_mode_fb_cmd2 */ |
|
const struct msm_format *(*get_format)(struct msm_kms *kms, |
|
const uint32_t format, |
|
const uint64_t modifiers); |
|
/* do format checking on format modified through fb_cmd2 modifiers */ |
|
int (*check_modified_format)(const struct msm_kms *kms, |
|
const struct msm_format *msm_fmt, |
|
const struct drm_mode_fb_cmd2 *cmd, |
|
struct drm_gem_object **bos); |
|
|
|
/* misc: */ |
|
long (*round_pixclk)(struct msm_kms *kms, unsigned long rate, |
|
struct drm_encoder *encoder); |
|
int (*set_split_display)(struct msm_kms *kms, |
|
struct drm_encoder *encoder, |
|
struct drm_encoder *slave_encoder, |
|
bool is_cmd_mode); |
|
/* cleanup: */ |
|
void (*destroy)(struct msm_kms *kms); |
|
|
|
/* snapshot: */ |
|
void (*snapshot)(struct msm_disp_state *disp_state, struct msm_kms *kms); |
|
|
|
#ifdef CONFIG_DEBUG_FS |
|
/* debugfs: */ |
|
int (*debugfs_init)(struct msm_kms *kms, struct drm_minor *minor); |
|
#endif |
|
}; |
|
|
|
struct msm_kms; |
|
|
|
/* |
|
* A per-crtc timer for pending async atomic flushes. Scheduled to expire |
|
* shortly before vblank to flush pending async updates. |
|
*/ |
|
struct msm_pending_timer { |
|
struct msm_hrtimer_work work; |
|
struct kthread_worker *worker; |
|
struct msm_kms *kms; |
|
unsigned crtc_idx; |
|
}; |
|
|
|
struct msm_kms { |
|
const struct msm_kms_funcs *funcs; |
|
struct drm_device *dev; |
|
|
|
/* irq number to be passed on to msm_irq_install */ |
|
int irq; |
|
|
|
/* mapper-id used to request GEM buffer mapped for scanout: */ |
|
struct msm_gem_address_space *aspace; |
|
|
|
/* disp snapshot support */ |
|
struct kthread_worker *dump_worker; |
|
struct kthread_work dump_work; |
|
struct mutex dump_mutex; |
|
|
|
/* |
|
* For async commit, where ->flush_commit() and later happens |
|
* from the crtc's pending_timer close to end of the frame: |
|
*/ |
|
struct mutex commit_lock[MAX_CRTCS]; |
|
unsigned pending_crtc_mask; |
|
struct msm_pending_timer pending_timers[MAX_CRTCS]; |
|
}; |
|
|
|
static inline int msm_kms_init(struct msm_kms *kms, |
|
const struct msm_kms_funcs *funcs) |
|
{ |
|
unsigned i, ret; |
|
|
|
for (i = 0; i < ARRAY_SIZE(kms->commit_lock); i++) |
|
mutex_init(&kms->commit_lock[i]); |
|
|
|
kms->funcs = funcs; |
|
|
|
for (i = 0; i < ARRAY_SIZE(kms->pending_timers); i++) { |
|
ret = msm_atomic_init_pending_timer(&kms->pending_timers[i], kms, i); |
|
if (ret) { |
|
return ret; |
|
} |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
static inline void msm_kms_destroy(struct msm_kms *kms) |
|
{ |
|
unsigned i; |
|
|
|
for (i = 0; i < ARRAY_SIZE(kms->pending_timers); i++) |
|
msm_atomic_destroy_pending_timer(&kms->pending_timers[i]); |
|
} |
|
|
|
struct msm_kms *mdp4_kms_init(struct drm_device *dev); |
|
struct msm_kms *mdp5_kms_init(struct drm_device *dev); |
|
struct msm_kms *dpu_kms_init(struct drm_device *dev); |
|
|
|
extern const struct of_device_id dpu_dt_match[]; |
|
extern const struct of_device_id mdp5_dt_match[]; |
|
|
|
struct msm_mdss_funcs { |
|
int (*enable)(struct msm_mdss *mdss); |
|
int (*disable)(struct msm_mdss *mdss); |
|
void (*destroy)(struct msm_mdss *mdss); |
|
}; |
|
|
|
struct msm_mdss { |
|
struct device *dev; |
|
const struct msm_mdss_funcs *funcs; |
|
}; |
|
|
|
int mdp5_mdss_init(struct platform_device *dev); |
|
int dpu_mdss_init(struct platform_device *dev); |
|
|
|
#define for_each_crtc_mask(dev, crtc, crtc_mask) \ |
|
drm_for_each_crtc(crtc, dev) \ |
|
for_each_if (drm_crtc_mask(crtc) & (crtc_mask)) |
|
|
|
#define for_each_crtc_mask_reverse(dev, crtc, crtc_mask) \ |
|
drm_for_each_crtc_reverse(crtc, dev) \ |
|
for_each_if (drm_crtc_mask(crtc) & (crtc_mask)) |
|
|
|
#endif /* __MSM_KMS_H__ */
|
|
|