aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/platform/omap3isp/isp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/platform/omap3isp/isp.c')
-rw-r--r--drivers/media/platform/omap3isp/isp.c102
1 files changed, 76 insertions, 26 deletions
diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c
index 06a0df434249..5a4801b76282 100644
--- a/drivers/media/platform/omap3isp/isp.c
+++ b/drivers/media/platform/omap3isp/isp.c
@@ -69,6 +69,8 @@
69#include <linux/sched.h> 69#include <linux/sched.h>
70#include <linux/vmalloc.h> 70#include <linux/vmalloc.h>
71 71
72#include <asm/dma-iommu.h>
73
72#include <media/v4l2-common.h> 74#include <media/v4l2-common.h>
73#include <media/v4l2-device.h> 75#include <media/v4l2-device.h>
74 76
@@ -1625,7 +1627,7 @@ struct isp_device *omap3isp_get(struct isp_device *isp)
1625 * Decrement the reference count on the ISP. If the last reference is released, 1627 * Decrement the reference count on the ISP. If the last reference is released,
1626 * power-down all submodules, disable clocks and free temporary buffers. 1628 * power-down all submodules, disable clocks and free temporary buffers.
1627 */ 1629 */
1628void omap3isp_put(struct isp_device *isp) 1630static void __omap3isp_put(struct isp_device *isp, bool save_ctx)
1629{ 1631{
1630 if (isp == NULL) 1632 if (isp == NULL)
1631 return; 1633 return;
@@ -1634,7 +1636,7 @@ void omap3isp_put(struct isp_device *isp)
1634 BUG_ON(isp->ref_count == 0); 1636 BUG_ON(isp->ref_count == 0);
1635 if (--isp->ref_count == 0) { 1637 if (--isp->ref_count == 0) {
1636 isp_disable_interrupts(isp); 1638 isp_disable_interrupts(isp);
1637 if (isp->domain) { 1639 if (save_ctx) {
1638 isp_save_ctx(isp); 1640 isp_save_ctx(isp);
1639 isp->has_context = 1; 1641 isp->has_context = 1;
1640 } 1642 }
@@ -1648,6 +1650,11 @@ void omap3isp_put(struct isp_device *isp)
1648 mutex_unlock(&isp->isp_mutex); 1650 mutex_unlock(&isp->isp_mutex);
1649} 1651}
1650 1652
1653void omap3isp_put(struct isp_device *isp)
1654{
1655 __omap3isp_put(isp, true);
1656}
1657
1651/* -------------------------------------------------------------------------- 1658/* --------------------------------------------------------------------------
1652 * Platform device driver 1659 * Platform device driver
1653 */ 1660 */
@@ -2120,6 +2127,61 @@ error_csiphy:
2120 return ret; 2127 return ret;
2121} 2128}
2122 2129
2130static void isp_detach_iommu(struct isp_device *isp)
2131{
2132 arm_iommu_release_mapping(isp->mapping);
2133 isp->mapping = NULL;
2134 iommu_group_remove_device(isp->dev);
2135}
2136
2137static int isp_attach_iommu(struct isp_device *isp)
2138{
2139 struct dma_iommu_mapping *mapping;
2140 struct iommu_group *group;
2141 int ret;
2142
2143 /* Create a device group and add the device to it. */
2144 group = iommu_group_alloc();
2145 if (IS_ERR(group)) {
2146 dev_err(isp->dev, "failed to allocate IOMMU group\n");
2147 return PTR_ERR(group);
2148 }
2149
2150 ret = iommu_group_add_device(group, isp->dev);
2151 iommu_group_put(group);
2152
2153 if (ret < 0) {
2154 dev_err(isp->dev, "failed to add device to IPMMU group\n");
2155 return ret;
2156 }
2157
2158 /*
2159 * Create the ARM mapping, used by the ARM DMA mapping core to allocate
2160 * VAs. This will allocate a corresponding IOMMU domain.
2161 */
2162 mapping = arm_iommu_create_mapping(&platform_bus_type, SZ_1G, SZ_2G);
2163 if (IS_ERR(mapping)) {
2164 dev_err(isp->dev, "failed to create ARM IOMMU mapping\n");
2165 ret = PTR_ERR(mapping);
2166 goto error;
2167 }
2168
2169 isp->mapping = mapping;
2170
2171 /* Attach the ARM VA mapping to the device. */
2172 ret = arm_iommu_attach_device(isp->dev, mapping);
2173 if (ret < 0) {
2174 dev_err(isp->dev, "failed to attach device to VA mapping\n");
2175 goto error;
2176 }
2177
2178 return 0;
2179
2180error:
2181 isp_detach_iommu(isp);
2182 return ret;
2183}
2184
2123/* 2185/*
2124 * isp_remove - Remove ISP platform device 2186 * isp_remove - Remove ISP platform device
2125 * @pdev: Pointer to ISP platform device 2187 * @pdev: Pointer to ISP platform device
@@ -2135,10 +2197,8 @@ static int isp_remove(struct platform_device *pdev)
2135 isp_xclk_cleanup(isp); 2197 isp_xclk_cleanup(isp);
2136 2198
2137 __omap3isp_get(isp, false); 2199 __omap3isp_get(isp, false);
2138 iommu_detach_device(isp->domain, &pdev->dev); 2200 isp_detach_iommu(isp);
2139 iommu_domain_free(isp->domain); 2201 __omap3isp_put(isp, false);
2140 isp->domain = NULL;
2141 omap3isp_put(isp);
2142 2202
2143 return 0; 2203 return 0;
2144} 2204}
@@ -2265,39 +2325,32 @@ static int isp_probe(struct platform_device *pdev)
2265 } 2325 }
2266 } 2326 }
2267 2327
2268 isp->domain = iommu_domain_alloc(pdev->dev.bus); 2328 /* IOMMU */
2269 if (!isp->domain) { 2329 ret = isp_attach_iommu(isp);
2270 dev_err(isp->dev, "can't alloc iommu domain\n"); 2330 if (ret < 0) {
2271 ret = -ENOMEM; 2331 dev_err(&pdev->dev, "unable to attach to IOMMU\n");
2272 goto error_isp; 2332 goto error_isp;
2273 } 2333 }
2274 2334
2275 ret = iommu_attach_device(isp->domain, &pdev->dev);
2276 if (ret) {
2277 dev_err(&pdev->dev, "can't attach iommu device: %d\n", ret);
2278 ret = -EPROBE_DEFER;
2279 goto free_domain;
2280 }
2281
2282 /* Interrupt */ 2335 /* Interrupt */
2283 isp->irq_num = platform_get_irq(pdev, 0); 2336 isp->irq_num = platform_get_irq(pdev, 0);
2284 if (isp->irq_num <= 0) { 2337 if (isp->irq_num <= 0) {
2285 dev_err(isp->dev, "No IRQ resource\n"); 2338 dev_err(isp->dev, "No IRQ resource\n");
2286 ret = -ENODEV; 2339 ret = -ENODEV;
2287 goto detach_dev; 2340 goto error_iommu;
2288 } 2341 }
2289 2342
2290 if (devm_request_irq(isp->dev, isp->irq_num, isp_isr, IRQF_SHARED, 2343 if (devm_request_irq(isp->dev, isp->irq_num, isp_isr, IRQF_SHARED,
2291 "OMAP3 ISP", isp)) { 2344 "OMAP3 ISP", isp)) {
2292 dev_err(isp->dev, "Unable to request IRQ\n"); 2345 dev_err(isp->dev, "Unable to request IRQ\n");
2293 ret = -EINVAL; 2346 ret = -EINVAL;
2294 goto detach_dev; 2347 goto error_iommu;
2295 } 2348 }
2296 2349
2297 /* Entities */ 2350 /* Entities */
2298 ret = isp_initialize_modules(isp); 2351 ret = isp_initialize_modules(isp);
2299 if (ret < 0) 2352 if (ret < 0)
2300 goto detach_dev; 2353 goto error_iommu;
2301 2354
2302 ret = isp_register_entities(isp); 2355 ret = isp_register_entities(isp);
2303 if (ret < 0) 2356 if (ret < 0)
@@ -2310,14 +2363,11 @@ static int isp_probe(struct platform_device *pdev)
2310 2363
2311error_modules: 2364error_modules:
2312 isp_cleanup_modules(isp); 2365 isp_cleanup_modules(isp);
2313detach_dev: 2366error_iommu:
2314 iommu_detach_device(isp->domain, &pdev->dev); 2367 isp_detach_iommu(isp);
2315free_domain:
2316 iommu_domain_free(isp->domain);
2317 isp->domain = NULL;
2318error_isp: 2368error_isp:
2319 isp_xclk_cleanup(isp); 2369 isp_xclk_cleanup(isp);
2320 omap3isp_put(isp); 2370 __omap3isp_put(isp, false);
2321error: 2371error:
2322 mutex_destroy(&isp->isp_mutex); 2372 mutex_destroy(&isp->isp_mutex);
2323 2373