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