diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c index b4279e8749c0..08ce54779f11 100644 --- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c +++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c @@ -28,6 +28,7 @@ #include "msm_sd.h" #include "msm_camera_io_util.h" #include "cam_hw_ops.h" +#include "cam_soc_api.h" #ifdef CONFIG_MSM_ISPIF_V1 #include "msm_ispif_hwreg_v1.h" @@ -58,9 +59,7 @@ static int msm_ispif_clk_ahb_enable(struct ispif_device *ispif, int enable); static int ispif_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh); int msm_ispif_get_clk_info(struct ispif_device *ispif_dev, - struct platform_device *pdev, - struct msm_cam_clk_info *ahb_clk_info, - struct msm_cam_clk_info *clk_info); + struct platform_device *pdev); static void msm_ispif_io_dump_reg(struct ispif_device *ispif) { @@ -96,9 +95,6 @@ static struct msm_cam_clk_info ispif_8626_reset_clk_info[] = { {"camss_csi_vfe_clk", NO_SET_RATE}, }; -static struct msm_cam_clk_info ispif_ahb_clk_info[ISPIF_CLK_INFO_MAX]; -static struct msm_cam_clk_info ispif_clk_info[ISPIF_CLK_INFO_MAX]; - static void msm_ispif_put_regulator(struct ispif_device *ispif_dev) { int i; @@ -231,13 +227,13 @@ static int msm_ispif_reset_hw(struct ispif_device *ispif) if (rc < 0) return rc; - rc = msm_cam_clk_enable(&ispif->pdev->dev, - ispif_clk_info, ispif->clk, + rc = msm_camera_clk_enable(&ispif->pdev->dev, + ispif->clk_info, ispif->clks, ispif->num_clk, 1); if (rc < 0) { pr_err("%s: cannot enable clock, error = %d\n", __func__, rc); - rc = msm_cam_clk_enable(&ispif->pdev->dev, + rc = msm_camera_clk_enable(&ispif->pdev->dev, ispif_8626_reset_clk_info, reset_clk1, ARRAY_SIZE(ispif_8626_reset_clk_info), 1); if (rc < 0) { @@ -284,13 +280,13 @@ static int msm_ispif_reset_hw(struct ispif_device *ispif) clk_disable: if (ispif->clk_idx == 1) { - rc = rc ? rc : msm_cam_clk_enable(&ispif->pdev->dev, - ispif_clk_info, ispif->clk, + rc = rc ? rc : msm_camera_clk_enable(&ispif->pdev->dev, + ispif->clk_info, ispif->clks, ispif->num_clk, 0); } if (ispif->clk_idx == 2) { - rc = rc ? rc : msm_cam_clk_enable(&ispif->pdev->dev, + rc = rc ? rc : msm_camera_clk_enable(&ispif->pdev->dev, ispif_8626_reset_clk_info, reset_clk1, ARRAY_SIZE(ispif_8626_reset_clk_info), 0); } @@ -302,86 +298,76 @@ reg_disable: } int msm_ispif_get_clk_info(struct ispif_device *ispif_dev, - struct platform_device *pdev, - struct msm_cam_clk_info *ahb_clk_info, - struct msm_cam_clk_info *clk_info) + struct platform_device *pdev) { - uint32_t count, num_ahb_clk = 0, non_ahb_clk = 0; + uint32_t num_ahb_clk = 0, non_ahb_clk = 0; + size_t num_clks; int i, rc; - uint32_t rates[ISPIF_CLK_INFO_MAX]; - const char *clk_ctl = NULL; - const char *clk_name = NULL; - struct msm_cam_clk_info *clk_temp; + int j; + struct clk **clks, **temp_clks; + struct msm_cam_clk_info *clk_info, *temp_clk_info; struct device_node *of_node; of_node = pdev->dev.of_node; - count = of_property_count_strings(of_node, "clock-names"); + rc = msm_camera_get_clk_info(pdev, &clk_info, + &clks, &num_clks); - CDBG("count = %d\n", count); - if (count == 0) { - pr_err("no clocks found in device tree, count=%d", count); - return 0; - } - - if (count > ISPIF_CLK_INFO_MAX) { - pr_err("invalid count=%d, max is %d\n", count, - ISPIF_CLK_INFO_MAX); - return -EINVAL; - } - - rc = of_property_read_u32_array(of_node, "qcom,clock-rates", - rates, count); - if (rc < 0) { - pr_err("%s failed %d\n", __func__, __LINE__); + if (rc) return rc; + + /* + * reshuffle the clock arrays so that the ahb clocks are + * at the beginning of array + */ + temp_clks = kcalloc(num_clks, sizeof(struct clk *), + GFP_KERNEL); + temp_clk_info = kcalloc(num_clks, sizeof(struct msm_cam_clk_info), + GFP_KERNEL); + if (!temp_clks || !temp_clk_info) { + rc = -ENOMEM; + kfree(temp_clk_info); + kfree(temp_clks); + goto alloc_fail; } - - for (i = 0; i < count; i++) { - rc = of_property_read_string_index(of_node, "clock-names", - i, &clk_name); - if (rc < 0) { - pr_err("%s reading clock-name failed index %d\n", - __func__, i); - return rc; - } - - rc = of_property_read_string_index(of_node, - "qcom,clock-control", i, &clk_ctl); - if (rc < 0) { - pr_err("%s reading clock-control failed index %d\n", - __func__, i); - return rc; - } - - if (strnstr(clk_name, "ahb", strlen(clk_name))) { - clk_temp = &ahb_clk_info[num_ahb_clk]; + j = 0; + for (i = 0; i < num_clks; i++) { + if (strnstr(clk_info[i].clk_name, + "ahb", strlen(clk_info[i].clk_name))) { + temp_clk_info[j] = clk_info[i]; + temp_clks[j] = clks[i]; + j++; num_ahb_clk++; - } else { - clk_temp = &clk_info[non_ahb_clk]; + } + } + for (i = 0; i < num_clks; i++) { + if (!strnstr(clk_info[i].clk_name, + "ahb", strlen(clk_info[i].clk_name))) { + temp_clk_info[j] = clk_info[i]; + temp_clks[j] = clks[i]; + j++; non_ahb_clk++; } - - clk_temp->clk_name = clk_name; - if (!strcmp(clk_ctl, "NO_SET_RATE")) - clk_temp->clk_rate = NO_SET_RATE; - else if (!strcmp(clk_ctl, "INIT_RATE")) - clk_temp->clk_rate = INIT_RATE; - else if (!strcmp(clk_ctl, "SET_RATE")) - clk_temp->clk_rate = rates[i]; - else { - pr_err("%s: error: clock control has invalid value\n", - __func__); - return -EBUSY; - } - - CDBG("%s: clock-name= %s, clk_rate = %ld clock-control = %s\n", - __func__, clk_temp->clk_name, clk_temp->clk_rate, - clk_ctl); } + + for (i = 0; i < num_clks; i++) { + clk_info[i] = temp_clk_info[i]; + clks[i] = temp_clks[i]; + } + kfree(temp_clk_info); + kfree(temp_clks); + + ispif_dev->ahb_clk = clks; + ispif_dev->ahb_clk_info = clk_info; ispif_dev->num_ahb_clk = num_ahb_clk; + ispif_dev->clk_info = clk_info + num_ahb_clk; + ispif_dev->clks = clks + num_ahb_clk; ispif_dev->num_clk = non_ahb_clk; + return 0; +alloc_fail: + msm_camera_put_clk_info(pdev, &clk_info, &clks, num_clks); + return rc; } static int msm_ispif_clk_ahb_enable(struct ispif_device *ispif, int enable) @@ -389,7 +375,7 @@ static int msm_ispif_clk_ahb_enable(struct ispif_device *ispif, int enable) int rc = 0; rc = msm_cam_clk_enable(&ispif->pdev->dev, - ispif_ahb_clk_info, ispif->ahb_clk, + ispif->ahb_clk_info, ispif->ahb_clk, ispif->num_ahb_clk, enable); if (rc < 0) { pr_err("%s: cannot enable clock, error = %d", @@ -729,7 +715,7 @@ static int msm_ispif_config(struct ispif_device *ispif, } if (ispif->csid_version >= CSID_VERSION_V30) - msm_ispif_select_clk_mux(ispif, intftype, + msm_ispif_select_clk_mux(ispif, intftype, params->entries[i].csid, vfe_intf); rc = msm_ispif_validate_intf_status(ispif, intftype, vfe_intf); @@ -934,8 +920,8 @@ static int msm_ispif_restart_frame_boundary(struct ispif_device *ispif, if (rc < 0) return -EFAULT; - rc = msm_cam_clk_enable(&ispif->pdev->dev, - ispif_clk_info, ispif->clk, + rc = msm_camera_clk_enable(&ispif->pdev->dev, + ispif->clk_info, ispif->clks, ispif->num_clk, 1); if (rc < 0) goto disable_regulator; @@ -969,8 +955,8 @@ static int msm_ispif_restart_frame_boundary(struct ispif_device *ispif, } pr_info("%s: ISPIF reset hw done, Restarting", __func__); - rc = msm_cam_clk_enable(&ispif->pdev->dev, - ispif_clk_info, ispif->clk, + rc = msm_camera_clk_enable(&ispif->pdev->dev, + ispif->clk_info, ispif->clks, ispif->num_clk, 0); if (rc < 0) goto disable_regulator; @@ -1026,8 +1012,8 @@ static int msm_ispif_restart_frame_boundary(struct ispif_device *ispif, return rc; disable_clk: - msm_cam_clk_enable(&ispif->pdev->dev, - ispif_clk_info, ispif->clk, + msm_camera_clk_enable(&ispif->pdev->dev, + ispif->clk_info, ispif->clks, ispif->num_clk, 0); disable_regulator: /* Turn OFF regulators */ @@ -1325,41 +1311,18 @@ static int msm_ispif_init(struct ispif_device *ispif, ispif->csid_version = csid_version; - if (ispif->csid_version >= CSID_VERSION_V30) { - if (!ispif->clk_mux_mem || !ispif->clk_mux_io) { - pr_err("%s csi clk mux mem %p io %p\n", __func__, - ispif->clk_mux_mem, ispif->clk_mux_io); - rc = -ENOMEM; - return rc; - } - ispif->clk_mux_base = ioremap(ispif->clk_mux_mem->start, - resource_size(ispif->clk_mux_mem)); - if (!ispif->clk_mux_base) { - pr_err("%s: clk_mux_mem ioremap failed\n", __func__); - rc = -ENOMEM; - return rc; - } - } - - ispif->base = ioremap(ispif->mem->start, - resource_size(ispif->mem)); - if (!ispif->base) { - rc = -ENOMEM; - pr_err("%s: nomem\n", __func__); - goto end; - } - rc = request_irq(ispif->irq->start, msm_io_ispif_irq, - IRQF_TRIGGER_RISING, "ispif", ispif); - if (rc) { - pr_err("%s: request_irq error = %d\n", __func__, rc); - goto error_irq; + if (ispif->csid_version >= CSID_VERSION_V30 && !ispif->clk_mux_base) { + ispif->clk_mux_base = msm_camera_get_reg_base(ispif->pdev, + "csi_clk_mux", 1); + if (!ispif->clk_mux_base) + return -ENOMEM; } rc = cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_ISPIF, CAM_AHB_SVS_VOTE); if (rc < 0) { pr_err("%s: failed to vote for AHB\n", __func__); - goto ahb_vote_fail; + return rc; } rc = msm_ispif_reset_hw(ispif); @@ -1367,22 +1330,15 @@ static int msm_ispif_init(struct ispif_device *ispif, goto error_ahb; rc = msm_ispif_reset(ispif); - if (rc == 0) { - ispif->ispif_state = ISPIF_POWER_UP; - CDBG("%s: power up done\n", __func__); - goto end; - } + if (rc) + goto error_ahb; + ispif->ispif_state = ISPIF_POWER_UP; + return 0; error_ahb: if (cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_ISPIF, CAM_AHB_SUSPEND_VOTE) < 0) pr_err("%s: failed to remove vote for AHB\n", __func__); -ahb_vote_fail: - free_irq(ispif->irq->start, ispif); -error_irq: - iounmap(ispif->base); - -end: return rc; } @@ -1390,27 +1346,10 @@ static void msm_ispif_release(struct ispif_device *ispif) { BUG_ON(!ispif); - if (!ispif->base) { - pr_err("%s: ispif base is NULL\n", __func__); - return; - } - - if (ispif->ispif_state != ISPIF_POWER_UP) { - pr_err("%s: ispif invalid state %d\n", __func__, - ispif->ispif_state); - return; - } - - /* make sure no streaming going on */ msm_ispif_reset(ispif); msm_ispif_reset_hw(ispif); - disable_irq(ispif->irq->start); - free_irq(ispif->irq->start, ispif); - - iounmap(ispif->base); - - iounmap(ispif->clk_mux_base); + msm_camera_enable_irq(ispif->irq, 0); ispif->ispif_state = ISPIF_POWER_DOWN; @@ -1460,7 +1399,8 @@ static long msm_ispif_cmd(struct v4l2_subdev *sd, void *arg) msm_ispif_io_dump_reg(ispif); break; case ISPIF_RELEASE: - msm_ispif_release(ispif); + msm_ispif_reset(ispif); + msm_ispif_reset_hw(ispif); break; case ISPIF_SET_VFE_INFO: rc = msm_ispif_set_vfe_info(ispif, &pcdata->vfe_info); @@ -1526,15 +1466,22 @@ static int ispif_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) ispif->ispif_vdd_count, 1); if (rc) goto unlock; + rc = msm_ispif_clk_ahb_enable(ispif, 1); - if (rc) { - msm_ispif_set_regulators(ispif->ispif_vdd, - ispif->ispif_vdd_count, 0); - goto unlock; - } + if (rc) + goto ahb_clk_enable_fail; + rc = msm_camera_enable_irq(ispif->irq, 1); + if (rc) + goto irq_enable_fail; } /* mem remap is done in init when the clock is on */ ispif->open_cnt++; + mutex_unlock(&ispif->mutex); + return rc; +ahb_clk_enable_fail: + msm_ispif_set_regulators(ispif->ispif_vdd, ispif->ispif_vdd_count, 0); +irq_enable_fail: + msm_ispif_clk_ahb_enable(ispif, 0); unlock: mutex_unlock(&ispif->mutex); return rc; @@ -1606,46 +1553,35 @@ static int ispif_probe(struct platform_device *pdev) rc = msm_ispif_get_regulator_info(ispif, pdev); if (rc < 0) - return -EFAULT; + goto regulator_fail; - rc = msm_ispif_get_clk_info(ispif, pdev, - ispif_ahb_clk_info, ispif_clk_info); + rc = msm_ispif_get_clk_info(ispif, pdev); if (rc < 0) { pr_err("%s: msm_isp_get_clk_info() failed", __func__); - return -EFAULT; + rc = -EFAULT; + goto get_clk_fail; } mutex_init(&ispif->mutex); - ispif->mem = platform_get_resource_byname(pdev, - IORESOURCE_MEM, "ispif"); - if (!ispif->mem) { - pr_err("%s: no mem resource?\n", __func__); - rc = -ENODEV; - goto error; + ispif->base = msm_camera_get_reg_base(pdev, "ispif", 1); + if (!ispif->base) { + rc = -ENOMEM; + goto reg_base_fail; } - ispif->irq = platform_get_resource_byname(pdev, - IORESOURCE_IRQ, "ispif"); + + ispif->irq = msm_camera_get_irq(pdev, "ispif"); if (!ispif->irq) { - pr_err("%s: no irq resource?\n", __func__); rc = -ENODEV; - goto error; + goto get_irq_fail; } - ispif->io = request_mem_region(ispif->mem->start, - resource_size(ispif->mem), pdev->name); - if (!ispif->io) { - pr_err("%s: no valid mem region\n", __func__); - rc = -EBUSY; - goto error; - } - ispif->clk_mux_mem = platform_get_resource_byname(pdev, - IORESOURCE_MEM, "csi_clk_mux"); - if (ispif->clk_mux_mem) { - ispif->clk_mux_io = request_mem_region( - ispif->clk_mux_mem->start, - resource_size(ispif->clk_mux_mem), - ispif->clk_mux_mem->name); - if (!ispif->clk_mux_io) - pr_err("%s: no valid csi_mux region\n", __func__); + rc = msm_camera_register_irq(pdev, ispif->irq, msm_io_ispif_irq, + IRQF_TRIGGER_RISING, "ispif", ispif); + if (rc) { + rc = -ENODEV; + goto get_irq_fail; } + rc = msm_camera_enable_irq(ispif->irq, 0); + if (rc) + goto sd_reg_fail; ispif->pdev = pdev; @@ -1667,7 +1603,7 @@ static int ispif_probe(struct platform_device *pdev) rc = msm_sd_register(&ispif->msm_sd); if (rc) { pr_err("%s: msm_sd_register error = %d\n", __func__, rc); - goto error; + goto sd_reg_fail; } msm_cam_copy_v4l2_subdev_fops(&msm_ispif_v4l2_subdev_fops); msm_ispif_v4l2_subdev_fops.unlocked_ioctl = @@ -1684,8 +1620,17 @@ static int ispif_probe(struct platform_device *pdev) atomic_set(&ispif->reset_trig[VFE1], 0); return 0; -error: +sd_reg_fail: + msm_camera_unregister_irq(pdev, ispif->irq, ispif); +get_irq_fail: + msm_camera_put_reg_base(pdev, ispif->base, "ispif", 1); +reg_base_fail: + msm_camera_put_clk_info(pdev, &ispif->ahb_clk_info, + &ispif->ahb_clk, + ispif->num_ahb_clk + ispif->num_clk); +get_clk_fail: msm_ispif_put_regulator(ispif); +regulator_fail: mutex_destroy(&ispif->mutex); kfree(ispif); return rc; diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.h b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.h index cd1a171c07e3..61e8f1dd7aff 100644 --- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.h +++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-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 @@ -47,11 +47,7 @@ struct ispif_intf_cmd { struct ispif_device { struct platform_device *pdev; struct msm_sd_subdev msm_sd; - struct resource *mem; - struct resource *clk_mux_mem; struct resource *irq; - struct resource *io; - struct resource *clk_mux_io; void __iomem *base; void __iomem *clk_mux_base; struct mutex mutex; @@ -63,8 +59,10 @@ struct ispif_device { struct ispif_intf_cmd applied_intf_cmd[VFE_MAX]; enum msm_ispif_state_t ispif_state; struct msm_ispif_vfe_info vfe_info; - struct clk *ahb_clk[ISPIF_CLK_INFO_MAX]; - struct clk *clk[ISPIF_CLK_INFO_MAX]; + struct clk **ahb_clk; + struct msm_cam_clk_info *ahb_clk_info; + struct clk **clks; + struct msm_cam_clk_info *clk_info; struct completion reset_complete[VFE_MAX]; atomic_t reset_trig[VFE_MAX]; uint32_t hw_num_isps;