1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. 4 */ 5 6 #include <linux/clk.h> 7 #include <linux/interconnect.h> 8 #include <linux/module.h> 9 #include <linux/pm_domain.h> 10 #include <linux/pm_opp.h> 11 #include <linux/pm_runtime.h> 12 #include <linux/reset.h> 13 14 #include "iris_core.h" 15 #include "iris_ctrls.h" 16 #include "iris_vidc.h" 17 18 static int iris_init_icc(struct iris_core *core) 19 { 20 const struct icc_info *icc_tbl; 21 u32 i = 0; 22 23 icc_tbl = core->iris_platform_data->icc_tbl; 24 25 core->icc_count = core->iris_platform_data->icc_tbl_size; 26 core->icc_tbl = devm_kzalloc(core->dev, 27 sizeof(struct icc_bulk_data) * core->icc_count, 28 GFP_KERNEL); 29 if (!core->icc_tbl) 30 return -ENOMEM; 31 32 for (i = 0; i < core->icc_count; i++) { 33 core->icc_tbl[i].name = icc_tbl[i].name; 34 core->icc_tbl[i].avg_bw = icc_tbl[i].bw_min_kbps; 35 core->icc_tbl[i].peak_bw = 0; 36 } 37 38 return devm_of_icc_bulk_get(core->dev, core->icc_count, core->icc_tbl); 39 } 40 41 static int iris_init_power_domains(struct iris_core *core) 42 { 43 const struct platform_clk_data *clk_tbl; 44 u32 clk_cnt, i; 45 int ret; 46 47 struct dev_pm_domain_attach_data iris_pd_data = { 48 .pd_names = core->iris_platform_data->pmdomain_tbl, 49 .num_pd_names = core->iris_platform_data->pmdomain_tbl_size, 50 .pd_flags = PD_FLAG_NO_DEV_LINK, 51 }; 52 53 struct dev_pm_domain_attach_data iris_opp_pd_data = { 54 .pd_names = core->iris_platform_data->opp_pd_tbl, 55 .num_pd_names = core->iris_platform_data->opp_pd_tbl_size, 56 .pd_flags = PD_FLAG_DEV_LINK_ON, 57 }; 58 59 ret = devm_pm_domain_attach_list(core->dev, &iris_pd_data, &core->pmdomain_tbl); 60 if (ret < 0) 61 return ret; 62 63 ret = devm_pm_domain_attach_list(core->dev, &iris_opp_pd_data, &core->opp_pmdomain_tbl); 64 if (ret < 0) 65 return ret; 66 67 clk_tbl = core->iris_platform_data->clk_tbl; 68 clk_cnt = core->iris_platform_data->clk_tbl_size; 69 70 for (i = 0; i < clk_cnt; i++) { 71 if (clk_tbl[i].clk_type == IRIS_HW_CLK) { 72 ret = devm_pm_opp_set_clkname(core->dev, clk_tbl[i].clk_name); 73 if (ret) 74 return ret; 75 } 76 } 77 78 return devm_pm_opp_of_add_table(core->dev); 79 } 80 81 static int iris_init_clocks(struct iris_core *core) 82 { 83 int ret; 84 85 ret = devm_clk_bulk_get_all(core->dev, &core->clock_tbl); 86 if (ret < 0) 87 return ret; 88 89 core->clk_count = ret; 90 91 return 0; 92 } 93 94 static int iris_init_resets(struct iris_core *core) 95 { 96 const char * const *rst_tbl; 97 u32 rst_tbl_size; 98 u32 i = 0; 99 100 rst_tbl = core->iris_platform_data->clk_rst_tbl; 101 rst_tbl_size = core->iris_platform_data->clk_rst_tbl_size; 102 103 core->resets = devm_kzalloc(core->dev, 104 sizeof(*core->resets) * rst_tbl_size, 105 GFP_KERNEL); 106 if (!core->resets) 107 return -ENOMEM; 108 109 for (i = 0; i < rst_tbl_size; i++) 110 core->resets[i].id = rst_tbl[i]; 111 112 return devm_reset_control_bulk_get_exclusive(core->dev, rst_tbl_size, core->resets); 113 } 114 115 static int iris_init_resources(struct iris_core *core) 116 { 117 int ret; 118 119 ret = iris_init_icc(core); 120 if (ret) 121 return ret; 122 123 ret = iris_init_power_domains(core); 124 if (ret) 125 return ret; 126 127 ret = iris_init_clocks(core); 128 if (ret) 129 return ret; 130 131 return iris_init_resets(core); 132 } 133 134 static int iris_register_video_device(struct iris_core *core) 135 { 136 struct video_device *vdev; 137 int ret; 138 139 vdev = video_device_alloc(); 140 if (!vdev) 141 return -ENOMEM; 142 143 strscpy(vdev->name, "qcom-iris-decoder", sizeof(vdev->name)); 144 vdev->release = video_device_release; 145 vdev->fops = core->iris_v4l2_file_ops; 146 vdev->ioctl_ops = core->iris_v4l2_ioctl_ops; 147 vdev->vfl_dir = VFL_DIR_M2M; 148 vdev->v4l2_dev = &core->v4l2_dev; 149 vdev->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING; 150 151 ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); 152 if (ret) 153 goto err_vdev_release; 154 155 core->vdev_dec = vdev; 156 video_set_drvdata(vdev, core); 157 158 return 0; 159 160 err_vdev_release: 161 video_device_release(vdev); 162 163 return ret; 164 } 165 166 static void iris_remove(struct platform_device *pdev) 167 { 168 struct iris_core *core; 169 170 core = platform_get_drvdata(pdev); 171 if (!core) 172 return; 173 174 iris_core_deinit(core); 175 176 video_unregister_device(core->vdev_dec); 177 178 v4l2_device_unregister(&core->v4l2_dev); 179 180 mutex_destroy(&core->lock); 181 } 182 183 static void iris_sys_error_handler(struct work_struct *work) 184 { 185 struct iris_core *core = 186 container_of(work, struct iris_core, sys_error_handler.work); 187 188 iris_core_deinit(core); 189 iris_core_init(core); 190 } 191 192 static int iris_probe(struct platform_device *pdev) 193 { 194 struct device *dev = &pdev->dev; 195 struct iris_core *core; 196 u64 dma_mask; 197 int ret; 198 199 core = devm_kzalloc(&pdev->dev, sizeof(*core), GFP_KERNEL); 200 if (!core) 201 return -ENOMEM; 202 core->dev = dev; 203 204 core->state = IRIS_CORE_DEINIT; 205 mutex_init(&core->lock); 206 init_completion(&core->core_init_done); 207 208 core->response_packet = devm_kzalloc(core->dev, IFACEQ_CORE_PKT_SIZE, GFP_KERNEL); 209 if (!core->response_packet) 210 return -ENOMEM; 211 212 INIT_LIST_HEAD(&core->instances); 213 INIT_DELAYED_WORK(&core->sys_error_handler, iris_sys_error_handler); 214 215 core->reg_base = devm_platform_ioremap_resource(pdev, 0); 216 if (IS_ERR(core->reg_base)) 217 return PTR_ERR(core->reg_base); 218 219 core->irq = platform_get_irq(pdev, 0); 220 if (core->irq < 0) 221 return core->irq; 222 223 core->iris_platform_data = of_device_get_match_data(core->dev); 224 225 ret = devm_request_threaded_irq(core->dev, core->irq, iris_hfi_isr, 226 iris_hfi_isr_handler, IRQF_TRIGGER_HIGH, "iris", core); 227 if (ret) 228 return ret; 229 230 disable_irq_nosync(core->irq); 231 232 iris_init_ops(core); 233 core->iris_platform_data->init_hfi_command_ops(core); 234 core->iris_platform_data->init_hfi_response_ops(core); 235 236 ret = iris_init_resources(core); 237 if (ret) 238 return ret; 239 240 iris_session_init_caps(core); 241 242 ret = v4l2_device_register(dev, &core->v4l2_dev); 243 if (ret) 244 return ret; 245 246 ret = iris_register_video_device(core); 247 if (ret) 248 goto err_v4l2_unreg; 249 250 platform_set_drvdata(pdev, core); 251 252 dma_mask = core->iris_platform_data->dma_mask; 253 254 ret = dma_set_mask_and_coherent(dev, dma_mask); 255 if (ret) 256 goto err_vdev_unreg; 257 258 dma_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32)); 259 dma_set_seg_boundary(&pdev->dev, DMA_BIT_MASK(32)); 260 261 pm_runtime_set_autosuspend_delay(core->dev, AUTOSUSPEND_DELAY_VALUE); 262 pm_runtime_use_autosuspend(core->dev); 263 ret = devm_pm_runtime_enable(core->dev); 264 if (ret) 265 goto err_vdev_unreg; 266 267 return 0; 268 269 err_vdev_unreg: 270 video_unregister_device(core->vdev_dec); 271 err_v4l2_unreg: 272 v4l2_device_unregister(&core->v4l2_dev); 273 274 return ret; 275 } 276 277 static int __maybe_unused iris_pm_suspend(struct device *dev) 278 { 279 struct iris_core *core; 280 int ret = 0; 281 282 core = dev_get_drvdata(dev); 283 284 mutex_lock(&core->lock); 285 if (core->state != IRIS_CORE_INIT) 286 goto exit; 287 288 ret = iris_hfi_pm_suspend(core); 289 290 exit: 291 mutex_unlock(&core->lock); 292 293 return ret; 294 } 295 296 static int __maybe_unused iris_pm_resume(struct device *dev) 297 { 298 struct iris_core *core; 299 int ret = 0; 300 301 core = dev_get_drvdata(dev); 302 303 mutex_lock(&core->lock); 304 if (core->state != IRIS_CORE_INIT) 305 goto exit; 306 307 ret = iris_hfi_pm_resume(core); 308 pm_runtime_mark_last_busy(core->dev); 309 310 exit: 311 mutex_unlock(&core->lock); 312 313 return ret; 314 } 315 316 static const struct dev_pm_ops iris_pm_ops = { 317 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 318 pm_runtime_force_resume) 319 SET_RUNTIME_PM_OPS(iris_pm_suspend, iris_pm_resume, NULL) 320 }; 321 322 static const struct of_device_id iris_dt_match[] = { 323 { 324 .compatible = "qcom,sm8550-iris", 325 .data = &sm8550_data, 326 }, 327 #if (!IS_ENABLED(CONFIG_VIDEO_QCOM_VENUS)) 328 { 329 .compatible = "qcom,sm8250-venus", 330 .data = &sm8250_data, 331 }, 332 #endif 333 { }, 334 }; 335 MODULE_DEVICE_TABLE(of, iris_dt_match); 336 337 static struct platform_driver qcom_iris_driver = { 338 .probe = iris_probe, 339 .remove = iris_remove, 340 .driver = { 341 .name = "qcom-iris", 342 .of_match_table = iris_dt_match, 343 .pm = &iris_pm_ops, 344 }, 345 }; 346 347 module_platform_driver(qcom_iris_driver); 348 MODULE_DESCRIPTION("Qualcomm iris video driver"); 349 MODULE_LICENSE("GPL"); 350