Rajakumar Govindaram | 7d2b977 | 2017-07-19 15:16:12 -0700 | [diff] [blame] | 1 | /* Copyright (c) 2017, The Linux Foundation. All rights reserved. |
| 2 | * |
| 3 | * This program is free software; you can redistribute it and/or modify |
| 4 | * it under the terms of the GNU General Public License version 2 and |
| 5 | * only version 2 as published by the Free Software Foundation. |
| 6 | * |
| 7 | * This program is distributed in the hope that it will be useful, |
| 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 10 | * GNU General Public License for more details. |
| 11 | */ |
| 12 | |
| 13 | #include <linux/module.h> |
| 14 | #include <linux/slab.h> |
| 15 | #include <linux/mod_devicetable.h> |
| 16 | #include <linux/of_device.h> |
| 17 | #include <linux/timer.h> |
| 18 | |
| 19 | #include "jpeg_dma_core.h" |
| 20 | #include "jpeg_dma_soc.h" |
| 21 | #include "cam_hw.h" |
| 22 | #include "cam_hw_intf.h" |
| 23 | #include "cam_io_util.h" |
| 24 | #include "cam_jpeg_hw_intf.h" |
| 25 | #include "cam_jpeg_hw_mgr_intf.h" |
| 26 | #include "cam_cpas_api.h" |
| 27 | #include "cam_debug_util.h" |
| 28 | |
| 29 | static struct cam_jpeg_dma_device_hw_info cam_jpeg_dma_hw_info = { |
| 30 | .reserved = 0, |
| 31 | }; |
| 32 | EXPORT_SYMBOL(cam_jpeg_dma_hw_info); |
| 33 | |
| 34 | static int cam_jpeg_dma_register_cpas(struct cam_hw_soc_info *soc_info, |
| 35 | struct cam_jpeg_dma_device_core_info *core_info, |
| 36 | uint32_t hw_idx) |
| 37 | { |
| 38 | struct cam_cpas_register_params cpas_register_params; |
| 39 | int rc; |
| 40 | |
Jigarkumar Zala | b7b49f1 | 2017-08-21 16:45:38 -0700 | [diff] [blame] | 41 | cpas_register_params.dev = soc_info->dev; |
Rajakumar Govindaram | 7d2b977 | 2017-07-19 15:16:12 -0700 | [diff] [blame] | 42 | memcpy(cpas_register_params.identifier, "jpeg-dma", |
| 43 | sizeof("jpeg-dma")); |
| 44 | cpas_register_params.cam_cpas_client_cb = NULL; |
| 45 | cpas_register_params.cell_index = hw_idx; |
| 46 | cpas_register_params.userdata = NULL; |
| 47 | |
| 48 | rc = cam_cpas_register_client(&cpas_register_params); |
| 49 | if (rc) { |
| 50 | CAM_ERR(CAM_JPEG, "cpas_register failed: %d", rc); |
| 51 | return rc; |
| 52 | } |
| 53 | core_info->cpas_handle = cpas_register_params.client_handle; |
| 54 | |
| 55 | return rc; |
| 56 | } |
| 57 | |
| 58 | static int cam_jpeg_dma_unregister_cpas( |
| 59 | struct cam_jpeg_dma_device_core_info *core_info) |
| 60 | { |
| 61 | int rc; |
| 62 | |
| 63 | rc = cam_cpas_unregister_client(core_info->cpas_handle); |
| 64 | if (rc) |
| 65 | CAM_ERR(CAM_JPEG, "cpas unregister failed: %d", rc); |
| 66 | core_info->cpas_handle = 0; |
| 67 | |
| 68 | return rc; |
| 69 | } |
| 70 | |
| 71 | static int cam_jpeg_dma_remove(struct platform_device *pdev) |
| 72 | { |
| 73 | struct cam_hw_info *jpeg_dma_dev = NULL; |
| 74 | struct cam_hw_intf *jpeg_dma_dev_intf = NULL; |
| 75 | struct cam_jpeg_dma_device_core_info *core_info = NULL; |
| 76 | int rc; |
| 77 | |
| 78 | jpeg_dma_dev_intf = platform_get_drvdata(pdev); |
| 79 | if (!jpeg_dma_dev_intf) { |
| 80 | CAM_ERR(CAM_JPEG, "error No data in pdev"); |
| 81 | return -EINVAL; |
| 82 | } |
| 83 | |
| 84 | jpeg_dma_dev = jpeg_dma_dev_intf->hw_priv; |
| 85 | if (!jpeg_dma_dev) { |
| 86 | CAM_ERR(CAM_JPEG, "error HW data is NULL"); |
| 87 | rc = -ENODEV; |
| 88 | goto free_jpeg_hw_intf; |
| 89 | } |
| 90 | |
| 91 | core_info = (struct cam_jpeg_dma_device_core_info *) |
| 92 | jpeg_dma_dev->core_info; |
| 93 | if (!core_info) { |
| 94 | CAM_ERR(CAM_JPEG, "error core data NULL"); |
| 95 | goto deinit_soc; |
| 96 | } |
| 97 | |
| 98 | rc = cam_jpeg_dma_unregister_cpas(core_info); |
| 99 | if (rc) |
| 100 | CAM_ERR(CAM_JPEG, " unreg failed to reg cpas %d", rc); |
| 101 | |
Rajakumar Govindaram | 2264d15 | 2017-09-11 10:53:31 -0700 | [diff] [blame] | 102 | mutex_destroy(&core_info->core_mutex); |
Rajakumar Govindaram | 7d2b977 | 2017-07-19 15:16:12 -0700 | [diff] [blame] | 103 | kfree(core_info); |
| 104 | |
| 105 | deinit_soc: |
| 106 | rc = cam_soc_util_release_platform_resource(&jpeg_dma_dev->soc_info); |
| 107 | if (rc) |
| 108 | CAM_ERR(CAM_JPEG, "Failed to deinit soc rc=%d", rc); |
| 109 | |
| 110 | mutex_destroy(&jpeg_dma_dev->hw_mutex); |
| 111 | kfree(jpeg_dma_dev); |
| 112 | |
| 113 | free_jpeg_hw_intf: |
| 114 | kfree(jpeg_dma_dev_intf); |
| 115 | return rc; |
| 116 | } |
| 117 | |
| 118 | static int cam_jpeg_dma_probe(struct platform_device *pdev) |
| 119 | { |
| 120 | struct cam_hw_info *jpeg_dma_dev = NULL; |
| 121 | struct cam_hw_intf *jpeg_dma_dev_intf = NULL; |
| 122 | const struct of_device_id *match_dev = NULL; |
| 123 | struct cam_jpeg_dma_device_core_info *core_info = NULL; |
| 124 | struct cam_jpeg_dma_device_hw_info *hw_info = NULL; |
| 125 | int rc; |
| 126 | |
| 127 | jpeg_dma_dev_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL); |
| 128 | if (!jpeg_dma_dev_intf) |
| 129 | return -ENOMEM; |
| 130 | |
| 131 | of_property_read_u32(pdev->dev.of_node, |
| 132 | "cell-index", &jpeg_dma_dev_intf->hw_idx); |
| 133 | |
| 134 | jpeg_dma_dev = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL); |
| 135 | if (!jpeg_dma_dev) { |
| 136 | rc = -ENOMEM; |
| 137 | goto error_alloc_dev; |
| 138 | } |
| 139 | jpeg_dma_dev->soc_info.pdev = pdev; |
Jigarkumar Zala | b7b49f1 | 2017-08-21 16:45:38 -0700 | [diff] [blame] | 140 | jpeg_dma_dev->soc_info.dev = &pdev->dev; |
| 141 | jpeg_dma_dev->soc_info.dev_name = pdev->name; |
Rajakumar Govindaram | 7d2b977 | 2017-07-19 15:16:12 -0700 | [diff] [blame] | 142 | jpeg_dma_dev_intf->hw_priv = jpeg_dma_dev; |
| 143 | jpeg_dma_dev_intf->hw_ops.init = cam_jpeg_dma_init_hw; |
| 144 | jpeg_dma_dev_intf->hw_ops.deinit = cam_jpeg_dma_deinit_hw; |
| 145 | jpeg_dma_dev_intf->hw_ops.process_cmd = cam_jpeg_dma_process_cmd; |
| 146 | jpeg_dma_dev_intf->hw_type = CAM_JPEG_DEV_DMA; |
| 147 | |
| 148 | platform_set_drvdata(pdev, jpeg_dma_dev_intf); |
| 149 | jpeg_dma_dev->core_info = |
| 150 | kzalloc(sizeof(struct cam_jpeg_dma_device_core_info), |
| 151 | GFP_KERNEL); |
| 152 | if (!jpeg_dma_dev->core_info) { |
| 153 | rc = -ENOMEM; |
| 154 | goto error_alloc_core; |
| 155 | } |
| 156 | core_info = (struct cam_jpeg_dma_device_core_info *)jpeg_dma_dev-> |
| 157 | core_info; |
| 158 | |
| 159 | match_dev = of_match_device(pdev->dev.driver->of_match_table, |
| 160 | &pdev->dev); |
| 161 | if (!match_dev) { |
| 162 | CAM_ERR(CAM_JPEG, " No jpeg_dma hardware info"); |
| 163 | rc = -EINVAL; |
| 164 | goto error_match_dev; |
| 165 | } |
| 166 | hw_info = (struct cam_jpeg_dma_device_hw_info *)match_dev->data; |
| 167 | core_info->jpeg_dma_hw_info = hw_info; |
| 168 | core_info->core_state = CAM_JPEG_DMA_CORE_NOT_READY; |
Rajakumar Govindaram | 2264d15 | 2017-09-11 10:53:31 -0700 | [diff] [blame] | 169 | mutex_init(&core_info->core_mutex); |
Rajakumar Govindaram | 7d2b977 | 2017-07-19 15:16:12 -0700 | [diff] [blame] | 170 | |
| 171 | rc = cam_jpeg_dma_init_soc_resources(&jpeg_dma_dev->soc_info, |
| 172 | cam_jpeg_dma_irq, |
| 173 | jpeg_dma_dev); |
| 174 | if (rc) { |
Jigarkumar Zala | 3865c1c | 2017-11-28 12:08:50 -0800 | [diff] [blame] | 175 | CAM_ERR(CAM_JPEG, "failed to init_soc %d", rc); |
Rajakumar Govindaram | 2264d15 | 2017-09-11 10:53:31 -0700 | [diff] [blame] | 176 | goto error_init_soc; |
Rajakumar Govindaram | 7d2b977 | 2017-07-19 15:16:12 -0700 | [diff] [blame] | 177 | } |
| 178 | |
| 179 | rc = cam_jpeg_dma_register_cpas(&jpeg_dma_dev->soc_info, |
| 180 | core_info, jpeg_dma_dev_intf->hw_idx); |
| 181 | if (rc) { |
| 182 | CAM_ERR(CAM_JPEG, " failed to reg cpas %d", rc); |
| 183 | goto error_reg_cpas; |
| 184 | } |
| 185 | jpeg_dma_dev->hw_state = CAM_HW_STATE_POWER_DOWN; |
| 186 | mutex_init(&jpeg_dma_dev->hw_mutex); |
| 187 | spin_lock_init(&jpeg_dma_dev->hw_lock); |
| 188 | init_completion(&jpeg_dma_dev->hw_complete); |
| 189 | |
| 190 | CAM_DBG(CAM_JPEG, " hwidx %d", jpeg_dma_dev_intf->hw_idx); |
| 191 | |
| 192 | return rc; |
| 193 | |
| 194 | error_reg_cpas: |
| 195 | rc = cam_soc_util_release_platform_resource(&jpeg_dma_dev->soc_info); |
Rajakumar Govindaram | 2264d15 | 2017-09-11 10:53:31 -0700 | [diff] [blame] | 196 | error_init_soc: |
| 197 | mutex_destroy(&core_info->core_mutex); |
Rajakumar Govindaram | 7d2b977 | 2017-07-19 15:16:12 -0700 | [diff] [blame] | 198 | error_match_dev: |
| 199 | kfree(jpeg_dma_dev->core_info); |
| 200 | error_alloc_core: |
| 201 | kfree(jpeg_dma_dev); |
| 202 | error_alloc_dev: |
| 203 | kfree(jpeg_dma_dev_intf); |
| 204 | return rc; |
| 205 | } |
| 206 | |
| 207 | static const struct of_device_id cam_jpeg_dma_dt_match[] = { |
| 208 | { |
| 209 | .compatible = "qcom,cam_jpeg_dma", |
| 210 | .data = &cam_jpeg_dma_hw_info, |
| 211 | }, |
| 212 | {} |
| 213 | }; |
| 214 | MODULE_DEVICE_TABLE(of, cam_jpeg_dma_dt_match); |
| 215 | |
| 216 | static struct platform_driver cam_jpeg_dma_driver = { |
| 217 | .probe = cam_jpeg_dma_probe, |
| 218 | .remove = cam_jpeg_dma_remove, |
| 219 | .driver = { |
| 220 | .name = "cam-jpeg-dma", |
| 221 | .owner = THIS_MODULE, |
| 222 | .of_match_table = cam_jpeg_dma_dt_match, |
| 223 | }, |
| 224 | }; |
| 225 | |
| 226 | static int __init cam_jpeg_dma_init_module(void) |
| 227 | { |
| 228 | return platform_driver_register(&cam_jpeg_dma_driver); |
| 229 | } |
| 230 | |
| 231 | static void __exit cam_jpeg_dma_exit_module(void) |
| 232 | { |
| 233 | platform_driver_unregister(&cam_jpeg_dma_driver); |
| 234 | } |
| 235 | |
| 236 | module_init(cam_jpeg_dma_init_module); |
| 237 | module_exit(cam_jpeg_dma_exit_module); |
| 238 | MODULE_DESCRIPTION("CAM JPEG_DMA driver"); |
| 239 | MODULE_LICENSE("GPL v2"); |