1 /* SPDX-License-Identifier: MIT */ 2 /* 3 * Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 18 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 * USE OR OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * The above copyright notice and this permission notice (including the 23 * next paragraph) shall be included in all copies or substantial portions 24 * of the Software. 25 * 26 */ 27 28 #include <linux/gpio/machine.h> 29 #include <linux/pm_runtime.h> 30 #include "amdgpu.h" 31 #include "isp_v4_1_1.h" 32 33 MODULE_FIRMWARE("amdgpu/isp_4_1_1.bin"); 34 35 #define ISP_PERFORMANCE_STATE_LOW 0 36 #define ISP_PERFORMANCE_STATE_HIGH 1 37 38 #define ISP_HIGH_PERFORMANC_XCLK 788 39 #define ISP_HIGH_PERFORMANC_ICLK 788 40 41 static const unsigned int isp_4_1_1_int_srcid[MAX_ISP411_INT_SRC] = { 42 ISP_4_1__SRCID__ISP_RINGBUFFER_WPT9, 43 ISP_4_1__SRCID__ISP_RINGBUFFER_WPT10, 44 ISP_4_1__SRCID__ISP_RINGBUFFER_WPT11, 45 ISP_4_1__SRCID__ISP_RINGBUFFER_WPT12, 46 ISP_4_1__SRCID__ISP_RINGBUFFER_WPT13, 47 ISP_4_1__SRCID__ISP_RINGBUFFER_WPT14, 48 ISP_4_1__SRCID__ISP_RINGBUFFER_WPT15, 49 ISP_4_1__SRCID__ISP_RINGBUFFER_WPT16 50 }; 51 52 static struct gpiod_lookup_table isp_gpio_table = { 53 .dev_id = "amd_isp_capture", 54 .table = { 55 GPIO_LOOKUP("AMDI0030:00", 85, "enable_isp", GPIO_ACTIVE_HIGH), 56 { } 57 }, 58 }; 59 60 static struct gpiod_lookup_table isp_sensor_gpio_table = { 61 .dev_id = "i2c-ov05c10", 62 .table = { 63 GPIO_LOOKUP("amdisp-pinctrl", 0, "enable", GPIO_ACTIVE_HIGH), 64 { } 65 }, 66 }; 67 68 static int isp_poweroff(struct generic_pm_domain *genpd) 69 { 70 struct amdgpu_isp *isp = container_of(genpd, struct amdgpu_isp, ispgpd); 71 struct amdgpu_device *adev = isp->adev; 72 73 return amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ISP, true, 0); 74 } 75 76 static int isp_poweron(struct generic_pm_domain *genpd) 77 { 78 struct amdgpu_isp *isp = container_of(genpd, struct amdgpu_isp, ispgpd); 79 struct amdgpu_device *adev = isp->adev; 80 81 return amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ISP, false, 0); 82 } 83 84 static int isp_set_performance_state(struct generic_pm_domain *genpd, 85 unsigned int state) 86 { 87 struct amdgpu_isp *isp = container_of(genpd, struct amdgpu_isp, ispgpd); 88 struct amdgpu_device *adev = isp->adev; 89 u32 iclk, xclk; 90 int ret; 91 92 switch (state) { 93 case ISP_PERFORMANCE_STATE_HIGH: 94 xclk = ISP_HIGH_PERFORMANC_XCLK; 95 iclk = ISP_HIGH_PERFORMANC_ICLK; 96 break; 97 case ISP_PERFORMANCE_STATE_LOW: 98 /* isp runs at default lowest clock-rate on power-on, do nothing */ 99 return 0; 100 default: 101 return -EINVAL; 102 } 103 104 ret = amdgpu_dpm_set_soft_freq_range(adev, PP_ISPXCLK, xclk, 0); 105 if (ret) { 106 drm_err(&adev->ddev, "failed to set xclk %u to %u: %d\n", 107 xclk, state, ret); 108 return ret; 109 } 110 111 ret = amdgpu_dpm_set_soft_freq_range(adev, PP_ISPICLK, iclk, 0); 112 if (ret) { 113 drm_err(&adev->ddev, "failed to set iclk %u to %u: %d\n", 114 iclk, state, ret); 115 return ret; 116 } 117 118 return 0; 119 } 120 121 static int isp_genpd_add_device(struct device *dev, void *data) 122 { 123 struct generic_pm_domain *gpd = data; 124 struct platform_device *pdev = container_of(dev, struct platform_device, dev); 125 struct amdgpu_isp *isp = container_of(gpd, struct amdgpu_isp, ispgpd); 126 struct amdgpu_device *adev = isp->adev; 127 int ret; 128 129 if (!pdev) 130 return -EINVAL; 131 132 if (!dev->type->name) { 133 drm_dbg(&adev->ddev, "Invalid device type to add\n"); 134 goto exit; 135 } 136 137 if (strcmp(dev->type->name, "mfd_device")) { 138 drm_dbg(&adev->ddev, "Invalid isp mfd device %s to add\n", pdev->mfd_cell->name); 139 goto exit; 140 } 141 142 ret = pm_genpd_add_device(gpd, dev); 143 if (ret) { 144 drm_err(&adev->ddev, "Failed to add dev %s to genpd %d\n", 145 pdev->mfd_cell->name, ret); 146 return -ENODEV; 147 } 148 149 /* The devices will be managed by the pm ops from the parent */ 150 dev_pm_syscore_device(dev, true); 151 152 exit: 153 /* Continue to add */ 154 return 0; 155 } 156 157 static int isp_genpd_remove_device(struct device *dev, void *data) 158 { 159 struct generic_pm_domain *gpd = data; 160 struct platform_device *pdev = container_of(dev, struct platform_device, dev); 161 struct amdgpu_isp *isp = container_of(gpd, struct amdgpu_isp, ispgpd); 162 struct amdgpu_device *adev = isp->adev; 163 int ret; 164 165 if (!pdev) 166 return -EINVAL; 167 168 if (!dev->type->name) { 169 drm_dbg(&adev->ddev, "Invalid device type to remove\n"); 170 goto exit; 171 } 172 173 if (strcmp(dev->type->name, "mfd_device")) { 174 drm_dbg(&adev->ddev, "Invalid isp mfd device %s to remove\n", 175 pdev->mfd_cell->name); 176 goto exit; 177 } 178 179 ret = pm_genpd_remove_device(dev); 180 if (ret) { 181 drm_err(&adev->ddev, "Failed to remove dev from genpd %d\n", ret); 182 return -ENODEV; 183 } 184 dev_pm_syscore_device(dev, false); 185 186 exit: 187 /* Continue to remove */ 188 return 0; 189 } 190 191 static int isp_suspend_device(struct device *dev, void *data) 192 { 193 return pm_runtime_force_suspend(dev); 194 } 195 196 static int isp_resume_device(struct device *dev, void *data) 197 { 198 return pm_runtime_force_resume(dev); 199 } 200 201 static int isp_v4_1_1_hw_suspend(struct amdgpu_isp *isp) 202 { 203 int r; 204 205 r = device_for_each_child(isp->parent, NULL, 206 isp_suspend_device); 207 if (r) 208 dev_err(isp->parent, "failed to suspend hw devices (%d)\n", r); 209 210 return r; 211 } 212 213 static int isp_v4_1_1_hw_resume(struct amdgpu_isp *isp) 214 { 215 int r; 216 217 r = device_for_each_child(isp->parent, NULL, 218 isp_resume_device); 219 if (r) 220 dev_err(isp->parent, "failed to resume hw device (%d)\n", r); 221 222 return r; 223 } 224 225 static int isp_v4_1_1_hw_init(struct amdgpu_isp *isp) 226 { 227 const struct software_node *amd_camera_node, *isp4_node; 228 struct amdgpu_device *adev = isp->adev; 229 struct acpi_device *acpi_dev; 230 int idx, int_idx, num_res, r; 231 u64 isp_base; 232 233 if (adev->rmmio_size == 0 || adev->rmmio_size < 0x5289) 234 return -EINVAL; 235 236 r = amdgpu_acpi_get_isp4_dev(&acpi_dev); 237 if (r) { 238 drm_dbg(&adev->ddev, "Invalid isp platform detected (%d)", r); 239 /* allow GPU init to progress */ 240 return 0; 241 } 242 243 /* add GPIO resources required for OMNI5C10 sensor */ 244 if (!strcmp("OMNI5C10", acpi_device_hid(acpi_dev))) { 245 gpiod_add_lookup_table(&isp_gpio_table); 246 gpiod_add_lookup_table(&isp_sensor_gpio_table); 247 } 248 249 isp_base = adev->rmmio_base; 250 251 isp->ispgpd.name = "ISP_v_4_1_1"; 252 isp->ispgpd.power_off = isp_poweroff; 253 isp->ispgpd.power_on = isp_poweron; 254 isp->ispgpd.set_performance_state = isp_set_performance_state; 255 256 r = pm_genpd_init(&isp->ispgpd, NULL, true); 257 if (r) { 258 drm_err(&adev->ddev, "failed to initialize genpd (%d)\n", r); 259 return -EINVAL; 260 } 261 262 isp->isp_cell = kcalloc(3, sizeof(struct mfd_cell), GFP_KERNEL); 263 if (!isp->isp_cell) { 264 r = -ENOMEM; 265 drm_err(&adev->ddev, "isp mfd cell alloc failed (%d)\n", r); 266 goto failure; 267 } 268 269 num_res = MAX_ISP411_MEM_RES + MAX_ISP411_INT_SRC; 270 271 isp->isp_res = kcalloc(num_res, sizeof(struct resource), 272 GFP_KERNEL); 273 if (!isp->isp_res) { 274 r = -ENOMEM; 275 drm_err(&adev->ddev, "isp mfd resource alloc failed (%d)\n", r); 276 goto failure; 277 } 278 279 isp->isp_pdata = kzalloc(sizeof(*isp->isp_pdata), GFP_KERNEL); 280 if (!isp->isp_pdata) { 281 r = -ENOMEM; 282 drm_err(&adev->ddev, "isp platform data alloc failed (%d)\n", r); 283 goto failure; 284 } 285 286 amd_camera_node = (const struct software_node *)acpi_dev->driver_data; 287 isp4_node = software_node_find_by_name(amd_camera_node, "isp4"); 288 289 /* initialize isp platform data */ 290 isp->isp_pdata->adev = (void *)adev; 291 isp->isp_pdata->asic_type = adev->asic_type; 292 isp->isp_pdata->base_rmmio_size = adev->rmmio_size; 293 294 isp->isp_res[0].name = "isp_4_1_1_reg"; 295 isp->isp_res[0].flags = IORESOURCE_MEM; 296 isp->isp_res[0].start = isp_base; 297 isp->isp_res[0].end = isp_base + ISP_REGS_OFFSET_END; 298 299 isp->isp_res[1].name = "isp_4_1_1_phy0_reg"; 300 isp->isp_res[1].flags = IORESOURCE_MEM; 301 isp->isp_res[1].start = isp_base + ISP411_PHY0_OFFSET; 302 isp->isp_res[1].end = isp_base + ISP411_PHY0_OFFSET + ISP411_PHY0_SIZE; 303 304 for (idx = MAX_ISP411_MEM_RES, int_idx = 0; idx < num_res; idx++, int_idx++) { 305 isp->isp_res[idx].name = "isp_4_1_1_irq"; 306 isp->isp_res[idx].flags = IORESOURCE_IRQ; 307 isp->isp_res[idx].start = 308 amdgpu_irq_create_mapping(adev, isp_4_1_1_int_srcid[int_idx]); 309 isp->isp_res[idx].end = 310 isp->isp_res[idx].start; 311 } 312 313 isp->isp_cell[0].name = "amd_isp_capture"; 314 isp->isp_cell[0].num_resources = num_res; 315 isp->isp_cell[0].resources = &isp->isp_res[0]; 316 isp->isp_cell[0].platform_data = isp->isp_pdata; 317 isp->isp_cell[0].swnode = isp4_node; 318 isp->isp_cell[0].pdata_size = sizeof(struct isp_platform_data); 319 320 /* initialize isp i2c platform data */ 321 isp->isp_i2c_res = kcalloc(1, sizeof(struct resource), GFP_KERNEL); 322 if (!isp->isp_i2c_res) { 323 r = -ENOMEM; 324 drm_err(&adev->ddev, "isp mfd res alloc failed (%d)\n", r); 325 goto failure; 326 } 327 328 isp->isp_i2c_res[0].name = "isp_i2c0_reg"; 329 isp->isp_i2c_res[0].flags = IORESOURCE_MEM; 330 isp->isp_i2c_res[0].start = isp_base + ISP411_I2C0_OFFSET; 331 isp->isp_i2c_res[0].end = isp_base + ISP411_I2C0_OFFSET + ISP411_I2C0_SIZE; 332 333 isp->isp_cell[1].name = "amd_isp_i2c_designware"; 334 isp->isp_cell[1].num_resources = 1; 335 isp->isp_cell[1].resources = &isp->isp_i2c_res[0]; 336 isp->isp_cell[1].platform_data = isp->isp_pdata; 337 isp->isp_cell[1].pdata_size = sizeof(struct isp_platform_data); 338 339 /* initialize isp gpiochip platform data */ 340 isp->isp_gpio_res = kcalloc(1, sizeof(struct resource), GFP_KERNEL); 341 if (!isp->isp_gpio_res) { 342 r = -ENOMEM; 343 drm_err(&adev->ddev, "isp gpio resource alloc failed (%d)\n", r); 344 goto failure; 345 } 346 347 isp->isp_gpio_res[0].name = "isp_gpio_reg"; 348 isp->isp_gpio_res[0].flags = IORESOURCE_MEM; 349 isp->isp_gpio_res[0].start = isp_base + ISP411_GPIO_SENSOR_OFFSET; 350 isp->isp_gpio_res[0].end = isp_base + ISP411_GPIO_SENSOR_OFFSET + 351 ISP411_GPIO_SENSOR_SIZE; 352 353 isp->isp_cell[2].name = "amdisp-pinctrl"; 354 isp->isp_cell[2].num_resources = 1; 355 isp->isp_cell[2].resources = &isp->isp_gpio_res[0]; 356 isp->isp_cell[2].platform_data = isp->isp_pdata; 357 isp->isp_cell[2].pdata_size = sizeof(struct isp_platform_data); 358 359 /* add only amd_isp_capture and amd_isp_i2c_designware to genpd */ 360 r = mfd_add_hotplug_devices(isp->parent, isp->isp_cell, 2); 361 if (r) { 362 drm_err(&adev->ddev, "add mfd hotplug device failed (%d)\n", r); 363 goto failure; 364 } 365 366 r = device_for_each_child(isp->parent, &isp->ispgpd, 367 isp_genpd_add_device); 368 if (r) { 369 drm_err(&adev->ddev, "failed to add devices to genpd (%d)\n", r); 370 goto failure; 371 } 372 373 r = mfd_add_hotplug_devices(isp->parent, &isp->isp_cell[2], 1); 374 if (r) { 375 drm_err(&adev->ddev, "add pinctl hotplug device failed (%d)\n", r); 376 goto failure; 377 } 378 379 return 0; 380 381 failure: 382 383 kfree(isp->isp_pdata); 384 kfree(isp->isp_res); 385 kfree(isp->isp_cell); 386 kfree(isp->isp_i2c_res); 387 kfree(isp->isp_gpio_res); 388 389 return r; 390 } 391 392 static int isp_v4_1_1_hw_fini(struct amdgpu_isp *isp) 393 { 394 device_for_each_child(isp->parent, NULL, 395 isp_genpd_remove_device); 396 397 mfd_remove_devices(isp->parent); 398 399 kfree(isp->isp_res); 400 kfree(isp->isp_cell); 401 kfree(isp->isp_pdata); 402 kfree(isp->isp_i2c_res); 403 kfree(isp->isp_gpio_res); 404 405 return 0; 406 } 407 408 static const struct isp_funcs isp_v4_1_1_funcs = { 409 .hw_init = isp_v4_1_1_hw_init, 410 .hw_fini = isp_v4_1_1_hw_fini, 411 .hw_suspend = isp_v4_1_1_hw_suspend, 412 .hw_resume = isp_v4_1_1_hw_resume, 413 }; 414 415 void isp_v4_1_1_set_isp_funcs(struct amdgpu_isp *isp) 416 { 417 isp->funcs = &isp_v4_1_1_funcs; 418 } 419