summaryrefslogtreecommitdiff
path: root/drivers/gpu/ipu-v3/ipu-image-convert.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2020-08-05 19:50:06 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2020-08-05 19:50:06 -0700
commit8186749621ed6b8fc42644c399e8c755a2b6f630 (patch)
tree3a1db67415da013e5dd481367c77db21e491edfb /drivers/gpu/ipu-v3/ipu-image-convert.c
parente4a7b2dc35d9582c253cf5e6d6c3605aabc7284d (diff)
parentdc100bc8fae59aafd2ea2e1a1a43ef1f65f8a8bc (diff)
Merge tag 'drm-next-2020-08-06' of git://anongit.freedesktop.org/drm/drm
Pull drm updates from Dave Airlie: "New xilinx displayport driver, AMD support for two new GPUs (more header files), i915 initial support for RocketLake and some work on their DG1 (discrete chip). The core also grew some lockdep annotations to try and constrain what drivers do with dma-fences, and added some documentation on why the idea of indefinite fences doesn't work. The long list is below. I do have some fixes trees outstanding, but I'll follow up with those later. core: - add user def flag to cmd line modes - dma_fence_wait added might_sleep - dma-fence lockdep annotations - indefinite fences are bad documentation - gem CMA functions used in more drivers - struct mutex removal - more drm_ debug macro usage - set/drop master api fixes - fix for drm/mm hole size comparison - drm/mm remove invalid entry optimization - optimise drm/mm hole handling - VRR debugfs added - uncompressed AFBC modifier support - multiple display id blocks in EDID - multiple driver sg handling fixes - __drm_atomic_helper_crtc_reset in all drivers - managed vram helpers ttm: - ttm_mem_reg handling cleanup - remove bo offset field - drop CMA memtype flag - drop mappable flag xilinx: - New Xilinx ZynqMP DisplayPort Subsystem driver nouveau: - add CRC support - start using NVIDIA published class header files - convert all push buffer emission to new macros - Proper push buffer space management for EVO/NVD channels. - firmware loading fixes - 2MiB system memory pages support on Pascal and newer vkms: - larger cursor support i915: - Rocketlake platform enablement - Early DG1 enablement - Numerous GEM refactorings - DP MST fixes - FBC, PSR, Cursor, Color, Gamma fixes - TGL, RKL, EHL workaround updates - TGL 8K display support fixes - SDVO/HDMI/DVI fixes amdgpu: - Initial support for Sienna Cichlid GPU - Initial support for Navy Flounder GPU - SI UVD/VCE support - expose rotation property - Add support for unique id on Arcturus - Enable runtime PM on vega10 boards that support BACO - Skip BAR resizing if the bios already did id - Major swSMU code cleanup - Fixes for DCN bandwidth calculations amdkfd: - Track SDMA usage per process - SMI events interface radeon: - Default to on chip GART for AGP boards on all arches - Runtime PM reference count fixes msm: - headers regenerated causing churn - a650/a640 display and GPU enablement - dpu dither support for 6bpc panels - dpu cursor fix - dsi/mdp5 enablement for sdm630/sdm636/sdm66 tegra: - video capture prep support - reflection support mediatek: - convert mtk_dsi to bridge API meson: - FBC support sun4i: - iommu support rockchip: - register locking fix - per-pixel alpha support PX30 VOP mgag200: - ported to simple and shmem helpers - device init cleanups - use managed pci functions - dropped hw cursor support ast: - use managed pci functions - use managed VRAM helpers - rework cursor support malidp: - dev_groups support hibmc: - refactor hibmc_drv_vdac: vc4: - create TXP CRTC imx: - error path fixes and cleanups etnaviv: - clock handling and error handling cleanups - use pin_user_pages" * tag 'drm-next-2020-08-06' of git://anongit.freedesktop.org/drm/drm: (1747 commits) drm/msm: use kthread_create_worker instead of kthread_run drm/msm/mdp5: Add MDP5 configuration for SDM636/660 drm/msm/dsi: Add DSI configuration for SDM660 drm/msm/mdp5: Add MDP5 configuration for SDM630 drm/msm/dsi: Add phy configuration for SDM630/636/660 drm/msm/a6xx: add A640/A650 hwcg drm/msm/a6xx: hwcg tables in gpulist drm/msm/dpu: add SM8250 to hw catalog drm/msm/dpu: add SM8150 to hw catalog drm/msm/dpu: intf timing path for displayport drm/msm/dpu: set missing flush bits for INTF_2 and INTF_3 drm/msm/dpu: don't use INTF_INPUT_CTRL feature on sdm845 drm/msm/dpu: move some sspp caps to dpu_caps drm/msm/dpu: update UBWC config for sm8150 and sm8250 drm/msm/dpu: use right setup_blend_config for sm8150 and sm8250 drm/msm/a6xx: set ubwc config for A640 and A650 drm/msm/adreno: un-open-code some packets drm/msm: sync generated headers drm/msm/a6xx: add build_bw_table for A640/A650 drm/msm/a6xx: fix crashstate capture for A650 ...
Diffstat (limited to 'drivers/gpu/ipu-v3/ipu-image-convert.c')
-rw-r--r--drivers/gpu/ipu-v3/ipu-image-convert.c145
1 files changed, 91 insertions, 54 deletions
diff --git a/drivers/gpu/ipu-v3/ipu-image-convert.c b/drivers/gpu/ipu-v3/ipu-image-convert.c
index eeca50d9a1ee..aa1d4b6d278f 100644
--- a/drivers/gpu/ipu-v3/ipu-image-convert.c
+++ b/drivers/gpu/ipu-v3/ipu-image-convert.c
@@ -137,6 +137,17 @@ struct ipu_image_convert_ctx;
struct ipu_image_convert_chan;
struct ipu_image_convert_priv;
+enum eof_irq_mask {
+ EOF_IRQ_IN = BIT(0),
+ EOF_IRQ_ROT_IN = BIT(1),
+ EOF_IRQ_OUT = BIT(2),
+ EOF_IRQ_ROT_OUT = BIT(3),
+};
+
+#define EOF_IRQ_COMPLETE (EOF_IRQ_IN | EOF_IRQ_OUT)
+#define EOF_IRQ_ROT_COMPLETE (EOF_IRQ_IN | EOF_IRQ_OUT | \
+ EOF_IRQ_ROT_IN | EOF_IRQ_ROT_OUT)
+
struct ipu_image_convert_ctx {
struct ipu_image_convert_chan *chan;
@@ -173,6 +184,9 @@ struct ipu_image_convert_ctx {
/* where to place converted tile in dest image */
unsigned int out_tile_map[MAX_TILES];
+ /* mask of completed EOF irqs at every tile conversion */
+ enum eof_irq_mask eof_mask;
+
struct list_head list;
};
@@ -189,6 +203,8 @@ struct ipu_image_convert_chan {
struct ipuv3_channel *rotation_out_chan;
/* the IPU end-of-frame irqs */
+ int in_eof_irq;
+ int rot_in_eof_irq;
int out_eof_irq;
int rot_out_eof_irq;
@@ -1380,6 +1396,9 @@ static int convert_start(struct ipu_image_convert_run *run, unsigned int tile)
dev_dbg(priv->ipu->dev, "%s: task %u: starting ctx %p run %p tile %u -> %u\n",
__func__, chan->ic_task, ctx, run, tile, dst_tile);
+ /* clear EOF irq mask */
+ ctx->eof_mask = 0;
+
if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
/* swap width/height for resizer */
dest_width = d_image->tile[dst_tile].height;
@@ -1615,7 +1634,7 @@ static bool ic_settings_changed(struct ipu_image_convert_ctx *ctx)
}
/* hold irqlock when calling */
-static irqreturn_t do_irq(struct ipu_image_convert_run *run)
+static irqreturn_t do_tile_complete(struct ipu_image_convert_run *run)
{
struct ipu_image_convert_ctx *ctx = run->ctx;
struct ipu_image_convert_chan *chan = ctx->chan;
@@ -1700,6 +1719,7 @@ static irqreturn_t do_irq(struct ipu_image_convert_run *run)
ctx->cur_buf_num ^= 1;
}
+ ctx->eof_mask = 0; /* clear EOF irq mask for next tile */
ctx->next_tile++;
return IRQ_HANDLED;
done:
@@ -1709,13 +1729,15 @@ done:
return IRQ_WAKE_THREAD;
}
-static irqreturn_t norotate_irq(int irq, void *data)
+static irqreturn_t eof_irq(int irq, void *data)
{
struct ipu_image_convert_chan *chan = data;
+ struct ipu_image_convert_priv *priv = chan->priv;
struct ipu_image_convert_ctx *ctx;
struct ipu_image_convert_run *run;
+ irqreturn_t ret = IRQ_HANDLED;
+ bool tile_complete = false;
unsigned long flags;
- irqreturn_t ret;
spin_lock_irqsave(&chan->irqlock, flags);
@@ -1728,46 +1750,33 @@ static irqreturn_t norotate_irq(int irq, void *data)
ctx = run->ctx;
- if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
- /* this is a rotation operation, just ignore */
- spin_unlock_irqrestore(&chan->irqlock, flags);
- return IRQ_HANDLED;
- }
-
- ret = do_irq(run);
-out:
- spin_unlock_irqrestore(&chan->irqlock, flags);
- return ret;
-}
-
-static irqreturn_t rotate_irq(int irq, void *data)
-{
- struct ipu_image_convert_chan *chan = data;
- struct ipu_image_convert_priv *priv = chan->priv;
- struct ipu_image_convert_ctx *ctx;
- struct ipu_image_convert_run *run;
- unsigned long flags;
- irqreturn_t ret;
-
- spin_lock_irqsave(&chan->irqlock, flags);
-
- /* get current run and its context */
- run = chan->current_run;
- if (!run) {
+ if (irq == chan->in_eof_irq) {
+ ctx->eof_mask |= EOF_IRQ_IN;
+ } else if (irq == chan->out_eof_irq) {
+ ctx->eof_mask |= EOF_IRQ_OUT;
+ } else if (irq == chan->rot_in_eof_irq ||
+ irq == chan->rot_out_eof_irq) {
+ if (!ipu_rot_mode_is_irt(ctx->rot_mode)) {
+ /* this was NOT a rotation op, shouldn't happen */
+ dev_err(priv->ipu->dev,
+ "Unexpected rotation interrupt\n");
+ goto out;
+ }
+ ctx->eof_mask |= (irq == chan->rot_in_eof_irq) ?
+ EOF_IRQ_ROT_IN : EOF_IRQ_ROT_OUT;
+ } else {
+ dev_err(priv->ipu->dev, "Received unknown irq %d\n", irq);
ret = IRQ_NONE;
goto out;
}
- ctx = run->ctx;
-
- if (!ipu_rot_mode_is_irt(ctx->rot_mode)) {
- /* this was NOT a rotation operation, shouldn't happen */
- dev_err(priv->ipu->dev, "Unexpected rotation interrupt\n");
- spin_unlock_irqrestore(&chan->irqlock, flags);
- return IRQ_HANDLED;
- }
+ if (ipu_rot_mode_is_irt(ctx->rot_mode))
+ tile_complete = (ctx->eof_mask == EOF_IRQ_ROT_COMPLETE);
+ else
+ tile_complete = (ctx->eof_mask == EOF_IRQ_COMPLETE);
- ret = do_irq(run);
+ if (tile_complete)
+ ret = do_tile_complete(run);
out:
spin_unlock_irqrestore(&chan->irqlock, flags);
return ret;
@@ -1801,6 +1810,10 @@ static void force_abort(struct ipu_image_convert_ctx *ctx)
static void release_ipu_resources(struct ipu_image_convert_chan *chan)
{
+ if (chan->in_eof_irq >= 0)
+ free_irq(chan->in_eof_irq, chan);
+ if (chan->rot_in_eof_irq >= 0)
+ free_irq(chan->rot_in_eof_irq, chan);
if (chan->out_eof_irq >= 0)
free_irq(chan->out_eof_irq, chan);
if (chan->rot_out_eof_irq >= 0)
@@ -1819,7 +1832,27 @@ static void release_ipu_resources(struct ipu_image_convert_chan *chan)
chan->in_chan = chan->out_chan = chan->rotation_in_chan =
chan->rotation_out_chan = NULL;
- chan->out_eof_irq = chan->rot_out_eof_irq = -1;
+ chan->in_eof_irq = -1;
+ chan->rot_in_eof_irq = -1;
+ chan->out_eof_irq = -1;
+ chan->rot_out_eof_irq = -1;
+}
+
+static int get_eof_irq(struct ipu_image_convert_chan *chan,
+ struct ipuv3_channel *channel)
+{
+ struct ipu_image_convert_priv *priv = chan->priv;
+ int ret, irq;
+
+ irq = ipu_idmac_channel_irq(priv->ipu, channel, IPU_IRQ_EOF);
+
+ ret = request_threaded_irq(irq, eof_irq, do_bh, 0, "ipu-ic", chan);
+ if (ret < 0) {
+ dev_err(priv->ipu->dev, "could not acquire irq %d\n", irq);
+ return ret;
+ }
+
+ return irq;
}
static int get_ipu_resources(struct ipu_image_convert_chan *chan)
@@ -1855,31 +1888,33 @@ static int get_ipu_resources(struct ipu_image_convert_chan *chan)
}
/* acquire the EOF interrupts */
- chan->out_eof_irq = ipu_idmac_channel_irq(priv->ipu,
- chan->out_chan,
- IPU_IRQ_EOF);
+ ret = get_eof_irq(chan, chan->in_chan);
+ if (ret < 0) {
+ chan->in_eof_irq = -1;
+ goto err;
+ }
+ chan->in_eof_irq = ret;
- ret = request_threaded_irq(chan->out_eof_irq, norotate_irq, do_bh,
- 0, "ipu-ic", chan);
+ ret = get_eof_irq(chan, chan->rotation_in_chan);
if (ret < 0) {
- dev_err(priv->ipu->dev, "could not acquire irq %d\n",
- chan->out_eof_irq);
- chan->out_eof_irq = -1;
+ chan->rot_in_eof_irq = -1;
goto err;
}
+ chan->rot_in_eof_irq = ret;
- chan->rot_out_eof_irq = ipu_idmac_channel_irq(priv->ipu,
- chan->rotation_out_chan,
- IPU_IRQ_EOF);
+ ret = get_eof_irq(chan, chan->out_chan);
+ if (ret < 0) {
+ chan->out_eof_irq = -1;
+ goto err;
+ }
+ chan->out_eof_irq = ret;
- ret = request_threaded_irq(chan->rot_out_eof_irq, rotate_irq, do_bh,
- 0, "ipu-ic", chan);
+ ret = get_eof_irq(chan, chan->rotation_out_chan);
if (ret < 0) {
- dev_err(priv->ipu->dev, "could not acquire irq %d\n",
- chan->rot_out_eof_irq);
chan->rot_out_eof_irq = -1;
goto err;
}
+ chan->rot_out_eof_irq = ret;
return 0;
err:
@@ -2458,6 +2493,8 @@ int ipu_image_convert_init(struct ipu_soc *ipu, struct device *dev)
chan->ic_task = i;
chan->priv = priv;
chan->dma_ch = &image_convert_dma_chan[i];
+ chan->in_eof_irq = -1;
+ chan->rot_in_eof_irq = -1;
chan->out_eof_irq = -1;
chan->rot_out_eof_irq = -1;