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 int ret; 44 45 struct dev_pm_domain_attach_data iris_pd_data = { 46 .pd_names = core->iris_platform_data->pmdomain_tbl, 47 .num_pd_names = core->iris_platform_data->pmdomain_tbl_size, 48 .pd_flags = PD_FLAG_NO_DEV_LINK, 49 }; 50 51 struct dev_pm_domain_attach_data iris_opp_pd_data = { 52 .pd_names = core->iris_platform_data->opp_pd_tbl, 53 .num_pd_names = core->iris_platform_data->opp_pd_tbl_size, 54 .pd_flags = PD_FLAG_DEV_LINK_ON | PD_FLAG_REQUIRED_OPP, 55 }; 56 57 struct dev_pm_opp_config iris_opp_clk_data = { 58 .clk_names = core->iris_platform_data->opp_clk_tbl, 59 .config_clks = dev_pm_opp_config_clks_simple, 60 }; 61 62 ret = devm_pm_domain_attach_list(core->dev, &iris_pd_data, &core->pmdomain_tbl); 63 if (ret < 0) 64 return ret; 65 66 ret = devm_pm_domain_attach_list(core->dev, &iris_opp_pd_data, &core->opp_pmdomain_tbl); 67 if (ret < 0) 68 return ret; 69 70 ret = devm_pm_opp_set_config(core->dev, &iris_opp_clk_data); 71 if (ret) 72 return ret; 73 74 return devm_pm_opp_of_add_table(core->dev); 75 } 76 77 static int iris_init_clocks(struct iris_core *core) 78 { 79 int ret; 80 81 ret = devm_clk_bulk_get_all(core->dev, &core->clock_tbl); 82 if (ret < 0) 83 return ret; 84 85 core->clk_count = ret; 86 87 return 0; 88 } 89 90 static int iris_init_reset_table(struct iris_core *core, 91 struct reset_control_bulk_data **resets, 92 const char * const *rst_tbl, u32 rst_tbl_size) 93 { 94 u32 i = 0; 95 96 *resets = devm_kzalloc(core->dev, 97 sizeof(struct reset_control_bulk_data) * rst_tbl_size, 98 GFP_KERNEL); 99 if (!*resets) 100 return -ENOMEM; 101 102 for (i = 0; i < rst_tbl_size; i++) 103 (*resets)[i].id = rst_tbl[i]; 104 105 return devm_reset_control_bulk_get_exclusive(core->dev, rst_tbl_size, *resets); 106 } 107 108 static int iris_init_resets(struct iris_core *core) 109 { 110 int ret; 111 112 ret = iris_init_reset_table(core, &core->resets, 113 core->iris_platform_data->clk_rst_tbl, 114 core->iris_platform_data->clk_rst_tbl_size); 115 if (ret) 116 return ret; 117 118 if (!core->iris_platform_data->controller_rst_tbl_size) 119 return 0; 120 121 return iris_init_reset_table(core, &core->controller_resets, 122 core->iris_platform_data->controller_rst_tbl, 123 core->iris_platform_data->controller_rst_tbl_size); 124 } 125 126 static int iris_init_resources(struct iris_core *core) 127 { 128 int ret; 129 130 ret = iris_init_icc(core); 131 if (ret) 132 return ret; 133 134 ret = iris_init_power_domains(core); 135 if (ret) 136 return ret; 137 138 ret = iris_init_clocks(core); 139 if (ret) 140 return ret; 141 142 return iris_init_resets(core); 143 } 144 145 static int iris_register_video_device(struct iris_core *core, enum domain_type type) 146 { 147 struct video_device *vdev; 148 int ret; 149 150 vdev = video_device_alloc(); 151 if (!vdev) 152 return -ENOMEM; 153 154 vdev->release = video_device_release; 155 vdev->fops = core->iris_v4l2_file_ops; 156 vdev->vfl_dir = VFL_DIR_M2M; 157 vdev->v4l2_dev = &core->v4l2_dev; 158 vdev->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING; 159 160 if (type == DECODER) { 161 strscpy(vdev->name, "qcom-iris-decoder", sizeof(vdev->name)); 162 vdev->ioctl_ops = core->iris_v4l2_ioctl_ops_dec; 163 core->vdev_dec = vdev; 164 } else if (type == ENCODER) { 165 strscpy(vdev->name, "qcom-iris-encoder", sizeof(vdev->name)); 166 vdev->ioctl_ops = core->iris_v4l2_ioctl_ops_enc; 167 core->vdev_enc = vdev; 168 } else { 169 ret = -EINVAL; 170 goto err_vdev_release; 171 } 172 173 ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); 174 if (ret) 175 goto err_vdev_release; 176 177 video_set_drvdata(vdev, core); 178 179 return 0; 180 181 err_vdev_release: 182 video_device_release(vdev); 183 184 return ret; 185 } 186 187 static void iris_remove(struct platform_device *pdev) 188 { 189 struct iris_core *core; 190 191 core = platform_get_drvdata(pdev); 192 if (!core) 193 return; 194 195 iris_core_deinit(core); 196 197 video_unregister_device(core->vdev_dec); 198 video_unregister_device(core->vdev_enc); 199 200 v4l2_device_unregister(&core->v4l2_dev); 201 202 mutex_destroy(&core->lock); 203 } 204 205 static void iris_sys_error_handler(struct work_struct *work) 206 { 207 struct iris_core *core = 208 container_of(work, struct iris_core, sys_error_handler.work); 209 210 iris_core_deinit(core); 211 iris_core_init(core); 212 } 213 214 static int iris_probe(struct platform_device *pdev) 215 { 216 struct device *dev = &pdev->dev; 217 struct iris_core *core; 218 u64 dma_mask; 219 int ret; 220 221 core = devm_kzalloc(&pdev->dev, sizeof(*core), GFP_KERNEL); 222 if (!core) 223 return -ENOMEM; 224 core->dev = dev; 225 226 core->state = IRIS_CORE_DEINIT; 227 mutex_init(&core->lock); 228 init_completion(&core->core_init_done); 229 230 core->response_packet = devm_kzalloc(core->dev, IFACEQ_CORE_PKT_SIZE, GFP_KERNEL); 231 if (!core->response_packet) 232 return -ENOMEM; 233 234 INIT_LIST_HEAD(&core->instances); 235 INIT_DELAYED_WORK(&core->sys_error_handler, iris_sys_error_handler); 236 237 core->reg_base = devm_platform_ioremap_resource(pdev, 0); 238 if (IS_ERR(core->reg_base)) 239 return PTR_ERR(core->reg_base); 240 241 core->irq = platform_get_irq(pdev, 0); 242 if (core->irq < 0) 243 return core->irq; 244 245 core->iris_platform_data = of_device_get_match_data(core->dev); 246 247 ret = devm_request_threaded_irq(core->dev, core->irq, iris_hfi_isr, 248 iris_hfi_isr_handler, IRQF_TRIGGER_HIGH, "iris", core); 249 if (ret) 250 return ret; 251 252 disable_irq_nosync(core->irq); 253 254 iris_init_ops(core); 255 core->iris_platform_data->init_hfi_command_ops(core); 256 core->iris_platform_data->init_hfi_response_ops(core); 257 258 ret = iris_init_resources(core); 259 if (ret) 260 return ret; 261 262 iris_session_init_caps(core); 263 264 ret = v4l2_device_register(dev, &core->v4l2_dev); 265 if (ret) 266 return ret; 267 268 ret = iris_register_video_device(core, DECODER); 269 if (ret) 270 goto err_v4l2_unreg; 271 272 ret = iris_register_video_device(core, ENCODER); 273 if (ret) 274 goto err_vdev_unreg_dec; 275 276 platform_set_drvdata(pdev, core); 277 278 dma_mask = core->iris_platform_data->dma_mask; 279 280 ret = dma_set_mask_and_coherent(dev, dma_mask); 281 if (ret) 282 goto err_vdev_unreg_enc; 283 284 dma_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32)); 285 dma_set_seg_boundary(&pdev->dev, DMA_BIT_MASK(32)); 286 287 pm_runtime_set_autosuspend_delay(core->dev, AUTOSUSPEND_DELAY_VALUE); 288 pm_runtime_use_autosuspend(core->dev); 289 ret = devm_pm_runtime_enable(core->dev); 290 if (ret) 291 goto err_vdev_unreg_enc; 292 293 return 0; 294 295 err_vdev_unreg_enc: 296 video_unregister_device(core->vdev_enc); 297 err_vdev_unreg_dec: 298 video_unregister_device(core->vdev_dec); 299 err_v4l2_unreg: 300 v4l2_device_unregister(&core->v4l2_dev); 301 302 return ret; 303 } 304 305 static int __maybe_unused iris_pm_suspend(struct device *dev) 306 { 307 struct iris_core *core; 308 int ret = 0; 309 310 core = dev_get_drvdata(dev); 311 312 mutex_lock(&core->lock); 313 if (core->state != IRIS_CORE_INIT) 314 goto exit; 315 316 ret = iris_hfi_pm_suspend(core); 317 318 exit: 319 mutex_unlock(&core->lock); 320 321 return ret; 322 } 323 324 static int __maybe_unused iris_pm_resume(struct device *dev) 325 { 326 struct iris_core *core; 327 int ret = 0; 328 329 core = dev_get_drvdata(dev); 330 331 mutex_lock(&core->lock); 332 if (core->state != IRIS_CORE_INIT) 333 goto exit; 334 335 ret = iris_hfi_pm_resume(core); 336 pm_runtime_mark_last_busy(core->dev); 337 338 exit: 339 mutex_unlock(&core->lock); 340 341 return ret; 342 } 343 344 static const struct dev_pm_ops iris_pm_ops = { 345 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 346 pm_runtime_force_resume) 347 SET_RUNTIME_PM_OPS(iris_pm_suspend, iris_pm_resume, NULL) 348 }; 349 350 static const struct of_device_id iris_dt_match[] = { 351 { 352 .compatible = "qcom,qcs8300-iris", 353 .data = &qcs8300_data, 354 }, 355 #if (!IS_ENABLED(CONFIG_VIDEO_QCOM_VENUS)) 356 { 357 .compatible = "qcom,sc7280-venus", 358 .data = &sc7280_data, 359 }, 360 { 361 .compatible = "qcom,sm8250-venus", 362 .data = &sm8250_data, 363 }, 364 #endif 365 { 366 .compatible = "qcom,sm8550-iris", 367 .data = &sm8550_data, 368 }, 369 { 370 .compatible = "qcom,sm8650-iris", 371 .data = &sm8650_data, 372 }, 373 { 374 .compatible = "qcom,sm8750-iris", 375 .data = &sm8750_data, 376 }, 377 { }, 378 }; 379 MODULE_DEVICE_TABLE(of, iris_dt_match); 380 381 static struct platform_driver qcom_iris_driver = { 382 .probe = iris_probe, 383 .remove = iris_remove, 384 .driver = { 385 .name = "qcom-iris", 386 .of_match_table = iris_dt_match, 387 .pm = &iris_pm_ops, 388 }, 389 }; 390 391 module_platform_driver(qcom_iris_driver); 392 MODULE_DESCRIPTION("Qualcomm iris video driver"); 393 MODULE_LICENSE("GPL"); 394