Loading drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c +53 −14 Original line number Diff line number Diff line Loading @@ -14,7 +14,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/regulator/consumer.h> #include <linux/ion.h> #include <linux/msm_ion.h> #include <linux/delay.h> Loading Loading @@ -528,6 +527,8 @@ static int msm_jpegdma_release(struct file *file) { struct jpegdma_ctx *ctx = msm_jpegdma_ctx_from_fh(file->private_data); /* release all the resources */ msm_jpegdma_hw_put(ctx->jdma_device); atomic_set(&ctx->active, 0); complete_all(&ctx->completion); v4l2_m2m_ctx_release(ctx->m2m_ctx); Loading Loading @@ -1190,17 +1191,26 @@ static int jpegdma_probe(struct platform_device *pdev) init_completion(&jpegdma->hw_reset_completion); init_completion(&jpegdma->hw_halt_completion); jpegdma->dev = &pdev->dev; jpegdma->pdev = pdev; if (pdev->dev.of_node) of_property_read_u32((&pdev->dev)->of_node, "cell-index", &pdev->id); /* Get resources */ ret = msm_jpegdma_hw_get_mem_resources(pdev, jpegdma); if (ret < 0) goto error_mem_resources; ret = msm_jpegdma_hw_get_regulators(jpegdma); /* get all the regulators */ ret = msm_camera_get_regulator_info(pdev, &jpegdma->vdd, &jpegdma->num_reg); if (ret < 0) goto error_get_regulators; ret = msm_jpegdma_hw_get_clocks(jpegdma); /* get all the clocks */ ret = msm_camera_get_clk_info(pdev, &jpegdma->jpeg_clk_info, &jpegdma->clk, &jpegdma->num_clk); if (ret < 0) goto error_get_clocks; Loading @@ -1216,13 +1226,33 @@ static int jpegdma_probe(struct platform_device *pdev) if (ret < 0) goto error_prefetch_get; ret = msm_jpegdma_hw_request_irq(pdev, jpegdma); if (ret < 0) goto error_hw_get_request_irq; /* get the irq resource */ jpegdma->irq = msm_camera_get_irq(pdev, "jpeg"); if (!jpegdma->irq) goto error_hw_get_irq; switch (pdev->id) { case 3: jpegdma->bus_client = CAM_BUS_CLIENT_JPEG_DMA; break; default: pr_err("%s: invalid cell id :%d\n", __func__, pdev->id); goto error_reg_bus; } /* register bus client */ ret = msm_camera_register_bus_client(pdev, jpegdma->bus_client); if (ret < 0) { pr_err("Fail to register bus client\n"); ret = -EINVAL; goto error_reg_bus; } ret = msm_jpegdma_hw_get_capabilities(jpegdma); if (ret < 0) goto error_hw_get_request_irq; goto error_hw_get_cap; /* mem2mem device */ jpegdma->m2m_dev = v4l2_m2m_init(&msm_jpegdma_m2m_ops); Loading Loading @@ -1267,17 +1297,21 @@ error_video_register: error_v4l2_register: v4l2_m2m_release(jpegdma->m2m_dev); error_m2m_init: msm_jpegdma_hw_release_irq(jpegdma); error_hw_get_request_irq: error_hw_get_cap: msm_camera_unregister_bus_client(jpegdma->bus_client); error_reg_bus: error_hw_get_irq: msm_jpegdma_hw_put_prefetch(jpegdma); error_prefetch_get: msm_jpegdma_hw_put_vbif(jpegdma); error_vbif_get: msm_jpegdma_hw_put_qos(jpegdma); error_qos_get: msm_jpegdma_hw_put_clocks(jpegdma); msm_camera_put_clk_info(pdev, &jpegdma->jpeg_clk_info, &jpegdma->clk, jpegdma->num_clk); error_get_clocks: msm_jpegdma_hw_put_regulators(jpegdma); msm_camera_put_regulators(pdev, &jpegdma->vdd, jpegdma->num_reg); error_get_regulators: msm_jpegdma_hw_release_mem_resources(jpegdma); error_mem_resources: Loading @@ -1301,9 +1335,14 @@ static int jpegdma_device_remove(struct platform_device *pdev) video_unregister_device(&dma->video); v4l2_device_unregister(&dma->v4l2_dev); v4l2_m2m_release(dma->m2m_dev); msm_jpegdma_hw_release_irq(dma); msm_jpegdma_hw_put_clocks(dma); msm_jpegdma_hw_put_regulators(dma); /* unregister bus client */ msm_camera_unregister_bus_client(dma->bus_client); /* release all the regulators */ msm_camera_put_regulators(dma->pdev, &dma->vdd, dma->num_reg); /* release all the clocks */ msm_camera_put_clk_info(dma->pdev, &dma->jpeg_clk_info, &dma->clk, dma->num_clk); msm_jpegdma_hw_release_mem_resources(dma); kfree(dma); Loading drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.h +10 −9 Original line number Diff line number Diff line /* Copyright (c) 2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading @@ -17,6 +17,7 @@ #include <media/v4l2-fh.h> #include <media/v4l2-ctrls.h> #include <linux/msm-bus.h> #include "cam_soc_api.h" /* Max number of clocks defined in device tree */ #define MSM_JPEGDMA_MAX_CLK 10 Loading Loading @@ -330,16 +331,15 @@ struct msm_jpegdma_device { int ref_count; int irq_num; struct resource *res_mem[MSM_JPEGDMA_IOMEM_LAST]; void __iomem *iomem_base[MSM_JPEGDMA_IOMEM_LAST]; struct resource *ioarea[MSM_JPEGDMA_IOMEM_LAST]; struct regulator *vdd[MSM_JPEGDMA_MAX_REGULATOR_NUM]; unsigned int regulator_num; struct resource *irq; struct regulator **vdd; int num_reg; unsigned int clk_num; struct clk *clk[MSM_JPEGDMA_MAX_CLK]; unsigned int clk_rates[MSM_JPEGDMA_MAX_CLK]; struct clk **clk; size_t num_clk; struct msm_cam_clk_info *jpeg_clk_info; unsigned int vbif_regs_num; struct jpegdma_reg_cfg *vbif_regs; Loading @@ -348,7 +348,7 @@ struct msm_jpegdma_device { unsigned int prefetch_regs_num; struct jpegdma_reg_cfg *prefetch_regs; uint32_t bus_client; enum cam_bus_client bus_client; struct msm_bus_vectors bus_vectors; struct msm_bus_paths bus_paths; struct msm_bus_scale_pdata bus_scale_data; Loading @@ -366,6 +366,7 @@ struct msm_jpegdma_device { struct completion hw_reset_completion; struct completion hw_halt_completion; u64 active_clock_rate; struct platform_device *pdev; }; void msm_jpegdma_isr_processing_done(struct msm_jpegdma_device *dma); Loading drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_hw.c +78 −416 Original line number Diff line number Diff line /* Copyright (c) 2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -1245,38 +1245,34 @@ error_irq: return ret; } /* * msm_jpegdma_hw_release_irq - Free dma irq. * @dma: Pointer to dma device. */ void msm_jpegdma_hw_release_irq(struct msm_jpegdma_device *dma) { if (dma->irq_num >= 0) { free_irq(dma->irq_num, dma); dma->irq_num = -1; } } /* * msm_jpegdma_hw_release_mem_resources - Releases memory resources. * @dma: Pointer to dma device. */ void msm_jpegdma_hw_release_mem_resources(struct msm_jpegdma_device *dma) { int i; int i, reserve_mem_flag; char *dev_name; /* Prepare memory resources */ for (i = 0; i < MSM_JPEGDMA_IOMEM_LAST; i++) { if (dma->iomem_base[i]) { iounmap(dma->iomem_base[i]); dma->iomem_base[i] = NULL; } if (dma->ioarea[i]) { release_mem_region(dma->res_mem[i]->start, resource_size(dma->res_mem[i])); dma->ioarea[i] = NULL; switch (i) { case MSM_JPEGDMA_IOMEM_CORE: dev_name = "jpeg_hw"; reserve_mem_flag = true; break; case MSM_JPEGDMA_IOMEM_VBIF: dev_name = "jpeg_vbif"; reserve_mem_flag = false; break; default: pr_err("%s: Invalid device : %d\n", __func__, i); return; } dma->res_mem[i] = NULL; /* release the device address */ msm_camera_put_reg_base(dma->pdev, dma->iomem_base[i], dev_name, reserve_mem_flag); } } Loading @@ -1292,32 +1288,32 @@ int msm_jpegdma_hw_get_mem_resources(struct platform_device *pdev, { int i; int ret = 0; char *dev_name; int reserve_mem_flag; /* Prepare memory resources */ for (i = 0; i < MSM_JPEGDMA_IOMEM_LAST; i++) { /* Get resources */ dma->res_mem[i] = platform_get_resource(pdev, IORESOURCE_MEM, i); if (!dma->res_mem[i]) { dev_err(dma->dev, "Fail get resource idx %d\n", i); ret = -ENODEV; break; } dma->ioarea[i] = request_mem_region(dma->res_mem[i]->start, resource_size(dma->res_mem[i]), dma->res_mem[i]->name); if (!dma->ioarea[i]) { dev_err(dma->dev, "%s can not request mem\n", dma->res_mem[i]->name); ret = -ENODEV; switch (i) { case MSM_JPEGDMA_IOMEM_CORE: dev_name = "jpeg_hw"; reserve_mem_flag = true; break; case MSM_JPEGDMA_IOMEM_VBIF: dev_name = "jpeg_vbif"; reserve_mem_flag = false; break; default: pr_err("%s: Invalid device : %d\n", __func__, i); return -EINVAL; } dma->iomem_base[i] = ioremap(dma->res_mem[i]->start, resource_size(dma->res_mem[i])); /* get the device address base */ dma->iomem_base[i] = msm_camera_get_reg_base(pdev, dev_name, reserve_mem_flag); if (!dma->iomem_base[i]) { dev_err(dma->dev, "%s can not remap region\n", dma->res_mem[i]->name); dev_name); ret = -ENODEV; break; } Loading @@ -1329,202 +1325,6 @@ int msm_jpegdma_hw_get_mem_resources(struct platform_device *pdev, return ret; } /* * msm_jpegdma_hw_get_regulators - Get jpeg dma regulators. * @dma: Pointer to dma device. * * Read regulator information from device tree and perform get regulator. */ int msm_jpegdma_hw_get_regulators(struct msm_jpegdma_device *dma) { const char *name; uint32_t cnt; int i; int ret; if (of_get_property(dma->dev->of_node, "qcom,vdd-names", NULL)) { cnt = of_property_count_strings(dma->dev->of_node, "qcom,vdd-names"); if ((cnt == 0) || (cnt == -EINVAL)) { dev_err(dma->dev, "no regulators found %d\n", cnt); return -EINVAL; } if (cnt > MSM_JPEGDMA_MAX_REGULATOR_NUM) { dev_err(dma->dev, "Exceed max regulators %d\n", cnt); return -EINVAL; } for (i = 0; i < cnt; i++) { ret = of_property_read_string_index(dma->dev->of_node, "qcom,vdd-names", i, &name); if (ret < 0) { dev_err(dma->dev, "Fail regulator idx %d\n", i); goto regulator_get_error; } dma->vdd[i] = devm_regulator_get(dma->dev, name); if (IS_ERR(dma->vdd[i])) { ret = PTR_ERR(dma->vdd[i]); dma->vdd[i] = NULL; dev_err(dma->dev, "Error regulator get %s\n", name); goto regulator_get_error; } dev_dbg(dma->dev, "Regulator %s idx %d\n", name, i); } dma->regulator_num = cnt; } else { dma->regulator_num = 1; dma->vdd[0] = devm_regulator_get(dma->dev, "vdd"); if (IS_ERR(dma->vdd[0])) { dev_err(dma->dev, "Fail to get vdd regulator\n"); ret = PTR_ERR(dma->vdd[0]); dma->vdd[0] = NULL; return ret; } } return 0; regulator_get_error: for (; i > 0; i--) { if (!IS_ERR_OR_NULL(dma->vdd[i - 1])) devm_regulator_put(dma->vdd[i - 1]); } return ret; } /* * msm_jpegdma_hw_put_regulators - Put fd regulators. * @dma: Pointer to dma device. */ void msm_jpegdma_hw_put_regulators(struct msm_jpegdma_device *dma) { int i; for (i = dma->regulator_num - 1; i >= 0; i--) { if (!IS_ERR_OR_NULL(dma->vdd[i])) devm_regulator_put(dma->vdd[i]); dma->vdd[i] = NULL; } } /* * msm_jpegdma_hw_enable_regulators - Prepare and enable fd regulators. * @dma: Pointer to dma device. */ static int msm_jpegdma_hw_enable_regulators(struct msm_jpegdma_device *dma) { int i; int ret; for (i = 0; i < dma->regulator_num; i++) { ret = regulator_enable(dma->vdd[i]); if (ret < 0) { dev_err(dma->dev, "regulator enable failed %d\n", i); regulator_put(dma->vdd[i]); goto error; } } return 0; error: for (; i > 0; i--) { if (!IS_ERR_OR_NULL(dma->vdd[i - 1])) { regulator_disable(dma->vdd[i - 1]); regulator_put(dma->vdd[i - 1]); } } return ret; } /* * msm_jpegdma_hw_disable_regulators - Disable jpeg dma regulator. * @dma: Pointer to dma device. */ static void msm_jpegdma_hw_disable_regulators(struct msm_jpegdma_device *dma) { int i; for (i = dma->regulator_num - 1; i >= 0; i--) { if (!IS_ERR_OR_NULL(dma->vdd[i])) regulator_disable(dma->vdd[i]); } } /* * msm_jpegdma_hw_get_clocks - Get dma clocks. * @dma: Pointer to dma device. * * Read clock information from device tree and perform get clock. */ int msm_jpegdma_hw_get_clocks(struct msm_jpegdma_device *dma) { const char *clk_name; size_t cnt; int i; int ret; cnt = of_property_count_strings(dma->dev->of_node, "clock-names"); if (cnt > MSM_JPEGDMA_MAX_CLK) { dev_err(dma->dev, "Exceed max number of clocks %zu\n", cnt); return -EINVAL; } for (i = 0; i < cnt; i++) { ret = of_property_read_string_index(dma->dev->of_node, "clock-names", i, &clk_name); if (ret < 0) { dev_err(dma->dev, "Can not read clock name %d\n", i); goto error; } dma->clk[i] = clk_get(dma->dev, clk_name); if (IS_ERR(dma->clk[i])) { ret = -ENOENT; dev_err(dma->dev, "Error clock get %s\n", clk_name); goto error; } dev_dbg(dma->dev, "Clock name idx %d %s\n", i, clk_name); ret = of_property_read_u32_index(dma->dev->of_node, "qcom,clock-rates", i, &dma->clk_rates[i]); if (ret < 0) { dev_err(dma->dev, "Get clock rate fail %s\n", clk_name); goto error; } dev_dbg(dma->dev, "Clock rate idx %d value %d\n", i, dma->clk_rates[i]); } dma->clk_num = cnt; return 0; error: for (; i > 0; i--) clk_put(dma->clk[i - 1]); return ret; } /* * msm_jpegdma_hw_put_clocks - Put dma clocks. * @dma: Pointer to dma device. */ int msm_jpegdma_hw_put_clocks(struct msm_jpegdma_device *dma) { int i; for (i = 0; i < dma->clk_num; i++) { if (!IS_ERR_OR_NULL(dma->clk[i])) clk_put(dma->clk[i]); dma->clk_num = 0; } return 0; } /* * msm_jpegdma_hw_get_qos - Get dma qos settings from device-tree. * @dma: Pointer to dma device. Loading Loading @@ -1713,151 +1513,6 @@ void msm_jpegdma_hw_put_prefetch(struct msm_jpegdma_device *dma) dma->prefetch_regs = NULL; } /* * msm_jpegdma_hw_set_clock_rate - Set clock rates described in device tree. * @dma: Pointer to dma device. */ static int msm_jpegdma_hw_set_clock_rate(struct msm_jpegdma_device *dma) { int ret; long clk_rate; int i; for (i = 0; i < dma->clk_num; i++) { clk_rate = clk_round_rate(dma->clk[i], dma->clk_rates[i]); if (clk_rate < 0) { dev_dbg(dma->dev, "Clk round rate fail skip %d\n", i); continue; } ret = clk_set_rate(dma->clk[i], clk_rate); if (ret < 0) { dev_err(dma->dev, "Fail clock rate %ld\n", clk_rate); return -EINVAL; } dev_dbg(dma->dev, "Clk rate %d-%ld\n", i, clk_rate); } return 0; } /* * msm_jpegdma_hw_enable_clocks - Prepare and enable dma clocks. * @dma: Pointer to dma device. */ static int msm_jpegdma_hw_enable_clocks(struct msm_jpegdma_device *dma) { int i; int ret; for (i = 0; i < dma->clk_num; i++) { ret = clk_prepare(dma->clk[i]); if (ret < 0) { dev_err(dma->dev, "clock prepare failed %d\n", i); goto error; } ret = clk_enable(dma->clk[i]); if (ret < 0) { dev_err(dma->dev, "clock enable %d\n", i); clk_unprepare(dma->clk[i]); goto error; } } return 0; error: for (; i > 0; i--) { clk_disable(dma->clk[i - 1]); clk_unprepare(dma->clk[i - 1]); } return ret; } /* * msm_jpegdma_hw_disable_clocks - Disable dma clock. * @dma: Pointer to dma device. */ static void msm_jpegdma_hw_disable_clocks(struct msm_jpegdma_device *dma) { int i; for (i = 0; i < dma->clk_num; i++) { clk_disable(dma->clk[i]); clk_unprepare(dma->clk[i]); } } /* * msm_jpegdma_hw_bus_request - Request bus for memory access. * @dma: Pointer to dma device. * @clk_idx: Clock rate index. */ static int msm_jpegdma_hw_bus_request(struct msm_jpegdma_device *dma) { int ret; dma->bus_vectors.src = MSM_BUS_MASTER_JPEG; dma->bus_vectors.dst = MSM_BUS_SLAVE_EBI_CH0; dma->bus_vectors.ab = dma->clk_rates[MSM_JPEGDMA_CORE_CLK] * 2; dma->bus_vectors.ib = dma->clk_rates[MSM_JPEGDMA_CORE_CLK] * 2; dma->bus_paths.num_paths = 1; dma->bus_paths.vectors = &dma->bus_vectors; dma->bus_scale_data.usecase = &dma->bus_paths; dma->bus_scale_data.num_usecases = 1; dma->bus_scale_data.name = MSM_JPEGDMA_BUS_CLIENT_NAME; dma->bus_client = msm_bus_scale_register_client(&dma->bus_scale_data); if (!dma->bus_client) { dev_err(dma->dev, "Fail to register bus client\n"); return -ENOENT; } ret = msm_bus_scale_client_update_request(dma->bus_client, 0); if (ret < 0) { dev_err(dma->dev, "Fail bus scale update %d\n", ret); return -EINVAL; } return 0; } /* * msm_jpegdma_hw_bus_release - Release memory access bus. * @dma: Pointer to dma device. */ static void msm_jpegdma_hw_bus_release(struct msm_jpegdma_device *dma) { if (dma->bus_client) { msm_bus_scale_unregister_client(dma->bus_client); dma->bus_client = 0; } } /* * msm_jpegdma_hw_update_bus_data - Update bus data request * @dma: Pointer to dma device. * @clk_idx: Clock rate index. */ int msm_jpegdma_hw_update_bus_data(struct msm_jpegdma_device *dma, u64 ab, u64 ib) { int ret; dma->bus_vectors.ab = ab; dma->bus_vectors.ib = ib; ret = msm_bus_scale_client_update_request(dma->bus_client, 0); if (ret < 0) { dev_err(dma->dev, "Fail bus scale update %d\n", ret); return -EINVAL; } return 0; } /* * msm_jpegdma_hw_get_capabilities - Get dma hw for performing any hw operation. * @dma: Pointer to dma device. Loading @@ -1868,34 +1523,38 @@ int msm_jpegdma_hw_get_capabilities(struct msm_jpegdma_device *dma) mutex_lock(&dma->lock); ret = msm_jpegdma_hw_enable_regulators(dma); /* enable all the regulators */ ret = msm_camera_regulator_enable(dma->vdd, dma->num_reg, true); if (ret < 0) { dev_err(dma->dev, "Fail to enable regulators\n"); goto error_regulators_get; } ret = msm_jpegdma_hw_set_clock_rate(dma); if (ret < 0) { dev_err(dma->dev, "Fail to set clock rate\n"); goto error_fail_clock; } ret = msm_jpegdma_hw_enable_clocks(dma); /* enable all the clocks */ ret = msm_camera_clk_enable(&dma->pdev->dev, dma->jpeg_clk_info, dma->clk, dma->num_clk, true); if (ret < 0) { dev_err(dma->dev, "Fail to enable clocks\n"); goto error_fail_clock; goto error_clocks; } dma->hw_num_pipes = msm_jpegdma_hw_get_num_pipes(dma); msm_jpegdma_hw_disable_clocks(dma); msm_jpegdma_hw_disable_regulators(dma); /* disable all the clocks */ msm_camera_clk_enable(&dma->pdev->dev, dma->jpeg_clk_info, dma->clk, dma->num_clk, false); /* disable all the regulators */ msm_camera_regulator_enable(dma->vdd, dma->num_reg, false); mutex_unlock(&dma->lock); return 0; error_fail_clock: msm_jpegdma_hw_disable_regulators(dma); error_clocks: msm_camera_regulator_enable(dma->vdd, dma->num_reg, false); error_regulators_get: mutex_unlock(&dma->lock); return ret; Loading @@ -1917,29 +1576,25 @@ int msm_jpegdma_hw_get(struct msm_jpegdma_device *dma) if (dma->ref_count == 0) { dev_dbg(dma->dev, "msm_jpegdma_hw_get E\n"); ret = msm_jpegdma_hw_set_clock_rate(dma); if (ret < 0) { dev_err(dma->dev, "Fail to set clock rates\n"); goto error; } ret = msm_jpegdma_hw_enable_regulators(dma); /* enable all the regulators */ ret = msm_camera_regulator_enable(dma->vdd, dma->num_reg, true); if (ret < 0) { dev_err(dma->dev, "Fail to enable regulators\n"); goto error; goto error_regulators_get; } ret = msm_jpegdma_hw_enable_clocks(dma); /* enable all the clocks */ ret = msm_camera_clk_enable(&dma->pdev->dev, dma->jpeg_clk_info, dma->clk, dma->num_clk, true); if (ret < 0) { dev_err(dma->dev, "Fail to enable clocks\n"); goto error_clocks; } ret = msm_jpegdma_hw_bus_request(dma); if (ret < 0) { dev_err(dma->dev, "Fail bus request\n"); goto error_bus_request; } /* update the bus vector with valid bw */ msm_camera_update_bus_vector(dma->bus_client, 1); msm_jpegdma_hw_config_qos(dma); msm_jpegdma_hw_config_vbif(dma); Loading @@ -1962,11 +1617,11 @@ int msm_jpegdma_hw_get(struct msm_jpegdma_device *dma) error_hw_reset: msm_jpegdma_hw_disable_irq(dma); error_bus_request: msm_jpegdma_hw_disable_clocks(dma); msm_camera_clk_enable(&dma->pdev->dev, dma->jpeg_clk_info, dma->clk, dma->num_clk, false); error_clocks: msm_jpegdma_hw_disable_regulators(dma); error: msm_camera_regulator_enable(dma->vdd, dma->num_reg, false); error_regulators_get: mutex_unlock(&dma->lock); return ret; } Loading @@ -1986,9 +1641,16 @@ void msm_jpegdma_hw_put(struct msm_jpegdma_device *dma) if (--dma->ref_count == 0) { msm_jpegdma_hw_halt(dma); msm_jpegdma_hw_disable_irq(dma); msm_jpegdma_hw_bus_release(dma); msm_jpegdma_hw_disable_clocks(dma); msm_jpegdma_hw_disable_regulators(dma); /* release the irq */ msm_camera_unregister_irq(dma->pdev, dma->irq, dma); /* update the bus vector with zeroth vector */ msm_camera_update_bus_vector(dma->bus_client, 0); /* disable all the clocks */ msm_camera_clk_enable(&dma->pdev->dev, dma->jpeg_clk_info, dma->clk, dma->num_clk, false); /* disable all the regulators */ msm_camera_regulator_enable(dma->vdd, dma->num_reg, false); } /* Reset clock rate, need to be updated on next processing */ dma->active_clock_rate = -1; Loading Loading
drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c +53 −14 Original line number Diff line number Diff line Loading @@ -14,7 +14,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/regulator/consumer.h> #include <linux/ion.h> #include <linux/msm_ion.h> #include <linux/delay.h> Loading Loading @@ -528,6 +527,8 @@ static int msm_jpegdma_release(struct file *file) { struct jpegdma_ctx *ctx = msm_jpegdma_ctx_from_fh(file->private_data); /* release all the resources */ msm_jpegdma_hw_put(ctx->jdma_device); atomic_set(&ctx->active, 0); complete_all(&ctx->completion); v4l2_m2m_ctx_release(ctx->m2m_ctx); Loading Loading @@ -1190,17 +1191,26 @@ static int jpegdma_probe(struct platform_device *pdev) init_completion(&jpegdma->hw_reset_completion); init_completion(&jpegdma->hw_halt_completion); jpegdma->dev = &pdev->dev; jpegdma->pdev = pdev; if (pdev->dev.of_node) of_property_read_u32((&pdev->dev)->of_node, "cell-index", &pdev->id); /* Get resources */ ret = msm_jpegdma_hw_get_mem_resources(pdev, jpegdma); if (ret < 0) goto error_mem_resources; ret = msm_jpegdma_hw_get_regulators(jpegdma); /* get all the regulators */ ret = msm_camera_get_regulator_info(pdev, &jpegdma->vdd, &jpegdma->num_reg); if (ret < 0) goto error_get_regulators; ret = msm_jpegdma_hw_get_clocks(jpegdma); /* get all the clocks */ ret = msm_camera_get_clk_info(pdev, &jpegdma->jpeg_clk_info, &jpegdma->clk, &jpegdma->num_clk); if (ret < 0) goto error_get_clocks; Loading @@ -1216,13 +1226,33 @@ static int jpegdma_probe(struct platform_device *pdev) if (ret < 0) goto error_prefetch_get; ret = msm_jpegdma_hw_request_irq(pdev, jpegdma); if (ret < 0) goto error_hw_get_request_irq; /* get the irq resource */ jpegdma->irq = msm_camera_get_irq(pdev, "jpeg"); if (!jpegdma->irq) goto error_hw_get_irq; switch (pdev->id) { case 3: jpegdma->bus_client = CAM_BUS_CLIENT_JPEG_DMA; break; default: pr_err("%s: invalid cell id :%d\n", __func__, pdev->id); goto error_reg_bus; } /* register bus client */ ret = msm_camera_register_bus_client(pdev, jpegdma->bus_client); if (ret < 0) { pr_err("Fail to register bus client\n"); ret = -EINVAL; goto error_reg_bus; } ret = msm_jpegdma_hw_get_capabilities(jpegdma); if (ret < 0) goto error_hw_get_request_irq; goto error_hw_get_cap; /* mem2mem device */ jpegdma->m2m_dev = v4l2_m2m_init(&msm_jpegdma_m2m_ops); Loading Loading @@ -1267,17 +1297,21 @@ error_video_register: error_v4l2_register: v4l2_m2m_release(jpegdma->m2m_dev); error_m2m_init: msm_jpegdma_hw_release_irq(jpegdma); error_hw_get_request_irq: error_hw_get_cap: msm_camera_unregister_bus_client(jpegdma->bus_client); error_reg_bus: error_hw_get_irq: msm_jpegdma_hw_put_prefetch(jpegdma); error_prefetch_get: msm_jpegdma_hw_put_vbif(jpegdma); error_vbif_get: msm_jpegdma_hw_put_qos(jpegdma); error_qos_get: msm_jpegdma_hw_put_clocks(jpegdma); msm_camera_put_clk_info(pdev, &jpegdma->jpeg_clk_info, &jpegdma->clk, jpegdma->num_clk); error_get_clocks: msm_jpegdma_hw_put_regulators(jpegdma); msm_camera_put_regulators(pdev, &jpegdma->vdd, jpegdma->num_reg); error_get_regulators: msm_jpegdma_hw_release_mem_resources(jpegdma); error_mem_resources: Loading @@ -1301,9 +1335,14 @@ static int jpegdma_device_remove(struct platform_device *pdev) video_unregister_device(&dma->video); v4l2_device_unregister(&dma->v4l2_dev); v4l2_m2m_release(dma->m2m_dev); msm_jpegdma_hw_release_irq(dma); msm_jpegdma_hw_put_clocks(dma); msm_jpegdma_hw_put_regulators(dma); /* unregister bus client */ msm_camera_unregister_bus_client(dma->bus_client); /* release all the regulators */ msm_camera_put_regulators(dma->pdev, &dma->vdd, dma->num_reg); /* release all the clocks */ msm_camera_put_clk_info(dma->pdev, &dma->jpeg_clk_info, &dma->clk, dma->num_clk); msm_jpegdma_hw_release_mem_resources(dma); kfree(dma); Loading
drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.h +10 −9 Original line number Diff line number Diff line /* Copyright (c) 2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading @@ -17,6 +17,7 @@ #include <media/v4l2-fh.h> #include <media/v4l2-ctrls.h> #include <linux/msm-bus.h> #include "cam_soc_api.h" /* Max number of clocks defined in device tree */ #define MSM_JPEGDMA_MAX_CLK 10 Loading Loading @@ -330,16 +331,15 @@ struct msm_jpegdma_device { int ref_count; int irq_num; struct resource *res_mem[MSM_JPEGDMA_IOMEM_LAST]; void __iomem *iomem_base[MSM_JPEGDMA_IOMEM_LAST]; struct resource *ioarea[MSM_JPEGDMA_IOMEM_LAST]; struct regulator *vdd[MSM_JPEGDMA_MAX_REGULATOR_NUM]; unsigned int regulator_num; struct resource *irq; struct regulator **vdd; int num_reg; unsigned int clk_num; struct clk *clk[MSM_JPEGDMA_MAX_CLK]; unsigned int clk_rates[MSM_JPEGDMA_MAX_CLK]; struct clk **clk; size_t num_clk; struct msm_cam_clk_info *jpeg_clk_info; unsigned int vbif_regs_num; struct jpegdma_reg_cfg *vbif_regs; Loading @@ -348,7 +348,7 @@ struct msm_jpegdma_device { unsigned int prefetch_regs_num; struct jpegdma_reg_cfg *prefetch_regs; uint32_t bus_client; enum cam_bus_client bus_client; struct msm_bus_vectors bus_vectors; struct msm_bus_paths bus_paths; struct msm_bus_scale_pdata bus_scale_data; Loading @@ -366,6 +366,7 @@ struct msm_jpegdma_device { struct completion hw_reset_completion; struct completion hw_halt_completion; u64 active_clock_rate; struct platform_device *pdev; }; void msm_jpegdma_isr_processing_done(struct msm_jpegdma_device *dma); Loading
drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_hw.c +78 −416 Original line number Diff line number Diff line /* Copyright (c) 2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -1245,38 +1245,34 @@ error_irq: return ret; } /* * msm_jpegdma_hw_release_irq - Free dma irq. * @dma: Pointer to dma device. */ void msm_jpegdma_hw_release_irq(struct msm_jpegdma_device *dma) { if (dma->irq_num >= 0) { free_irq(dma->irq_num, dma); dma->irq_num = -1; } } /* * msm_jpegdma_hw_release_mem_resources - Releases memory resources. * @dma: Pointer to dma device. */ void msm_jpegdma_hw_release_mem_resources(struct msm_jpegdma_device *dma) { int i; int i, reserve_mem_flag; char *dev_name; /* Prepare memory resources */ for (i = 0; i < MSM_JPEGDMA_IOMEM_LAST; i++) { if (dma->iomem_base[i]) { iounmap(dma->iomem_base[i]); dma->iomem_base[i] = NULL; } if (dma->ioarea[i]) { release_mem_region(dma->res_mem[i]->start, resource_size(dma->res_mem[i])); dma->ioarea[i] = NULL; switch (i) { case MSM_JPEGDMA_IOMEM_CORE: dev_name = "jpeg_hw"; reserve_mem_flag = true; break; case MSM_JPEGDMA_IOMEM_VBIF: dev_name = "jpeg_vbif"; reserve_mem_flag = false; break; default: pr_err("%s: Invalid device : %d\n", __func__, i); return; } dma->res_mem[i] = NULL; /* release the device address */ msm_camera_put_reg_base(dma->pdev, dma->iomem_base[i], dev_name, reserve_mem_flag); } } Loading @@ -1292,32 +1288,32 @@ int msm_jpegdma_hw_get_mem_resources(struct platform_device *pdev, { int i; int ret = 0; char *dev_name; int reserve_mem_flag; /* Prepare memory resources */ for (i = 0; i < MSM_JPEGDMA_IOMEM_LAST; i++) { /* Get resources */ dma->res_mem[i] = platform_get_resource(pdev, IORESOURCE_MEM, i); if (!dma->res_mem[i]) { dev_err(dma->dev, "Fail get resource idx %d\n", i); ret = -ENODEV; break; } dma->ioarea[i] = request_mem_region(dma->res_mem[i]->start, resource_size(dma->res_mem[i]), dma->res_mem[i]->name); if (!dma->ioarea[i]) { dev_err(dma->dev, "%s can not request mem\n", dma->res_mem[i]->name); ret = -ENODEV; switch (i) { case MSM_JPEGDMA_IOMEM_CORE: dev_name = "jpeg_hw"; reserve_mem_flag = true; break; case MSM_JPEGDMA_IOMEM_VBIF: dev_name = "jpeg_vbif"; reserve_mem_flag = false; break; default: pr_err("%s: Invalid device : %d\n", __func__, i); return -EINVAL; } dma->iomem_base[i] = ioremap(dma->res_mem[i]->start, resource_size(dma->res_mem[i])); /* get the device address base */ dma->iomem_base[i] = msm_camera_get_reg_base(pdev, dev_name, reserve_mem_flag); if (!dma->iomem_base[i]) { dev_err(dma->dev, "%s can not remap region\n", dma->res_mem[i]->name); dev_name); ret = -ENODEV; break; } Loading @@ -1329,202 +1325,6 @@ int msm_jpegdma_hw_get_mem_resources(struct platform_device *pdev, return ret; } /* * msm_jpegdma_hw_get_regulators - Get jpeg dma regulators. * @dma: Pointer to dma device. * * Read regulator information from device tree and perform get regulator. */ int msm_jpegdma_hw_get_regulators(struct msm_jpegdma_device *dma) { const char *name; uint32_t cnt; int i; int ret; if (of_get_property(dma->dev->of_node, "qcom,vdd-names", NULL)) { cnt = of_property_count_strings(dma->dev->of_node, "qcom,vdd-names"); if ((cnt == 0) || (cnt == -EINVAL)) { dev_err(dma->dev, "no regulators found %d\n", cnt); return -EINVAL; } if (cnt > MSM_JPEGDMA_MAX_REGULATOR_NUM) { dev_err(dma->dev, "Exceed max regulators %d\n", cnt); return -EINVAL; } for (i = 0; i < cnt; i++) { ret = of_property_read_string_index(dma->dev->of_node, "qcom,vdd-names", i, &name); if (ret < 0) { dev_err(dma->dev, "Fail regulator idx %d\n", i); goto regulator_get_error; } dma->vdd[i] = devm_regulator_get(dma->dev, name); if (IS_ERR(dma->vdd[i])) { ret = PTR_ERR(dma->vdd[i]); dma->vdd[i] = NULL; dev_err(dma->dev, "Error regulator get %s\n", name); goto regulator_get_error; } dev_dbg(dma->dev, "Regulator %s idx %d\n", name, i); } dma->regulator_num = cnt; } else { dma->regulator_num = 1; dma->vdd[0] = devm_regulator_get(dma->dev, "vdd"); if (IS_ERR(dma->vdd[0])) { dev_err(dma->dev, "Fail to get vdd regulator\n"); ret = PTR_ERR(dma->vdd[0]); dma->vdd[0] = NULL; return ret; } } return 0; regulator_get_error: for (; i > 0; i--) { if (!IS_ERR_OR_NULL(dma->vdd[i - 1])) devm_regulator_put(dma->vdd[i - 1]); } return ret; } /* * msm_jpegdma_hw_put_regulators - Put fd regulators. * @dma: Pointer to dma device. */ void msm_jpegdma_hw_put_regulators(struct msm_jpegdma_device *dma) { int i; for (i = dma->regulator_num - 1; i >= 0; i--) { if (!IS_ERR_OR_NULL(dma->vdd[i])) devm_regulator_put(dma->vdd[i]); dma->vdd[i] = NULL; } } /* * msm_jpegdma_hw_enable_regulators - Prepare and enable fd regulators. * @dma: Pointer to dma device. */ static int msm_jpegdma_hw_enable_regulators(struct msm_jpegdma_device *dma) { int i; int ret; for (i = 0; i < dma->regulator_num; i++) { ret = regulator_enable(dma->vdd[i]); if (ret < 0) { dev_err(dma->dev, "regulator enable failed %d\n", i); regulator_put(dma->vdd[i]); goto error; } } return 0; error: for (; i > 0; i--) { if (!IS_ERR_OR_NULL(dma->vdd[i - 1])) { regulator_disable(dma->vdd[i - 1]); regulator_put(dma->vdd[i - 1]); } } return ret; } /* * msm_jpegdma_hw_disable_regulators - Disable jpeg dma regulator. * @dma: Pointer to dma device. */ static void msm_jpegdma_hw_disable_regulators(struct msm_jpegdma_device *dma) { int i; for (i = dma->regulator_num - 1; i >= 0; i--) { if (!IS_ERR_OR_NULL(dma->vdd[i])) regulator_disable(dma->vdd[i]); } } /* * msm_jpegdma_hw_get_clocks - Get dma clocks. * @dma: Pointer to dma device. * * Read clock information from device tree and perform get clock. */ int msm_jpegdma_hw_get_clocks(struct msm_jpegdma_device *dma) { const char *clk_name; size_t cnt; int i; int ret; cnt = of_property_count_strings(dma->dev->of_node, "clock-names"); if (cnt > MSM_JPEGDMA_MAX_CLK) { dev_err(dma->dev, "Exceed max number of clocks %zu\n", cnt); return -EINVAL; } for (i = 0; i < cnt; i++) { ret = of_property_read_string_index(dma->dev->of_node, "clock-names", i, &clk_name); if (ret < 0) { dev_err(dma->dev, "Can not read clock name %d\n", i); goto error; } dma->clk[i] = clk_get(dma->dev, clk_name); if (IS_ERR(dma->clk[i])) { ret = -ENOENT; dev_err(dma->dev, "Error clock get %s\n", clk_name); goto error; } dev_dbg(dma->dev, "Clock name idx %d %s\n", i, clk_name); ret = of_property_read_u32_index(dma->dev->of_node, "qcom,clock-rates", i, &dma->clk_rates[i]); if (ret < 0) { dev_err(dma->dev, "Get clock rate fail %s\n", clk_name); goto error; } dev_dbg(dma->dev, "Clock rate idx %d value %d\n", i, dma->clk_rates[i]); } dma->clk_num = cnt; return 0; error: for (; i > 0; i--) clk_put(dma->clk[i - 1]); return ret; } /* * msm_jpegdma_hw_put_clocks - Put dma clocks. * @dma: Pointer to dma device. */ int msm_jpegdma_hw_put_clocks(struct msm_jpegdma_device *dma) { int i; for (i = 0; i < dma->clk_num; i++) { if (!IS_ERR_OR_NULL(dma->clk[i])) clk_put(dma->clk[i]); dma->clk_num = 0; } return 0; } /* * msm_jpegdma_hw_get_qos - Get dma qos settings from device-tree. * @dma: Pointer to dma device. Loading Loading @@ -1713,151 +1513,6 @@ void msm_jpegdma_hw_put_prefetch(struct msm_jpegdma_device *dma) dma->prefetch_regs = NULL; } /* * msm_jpegdma_hw_set_clock_rate - Set clock rates described in device tree. * @dma: Pointer to dma device. */ static int msm_jpegdma_hw_set_clock_rate(struct msm_jpegdma_device *dma) { int ret; long clk_rate; int i; for (i = 0; i < dma->clk_num; i++) { clk_rate = clk_round_rate(dma->clk[i], dma->clk_rates[i]); if (clk_rate < 0) { dev_dbg(dma->dev, "Clk round rate fail skip %d\n", i); continue; } ret = clk_set_rate(dma->clk[i], clk_rate); if (ret < 0) { dev_err(dma->dev, "Fail clock rate %ld\n", clk_rate); return -EINVAL; } dev_dbg(dma->dev, "Clk rate %d-%ld\n", i, clk_rate); } return 0; } /* * msm_jpegdma_hw_enable_clocks - Prepare and enable dma clocks. * @dma: Pointer to dma device. */ static int msm_jpegdma_hw_enable_clocks(struct msm_jpegdma_device *dma) { int i; int ret; for (i = 0; i < dma->clk_num; i++) { ret = clk_prepare(dma->clk[i]); if (ret < 0) { dev_err(dma->dev, "clock prepare failed %d\n", i); goto error; } ret = clk_enable(dma->clk[i]); if (ret < 0) { dev_err(dma->dev, "clock enable %d\n", i); clk_unprepare(dma->clk[i]); goto error; } } return 0; error: for (; i > 0; i--) { clk_disable(dma->clk[i - 1]); clk_unprepare(dma->clk[i - 1]); } return ret; } /* * msm_jpegdma_hw_disable_clocks - Disable dma clock. * @dma: Pointer to dma device. */ static void msm_jpegdma_hw_disable_clocks(struct msm_jpegdma_device *dma) { int i; for (i = 0; i < dma->clk_num; i++) { clk_disable(dma->clk[i]); clk_unprepare(dma->clk[i]); } } /* * msm_jpegdma_hw_bus_request - Request bus for memory access. * @dma: Pointer to dma device. * @clk_idx: Clock rate index. */ static int msm_jpegdma_hw_bus_request(struct msm_jpegdma_device *dma) { int ret; dma->bus_vectors.src = MSM_BUS_MASTER_JPEG; dma->bus_vectors.dst = MSM_BUS_SLAVE_EBI_CH0; dma->bus_vectors.ab = dma->clk_rates[MSM_JPEGDMA_CORE_CLK] * 2; dma->bus_vectors.ib = dma->clk_rates[MSM_JPEGDMA_CORE_CLK] * 2; dma->bus_paths.num_paths = 1; dma->bus_paths.vectors = &dma->bus_vectors; dma->bus_scale_data.usecase = &dma->bus_paths; dma->bus_scale_data.num_usecases = 1; dma->bus_scale_data.name = MSM_JPEGDMA_BUS_CLIENT_NAME; dma->bus_client = msm_bus_scale_register_client(&dma->bus_scale_data); if (!dma->bus_client) { dev_err(dma->dev, "Fail to register bus client\n"); return -ENOENT; } ret = msm_bus_scale_client_update_request(dma->bus_client, 0); if (ret < 0) { dev_err(dma->dev, "Fail bus scale update %d\n", ret); return -EINVAL; } return 0; } /* * msm_jpegdma_hw_bus_release - Release memory access bus. * @dma: Pointer to dma device. */ static void msm_jpegdma_hw_bus_release(struct msm_jpegdma_device *dma) { if (dma->bus_client) { msm_bus_scale_unregister_client(dma->bus_client); dma->bus_client = 0; } } /* * msm_jpegdma_hw_update_bus_data - Update bus data request * @dma: Pointer to dma device. * @clk_idx: Clock rate index. */ int msm_jpegdma_hw_update_bus_data(struct msm_jpegdma_device *dma, u64 ab, u64 ib) { int ret; dma->bus_vectors.ab = ab; dma->bus_vectors.ib = ib; ret = msm_bus_scale_client_update_request(dma->bus_client, 0); if (ret < 0) { dev_err(dma->dev, "Fail bus scale update %d\n", ret); return -EINVAL; } return 0; } /* * msm_jpegdma_hw_get_capabilities - Get dma hw for performing any hw operation. * @dma: Pointer to dma device. Loading @@ -1868,34 +1523,38 @@ int msm_jpegdma_hw_get_capabilities(struct msm_jpegdma_device *dma) mutex_lock(&dma->lock); ret = msm_jpegdma_hw_enable_regulators(dma); /* enable all the regulators */ ret = msm_camera_regulator_enable(dma->vdd, dma->num_reg, true); if (ret < 0) { dev_err(dma->dev, "Fail to enable regulators\n"); goto error_regulators_get; } ret = msm_jpegdma_hw_set_clock_rate(dma); if (ret < 0) { dev_err(dma->dev, "Fail to set clock rate\n"); goto error_fail_clock; } ret = msm_jpegdma_hw_enable_clocks(dma); /* enable all the clocks */ ret = msm_camera_clk_enable(&dma->pdev->dev, dma->jpeg_clk_info, dma->clk, dma->num_clk, true); if (ret < 0) { dev_err(dma->dev, "Fail to enable clocks\n"); goto error_fail_clock; goto error_clocks; } dma->hw_num_pipes = msm_jpegdma_hw_get_num_pipes(dma); msm_jpegdma_hw_disable_clocks(dma); msm_jpegdma_hw_disable_regulators(dma); /* disable all the clocks */ msm_camera_clk_enable(&dma->pdev->dev, dma->jpeg_clk_info, dma->clk, dma->num_clk, false); /* disable all the regulators */ msm_camera_regulator_enable(dma->vdd, dma->num_reg, false); mutex_unlock(&dma->lock); return 0; error_fail_clock: msm_jpegdma_hw_disable_regulators(dma); error_clocks: msm_camera_regulator_enable(dma->vdd, dma->num_reg, false); error_regulators_get: mutex_unlock(&dma->lock); return ret; Loading @@ -1917,29 +1576,25 @@ int msm_jpegdma_hw_get(struct msm_jpegdma_device *dma) if (dma->ref_count == 0) { dev_dbg(dma->dev, "msm_jpegdma_hw_get E\n"); ret = msm_jpegdma_hw_set_clock_rate(dma); if (ret < 0) { dev_err(dma->dev, "Fail to set clock rates\n"); goto error; } ret = msm_jpegdma_hw_enable_regulators(dma); /* enable all the regulators */ ret = msm_camera_regulator_enable(dma->vdd, dma->num_reg, true); if (ret < 0) { dev_err(dma->dev, "Fail to enable regulators\n"); goto error; goto error_regulators_get; } ret = msm_jpegdma_hw_enable_clocks(dma); /* enable all the clocks */ ret = msm_camera_clk_enable(&dma->pdev->dev, dma->jpeg_clk_info, dma->clk, dma->num_clk, true); if (ret < 0) { dev_err(dma->dev, "Fail to enable clocks\n"); goto error_clocks; } ret = msm_jpegdma_hw_bus_request(dma); if (ret < 0) { dev_err(dma->dev, "Fail bus request\n"); goto error_bus_request; } /* update the bus vector with valid bw */ msm_camera_update_bus_vector(dma->bus_client, 1); msm_jpegdma_hw_config_qos(dma); msm_jpegdma_hw_config_vbif(dma); Loading @@ -1962,11 +1617,11 @@ int msm_jpegdma_hw_get(struct msm_jpegdma_device *dma) error_hw_reset: msm_jpegdma_hw_disable_irq(dma); error_bus_request: msm_jpegdma_hw_disable_clocks(dma); msm_camera_clk_enable(&dma->pdev->dev, dma->jpeg_clk_info, dma->clk, dma->num_clk, false); error_clocks: msm_jpegdma_hw_disable_regulators(dma); error: msm_camera_regulator_enable(dma->vdd, dma->num_reg, false); error_regulators_get: mutex_unlock(&dma->lock); return ret; } Loading @@ -1986,9 +1641,16 @@ void msm_jpegdma_hw_put(struct msm_jpegdma_device *dma) if (--dma->ref_count == 0) { msm_jpegdma_hw_halt(dma); msm_jpegdma_hw_disable_irq(dma); msm_jpegdma_hw_bus_release(dma); msm_jpegdma_hw_disable_clocks(dma); msm_jpegdma_hw_disable_regulators(dma); /* release the irq */ msm_camera_unregister_irq(dma->pdev, dma->irq, dma); /* update the bus vector with zeroth vector */ msm_camera_update_bus_vector(dma->bus_client, 0); /* disable all the clocks */ msm_camera_clk_enable(&dma->pdev->dev, dma->jpeg_clk_info, dma->clk, dma->num_clk, false); /* disable all the regulators */ msm_camera_regulator_enable(dma->vdd, dma->num_reg, false); } /* Reset clock rate, need to be updated on next processing */ dma->active_clock_rate = -1; Loading