Loading drivers/media/platform/msm/camera_v2/common/cam_soc_api.c +264 −45 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 @@ -33,9 +33,10 @@ struct msm_cam_bus_pscale_data { uint32_t num_paths; unsigned int vector_index; bool dyn_vote; struct mutex lock; }; struct msm_cam_bus_pscale_data g_cv[CAM_AHB_CLIENT_MAX]; struct msm_cam_bus_pscale_data g_cv[CAM_BUS_CLIENT_MAX]; /* Get all clocks from DT */ Loading Loading @@ -183,6 +184,135 @@ err1: } EXPORT_SYMBOL(msm_camera_get_clk_info); /* Get all clocks and multiple rates from DT */ int msm_camera_get_clk_info_and_rates( struct platform_device *pdev, struct msm_cam_clk_info **pclk_info, struct clk ***pclks, uint32_t ***pclk_rates, size_t *num_set, size_t *num_clk) { int rc = 0, tmp_var, cnt, tmp; uint32_t i = 0, j = 0; struct device_node *of_node; uint32_t **rates; struct clk **clks; struct msm_cam_clk_info *clk_info; if (!pdev || !pclk_info || !num_clk || !pclk_rates || !pclks || !num_set) return -EINVAL; of_node = pdev->dev.of_node; cnt = of_property_count_strings(of_node, "clock-names"); if (cnt <= 0) { pr_err("err: No clocks found in DT=%d\n", cnt); return -EINVAL; } tmp = of_property_count_u32_elems(of_node, "qcom,clock-rates"); if (tmp <= 0) { pr_err("err: No clk rates device tree, count=%d\n", tmp); return -EINVAL; } if ((tmp % cnt) != 0) { pr_err("err: clk name/rates mismatch, strings=%d, rates=%d\n", cnt, tmp); return -EINVAL; } *num_clk = cnt; *num_set = (tmp / cnt); clk_info = devm_kcalloc(&pdev->dev, cnt, sizeof(struct msm_cam_clk_info), GFP_KERNEL); if (!clk_info) return -ENOMEM; clks = devm_kcalloc(&pdev->dev, cnt, sizeof(struct clk *), GFP_KERNEL); if (!clks) { rc = -ENOMEM; goto err1; } rates = devm_kcalloc(&pdev->dev, *num_set, sizeof(uint32_t *), GFP_KERNEL); if (!rates) { rc = -ENOMEM; goto err2; } for (i = 0; i < *num_set; i++) { rates[i] = devm_kcalloc(&pdev->dev, *num_clk, sizeof(uint32_t), GFP_KERNEL); if (!rates[i]) { rc = -ENOMEM; for (--i; i >= 0; i--) devm_kfree(&pdev->dev, rates[i]); goto err3; } } tmp_var = 0; for (i = 0; i < *num_set; i++) { for (j = 0; j < *num_clk; j++) { rc = of_property_read_u32_index(of_node, "qcom,clock-rates", tmp_var++, &rates[i][j]); if (rc < 0) { pr_err("err: failed reading clock rates\n"); rc = -EINVAL; goto err4; } CDBG("Clock rate idx %d idx %d value %d\n", i, j, rates[i][j]); } } for (i = 0; i < *num_clk; i++) { rc = of_property_read_string_index(of_node, "clock-names", i, &clk_info[i].clk_name); if (rc < 0) { pr_err("%s reading clock-name failed index %d\n", __func__, i); rc = -EINVAL; goto err4; } CDBG("dbg: clk-name[%d] = %s\n", i, clk_info[i].clk_name); clks[i] = devm_clk_get(&pdev->dev, clk_info[i].clk_name); if (IS_ERR(clks[i])) { rc = PTR_ERR(clks[i]); goto err5; } CDBG("clk ptr[%d] :%p\n", i, clks[i]); } *pclk_info = clk_info; *pclks = clks; *pclk_rates = rates; return rc; err5: for (--i; i >= 0; i--) devm_clk_put(&pdev->dev, clks[i]); err4: for (i = 0; i < *num_set; i++) devm_kfree(&pdev->dev, rates[i]); err3: devm_kfree(&pdev->dev, rates); err2: devm_kfree(&pdev->dev, clks); err1: devm_kfree(&pdev->dev, clk_info); return rc; } EXPORT_SYMBOL(msm_camera_get_clk_info_and_rates); /* Enable/Disable all clocks */ int msm_camera_clk_enable(struct device *dev, struct msm_cam_clk_info *clk_info, Loading Loading @@ -274,17 +404,21 @@ int msm_camera_clk_set_rate(struct device *dev, if (!dev || !clk) return -EINVAL; CDBG("clk : %p, enable : %ld\n", clk, clk_rate); if (clk_rate > 0) { clk_rate = clk_round_rate(clk, clk_rate); if (clk_rate < 0) { pr_err("round rate failed:\n"); pr_err("round rate failed\n"); return -EINVAL; } rc = clk_set_rate(clk, clk_rate); if (rc < 0) { pr_err("set rate failed:\n"); pr_err("set rate failed\n"); return -EINVAL; } } return 0; } Loading @@ -311,6 +445,31 @@ int msm_camera_put_clk_info(struct platform_device *pdev, } EXPORT_SYMBOL(msm_camera_put_clk_info); int msm_camera_put_clk_info_and_rates(struct platform_device *pdev, struct msm_cam_clk_info **clk_info, struct clk ***clk_ptr, uint32_t ***clk_rates, size_t set, size_t cnt) { int i; for (i = set - 1; i >= 0; i--) devm_kfree(&pdev->dev, (*clk_rates)[i]); devm_kfree(&pdev->dev, *clk_rates); for (i = cnt - 1; i >= 0; i--) { if (clk_ptr[i] != NULL) devm_clk_put(&pdev->dev, (*clk_ptr)[i]); CDBG("clk ptr[%d] :%p\n", i, (*clk_ptr)[i]); } devm_kfree(&pdev->dev, *clk_info); devm_kfree(&pdev->dev, *clk_ptr); *clk_info = NULL; *clk_ptr = NULL; *clk_rates = NULL; return 0; } EXPORT_SYMBOL(msm_camera_put_clk_info_and_rates); /* Get regulators from DT */ int msm_camera_get_regulator_info(struct platform_device *pdev, struct regulator ***vdd, Loading Loading @@ -392,7 +551,7 @@ int msm_camera_regulator_enable(struct regulator **vdd, CDBG("cnt : %d, enable : %d\n", cnt, enable); if (!vdd) { pr_err("Invalid Params"); pr_err("Invalid params"); return -EINVAL; } Loading Loading @@ -447,7 +606,7 @@ struct resource *msm_camera_get_irq(struct platform_device *pdev, char *irq_name) { if (!pdev || !irq_name) { pr_err("Invalid Params\n"); pr_err("Invalid params\n"); return NULL; } Loading @@ -458,17 +617,17 @@ EXPORT_SYMBOL(msm_camera_get_irq); int msm_camera_register_irq(struct platform_device *pdev, struct resource *irq, irq_handler_t handler, char *irq_name, void *dev_id) unsigned long irqflags, char *irq_name, void *dev_id) { int rc = 0; if (!pdev || !irq || !handler || !irq_name || !dev_id) { pr_err("Invalid Params\n"); pr_err("Invalid params\n"); return -EINVAL; } rc = devm_request_irq(&pdev->dev, irq->start, handler, IRQF_TRIGGER_RISING, irq_name, dev_id); irqflags, irq_name, dev_id); if (rc < 0) { pr_err("irq request fail\n"); rc = -EINVAL; Loading @@ -480,10 +639,36 @@ int msm_camera_register_irq(struct platform_device *pdev, } EXPORT_SYMBOL(msm_camera_register_irq); int msm_camera_register_threaded_irq(struct platform_device *pdev, struct resource *irq, irq_handler_t handler_fn, irq_handler_t thread_fn, unsigned long irqflags, char *irq_name, void *dev_id) { int rc = 0; if (!pdev || !irq || !handler_fn || !thread_fn || !irq_name || !dev_id) { pr_err("Invalid params\n"); return -EINVAL; } rc = devm_request_threaded_irq(&pdev->dev, irq->start, handler_fn, thread_fn, irqflags, irq_name, dev_id); if (rc < 0) { pr_err("irq request fail\n"); rc = -EINVAL; } CDBG("Registered irq for %s[resource - %p]\n", irq_name, irq); return rc; } EXPORT_SYMBOL(msm_camera_register_threaded_irq); int msm_camera_enable_irq(struct resource *irq, int enable) { if (!irq) { pr_err("Invalid Params\n"); pr_err("Invalid params\n"); return -EINVAL; } Loading @@ -502,7 +687,7 @@ int msm_camera_unregister_irq(struct platform_device *pdev, { if (!pdev || !irq || !dev_id) { pr_err("Invalid Params\n"); pr_err("Invalid params\n"); return -EINVAL; } Loading @@ -514,13 +699,13 @@ int msm_camera_unregister_irq(struct platform_device *pdev, EXPORT_SYMBOL(msm_camera_unregister_irq); void __iomem *msm_camera_get_reg_base(struct platform_device *pdev, char *device_name) char *device_name, int reserve_mem) { struct resource *mem; void *base; if (!pdev || !device_name) { pr_err("Invalid Params\n"); pr_err("Invalid params\n"); return NULL; } Loading @@ -532,11 +717,17 @@ void __iomem *msm_camera_get_reg_base(struct platform_device *pdev, return NULL; } if (!devm_request_mem_region(&pdev->dev, mem->start, resource_size(mem), if (reserve_mem) { CDBG("device:%p, mem : %p, size : %d\n", &pdev->dev, mem, (int)resource_size(mem)); if (!devm_request_mem_region(&pdev->dev, mem->start, resource_size(mem), device_name)) { pr_err("err: no valid mem region for device:%s\n", device_name); pr_err("err: no valid mem region for device:%s\n", device_name); return NULL; } } base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); if (!base) { Loading @@ -551,13 +742,35 @@ void __iomem *msm_camera_get_reg_base(struct platform_device *pdev, } EXPORT_SYMBOL(msm_camera_get_reg_base); int msm_camera_put_reg_base(struct platform_device *pdev, void __iomem *base, uint32_t msm_camera_get_res_size(struct platform_device *pdev, char *device_name) { struct resource *mem; if (!pdev || !device_name) { pr_err("Invalid params\n"); return 0; } CDBG("device name :%s\n", device_name); mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, device_name); if (!mem) { pr_err("err: mem resource %s not found\n", device_name); return 0; } return resource_size(mem); } EXPORT_SYMBOL(msm_camera_get_res_size); int msm_camera_put_reg_base(struct platform_device *pdev, void __iomem *base, char *device_name, int reserve_mem) { struct resource *mem; if (!pdev || !base || !device_name) { pr_err("Invalid Params\n"); pr_err("Invalid params\n"); return -EINVAL; } Loading @@ -568,9 +781,12 @@ int msm_camera_put_reg_base(struct platform_device *pdev, void __iomem *base, pr_err("err: mem resource %s not found\n", device_name); return -EINVAL; } CDBG("mem : %p, size : %d\n", mem, (int)resource_size(mem)); devm_iounmap(&pdev->dev, base); devm_release_mem_region(&pdev->dev, mem->start, resource_size(mem)); if (reserve_mem) devm_release_mem_region(&pdev->dev, mem->start, resource_size(mem)); return 0; } Loading @@ -578,7 +794,7 @@ EXPORT_SYMBOL(msm_camera_put_reg_base); /* Register the bus client */ uint32_t msm_camera_register_bus_client(struct platform_device *pdev, enum cam_ahb_clk_client id) enum cam_bus_client id) { int rc = 0; uint32_t bus_client, num_usecases, num_paths; Loading @@ -587,8 +803,8 @@ uint32_t msm_camera_register_bus_client(struct platform_device *pdev, CDBG("Register client ID: %d\n", id); if (id >= CAM_AHB_CLIENT_MAX || !pdev) { pr_err("Invalid Params"); if (id >= CAM_BUS_CLIENT_MAX || !pdev) { pr_err("Invalid params"); return -EINVAL; } Loading Loading @@ -642,7 +858,7 @@ uint32_t msm_camera_register_bus_client(struct platform_device *pdev, g_cv[id].vector_index = 0; g_cv[id].num_usecases = num_usecases; g_cv[id].num_paths = num_paths; mutex_init(&g_cv[id].lock); CDBG("Exit Client ID: %d\n", id); return 0; } Loading @@ -655,8 +871,8 @@ uint32_t msm_camera_update_bus_bw(int id, uint64_t ab, uint64_t ib) struct msm_bus_scale_pdata *pdata; int idx = 0; if (id >= CAM_AHB_CLIENT_MAX) { pr_err("Invalid Params"); if (id >= CAM_BUS_CLIENT_MAX) { pr_err("Invalid params"); return -EINVAL; } if (g_cv[id].num_usecases != 2 || Loading @@ -666,11 +882,13 @@ uint32_t msm_camera_update_bus_bw(int id, uint64_t ab, uint64_t ib) return -EINVAL; } mutex_lock(&g_cv[id].lock); idx = g_cv[id].vector_index; pdata = g_cv[id].pdata; idx = 1 - idx; g_cv[id].vector_index = idx; mutex_unlock(&g_cv[id].lock); pdata = g_cv[id].pdata; path = &(pdata->usecase[idx]); path->vectors[0].ab = ab; path->vectors[0].ib = ib; Loading @@ -678,26 +896,26 @@ uint32_t msm_camera_update_bus_bw(int id, uint64_t ab, uint64_t ib) CDBG("Register client ID : %d [ab : %llx, ib : %llx], update :%d\n", id, ab, ib, idx); msm_bus_scale_client_update_request(g_cv[id].bus_client, idx); g_cv[id].vector_index = idx; return 0; } EXPORT_SYMBOL(msm_camera_update_bus_bw); /* Update the bus vector */ uint32_t msm_camera_update_bus_vector(enum cam_ahb_clk_client id, uint32_t msm_camera_update_bus_vector(enum cam_bus_client id, int vector_index) { if (id >= CAM_AHB_CLIENT_MAX || g_cv[id].dyn_vote == true) { pr_err("Invalid Params"); if (id >= CAM_BUS_CLIENT_MAX || g_cv[id].dyn_vote == true) { pr_err("Invalid params"); return -EINVAL; } if (vector_index < 0 || vector_index > g_cv[id].num_usecases) { pr_err("Invalid Params"); pr_err("Invalid params"); return -EINVAL; } CDBG("Register client ID : %d vector idx: %d,\n", id, vector_index); msm_bus_scale_client_update_request(g_cv[id].bus_client, vector_index); Loading @@ -706,15 +924,16 @@ uint32_t msm_camera_update_bus_vector(enum cam_ahb_clk_client id, EXPORT_SYMBOL(msm_camera_update_bus_vector); /* Unregister the bus client */ uint32_t msm_camera_unregister_bus_client(enum cam_ahb_clk_client id) uint32_t msm_camera_unregister_bus_client(enum cam_bus_client id) { if (id >= CAM_AHB_CLIENT_MAX) { pr_err("Invalid Params"); if (id >= CAM_BUS_CLIENT_MAX) { pr_err("Invalid params"); return -EINVAL; } CDBG("UnRegister client ID: %d\n", id); mutex_destroy(&g_cv[id].lock); msm_bus_scale_unregister_client(g_cv[id].bus_client); msm_bus_cl_clear_pdata(g_cv[id].pdata); memset(&g_cv[id], 0, sizeof(struct msm_cam_bus_pscale_data)); Loading drivers/media/platform/msm/camera_v2/common/cam_soc_api.h +107 −10 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 @@ -22,7 +22,17 @@ #include <linux/interrupt.h> #include <linux/slab.h> #include <soc/qcom/camera2.h> #include "cam_hw_ops.h" enum cam_bus_client { CAM_BUS_CLIENT_VFE, CAM_BUS_CLIENT_CPP, CAM_BUS_CLIENT_FD, CAM_BUS_CLIENT_JPEG_ENC0, CAM_BUS_CLIENT_JPEG_ENC1, CAM_BUS_CLIENT_JPEG_DEC, CAM_BUS_CLIENT_JPEG_DMA, CAM_BUS_CLIENT_MAX }; /** * @brief : Gets clock information from dtsi Loading @@ -32,7 +42,7 @@ * * @param pdev : Platform device to get clocks information * @param clk_info : Pointer to populate clock information array * @param clk_info : Pointer to populate clock resource pointers * @param clk_ptr : Pointer to populate clock resource pointers * @param num_clk: Pointer to populate the number of clocks * extracted from dtsi * Loading @@ -43,6 +53,30 @@ int msm_camera_get_clk_info(struct platform_device *pdev, struct msm_cam_clk_info **clk_info, struct clk ***clk_ptr, size_t *num_clk); /** * @brief : Gets clock information and rates from dtsi * * This function extracts the clocks information for a specific * platform device * * @param pdev : Platform device to get clocks information * @param clk_info : Pointer to populate clock information array * @param clk_ptr : Pointer to populate clock resource pointers * @param clk_rates : Pointer to populate clock rates * @param num_set: Pointer to populate the number of sets of rates * @param num_clk: Pointer to populate the number of clocks * extracted from dtsi * * @return Status of operation. Negative in case of error. Zero otherwise. */ int msm_camera_get_clk_info_and_rates( struct platform_device *pdev, struct msm_cam_clk_info **clk_info, struct clk ***clk_ptr, uint32_t ***clk_rates, size_t *num_set, size_t *num_clk); /** * @brief : Puts clock information * Loading @@ -58,6 +92,25 @@ int msm_camera_get_clk_info(struct platform_device *pdev, int msm_camera_put_clk_info(struct platform_device *pdev, struct msm_cam_clk_info **clk_info, struct clk ***clk_ptr, int cnt); /** * @brief : Puts clock information * * This function releases the memory allocated for the clocks * * @param pdev : Pointer to platform device * @param clk_info : Pointer to release the allocated memory * @param clk_ptr : Pointer to release the clock resources * @param clk_ptr : Pointer to release the clock rates * @param set : Number of sets of clock rates * @param cnt : Number of clk resources * * @return Status of operation. Negative in case of error. Zero otherwise. */ int msm_camera_put_clk_info_and_rates(struct platform_device *pdev, struct msm_cam_clk_info **clk_info, struct clk ***clk_ptr, uint32_t ***clk_rates, size_t set, size_t cnt); /** * @brief : Enable clocks * Loading Loading @@ -160,6 +213,7 @@ struct resource *msm_camera_get_irq(struct platform_device *pdev, * @param pdev : Platform device to register IRQ resource * @param irq : IRQ resource * @param handler : IRQ handler * @param irqflags : IRQ flags * @param irq_name: Name of the IRQ * @param dev : Token of the device * Loading @@ -169,6 +223,31 @@ struct resource *msm_camera_get_irq(struct platform_device *pdev, int msm_camera_register_irq(struct platform_device *pdev, struct resource *irq, irq_handler_t handler, unsigned long irqflags, char *irq_name, void *dev); /** * @brief : Register the threaded IRQ * * This function registers the irq resource for specified hardware * * @param pdev : Platform device to register IRQ resource * @param irq : IRQ resource * @param handler_fn : IRQ handler function * @param thread_fn : thread handler function * @param irqflags : IRQ flags * @param irq_name: Name of the IRQ * @param dev : Token of the device * * @return Status of operation. Negative in case of error. Zero otherwise. */ int msm_camera_register_threaded_irq(struct platform_device *pdev, struct resource *irq, irq_handler_t handler_fn, irq_handler_t thread_fn, unsigned long irqflags, char *irq_name, void *dev); Loading Loading @@ -208,12 +287,14 @@ int msm_camera_unregister_irq(struct platform_device *pdev, * * @param pdev : Platform device to get regulator infor * @param device_name : Name of the device to fetch the register base * @param reserve_mem : Flag to decide whether to reserve memory * region or not. * * @return Pointer to resource if success else null */ void __iomem *msm_camera_get_reg_base(struct platform_device *pdev, char *device_name); char *device_name, int reserve_mem); /** * @brief : Puts device register base Loading @@ -224,27 +305,28 @@ void __iomem *msm_camera_get_reg_base(struct platform_device *pdev, * @param pdev : Pointer to platform device * @param base : Pointer to base to unmap * @param device_name : Device name * @param reserve_mem : Flag to decide whether to release memory * region or not. * * @return Status of operation. Negative in case of error. Zero otherwise. */ int msm_camera_put_reg_base(struct platform_device *pdev, void __iomem *base, char *device_name); char *device_name, int reserve_mem); /** * @brief : Register the bus client * * This function registers the bus client * * @param client_id : client identifier * @param pdev : Pointer to platform device * @param vector_index : vector index to register * @param id : client identifier * * @return Status of operation. Negative in case of error. Zero otherwise. */ uint32_t msm_camera_register_bus_client(struct platform_device *pdev, enum cam_ahb_clk_client id); enum cam_bus_client id); /** * @brief : Update bus vector Loading @@ -257,7 +339,7 @@ uint32_t msm_camera_register_bus_client(struct platform_device *pdev, * @return Status of operation. Negative in case of error. Zero otherwise. */ uint32_t msm_camera_update_bus_vector(enum cam_ahb_clk_client id, uint32_t msm_camera_update_bus_vector(enum cam_bus_client id, int vector_index); /** Loading @@ -284,6 +366,21 @@ uint32_t msm_camera_update_bus_bw(int id, uint64_t ab, uint64_t ib); * @return Status of operation. Negative in case of error. Zero otherwise. */ uint32_t msm_camera_unregister_bus_client(enum cam_ahb_clk_client id); uint32_t msm_camera_unregister_bus_client(enum cam_bus_client id); /** * @brief : Gets resource size * * This function returns the size of the resource for the * specified platform device * * @param pdev : Platform device to get regulator infor * @param device_name : Name of the device to fetch the register base * * @return size of the resource */ uint32_t msm_camera_get_res_size(struct platform_device *pdev, char *device_name); #endif Loading
drivers/media/platform/msm/camera_v2/common/cam_soc_api.c +264 −45 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 @@ -33,9 +33,10 @@ struct msm_cam_bus_pscale_data { uint32_t num_paths; unsigned int vector_index; bool dyn_vote; struct mutex lock; }; struct msm_cam_bus_pscale_data g_cv[CAM_AHB_CLIENT_MAX]; struct msm_cam_bus_pscale_data g_cv[CAM_BUS_CLIENT_MAX]; /* Get all clocks from DT */ Loading Loading @@ -183,6 +184,135 @@ err1: } EXPORT_SYMBOL(msm_camera_get_clk_info); /* Get all clocks and multiple rates from DT */ int msm_camera_get_clk_info_and_rates( struct platform_device *pdev, struct msm_cam_clk_info **pclk_info, struct clk ***pclks, uint32_t ***pclk_rates, size_t *num_set, size_t *num_clk) { int rc = 0, tmp_var, cnt, tmp; uint32_t i = 0, j = 0; struct device_node *of_node; uint32_t **rates; struct clk **clks; struct msm_cam_clk_info *clk_info; if (!pdev || !pclk_info || !num_clk || !pclk_rates || !pclks || !num_set) return -EINVAL; of_node = pdev->dev.of_node; cnt = of_property_count_strings(of_node, "clock-names"); if (cnt <= 0) { pr_err("err: No clocks found in DT=%d\n", cnt); return -EINVAL; } tmp = of_property_count_u32_elems(of_node, "qcom,clock-rates"); if (tmp <= 0) { pr_err("err: No clk rates device tree, count=%d\n", tmp); return -EINVAL; } if ((tmp % cnt) != 0) { pr_err("err: clk name/rates mismatch, strings=%d, rates=%d\n", cnt, tmp); return -EINVAL; } *num_clk = cnt; *num_set = (tmp / cnt); clk_info = devm_kcalloc(&pdev->dev, cnt, sizeof(struct msm_cam_clk_info), GFP_KERNEL); if (!clk_info) return -ENOMEM; clks = devm_kcalloc(&pdev->dev, cnt, sizeof(struct clk *), GFP_KERNEL); if (!clks) { rc = -ENOMEM; goto err1; } rates = devm_kcalloc(&pdev->dev, *num_set, sizeof(uint32_t *), GFP_KERNEL); if (!rates) { rc = -ENOMEM; goto err2; } for (i = 0; i < *num_set; i++) { rates[i] = devm_kcalloc(&pdev->dev, *num_clk, sizeof(uint32_t), GFP_KERNEL); if (!rates[i]) { rc = -ENOMEM; for (--i; i >= 0; i--) devm_kfree(&pdev->dev, rates[i]); goto err3; } } tmp_var = 0; for (i = 0; i < *num_set; i++) { for (j = 0; j < *num_clk; j++) { rc = of_property_read_u32_index(of_node, "qcom,clock-rates", tmp_var++, &rates[i][j]); if (rc < 0) { pr_err("err: failed reading clock rates\n"); rc = -EINVAL; goto err4; } CDBG("Clock rate idx %d idx %d value %d\n", i, j, rates[i][j]); } } for (i = 0; i < *num_clk; i++) { rc = of_property_read_string_index(of_node, "clock-names", i, &clk_info[i].clk_name); if (rc < 0) { pr_err("%s reading clock-name failed index %d\n", __func__, i); rc = -EINVAL; goto err4; } CDBG("dbg: clk-name[%d] = %s\n", i, clk_info[i].clk_name); clks[i] = devm_clk_get(&pdev->dev, clk_info[i].clk_name); if (IS_ERR(clks[i])) { rc = PTR_ERR(clks[i]); goto err5; } CDBG("clk ptr[%d] :%p\n", i, clks[i]); } *pclk_info = clk_info; *pclks = clks; *pclk_rates = rates; return rc; err5: for (--i; i >= 0; i--) devm_clk_put(&pdev->dev, clks[i]); err4: for (i = 0; i < *num_set; i++) devm_kfree(&pdev->dev, rates[i]); err3: devm_kfree(&pdev->dev, rates); err2: devm_kfree(&pdev->dev, clks); err1: devm_kfree(&pdev->dev, clk_info); return rc; } EXPORT_SYMBOL(msm_camera_get_clk_info_and_rates); /* Enable/Disable all clocks */ int msm_camera_clk_enable(struct device *dev, struct msm_cam_clk_info *clk_info, Loading Loading @@ -274,17 +404,21 @@ int msm_camera_clk_set_rate(struct device *dev, if (!dev || !clk) return -EINVAL; CDBG("clk : %p, enable : %ld\n", clk, clk_rate); if (clk_rate > 0) { clk_rate = clk_round_rate(clk, clk_rate); if (clk_rate < 0) { pr_err("round rate failed:\n"); pr_err("round rate failed\n"); return -EINVAL; } rc = clk_set_rate(clk, clk_rate); if (rc < 0) { pr_err("set rate failed:\n"); pr_err("set rate failed\n"); return -EINVAL; } } return 0; } Loading @@ -311,6 +445,31 @@ int msm_camera_put_clk_info(struct platform_device *pdev, } EXPORT_SYMBOL(msm_camera_put_clk_info); int msm_camera_put_clk_info_and_rates(struct platform_device *pdev, struct msm_cam_clk_info **clk_info, struct clk ***clk_ptr, uint32_t ***clk_rates, size_t set, size_t cnt) { int i; for (i = set - 1; i >= 0; i--) devm_kfree(&pdev->dev, (*clk_rates)[i]); devm_kfree(&pdev->dev, *clk_rates); for (i = cnt - 1; i >= 0; i--) { if (clk_ptr[i] != NULL) devm_clk_put(&pdev->dev, (*clk_ptr)[i]); CDBG("clk ptr[%d] :%p\n", i, (*clk_ptr)[i]); } devm_kfree(&pdev->dev, *clk_info); devm_kfree(&pdev->dev, *clk_ptr); *clk_info = NULL; *clk_ptr = NULL; *clk_rates = NULL; return 0; } EXPORT_SYMBOL(msm_camera_put_clk_info_and_rates); /* Get regulators from DT */ int msm_camera_get_regulator_info(struct platform_device *pdev, struct regulator ***vdd, Loading Loading @@ -392,7 +551,7 @@ int msm_camera_regulator_enable(struct regulator **vdd, CDBG("cnt : %d, enable : %d\n", cnt, enable); if (!vdd) { pr_err("Invalid Params"); pr_err("Invalid params"); return -EINVAL; } Loading Loading @@ -447,7 +606,7 @@ struct resource *msm_camera_get_irq(struct platform_device *pdev, char *irq_name) { if (!pdev || !irq_name) { pr_err("Invalid Params\n"); pr_err("Invalid params\n"); return NULL; } Loading @@ -458,17 +617,17 @@ EXPORT_SYMBOL(msm_camera_get_irq); int msm_camera_register_irq(struct platform_device *pdev, struct resource *irq, irq_handler_t handler, char *irq_name, void *dev_id) unsigned long irqflags, char *irq_name, void *dev_id) { int rc = 0; if (!pdev || !irq || !handler || !irq_name || !dev_id) { pr_err("Invalid Params\n"); pr_err("Invalid params\n"); return -EINVAL; } rc = devm_request_irq(&pdev->dev, irq->start, handler, IRQF_TRIGGER_RISING, irq_name, dev_id); irqflags, irq_name, dev_id); if (rc < 0) { pr_err("irq request fail\n"); rc = -EINVAL; Loading @@ -480,10 +639,36 @@ int msm_camera_register_irq(struct platform_device *pdev, } EXPORT_SYMBOL(msm_camera_register_irq); int msm_camera_register_threaded_irq(struct platform_device *pdev, struct resource *irq, irq_handler_t handler_fn, irq_handler_t thread_fn, unsigned long irqflags, char *irq_name, void *dev_id) { int rc = 0; if (!pdev || !irq || !handler_fn || !thread_fn || !irq_name || !dev_id) { pr_err("Invalid params\n"); return -EINVAL; } rc = devm_request_threaded_irq(&pdev->dev, irq->start, handler_fn, thread_fn, irqflags, irq_name, dev_id); if (rc < 0) { pr_err("irq request fail\n"); rc = -EINVAL; } CDBG("Registered irq for %s[resource - %p]\n", irq_name, irq); return rc; } EXPORT_SYMBOL(msm_camera_register_threaded_irq); int msm_camera_enable_irq(struct resource *irq, int enable) { if (!irq) { pr_err("Invalid Params\n"); pr_err("Invalid params\n"); return -EINVAL; } Loading @@ -502,7 +687,7 @@ int msm_camera_unregister_irq(struct platform_device *pdev, { if (!pdev || !irq || !dev_id) { pr_err("Invalid Params\n"); pr_err("Invalid params\n"); return -EINVAL; } Loading @@ -514,13 +699,13 @@ int msm_camera_unregister_irq(struct platform_device *pdev, EXPORT_SYMBOL(msm_camera_unregister_irq); void __iomem *msm_camera_get_reg_base(struct platform_device *pdev, char *device_name) char *device_name, int reserve_mem) { struct resource *mem; void *base; if (!pdev || !device_name) { pr_err("Invalid Params\n"); pr_err("Invalid params\n"); return NULL; } Loading @@ -532,11 +717,17 @@ void __iomem *msm_camera_get_reg_base(struct platform_device *pdev, return NULL; } if (!devm_request_mem_region(&pdev->dev, mem->start, resource_size(mem), if (reserve_mem) { CDBG("device:%p, mem : %p, size : %d\n", &pdev->dev, mem, (int)resource_size(mem)); if (!devm_request_mem_region(&pdev->dev, mem->start, resource_size(mem), device_name)) { pr_err("err: no valid mem region for device:%s\n", device_name); pr_err("err: no valid mem region for device:%s\n", device_name); return NULL; } } base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); if (!base) { Loading @@ -551,13 +742,35 @@ void __iomem *msm_camera_get_reg_base(struct platform_device *pdev, } EXPORT_SYMBOL(msm_camera_get_reg_base); int msm_camera_put_reg_base(struct platform_device *pdev, void __iomem *base, uint32_t msm_camera_get_res_size(struct platform_device *pdev, char *device_name) { struct resource *mem; if (!pdev || !device_name) { pr_err("Invalid params\n"); return 0; } CDBG("device name :%s\n", device_name); mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, device_name); if (!mem) { pr_err("err: mem resource %s not found\n", device_name); return 0; } return resource_size(mem); } EXPORT_SYMBOL(msm_camera_get_res_size); int msm_camera_put_reg_base(struct platform_device *pdev, void __iomem *base, char *device_name, int reserve_mem) { struct resource *mem; if (!pdev || !base || !device_name) { pr_err("Invalid Params\n"); pr_err("Invalid params\n"); return -EINVAL; } Loading @@ -568,9 +781,12 @@ int msm_camera_put_reg_base(struct platform_device *pdev, void __iomem *base, pr_err("err: mem resource %s not found\n", device_name); return -EINVAL; } CDBG("mem : %p, size : %d\n", mem, (int)resource_size(mem)); devm_iounmap(&pdev->dev, base); devm_release_mem_region(&pdev->dev, mem->start, resource_size(mem)); if (reserve_mem) devm_release_mem_region(&pdev->dev, mem->start, resource_size(mem)); return 0; } Loading @@ -578,7 +794,7 @@ EXPORT_SYMBOL(msm_camera_put_reg_base); /* Register the bus client */ uint32_t msm_camera_register_bus_client(struct platform_device *pdev, enum cam_ahb_clk_client id) enum cam_bus_client id) { int rc = 0; uint32_t bus_client, num_usecases, num_paths; Loading @@ -587,8 +803,8 @@ uint32_t msm_camera_register_bus_client(struct platform_device *pdev, CDBG("Register client ID: %d\n", id); if (id >= CAM_AHB_CLIENT_MAX || !pdev) { pr_err("Invalid Params"); if (id >= CAM_BUS_CLIENT_MAX || !pdev) { pr_err("Invalid params"); return -EINVAL; } Loading Loading @@ -642,7 +858,7 @@ uint32_t msm_camera_register_bus_client(struct platform_device *pdev, g_cv[id].vector_index = 0; g_cv[id].num_usecases = num_usecases; g_cv[id].num_paths = num_paths; mutex_init(&g_cv[id].lock); CDBG("Exit Client ID: %d\n", id); return 0; } Loading @@ -655,8 +871,8 @@ uint32_t msm_camera_update_bus_bw(int id, uint64_t ab, uint64_t ib) struct msm_bus_scale_pdata *pdata; int idx = 0; if (id >= CAM_AHB_CLIENT_MAX) { pr_err("Invalid Params"); if (id >= CAM_BUS_CLIENT_MAX) { pr_err("Invalid params"); return -EINVAL; } if (g_cv[id].num_usecases != 2 || Loading @@ -666,11 +882,13 @@ uint32_t msm_camera_update_bus_bw(int id, uint64_t ab, uint64_t ib) return -EINVAL; } mutex_lock(&g_cv[id].lock); idx = g_cv[id].vector_index; pdata = g_cv[id].pdata; idx = 1 - idx; g_cv[id].vector_index = idx; mutex_unlock(&g_cv[id].lock); pdata = g_cv[id].pdata; path = &(pdata->usecase[idx]); path->vectors[0].ab = ab; path->vectors[0].ib = ib; Loading @@ -678,26 +896,26 @@ uint32_t msm_camera_update_bus_bw(int id, uint64_t ab, uint64_t ib) CDBG("Register client ID : %d [ab : %llx, ib : %llx], update :%d\n", id, ab, ib, idx); msm_bus_scale_client_update_request(g_cv[id].bus_client, idx); g_cv[id].vector_index = idx; return 0; } EXPORT_SYMBOL(msm_camera_update_bus_bw); /* Update the bus vector */ uint32_t msm_camera_update_bus_vector(enum cam_ahb_clk_client id, uint32_t msm_camera_update_bus_vector(enum cam_bus_client id, int vector_index) { if (id >= CAM_AHB_CLIENT_MAX || g_cv[id].dyn_vote == true) { pr_err("Invalid Params"); if (id >= CAM_BUS_CLIENT_MAX || g_cv[id].dyn_vote == true) { pr_err("Invalid params"); return -EINVAL; } if (vector_index < 0 || vector_index > g_cv[id].num_usecases) { pr_err("Invalid Params"); pr_err("Invalid params"); return -EINVAL; } CDBG("Register client ID : %d vector idx: %d,\n", id, vector_index); msm_bus_scale_client_update_request(g_cv[id].bus_client, vector_index); Loading @@ -706,15 +924,16 @@ uint32_t msm_camera_update_bus_vector(enum cam_ahb_clk_client id, EXPORT_SYMBOL(msm_camera_update_bus_vector); /* Unregister the bus client */ uint32_t msm_camera_unregister_bus_client(enum cam_ahb_clk_client id) uint32_t msm_camera_unregister_bus_client(enum cam_bus_client id) { if (id >= CAM_AHB_CLIENT_MAX) { pr_err("Invalid Params"); if (id >= CAM_BUS_CLIENT_MAX) { pr_err("Invalid params"); return -EINVAL; } CDBG("UnRegister client ID: %d\n", id); mutex_destroy(&g_cv[id].lock); msm_bus_scale_unregister_client(g_cv[id].bus_client); msm_bus_cl_clear_pdata(g_cv[id].pdata); memset(&g_cv[id], 0, sizeof(struct msm_cam_bus_pscale_data)); Loading
drivers/media/platform/msm/camera_v2/common/cam_soc_api.h +107 −10 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 @@ -22,7 +22,17 @@ #include <linux/interrupt.h> #include <linux/slab.h> #include <soc/qcom/camera2.h> #include "cam_hw_ops.h" enum cam_bus_client { CAM_BUS_CLIENT_VFE, CAM_BUS_CLIENT_CPP, CAM_BUS_CLIENT_FD, CAM_BUS_CLIENT_JPEG_ENC0, CAM_BUS_CLIENT_JPEG_ENC1, CAM_BUS_CLIENT_JPEG_DEC, CAM_BUS_CLIENT_JPEG_DMA, CAM_BUS_CLIENT_MAX }; /** * @brief : Gets clock information from dtsi Loading @@ -32,7 +42,7 @@ * * @param pdev : Platform device to get clocks information * @param clk_info : Pointer to populate clock information array * @param clk_info : Pointer to populate clock resource pointers * @param clk_ptr : Pointer to populate clock resource pointers * @param num_clk: Pointer to populate the number of clocks * extracted from dtsi * Loading @@ -43,6 +53,30 @@ int msm_camera_get_clk_info(struct platform_device *pdev, struct msm_cam_clk_info **clk_info, struct clk ***clk_ptr, size_t *num_clk); /** * @brief : Gets clock information and rates from dtsi * * This function extracts the clocks information for a specific * platform device * * @param pdev : Platform device to get clocks information * @param clk_info : Pointer to populate clock information array * @param clk_ptr : Pointer to populate clock resource pointers * @param clk_rates : Pointer to populate clock rates * @param num_set: Pointer to populate the number of sets of rates * @param num_clk: Pointer to populate the number of clocks * extracted from dtsi * * @return Status of operation. Negative in case of error. Zero otherwise. */ int msm_camera_get_clk_info_and_rates( struct platform_device *pdev, struct msm_cam_clk_info **clk_info, struct clk ***clk_ptr, uint32_t ***clk_rates, size_t *num_set, size_t *num_clk); /** * @brief : Puts clock information * Loading @@ -58,6 +92,25 @@ int msm_camera_get_clk_info(struct platform_device *pdev, int msm_camera_put_clk_info(struct platform_device *pdev, struct msm_cam_clk_info **clk_info, struct clk ***clk_ptr, int cnt); /** * @brief : Puts clock information * * This function releases the memory allocated for the clocks * * @param pdev : Pointer to platform device * @param clk_info : Pointer to release the allocated memory * @param clk_ptr : Pointer to release the clock resources * @param clk_ptr : Pointer to release the clock rates * @param set : Number of sets of clock rates * @param cnt : Number of clk resources * * @return Status of operation. Negative in case of error. Zero otherwise. */ int msm_camera_put_clk_info_and_rates(struct platform_device *pdev, struct msm_cam_clk_info **clk_info, struct clk ***clk_ptr, uint32_t ***clk_rates, size_t set, size_t cnt); /** * @brief : Enable clocks * Loading Loading @@ -160,6 +213,7 @@ struct resource *msm_camera_get_irq(struct platform_device *pdev, * @param pdev : Platform device to register IRQ resource * @param irq : IRQ resource * @param handler : IRQ handler * @param irqflags : IRQ flags * @param irq_name: Name of the IRQ * @param dev : Token of the device * Loading @@ -169,6 +223,31 @@ struct resource *msm_camera_get_irq(struct platform_device *pdev, int msm_camera_register_irq(struct platform_device *pdev, struct resource *irq, irq_handler_t handler, unsigned long irqflags, char *irq_name, void *dev); /** * @brief : Register the threaded IRQ * * This function registers the irq resource for specified hardware * * @param pdev : Platform device to register IRQ resource * @param irq : IRQ resource * @param handler_fn : IRQ handler function * @param thread_fn : thread handler function * @param irqflags : IRQ flags * @param irq_name: Name of the IRQ * @param dev : Token of the device * * @return Status of operation. Negative in case of error. Zero otherwise. */ int msm_camera_register_threaded_irq(struct platform_device *pdev, struct resource *irq, irq_handler_t handler_fn, irq_handler_t thread_fn, unsigned long irqflags, char *irq_name, void *dev); Loading Loading @@ -208,12 +287,14 @@ int msm_camera_unregister_irq(struct platform_device *pdev, * * @param pdev : Platform device to get regulator infor * @param device_name : Name of the device to fetch the register base * @param reserve_mem : Flag to decide whether to reserve memory * region or not. * * @return Pointer to resource if success else null */ void __iomem *msm_camera_get_reg_base(struct platform_device *pdev, char *device_name); char *device_name, int reserve_mem); /** * @brief : Puts device register base Loading @@ -224,27 +305,28 @@ void __iomem *msm_camera_get_reg_base(struct platform_device *pdev, * @param pdev : Pointer to platform device * @param base : Pointer to base to unmap * @param device_name : Device name * @param reserve_mem : Flag to decide whether to release memory * region or not. * * @return Status of operation. Negative in case of error. Zero otherwise. */ int msm_camera_put_reg_base(struct platform_device *pdev, void __iomem *base, char *device_name); char *device_name, int reserve_mem); /** * @brief : Register the bus client * * This function registers the bus client * * @param client_id : client identifier * @param pdev : Pointer to platform device * @param vector_index : vector index to register * @param id : client identifier * * @return Status of operation. Negative in case of error. Zero otherwise. */ uint32_t msm_camera_register_bus_client(struct platform_device *pdev, enum cam_ahb_clk_client id); enum cam_bus_client id); /** * @brief : Update bus vector Loading @@ -257,7 +339,7 @@ uint32_t msm_camera_register_bus_client(struct platform_device *pdev, * @return Status of operation. Negative in case of error. Zero otherwise. */ uint32_t msm_camera_update_bus_vector(enum cam_ahb_clk_client id, uint32_t msm_camera_update_bus_vector(enum cam_bus_client id, int vector_index); /** Loading @@ -284,6 +366,21 @@ uint32_t msm_camera_update_bus_bw(int id, uint64_t ab, uint64_t ib); * @return Status of operation. Negative in case of error. Zero otherwise. */ uint32_t msm_camera_unregister_bus_client(enum cam_ahb_clk_client id); uint32_t msm_camera_unregister_bus_client(enum cam_bus_client id); /** * @brief : Gets resource size * * This function returns the size of the resource for the * specified platform device * * @param pdev : Platform device to get regulator infor * @param device_name : Name of the device to fetch the register base * * @return size of the resource */ uint32_t msm_camera_get_res_size(struct platform_device *pdev, char *device_name); #endif