aboutsummaryrefslogtreecommitdiff
path: root/camera/jpeg_10/msm_jpeg_platform.c
diff options
context:
space:
mode:
Diffstat (limited to 'camera/jpeg_10/msm_jpeg_platform.c')
-rw-r--r--camera/jpeg_10/msm_jpeg_platform.c515
1 files changed, 515 insertions, 0 deletions
diff --git a/camera/jpeg_10/msm_jpeg_platform.c b/camera/jpeg_10/msm_jpeg_platform.c
new file mode 100644
index 00000000..e076d356
--- /dev/null
+++ b/camera/jpeg_10/msm_jpeg_platform.c
@@ -0,0 +1,515 @@
+/* Copyright (c) 2012-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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+
+
+#include <linux/module.h>
+#include <linux/pm_qos.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/clk/msm-clk.h>
+#include <linux/msm-bus.h>
+#include <linux/msm-bus-board.h>
+#include <linux/iommu.h>
+#include <asm/dma-iommu.h>
+#include <linux/dma-direction.h>
+#include <linux/dma-attrs.h>
+#include <linux/dma-buf.h>
+
+#include "msm_camera_io_util.h"
+#include "msm_jpeg_platform.h"
+#include "msm_jpeg_sync.h"
+#include "msm_jpeg_common.h"
+#include "msm_jpeg_hw.h"
+
+#define JPEG_DT_PROP_CNT 2
+
+
+int msm_jpeg_get_clock_index(struct msm_jpeg_device *pgmn_dev,
+ const char *clk_name)
+{
+ uint32_t i = 0;
+
+ for (i = 0; i < pgmn_dev->num_clk; i++) {
+ if (!strcmp(clk_name, pgmn_dev->jpeg_clk_info[i].clk_name))
+ return i;
+ }
+ return -EINVAL;
+}
+
+int msm_jpeg_platform_set_clk_rate(struct msm_jpeg_device *pgmn_dev,
+ long clk_rate)
+{
+ int rc = 0;
+ uint32_t msm_jpeg_idx;
+
+ /* retrieve clock index from list of clocks */
+ msm_jpeg_idx = msm_jpeg_get_clock_index(pgmn_dev,
+ "core_clk");
+ if (msm_jpeg_idx < 0) {
+ JPEG_PR_ERR("%s:Fail to get clock index\n", __func__);
+ return -EINVAL;
+ }
+
+ /* set the rate */
+ msm_camera_clk_set_rate(&pgmn_dev->pdev->dev,
+ pgmn_dev->jpeg_clk[msm_jpeg_idx], clk_rate);
+
+ return rc;
+}
+
+void msm_jpeg_platform_p2v(int iommu_hdl, int fd)
+{
+ cam_smmu_put_phy_addr(iommu_hdl, fd);
+ return;
+}
+
+uint32_t msm_jpeg_platform_v2p(struct msm_jpeg_device *pgmn_dev, int fd,
+ uint32_t len, int iommu_hdl)
+{
+ dma_addr_t paddr;
+ size_t size;
+ int rc;
+
+ rc = cam_smmu_get_phy_addr(pgmn_dev->iommu_hdl, fd, CAM_SMMU_MAP_RW,
+ &paddr, &size);
+ JPEG_DBG("%s:%d] addr 0x%x size %zu", __func__, __LINE__,
+ (uint32_t)paddr, size);
+
+ if (rc < 0) {
+ JPEG_PR_ERR("%s: fd %d got phy addr error %d\n", __func__, fd,
+ rc);
+ goto err_get_phy;
+ }
+
+ /* validate user input */
+ if (len > size) {
+ JPEG_PR_ERR("%s: invalid offset + len\n", __func__);
+ goto err_size;
+ }
+
+ return paddr;
+err_size:
+ cam_smmu_put_phy_addr(pgmn_dev->iommu_hdl, fd);
+err_get_phy:
+ return 0;
+}
+
+static void set_vbif_params(struct msm_jpeg_device *pgmn_dev,
+ void *jpeg_vbif_base)
+{
+ msm_camera_io_w(0x1,
+ jpeg_vbif_base + JPEG_VBIF_CLKON);
+
+ if (pgmn_dev->hw_version != JPEG_8994) {
+ msm_camera_io_w(0x10101010,
+ jpeg_vbif_base + JPEG_VBIF_IN_RD_LIM_CONF0);
+ msm_camera_io_w(0x10101010,
+ jpeg_vbif_base + JPEG_VBIF_IN_RD_LIM_CONF1);
+ msm_camera_io_w(0x10101010,
+ jpeg_vbif_base + JPEG_VBIF_IN_RD_LIM_CONF2);
+ msm_camera_io_w(0x10101010,
+ jpeg_vbif_base + JPEG_VBIF_IN_WR_LIM_CONF0);
+ msm_camera_io_w(0x10101010,
+ jpeg_vbif_base + JPEG_VBIF_IN_WR_LIM_CONF1);
+ msm_camera_io_w(0x10101010,
+ jpeg_vbif_base + JPEG_VBIF_IN_WR_LIM_CONF2);
+ msm_camera_io_w(0x00001010,
+ jpeg_vbif_base + JPEG_VBIF_OUT_RD_LIM_CONF0);
+ msm_camera_io_w(0x00000110,
+ jpeg_vbif_base + JPEG_VBIF_OUT_WR_LIM_CONF0);
+ msm_camera_io_w(0x00000707,
+ jpeg_vbif_base + JPEG_VBIF_DDR_OUT_MAX_BURST);
+ msm_camera_io_w(0x00000FFF,
+ jpeg_vbif_base + JPEG_VBIF_OUT_AXI_AOOO_EN);
+ msm_camera_io_w(0x0FFF0FFF,
+ jpeg_vbif_base + JPEG_VBIF_OUT_AXI_AOOO);
+ msm_camera_io_w(0x2222,
+ jpeg_vbif_base + JPEG_VBIF_OUT_AXI_AMEMTYPE_CONF1);
+ }
+
+ msm_camera_io_w(0x7,
+ jpeg_vbif_base + JPEG_VBIF_OCMEM_OUT_MAX_BURST);
+ msm_camera_io_w(0x00000030,
+ jpeg_vbif_base + JPEG_VBIF_ARB_CTL);
+
+ /*FE and WE QOS configuration need to be set when
+ QOS RR arbitration is enabled*/
+ if (pgmn_dev->hw_version != JPEG_8974_V1)
+ msm_camera_io_w(0x00000003,
+ jpeg_vbif_base + JPEG_VBIF_ROUND_ROBIN_QOS_ARB);
+ else
+ msm_camera_io_w(0x00000001,
+ jpeg_vbif_base + JPEG_VBIF_ROUND_ROBIN_QOS_ARB);
+
+ msm_camera_io_w(0x22222222,
+ jpeg_vbif_base + JPEG_VBIF_OUT_AXI_AMEMTYPE_CONF0);
+
+}
+
+/*
+ * msm_jpeg_set_init_dt_parms() - get device tree config and write to registers.
+ * @pgmn_dev: Pointer to jpeg device.
+ * @dt_prop_name: Device tree property name.
+ * @base: Base address.
+ *
+ * This function reads register offsets and values from dtsi based on
+ * device tree property name and writes to jpeg registers.
+ *
+ * Return: 0 on success and negative error on failure.
+ */
+static int32_t msm_jpeg_set_init_dt_parms(struct msm_jpeg_device *pgmn_dev,
+ const char *dt_prop_name,
+ void *base)
+{
+ struct device_node *of_node;
+ int32_t i = 0 , rc = 0;
+ uint32_t *dt_reg_settings = NULL;
+ uint32_t dt_count = 0;
+
+ of_node = pgmn_dev->pdev->dev.of_node;
+ JPEG_DBG("%s:%d E\n", __func__, __LINE__);
+
+ if (!of_get_property(of_node, dt_prop_name,
+ &dt_count)) {
+ JPEG_DBG("%s: Error property does not exist\n",
+ __func__);
+ return -ENOENT;
+ }
+ if (dt_count % 8) {
+ JPEG_PR_ERR("%s: Error invalid entries\n",
+ __func__);
+ return -EINVAL;
+ }
+ dt_count /= 4;
+ if (dt_count != 0) {
+ dt_reg_settings = kcalloc(dt_count, sizeof(uint32_t),
+ GFP_KERNEL);
+ if (!dt_reg_settings) {
+ JPEG_PR_ERR("%s:%d No memory\n",
+ __func__, __LINE__);
+ return -ENOMEM;
+ }
+ rc = of_property_read_u32_array(of_node,
+ dt_prop_name,
+ dt_reg_settings,
+ dt_count);
+ if (rc < 0) {
+ JPEG_PR_ERR("%s: No reg info\n",
+ __func__);
+ kfree(dt_reg_settings);
+ return -EINVAL;
+ }
+ for (i = 0; i < dt_count; i = i + 2) {
+ JPEG_DBG("%s:%d] %p %08x\n",
+ __func__, __LINE__,
+ base + dt_reg_settings[i],
+ dt_reg_settings[i + 1]);
+ msm_camera_io_w(dt_reg_settings[i + 1],
+ base + dt_reg_settings[i]);
+ }
+ kfree(dt_reg_settings);
+ }
+ return 0;
+}
+
+static int msm_jpeg_attach_iommu(struct msm_jpeg_device *pgmn_dev)
+{
+ int rc;
+ rc = cam_smmu_ops(pgmn_dev->iommu_hdl, CAM_SMMU_ATTACH);
+ if (rc < 0) {
+ JPEG_PR_ERR("%s: Device attach failed\n", __func__);
+ return -ENODEV;
+ }
+ JPEG_DBG("%s:%d] handle %d attach\n",
+ __func__, __LINE__, pgmn_dev->iommu_hdl);
+ return 0;
+}
+
+static int msm_jpeg_detach_iommu(struct msm_jpeg_device *pgmn_dev)
+{
+ JPEG_DBG("%s:%d] handle %d detach\n",
+ __func__, __LINE__, pgmn_dev->iommu_hdl);
+ cam_smmu_ops(pgmn_dev->iommu_hdl, CAM_SMMU_DETACH);
+ return 0;
+}
+
+
+int msm_jpeg_platform_init(irqreturn_t (*handler)(int, void *),
+ void *context)
+{
+ int rc = -1;
+ struct msm_jpeg_device *pgmn_dev =
+ (struct msm_jpeg_device *) context;
+ struct platform_device *pdev = pgmn_dev->pdev;
+
+ pgmn_dev->state = MSM_JPEG_IDLE;
+
+ /* enable all regulators */
+ rc = msm_camera_regulator_enable(pgmn_dev->jpeg_vdd,
+ pgmn_dev->num_reg, true);
+ if (rc < 0) {
+ JPEG_PR_ERR("%s: failed to enable regulators\n", __func__);
+ goto err_reg_enable;
+ }
+
+ /* enable all clocks */
+ rc = msm_camera_clk_enable(&pgmn_dev->pdev->dev,
+ pgmn_dev->jpeg_clk_info, pgmn_dev->jpeg_clk,
+ pgmn_dev->num_clk, true);
+ if (rc < 0) {
+ JPEG_PR_ERR("%s: clk enable failed\n", __func__);
+ goto err_clk_enable;
+ }
+
+ /* attach the smmu context banks */
+ rc = msm_jpeg_attach_iommu(pgmn_dev);
+ if (rc < 0) {
+ JPEG_PR_ERR("%s: iommu attach failed\n", __func__);
+ goto err_fail_iommu;
+ }
+ rc = msm_jpeg_set_init_dt_parms(pgmn_dev, "qcom,vbif-reg-settings",
+ pgmn_dev->vbif_base);
+ if (rc == -ENOENT) {
+ JPEG_DBG("%s: No qcom,vbif-reg-settings property\n", __func__);
+ set_vbif_params(pgmn_dev, pgmn_dev->vbif_base);
+ } else if (rc < 0) {
+ JPEG_PR_ERR("%s: vbif params set fail\n", __func__);
+ goto err_fail_set_vbif;
+ }
+
+ /* register the interrupt handler */
+ rc = msm_camera_register_irq(pgmn_dev->pdev,
+ pgmn_dev->jpeg_irq_res, handler, IRQF_TRIGGER_RISING,
+ "jpeg", context);
+ if (rc < 0) {
+ JPEG_PR_ERR("%s: irq request fail\n", __func__);
+ goto err_reg_irq_fail;
+ }
+
+ pgmn_dev->hw_version = msm_camera_io_r(pgmn_dev->base +
+ JPEG_HW_VERSION);
+ JPEG_DBG_HIGH("%s:%d] jpeg HW version 0x%x", __func__, __LINE__,
+ pgmn_dev->hw_version);
+ pgmn_dev->state = MSM_JPEG_INIT;
+
+ return 0;
+err_reg_irq_fail:
+err_fail_set_vbif:
+ msm_jpeg_detach_iommu(pgmn_dev);
+err_fail_iommu:
+ msm_camera_clk_enable(&pdev->dev, pgmn_dev->jpeg_clk_info,
+ pgmn_dev->jpeg_clk, pgmn_dev->num_clk, false);
+err_clk_enable:
+ msm_camera_regulator_enable(pgmn_dev->jpeg_vdd,
+ pgmn_dev->num_reg, false);
+err_reg_enable:
+ return rc;
+}
+
+int msm_jpeg_platform_setup(struct msm_jpeg_device *pgmn_dev)
+{
+ int rc = -1;
+ struct resource *jpeg_irq_res;
+ void *jpeg_base, *vbif_base;
+ struct platform_device *pdev = pgmn_dev->pdev;
+
+ /* get the jpeg hardware device address */
+ jpeg_base = msm_camera_get_reg_base(pdev, "jpeg_hw", true);
+ if (!jpeg_base) {
+ JPEG_PR_ERR("%s: jpeg no mem resource?\n", __func__);
+ rc = -ENXIO;
+ goto out;
+ }
+
+ /* get the jpeg vbif device address */
+ vbif_base = msm_camera_get_reg_base(pdev, "jpeg_vbif", false);
+ if (!vbif_base) {
+ JPEG_PR_ERR("%s: vbif no mem resource?\n", __func__);
+ rc = -ENXIO;
+ goto err_vbif_base;
+ }
+
+ /* get the irq resource for the jpeg hardware */
+ jpeg_irq_res = msm_camera_get_irq(pdev, "jpeg");
+ if (!jpeg_irq_res) {
+ JPEG_PR_ERR("%s: no irq resource?\n", __func__);
+ rc = -ENXIO;
+ goto err_jpeg_irq_res;
+ }
+
+ /* get all the clocks information */
+ rc = msm_camera_get_clk_info(pdev, &pgmn_dev->jpeg_clk_info,
+ &pgmn_dev->jpeg_clk, &pgmn_dev->num_clk);
+ if (rc < 0) {
+ JPEG_PR_ERR("%s: failed to get the clocks\n", __func__);
+ rc = -ENXIO;
+ goto err_jpeg_clk;
+ }
+
+ /* get all the regulators information */
+ rc = msm_camera_get_regulator_info(pdev, &pgmn_dev->jpeg_vdd,
+ &pgmn_dev->num_reg);
+ if (rc < 0) {
+ JPEG_PR_ERR("%s: failed to get the regulators\n", __func__);
+ rc = -ENXIO;
+ goto err_jpeg_get_reg;
+ }
+
+ /* map the dtsi cell id to bus client id */
+ switch (pgmn_dev->pdev->id) {
+ case 0:
+ pgmn_dev->bus_client = CAM_BUS_CLIENT_JPEG_ENC0;
+ break;
+ case 1:
+ pgmn_dev->bus_client = CAM_BUS_CLIENT_JPEG_ENC1;
+ break;
+ case 2:
+ pgmn_dev->bus_client = CAM_BUS_CLIENT_JPEG_DEC;
+ break;
+ case 3:
+ pgmn_dev->bus_client = CAM_BUS_CLIENT_JPEG_DMA;
+ break;
+ default:
+ JPEG_PR_ERR("%s: invalid cell id :%d\n",
+ __func__, pgmn_dev->pdev->id);
+ goto err_jpeg_get_reg;
+ }
+
+ /* register the bus client */
+ rc = msm_camera_register_bus_client(pgmn_dev->pdev,
+ pgmn_dev->bus_client);
+ if (rc < 0) {
+ JPEG_PR_ERR("Fail to register bus client\n");
+ rc = -EINVAL;
+ goto err_reg_bus;
+ }
+
+ /* get the resource size of jpeg hardware */
+ pgmn_dev->res_size = msm_camera_get_res_size(pdev, "jpeg_hw");
+ if (!pgmn_dev->res_size) {
+ JPEG_PR_ERR("Fail to resource size\n");
+ rc = -EINVAL;
+ goto err_res_size;
+ }
+
+ pgmn_dev->base = jpeg_base;
+ pgmn_dev->vbif_base = vbif_base;
+ pgmn_dev->jpeg_irq_res = jpeg_irq_res;
+
+ return 0;
+
+err_res_size:
+ msm_camera_unregister_bus_client(pgmn_dev->bus_client);
+err_reg_bus:
+ msm_camera_put_regulators(pdev, &pgmn_dev->jpeg_vdd,
+ pgmn_dev->num_reg);
+err_jpeg_get_reg:
+ msm_camera_put_clk_info(pdev, &pgmn_dev->jpeg_clk_info,
+ &pgmn_dev->jpeg_clk, pgmn_dev->num_clk);
+err_jpeg_clk:
+err_jpeg_irq_res:
+ msm_camera_put_reg_base(pdev, vbif_base, "jpeg_vbif", false);
+err_vbif_base:
+ msm_camera_put_reg_base(pdev, jpeg_base, "jpeg_hw", true);
+out:
+ return rc;
+}
+
+void msm_jpeg_platform_cleanup(struct msm_jpeg_device *pgmn_dev)
+{
+ /* unregister the bus client */
+ msm_camera_unregister_bus_client(pgmn_dev->bus_client);
+ /* release the regulators */
+ msm_camera_put_regulators(pgmn_dev->pdev, &pgmn_dev->jpeg_vdd,
+ pgmn_dev->num_reg);
+ /* release all the clocks */
+ msm_camera_put_clk_info(pgmn_dev->pdev, &pgmn_dev->jpeg_clk_info,
+ &pgmn_dev->jpeg_clk, pgmn_dev->num_clk);
+ /* release the jpeg device memory */
+ msm_camera_put_reg_base(pgmn_dev->pdev, pgmn_dev->vbif_base,
+ "jpeg_vbif", false);
+ /* release the jpeg vbif device memory */
+ msm_camera_put_reg_base(pgmn_dev->pdev, pgmn_dev->base,
+ "jpeg_hw", true);
+}
+
+int msm_jpeg_platform_release(void *context)
+{
+ int result = 0;
+
+ struct msm_jpeg_device *pgmn_dev =
+ (struct msm_jpeg_device *) context;
+
+ /* release the irq */
+ msm_camera_unregister_irq(pgmn_dev->pdev,
+ pgmn_dev->jpeg_irq_res, context);
+
+ msm_jpeg_detach_iommu(pgmn_dev);
+
+ if (pgmn_dev->bus_client) {
+ if (pgmn_dev->jpeg_bus_vote) {
+ /* update the bw with zeroth vector */
+ msm_camera_update_bus_vector(pgmn_dev->bus_client, 0);
+ JPEG_BUS_UNVOTED(pgmn_dev);
+ JPEG_DBG("%s:%d] Bus unvoted\n", __func__, __LINE__);
+ }
+ }
+
+ /* disable all the clocks */
+ msm_camera_clk_enable(&pgmn_dev->pdev->dev, pgmn_dev->jpeg_clk_info,
+ pgmn_dev->jpeg_clk, pgmn_dev->num_clk, false);
+ JPEG_DBG("%s:%d] clock disbale done", __func__, __LINE__);
+
+ /* disable all the regulators */
+ msm_camera_regulator_enable(pgmn_dev->jpeg_vdd,
+ pgmn_dev->num_reg, false);
+ JPEG_DBG("%s:%d] regulator disable done", __func__, __LINE__);
+
+ pgmn_dev->state = MSM_JPEG_IDLE;
+ JPEG_DBG("%s:%d] success\n", __func__, __LINE__);
+ return result;
+}
+
+/*
+ * msm_jpeg_platform_set_dt_config() - set jpeg device tree configuration.
+ * @pgmn_dev: Pointer to jpeg device.
+ *
+ * This function holds an array of device tree property names and calls
+ * msm_jpeg_set_init_dt_parms() for each property.
+ *
+ * Return: 0 on success and negative error on failure.
+ */
+int msm_jpeg_platform_set_dt_config(struct msm_jpeg_device *pgmn_dev)
+{
+ int rc = 0;
+ uint8_t dt_prop_cnt = JPEG_DT_PROP_CNT;
+ char *dt_prop_name[JPEG_DT_PROP_CNT] = {"qcom,qos-reg-settings",
+ "qcom,prefetch-reg-settings"};
+
+ while (dt_prop_cnt) {
+ dt_prop_cnt--;
+ rc = msm_jpeg_set_init_dt_parms(pgmn_dev,
+ dt_prop_name[dt_prop_cnt],
+ pgmn_dev->base);
+ if (rc == -ENOENT) {
+ JPEG_DBG("%s: No %s property\n", __func__,
+ dt_prop_name[dt_prop_cnt]);
+ } else if (rc < 0) {
+ JPEG_PR_ERR("%s: %s params set fail\n", __func__,
+ dt_prop_name[dt_prop_cnt]);
+ return rc;
+ }
+ }
+ return rc;
+}
+