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