mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-19 19:47:03 +07:00
drm/vc4: txp: Turn the TXP into a CRTC of its own
The TXP so far has been leveraging the PixelValve infrastructure in the driver, that was really two things: the interaction with DRM's CRTC concept, the setup of the underlying pixelvalve and the setup of the shared HVS, the pixelvalve part being irrelevant to the TXP since it accesses the HVS directly. Now that we have a clear separation between the three parts, we can represent the TXP as a CRTC of its own, leveraging the common CRTC and HVS code, but leaving aside the pixelvalve setup. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Reviewed-by: Eric Anholt <eric@anholt.net> Link: https://patchwork.freedesktop.org/patch/msgid/20f387f881b57f3474fa42d94cfd8bc1b7b80595.1591882579.git-series.maxime@cerno.tech
This commit is contained in:
parent
e25a21abb9
commit
39fcb28083
@ -474,17 +474,6 @@ static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
|
||||
if (conn_state->crtc != crtc)
|
||||
continue;
|
||||
|
||||
/* The writeback connector is implemented using the transposer
|
||||
* block which is directly taking its data from the HVS FIFO.
|
||||
*/
|
||||
if (conn->connector_type == DRM_MODE_CONNECTOR_WRITEBACK) {
|
||||
state->no_vblank = true;
|
||||
vc4_state->feed_txp = true;
|
||||
} else {
|
||||
state->no_vblank = false;
|
||||
vc4_state->feed_txp = false;
|
||||
}
|
||||
|
||||
vc4_state->margins.left = conn_state->tv.margins.left;
|
||||
vc4_state->margins.right = conn_state->tv.margins.right;
|
||||
vc4_state->margins.top = conn_state->tv.margins.top;
|
||||
@ -826,7 +815,6 @@ static void vc4_set_crtc_possible_masks(struct drm_device *drm,
|
||||
struct drm_crtc *crtc)
|
||||
{
|
||||
struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
|
||||
const struct vc4_crtc_data *crtc_data = vc4_crtc_to_vc4_crtc_data(vc4_crtc);
|
||||
const struct vc4_pv_data *pv_data = vc4_crtc_to_vc4_pv_data(vc4_crtc);
|
||||
const enum vc4_encoder_type *encoder_types = pv_data->encoder_types;
|
||||
struct drm_encoder *encoder;
|
||||
@ -835,13 +823,6 @@ static void vc4_set_crtc_possible_masks(struct drm_device *drm,
|
||||
struct vc4_encoder *vc4_encoder;
|
||||
int i;
|
||||
|
||||
/* HVS FIFO2 can feed the TXP IP. */
|
||||
if (crtc_data->hvs_channel == 2 &&
|
||||
encoder->encoder_type == DRM_MODE_ENCODER_VIRTUAL) {
|
||||
encoder->possible_crtcs |= drm_crtc_mask(crtc);
|
||||
continue;
|
||||
}
|
||||
|
||||
vc4_encoder = to_vc4_encoder(encoder);
|
||||
for (i = 0; i < ARRAY_SIZE(pv_data->encoder_types); i++) {
|
||||
if (vc4_encoder->type == encoder_types[i]) {
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_panel.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
#include <drm/drm_writeback.h>
|
||||
|
||||
#include "vc4_drv.h"
|
||||
@ -145,6 +146,8 @@
|
||||
#define TXP_WRITE(offset, val) writel(val, txp->regs + (offset))
|
||||
|
||||
struct vc4_txp {
|
||||
struct vc4_crtc base;
|
||||
|
||||
struct platform_device *pdev;
|
||||
|
||||
struct drm_writeback_connector connector;
|
||||
@ -362,23 +365,105 @@ static const struct drm_encoder_helper_funcs vc4_txp_encoder_helper_funcs = {
|
||||
.disable = vc4_txp_encoder_disable,
|
||||
};
|
||||
|
||||
static int vc4_txp_enable_vblank(struct drm_crtc *crtc)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vc4_txp_disable_vblank(struct drm_crtc *crtc) {}
|
||||
|
||||
static const struct drm_crtc_funcs vc4_txp_crtc_funcs = {
|
||||
.set_config = drm_atomic_helper_set_config,
|
||||
.destroy = vc4_crtc_destroy,
|
||||
.page_flip = vc4_page_flip,
|
||||
.reset = vc4_crtc_reset,
|
||||
.atomic_duplicate_state = vc4_crtc_duplicate_state,
|
||||
.atomic_destroy_state = vc4_crtc_destroy_state,
|
||||
.gamma_set = drm_atomic_helper_legacy_gamma_set,
|
||||
.enable_vblank = vc4_txp_enable_vblank,
|
||||
.disable_vblank = vc4_txp_disable_vblank,
|
||||
};
|
||||
|
||||
static int vc4_txp_atomic_check(struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *state)
|
||||
{
|
||||
struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(state);
|
||||
int ret;
|
||||
|
||||
ret = vc4_hvs_atomic_check(crtc, state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
state->no_vblank = true;
|
||||
vc4_state->feed_txp = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vc4_txp_atomic_enable(struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *old_state)
|
||||
{
|
||||
drm_crtc_vblank_on(crtc);
|
||||
vc4_hvs_atomic_enable(crtc, old_state);
|
||||
}
|
||||
|
||||
static void vc4_txp_atomic_disable(struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *old_state)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
|
||||
/* Disable vblank irq handling before crtc is disabled. */
|
||||
drm_crtc_vblank_off(crtc);
|
||||
|
||||
vc4_hvs_atomic_disable(crtc, old_state);
|
||||
|
||||
/*
|
||||
* Make sure we issue a vblank event after disabling the CRTC if
|
||||
* someone was waiting it.
|
||||
*/
|
||||
if (crtc->state->event) {
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&dev->event_lock, flags);
|
||||
drm_crtc_send_vblank_event(crtc, crtc->state->event);
|
||||
crtc->state->event = NULL;
|
||||
spin_unlock_irqrestore(&dev->event_lock, flags);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct drm_crtc_helper_funcs vc4_txp_crtc_helper_funcs = {
|
||||
.atomic_check = vc4_txp_atomic_check,
|
||||
.atomic_flush = vc4_hvs_atomic_flush,
|
||||
.atomic_enable = vc4_txp_atomic_enable,
|
||||
.atomic_disable = vc4_txp_atomic_disable,
|
||||
.mode_set_nofb = vc4_hvs_mode_set_nofb,
|
||||
};
|
||||
|
||||
static irqreturn_t vc4_txp_interrupt(int irq, void *data)
|
||||
{
|
||||
struct vc4_txp *txp = data;
|
||||
struct vc4_crtc *vc4_crtc = &txp->base;
|
||||
|
||||
TXP_WRITE(TXP_DST_CTRL, TXP_READ(TXP_DST_CTRL) & ~TXP_EI);
|
||||
vc4_crtc_handle_vblank(to_vc4_crtc(txp->connector.base.state->crtc));
|
||||
vc4_crtc_handle_vblank(vc4_crtc);
|
||||
drm_writeback_signal_completion(&txp->connector, 0);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static const struct vc4_crtc_data vc4_txp_crtc_data = {
|
||||
.hvs_channel = 2,
|
||||
};
|
||||
|
||||
static int vc4_txp_bind(struct device *dev, struct device *master, void *data)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct drm_device *drm = dev_get_drvdata(master);
|
||||
struct vc4_dev *vc4 = to_vc4_dev(drm);
|
||||
struct vc4_crtc *vc4_crtc;
|
||||
struct vc4_txp *txp;
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_encoder *encoder;
|
||||
int ret, irq;
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
@ -388,6 +473,11 @@ static int vc4_txp_bind(struct device *dev, struct device *master, void *data)
|
||||
txp = devm_kzalloc(dev, sizeof(*txp), GFP_KERNEL);
|
||||
if (!txp)
|
||||
return -ENOMEM;
|
||||
vc4_crtc = &txp->base;
|
||||
crtc = &vc4_crtc->base;
|
||||
|
||||
vc4_crtc->pdev = pdev;
|
||||
vc4_crtc->data = &vc4_txp_crtc_data;
|
||||
|
||||
txp->pdev = pdev;
|
||||
|
||||
@ -407,6 +497,14 @@ static int vc4_txp_bind(struct device *dev, struct device *master, void *data)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = vc4_crtc_init(drm, vc4_crtc,
|
||||
&vc4_txp_crtc_funcs, &vc4_txp_crtc_helper_funcs);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
encoder = &txp->connector.encoder;
|
||||
encoder->possible_crtcs |= drm_crtc_mask(crtc);
|
||||
|
||||
ret = devm_request_irq(dev, irq, vc4_txp_interrupt, 0,
|
||||
dev_name(dev), txp);
|
||||
if (ret)
|
||||
|
Loading…
Reference in New Issue
Block a user