Skip to content

Commit

Permalink
Merge branch 'topic/omap3isp' of git://git.kernel.org/pub/scm/linux/k…
Browse files Browse the repository at this point in the history
…ernel/git/mchehab/linux-media

Pull OMAP3 updates from Mauro Carvalho Chehab:
 "Some driver improvements on OMAP3.  This series depend on some iommu
  patches already merged"

* 'topic/omap3isp' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (26 commits)
  [media] omap3isp: Rename isp_buffer isp_addr field to dma
  [media] omap3isp: Move to videobuf2
  [media] v4l: vb2: Add a function to discard all DONE buffers
  [media] omap3isp: Cancel all queued buffers when stopping the video stream
  [media] omap3isp: Move buffer irqlist to isp_buffer structure
  [media] omap3isp: Move queue irqlock to isp_video structure
  [media] omap3isp: Move queue mutex to isp_video structure
  [media] omap3isp: queue: Don't build scatterlist for kernel buffer
  [media] omap3isp: Use the ARM DMA IOMMU-aware operations
  [media] omap3isp: queue: Use sg_alloc_table_from_pages()
  [media] omap3isp: queue: Map PFNMAP buffers to device
  [media] omap3isp: queue: Fix the dma_map_sg() return value check
  [media] omap3isp: queue: Allocate kernel buffers with dma_alloc_coherent
  [media] omap3isp: queue: Inline the ispmmu_v(un)map functions
  [media] omap3isp: queue: Merge the prepare and sglist functions
  [media] omap3isp: queue: Use sg_table structure
  [media] omap3isp: queue: Move IOMMU handling code to the queue
  [media] omap3isp: video: Set the buffer bytesused field at completion time
  [media] omap3isp: ccdc: Use the DMA API for FPC
  [media] omap3isp: ccdc: Use the DMA API for LSC
  ...
  • Loading branch information
torvalds committed Jun 13, 2014
2 parents ed9ea4e + 21d8582 commit 338c09a
Show file tree
Hide file tree
Showing 21 changed files with 458 additions and 1,745 deletions.
4 changes: 3 additions & 1 deletion drivers/media/platform/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,9 @@ config VIDEO_M32R_AR_M64278

config VIDEO_OMAP3
tristate "OMAP 3 Camera support"
depends on OMAP_IOVMM && VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && ARCH_OMAP3
depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && ARCH_OMAP3
select ARM_DMA_USE_IOMMU
select OMAP_IOMMU
---help---
Driver for an OMAP 3 camera controller.

Expand Down
2 changes: 1 addition & 1 deletion drivers/media/platform/omap3isp/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
ccflags-$(CONFIG_VIDEO_OMAP3_DEBUG) += -DDEBUG

omap3-isp-objs += \
isp.o ispqueue.o ispvideo.o \
isp.o ispvideo.o \
ispcsiphy.o ispccp2.o ispcsi2.o \
ispccdc.o isppreview.o ispresizer.o \
ispstat.o isph3a_aewb.o isph3a_af.o isphist.o
Expand Down
108 changes: 79 additions & 29 deletions drivers/media/platform/omap3isp/isp.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@
#include <linux/sched.h>
#include <linux/vmalloc.h>

#include <asm/dma-iommu.h>

#include <media/v4l2-common.h>
#include <media/v4l2-device.h>

Expand Down Expand Up @@ -1397,14 +1399,14 @@ int omap3isp_module_sync_idle(struct media_entity *me, wait_queue_head_t *wait,
if (isp_pipeline_is_last(me)) {
struct isp_video *video = pipe->output;
unsigned long flags;
spin_lock_irqsave(&video->queue->irqlock, flags);
spin_lock_irqsave(&video->irqlock, flags);
if (video->dmaqueue_flags & ISP_VIDEO_DMAQUEUE_UNDERRUN) {
spin_unlock_irqrestore(&video->queue->irqlock, flags);
spin_unlock_irqrestore(&video->irqlock, flags);
atomic_set(stopping, 0);
smp_mb();
return 0;
}
spin_unlock_irqrestore(&video->queue->irqlock, flags);
spin_unlock_irqrestore(&video->irqlock, flags);
if (!wait_event_timeout(*wait, !atomic_read(stopping),
msecs_to_jiffies(1000))) {
atomic_set(stopping, 0);
Expand Down Expand Up @@ -1625,7 +1627,7 @@ struct isp_device *omap3isp_get(struct isp_device *isp)
* Decrement the reference count on the ISP. If the last reference is released,
* power-down all submodules, disable clocks and free temporary buffers.
*/
void omap3isp_put(struct isp_device *isp)
static void __omap3isp_put(struct isp_device *isp, bool save_ctx)
{
if (isp == NULL)
return;
Expand All @@ -1634,7 +1636,7 @@ void omap3isp_put(struct isp_device *isp)
BUG_ON(isp->ref_count == 0);
if (--isp->ref_count == 0) {
isp_disable_interrupts(isp);
if (isp->domain) {
if (save_ctx) {
isp_save_ctx(isp);
isp->has_context = 1;
}
Expand All @@ -1648,6 +1650,11 @@ void omap3isp_put(struct isp_device *isp)
mutex_unlock(&isp->isp_mutex);
}

void omap3isp_put(struct isp_device *isp)
{
__omap3isp_put(isp, true);
}

/* --------------------------------------------------------------------------
* Platform device driver
*/
Expand Down Expand Up @@ -2120,6 +2127,61 @@ static int isp_initialize_modules(struct isp_device *isp)
return ret;
}

static void isp_detach_iommu(struct isp_device *isp)
{
arm_iommu_release_mapping(isp->mapping);
isp->mapping = NULL;
iommu_group_remove_device(isp->dev);
}

static int isp_attach_iommu(struct isp_device *isp)
{
struct dma_iommu_mapping *mapping;
struct iommu_group *group;
int ret;

/* Create a device group and add the device to it. */
group = iommu_group_alloc();
if (IS_ERR(group)) {
dev_err(isp->dev, "failed to allocate IOMMU group\n");
return PTR_ERR(group);
}

ret = iommu_group_add_device(group, isp->dev);
iommu_group_put(group);

if (ret < 0) {
dev_err(isp->dev, "failed to add device to IPMMU group\n");
return ret;
}

/*
* Create the ARM mapping, used by the ARM DMA mapping core to allocate
* VAs. This will allocate a corresponding IOMMU domain.
*/
mapping = arm_iommu_create_mapping(&platform_bus_type, SZ_1G, SZ_2G);
if (IS_ERR(mapping)) {
dev_err(isp->dev, "failed to create ARM IOMMU mapping\n");
ret = PTR_ERR(mapping);
goto error;
}

isp->mapping = mapping;

/* Attach the ARM VA mapping to the device. */
ret = arm_iommu_attach_device(isp->dev, mapping);
if (ret < 0) {
dev_err(isp->dev, "failed to attach device to VA mapping\n");
goto error;
}

return 0;

error:
isp_detach_iommu(isp);
return ret;
}

/*
* isp_remove - Remove ISP platform device
* @pdev: Pointer to ISP platform device
Expand All @@ -2135,10 +2197,8 @@ static int isp_remove(struct platform_device *pdev)
isp_xclk_cleanup(isp);

__omap3isp_get(isp, false);
iommu_detach_device(isp->domain, &pdev->dev);
iommu_domain_free(isp->domain);
isp->domain = NULL;
omap3isp_put(isp);
isp_detach_iommu(isp);
__omap3isp_put(isp, false);

return 0;
}
Expand Down Expand Up @@ -2265,39 +2325,32 @@ static int isp_probe(struct platform_device *pdev)
}
}

isp->domain = iommu_domain_alloc(pdev->dev.bus);
if (!isp->domain) {
dev_err(isp->dev, "can't alloc iommu domain\n");
ret = -ENOMEM;
/* IOMMU */
ret = isp_attach_iommu(isp);
if (ret < 0) {
dev_err(&pdev->dev, "unable to attach to IOMMU\n");
goto error_isp;
}

ret = iommu_attach_device(isp->domain, &pdev->dev);
if (ret) {
dev_err(&pdev->dev, "can't attach iommu device: %d\n", ret);
ret = -EPROBE_DEFER;
goto free_domain;
}

/* Interrupt */
isp->irq_num = platform_get_irq(pdev, 0);
if (isp->irq_num <= 0) {
dev_err(isp->dev, "No IRQ resource\n");
ret = -ENODEV;
goto detach_dev;
goto error_iommu;
}

if (devm_request_irq(isp->dev, isp->irq_num, isp_isr, IRQF_SHARED,
"OMAP3 ISP", isp)) {
dev_err(isp->dev, "Unable to request IRQ\n");
ret = -EINVAL;
goto detach_dev;
goto error_iommu;
}

/* Entities */
ret = isp_initialize_modules(isp);
if (ret < 0)
goto detach_dev;
goto error_iommu;

ret = isp_register_entities(isp);
if (ret < 0)
Expand All @@ -2310,14 +2363,11 @@ static int isp_probe(struct platform_device *pdev)

error_modules:
isp_cleanup_modules(isp);
detach_dev:
iommu_detach_device(isp->domain, &pdev->dev);
free_domain:
iommu_domain_free(isp->domain);
isp->domain = NULL;
error_iommu:
isp_detach_iommu(isp);
error_isp:
isp_xclk_cleanup(isp);
omap3isp_put(isp);
__omap3isp_put(isp, false);
error:
mutex_destroy(&isp->isp_mutex);

Expand Down
8 changes: 3 additions & 5 deletions drivers/media/platform/omap3isp/isp.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@
#include "ispcsi2.h"
#include "ispccp2.h"

#define IOMMU_FLAG (IOVMF_ENDIAN_LITTLE | IOVMF_ELSZ_8)

#define ISP_TOK_TERM 0xFFFFFFFF /*
* terminating token for ISP
* modules reg list
Expand Down Expand Up @@ -152,6 +150,7 @@ struct isp_xclk {
* regions.
* @mmio_base_phys: Array with physical L4 bus addresses for ISP register
* regions.
* @mapping: IOMMU mapping
* @stat_lock: Spinlock for handling statistics
* @isp_mutex: Mutex for serializing requests to ISP.
* @stop_failure: Indicates that an entity failed to stop.
Expand All @@ -171,7 +170,6 @@ struct isp_xclk {
* @isp_res: Pointer to current settings for ISP Resizer.
* @isp_prev: Pointer to current settings for ISP Preview.
* @isp_ccdc: Pointer to current settings for ISP CCDC.
* @iommu: Pointer to requested IOMMU instance for ISP.
* @platform_cb: ISP driver callback function pointers for platform code
*
* This structure is used to store the OMAP ISP Information.
Expand All @@ -189,6 +187,8 @@ struct isp_device {
void __iomem *mmio_base[OMAP3_ISP_IOMEM_LAST];
unsigned long mmio_base_phys[OMAP3_ISP_IOMEM_LAST];

struct dma_iommu_mapping *mapping;

/* ISP Obj */
spinlock_t stat_lock; /* common lock for statistic drivers */
struct mutex isp_mutex; /* For handling ref_count field */
Expand Down Expand Up @@ -219,8 +219,6 @@ struct isp_device {

unsigned int sbl_resources;
unsigned int subclk_resources;

struct iommu_domain *domain;
};

#define v4l2_dev_to_isp_device(dev) \
Expand Down
Loading

0 comments on commit 338c09a

Please sign in to comment.