diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-07-09 18:48:37 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-07-09 18:48:37 -0700 |
commit | af3c8d98508d37541d4bf57f13a984a7f73a328c (patch) | |
tree | e8dd974d6ebccd38b1e373be8a5e4a2f8bf3c6ce /drivers/media | |
parent | d3e3b7eac886fb1383db2f22b81550fa6d87f62f (diff) | |
parent | 00fc2c26bc46a64545cdf95a1511461ea9acecb4 (diff) | |
download | linux-af3c8d98508d37541d4bf57f13a984a7f73a328c.tar.bz2 |
Merge tag 'drm-for-v4.13' of git://people.freedesktop.org/~airlied/linux
Pull drm updates from Dave Airlie:
"This is the main pull request for the drm, I think I've got one later
driver pull for mediatek SoC driver, I'm undecided on if it needs to
go to you yet.
Otherwise summary below:
Core drm:
- Atomic add driver private objects
- Deprecate preclose hook in modern drivers
- MST bandwidth tracking
- Use kvmalloc in more places
- Add mode_valid hook for crtc/encoder/bridge
- Reduce sync_file construction time
- Documentation updates
- New DRM synchronisation object support
New drivers:
- pl111 - pl111 CLCD display controller
Panel:
- Innolux P079ZCA panel driver
- Add NL12880B20-05, NL192108AC18-02D, P320HVN03 panels
- panel-samsung-s6e3ha2: Add s6e3hf2 panel support
i915:
- SKL+ watermark fixes
- G4x/G33 reset improvements
- DP AUX backlight improvements
- Buffer based GuC/host communication
- New getparam for (sub)slice infomation
- Cannonlake and Coffeelake initial patches
- Execbuf optimisations
radeon/amdgpu:
- Lots of Vega10 bug fixes
- Preliminary raven support
- KIQ support for compute rings
- MEC queue management rework
- DCE6 Audio support
- SR-IOV improvements
- Better radeon/amdgpu selection support
nouveau:
- HDMI stereoscopic support
- Display code rework for >= GM20x GPUs
msm:
- GEM rework for fine-grained locking
- Per-process pagetable work
- HDMI fixes for Snapdragon 820.
vc4:
- Remove 256MB CMA limit from vc4
- Add out-fence support
- Add support for cygnus
- Get/set tiling ioctls support
- Add T-format tiling support for scanout
zte:
- add VGA support.
etnaviv:
- Thermal throttle support for newer GPUs
- Restore userspace buffer cache performance
- dma-buf sync fix
stm:
- add stm32f429 display support
exynos:
- Rework vblank handling
- Fixup sw-trigger code
sun4i:
- V3s display engine support
- HDMI support for older SoCs
- Preliminary work on dual-pipeline SoCs.
rcar-du:
- VSP work
imx-drm:
- Remove counter load enable from PRE
- Double read/write reduction flag support
tegra:
- Documentation for the host1x and drm driver.
- Lots of staging ioctl fixes due to grate project work.
omapdrm:
- dma-buf fence support
- TILER rotation fixes"
* tag 'drm-for-v4.13' of git://people.freedesktop.org/~airlied/linux: (1270 commits)
drm: Remove unused drm_file parameter to drm_syncobj_replace_fence()
drm/amd/powerplay: fix bug fail to remove sysfs when rmmod amdgpu.
amdgpu: Set cik/si_support to 1 by default if radeon isn't built
drm/amdgpu/gfx9: fix driver reload with KIQ
drm/amdgpu/gfx8: fix driver reload with KIQ
drm/amdgpu: Don't call amd_powerplay_destroy() if we don't have powerplay
drm/ttm: Fix use-after-free in ttm_bo_clean_mm
drm/amd/amdgpu: move get memory type function from early init to sw init
drm/amdgpu/cgs: always set reference clock in mode_info
drm/amdgpu: fix vblank_time when displays are off
drm/amd/powerplay: power value format change for Vega10
drm/amdgpu/gfx9: support the amdgpu.disable_cu option
drm/amd/powerplay: change PPSMC_MSG_GetCurrPkgPwr for Vega10
drm/amdgpu: Make amdgpu_cs_parser_init static (v2)
drm/amdgpu/cs: fix a typo in a comment
drm/amdgpu: Fix the exported always on CU bitmap
drm/amdgpu/gfx9: gfx_v9_0_enable_gfx_static_mg_power_gating() can be static
drm/amdgpu/psp: upper_32_bits/lower_32_bits for address setup
drm/amd/powerplay/cz: print message if smc message fails
drm/amdgpu: fix typo in amdgpu_debugfs_test_ib_init
...
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/platform/rcar-fcp.c | 17 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1.h | 1 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_dl.c | 23 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_dl.h | 2 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_drm.c | 41 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_drm.h | 11 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_drv.c | 9 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_pipe.c | 13 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_video.c | 2 |
9 files changed, 103 insertions, 16 deletions
diff --git a/drivers/media/platform/rcar-fcp.c b/drivers/media/platform/rcar-fcp.c index 7146fc5ef168..2988031d285d 100644 --- a/drivers/media/platform/rcar-fcp.c +++ b/drivers/media/platform/rcar-fcp.c @@ -53,14 +53,7 @@ struct rcar_fcp_device *rcar_fcp_get(const struct device_node *np) if (fcp->dev->of_node != np) continue; - /* - * Make sure the module won't be unloaded behind our back. This - * is a poor man's safety net, the module should really not be - * unloaded while FCP users can be active. - */ - if (!try_module_get(fcp->dev->driver->owner)) - fcp = NULL; - + get_device(fcp->dev); goto done; } @@ -81,10 +74,16 @@ EXPORT_SYMBOL_GPL(rcar_fcp_get); void rcar_fcp_put(struct rcar_fcp_device *fcp) { if (fcp) - module_put(fcp->dev->driver->owner); + put_device(fcp->dev); } EXPORT_SYMBOL_GPL(rcar_fcp_put); +struct device *rcar_fcp_get_device(struct rcar_fcp_device *fcp) +{ + return fcp->dev; +} +EXPORT_SYMBOL_GPL(rcar_fcp_get_device); + /** * rcar_fcp_enable - Enable an FCP * @fcp: The FCP instance diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h index 85387a64179a..847963b6e9eb 100644 --- a/drivers/media/platform/vsp1/vsp1.h +++ b/drivers/media/platform/vsp1/vsp1.h @@ -74,6 +74,7 @@ struct vsp1_device { void __iomem *mmio; struct rcar_fcp_device *fcp; + struct device *bus_master; struct vsp1_bru *bru; struct vsp1_clu *clu; diff --git a/drivers/media/platform/vsp1/vsp1_dl.c b/drivers/media/platform/vsp1/vsp1_dl.c index 7d8f37772b56..aaf17b13fd78 100644 --- a/drivers/media/platform/vsp1/vsp1_dl.c +++ b/drivers/media/platform/vsp1/vsp1_dl.c @@ -137,7 +137,7 @@ static int vsp1_dl_body_init(struct vsp1_device *vsp1, dlb->vsp1 = vsp1; dlb->size = size; - dlb->entries = dma_alloc_wc(vsp1->dev, dlb->size, &dlb->dma, + dlb->entries = dma_alloc_wc(vsp1->bus_master, dlb->size, &dlb->dma, GFP_KERNEL); if (!dlb->entries) return -ENOMEM; @@ -150,7 +150,7 @@ static int vsp1_dl_body_init(struct vsp1_device *vsp1, */ static void vsp1_dl_body_cleanup(struct vsp1_dl_body *dlb) { - dma_free_wc(dlb->vsp1->dev, dlb->size, dlb->entries, dlb->dma); + dma_free_wc(dlb->vsp1->bus_master, dlb->size, dlb->entries, dlb->dma); } /** @@ -561,9 +561,19 @@ void vsp1_dlm_irq_display_start(struct vsp1_dl_manager *dlm) spin_unlock(&dlm->lock); } -void vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm) +/** + * vsp1_dlm_irq_frame_end - Display list handler for the frame end interrupt + * @dlm: the display list manager + * + * Return true if the previous display list has completed at frame end, or false + * if it has been delayed by one frame because the display list commit raced + * with the frame end interrupt. The function always returns true in header mode + * as display list processing is then not continuous and races never occur. + */ +bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm) { struct vsp1_device *vsp1 = dlm->vsp1; + bool completed = false; spin_lock(&dlm->lock); @@ -575,8 +585,10 @@ void vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm) * perform any operation as there can't be any new display list queued * in that case. */ - if (dlm->mode == VSP1_DL_MODE_HEADER) + if (dlm->mode == VSP1_DL_MODE_HEADER) { + completed = true; goto done; + } /* * The UPD bit set indicates that the commit operation raced with the @@ -594,6 +606,7 @@ void vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm) if (dlm->queued) { dlm->active = dlm->queued; dlm->queued = NULL; + completed = true; } /* @@ -614,6 +627,8 @@ void vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm) done: spin_unlock(&dlm->lock); + + return completed; } /* Hardware Setup */ diff --git a/drivers/media/platform/vsp1/vsp1_dl.h b/drivers/media/platform/vsp1/vsp1_dl.h index 7131aa3c5978..6ec1380a10af 100644 --- a/drivers/media/platform/vsp1/vsp1_dl.h +++ b/drivers/media/platform/vsp1/vsp1_dl.h @@ -28,7 +28,7 @@ struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device *vsp1, void vsp1_dlm_destroy(struct vsp1_dl_manager *dlm); void vsp1_dlm_reset(struct vsp1_dl_manager *dlm); void vsp1_dlm_irq_display_start(struct vsp1_dl_manager *dlm); -void vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm); +bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm); struct vsp1_dl_list *vsp1_dl_list_get(struct vsp1_dl_manager *dlm); void vsp1_dl_list_put(struct vsp1_dl_list *dl); diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index 9d235e830f5a..9377aafa8996 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -12,6 +12,7 @@ */ #include <linux/device.h> +#include <linux/dma-mapping.h> #include <linux/slab.h> #include <media/media-entity.h> @@ -36,6 +37,14 @@ void vsp1_drm_display_start(struct vsp1_device *vsp1) vsp1_dlm_irq_display_start(vsp1->drm->pipe.output->dlm); } +static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe) +{ + struct vsp1_drm *drm = to_vsp1_drm(pipe); + + if (drm->du_complete) + drm->du_complete(drm->du_private); +} + /* ----------------------------------------------------------------------------- * DU Driver API */ @@ -95,6 +104,7 @@ int vsp1_du_setup_lif(struct device *dev, const struct vsp1_du_lif_config *cfg) } pipe->num_inputs = 0; + vsp1->drm->du_complete = NULL; vsp1_dlm_reset(pipe->output->dlm); vsp1_device_put(vsp1); @@ -199,6 +209,13 @@ int vsp1_du_setup_lif(struct device *dev, const struct vsp1_du_lif_config *cfg) if (ret < 0) return ret; + /* + * Register a callback to allow us to notify the DRM driver of frame + * completion events. + */ + vsp1->drm->du_complete = cfg->callback; + vsp1->drm->du_private = cfg->callback_data; + ret = media_pipeline_start(&pipe->output->entity.subdev.entity, &pipe->pipe); if (ret < 0) { @@ -524,6 +541,29 @@ void vsp1_du_atomic_flush(struct device *dev) } EXPORT_SYMBOL_GPL(vsp1_du_atomic_flush); +int vsp1_du_map_sg(struct device *dev, struct sg_table *sgt) +{ + struct vsp1_device *vsp1 = dev_get_drvdata(dev); + + /* + * As all the buffers allocated by the DU driver are coherent, we can + * skip cache sync. This will need to be revisited when support for + * non-coherent buffers will be added to the DU driver. + */ + return dma_map_sg_attrs(vsp1->bus_master, sgt->sgl, sgt->nents, + DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); +} +EXPORT_SYMBOL_GPL(vsp1_du_map_sg); + +void vsp1_du_unmap_sg(struct device *dev, struct sg_table *sgt) +{ + struct vsp1_device *vsp1 = dev_get_drvdata(dev); + + dma_unmap_sg_attrs(vsp1->bus_master, sgt->sgl, sgt->nents, + DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); +} +EXPORT_SYMBOL_GPL(vsp1_du_unmap_sg); + /* ----------------------------------------------------------------------------- * Initialization */ @@ -603,6 +643,7 @@ int vsp1_drm_init(struct vsp1_device *vsp1) pipe->lif = &vsp1->lif->entity; pipe->output = vsp1->wpf[0]; pipe->output->pipe = pipe; + pipe->frame_end = vsp1_du_pipeline_frame_end; return 0; } diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h index c8d2f88fc483..e9f80727ff92 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.h +++ b/drivers/media/platform/vsp1/vsp1_drm.h @@ -23,6 +23,8 @@ * @num_inputs: number of active pipeline inputs at the beginning of an update * @inputs: source crop rectangle, destination compose rectangle and z-order * position for every input + * @du_complete: frame completion callback for the DU driver (optional) + * @du_private: data to be passed to the du_complete callback */ struct vsp1_drm { struct vsp1_pipeline pipe; @@ -33,8 +35,17 @@ struct vsp1_drm { struct v4l2_rect compose; unsigned int zpos; } inputs[VSP1_MAX_RPF]; + + /* Frame synchronisation */ + void (*du_complete)(void *); + void *du_private; }; +static inline struct vsp1_drm *to_vsp1_drm(struct vsp1_pipeline *pipe) +{ + return container_of(pipe, struct vsp1_drm, pipe); +} + int vsp1_drm_init(struct vsp1_device *vsp1); void vsp1_drm_cleanup(struct vsp1_device *vsp1); int vsp1_drm_create_links(struct vsp1_device *vsp1); diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index 048446af5ae7..95c26edead85 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c @@ -764,6 +764,15 @@ static int vsp1_probe(struct platform_device *pdev) PTR_ERR(vsp1->fcp)); return PTR_ERR(vsp1->fcp); } + + /* + * When the FCP is present, it handles all bus master accesses + * for the VSP and must thus be used in place of the VSP device + * to map DMA buffers. + */ + vsp1->bus_master = rcar_fcp_get_device(vsp1->fcp); + } else { + vsp1->bus_master = vsp1->dev; } /* Configure device parameters based on the version register. */ diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c index edebf3fa926f..e817623b84e0 100644 --- a/drivers/media/platform/vsp1/vsp1_pipe.c +++ b/drivers/media/platform/vsp1/vsp1_pipe.c @@ -330,10 +330,21 @@ bool vsp1_pipeline_ready(struct vsp1_pipeline *pipe) void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe) { + bool completed; + if (pipe == NULL) return; - vsp1_dlm_irq_frame_end(pipe->output->dlm); + completed = vsp1_dlm_irq_frame_end(pipe->output->dlm); + if (!completed) { + /* + * If the DL commit raced with the frame end interrupt, the + * commit ends up being postponed by one frame. Return + * immediately without calling the pipeline's frame end handler + * or incrementing the sequence number. + */ + return; + } if (pipe->hgo) vsp1_hgo_frame_end(pipe->hgo); diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index eab3c3ea85d7..5af3486afe07 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -1197,7 +1197,7 @@ struct vsp1_video *vsp1_video_create(struct vsp1_device *vsp1, video->queue.ops = &vsp1_video_queue_qops; video->queue.mem_ops = &vb2_dma_contig_memops; video->queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; - video->queue.dev = video->vsp1->dev; + video->queue.dev = video->vsp1->bus_master; ret = vb2_queue_init(&video->queue); if (ret < 0) { dev_err(video->vsp1->dev, "failed to initialize vb2 queue\n"); |