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 "amdgpu.h" 30 #include "isp_v4_1_1.h" 31 32 MODULE_FIRMWARE("amdgpu/isp_4_1_1.bin"); 33 34 #define ISP_PERFORMANCE_STATE_LOW 0 35 #define ISP_PERFORMANCE_STATE_HIGH 1 36 37 #define ISP_HIGH_PERFORMANC_XCLK 788 38 #define ISP_HIGH_PERFORMANC_ICLK 788 39 40 static const unsigned int isp_4_1_1_int_srcid[MAX_ISP411_INT_SRC] = { 41 ISP_4_1__SRCID__ISP_RINGBUFFER_WPT9, 42 ISP_4_1__SRCID__ISP_RINGBUFFER_WPT10, 43 ISP_4_1__SRCID__ISP_RINGBUFFER_WPT11, 44 ISP_4_1__SRCID__ISP_RINGBUFFER_WPT12, 45 ISP_4_1__SRCID__ISP_RINGBUFFER_WPT13, 46 ISP_4_1__SRCID__ISP_RINGBUFFER_WPT14, 47 ISP_4_1__SRCID__ISP_RINGBUFFER_WPT15, 48 ISP_4_1__SRCID__ISP_RINGBUFFER_WPT16 49 }; 50 51 static struct gpiod_lookup_table isp_gpio_table = { 52 .dev_id = "amd_isp_capture", 53 .table = { 54 GPIO_LOOKUP("AMDI0030:00", 85, "enable_isp", GPIO_ACTIVE_HIGH), 55 { } 56 }, 57 }; 58 59 static struct gpiod_lookup_table isp_sensor_gpio_table = { 60 .dev_id = "i2c-ov05c10", 61 .table = { 62 GPIO_LOOKUP("amdisp-pinctrl", 0, "enable", GPIO_ACTIVE_HIGH), 63 { } 64 }, 65 }; 66 67 static int isp_poweroff(struct generic_pm_domain *genpd) 68 { 69 struct amdgpu_isp *isp = container_of(genpd, struct amdgpu_isp, ispgpd); 70 struct amdgpu_device *adev = isp->adev; 71 72 return amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ISP, true, 0); 73 } 74 75 static int isp_poweron(struct generic_pm_domain *genpd) 76 { 77 struct amdgpu_isp *isp = container_of(genpd, struct amdgpu_isp, ispgpd); 78 struct amdgpu_device *adev = isp->adev; 79 80 return amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ISP, false, 0); 81 } 82 83 static int isp_set_performance_state(struct generic_pm_domain *genpd, 84 unsigned int state) 85 { 86 struct amdgpu_isp *isp = container_of(genpd, struct amdgpu_isp, ispgpd); 87 struct amdgpu_device *adev = isp->adev; 88 u32 iclk, xclk; 89 int ret; 90 91 switch (state) { 92 case ISP_PERFORMANCE_STATE_HIGH: 93 xclk = ISP_HIGH_PERFORMANC_XCLK; 94 iclk = ISP_HIGH_PERFORMANC_ICLK; 95 break; 96 case ISP_PERFORMANCE_STATE_LOW: 97 /* isp runs at default lowest clock-rate on power-on, do nothing */ 98 return 0; 99 default: 100 return -EINVAL; 101 } 102 103 ret = amdgpu_dpm_set_soft_freq_range(adev, PP_ISPXCLK, xclk, 0); 104 if (ret) { 105 drm_err(&adev->ddev, "failed to set xclk %u to %u: %d\n", 106 xclk, state, ret); 107 return ret; 108 } 109 110 ret = amdgpu_dpm_set_soft_freq_range(adev, PP_ISPICLK, iclk, 0); 111 if (ret) { 112 drm_err(&adev->ddev, "failed to set iclk %u to %u: %d\n", 113 iclk, state, ret); 114 return ret; 115 } 116 117 return 0; 118 } 119 120 static int isp_genpd_add_device(struct device *dev, void *data) 121 { 122 struct generic_pm_domain *gpd = data; 123 struct platform_device *pdev = container_of(dev, struct platform_device, dev); 124 struct amdgpu_isp *isp = container_of(gpd, struct amdgpu_isp, ispgpd); 125 struct amdgpu_device *adev = isp->adev; 126 int ret; 127 128 if (!pdev) 129 return -EINVAL; 130 131 if (!dev->type->name) { 132 drm_dbg(&adev->ddev, "Invalid device type to add\n"); 133 goto exit; 134 } 135 136 if (strcmp(dev->type->name, "mfd_device")) { 137 drm_dbg(&adev->ddev, "Invalid isp mfd device %s to add\n", pdev->mfd_cell->name); 138 goto exit; 139 } 140 141 ret = pm_genpd_add_device(gpd, dev); 142 if (ret) { 143 drm_err(&adev->ddev, "Failed to add dev %s to genpd %d\n", 144 pdev->mfd_cell->name, ret); 145 return -ENODEV; 146 } 147 148 exit: 149 /* Continue to add */ 150 return 0; 151 } 152 153 static int isp_genpd_remove_device(struct device *dev, void *data) 154 { 155 struct generic_pm_domain *gpd = data; 156 struct platform_device *pdev = container_of(dev, struct platform_device, dev); 157 struct amdgpu_isp *isp = container_of(gpd, struct amdgpu_isp, ispgpd); 158 struct amdgpu_device *adev = isp->adev; 159 int ret; 160 161 if (!pdev) 162 return -EINVAL; 163 164 if (!dev->type->name) { 165 drm_dbg(&adev->ddev, "Invalid device type to remove\n"); 166 goto exit; 167 } 168 169 if (strcmp(dev->type->name, "mfd_device")) { 170 drm_dbg(&adev->ddev, "Invalid isp mfd device %s to remove\n", 171 pdev->mfd_cell->name); 172 goto exit; 173 } 174 175 ret = pm_genpd_remove_device(dev); 176 if (ret) { 177 drm_err(&adev->ddev, "Failed to remove dev from genpd %d\n", ret); 178 return -ENODEV; 179 } 180 181 exit: 182 /* Continue to remove */ 183 return 0; 184 } 185 186 static int isp_v4_1_1_hw_init(struct amdgpu_isp *isp) 187 { 188 const struct software_node *amd_camera_node, *isp4_node; 189 struct amdgpu_device *adev = isp->adev; 190 struct acpi_device *acpi_dev; 191 int idx, int_idx, num_res, r; 192 u64 isp_base; 193 194 if (adev->rmmio_size == 0 || adev->rmmio_size < 0x5289) 195 return -EINVAL; 196 197 r = amdgpu_acpi_get_isp4_dev(&acpi_dev); 198 if (r) { 199 drm_dbg(&adev->ddev, "Invalid isp platform detected (%d)", r); 200 /* allow GPU init to progress */ 201 return 0; 202 } 203 204 /* add GPIO resources required for OMNI5C10 sensor */ 205 if (!strcmp("OMNI5C10", acpi_device_hid(acpi_dev))) { 206 gpiod_add_lookup_table(&isp_gpio_table); 207 gpiod_add_lookup_table(&isp_sensor_gpio_table); 208 } 209 210 isp_base = adev->rmmio_base; 211 212 isp->ispgpd.name = "ISP_v_4_1_1"; 213 isp->ispgpd.power_off = isp_poweroff; 214 isp->ispgpd.power_on = isp_poweron; 215 isp->ispgpd.set_performance_state = isp_set_performance_state; 216 217 r = pm_genpd_init(&isp->ispgpd, NULL, true); 218 if (r) { 219 drm_err(&adev->ddev, "failed to initialize genpd (%d)\n", r); 220 return -EINVAL; 221 } 222 223 isp->isp_cell = kcalloc(3, sizeof(struct mfd_cell), GFP_KERNEL); 224 if (!isp->isp_cell) { 225 r = -ENOMEM; 226 drm_err(&adev->ddev, "isp mfd cell alloc failed (%d)\n", r); 227 goto failure; 228 } 229 230 num_res = MAX_ISP411_MEM_RES + MAX_ISP411_INT_SRC; 231 232 isp->isp_res = kcalloc(num_res, sizeof(struct resource), 233 GFP_KERNEL); 234 if (!isp->isp_res) { 235 r = -ENOMEM; 236 drm_err(&adev->ddev, "isp mfd resource alloc failed (%d)\n", r); 237 goto failure; 238 } 239 240 isp->isp_pdata = kzalloc(sizeof(*isp->isp_pdata), GFP_KERNEL); 241 if (!isp->isp_pdata) { 242 r = -ENOMEM; 243 drm_err(&adev->ddev, "isp platform data alloc failed (%d)\n", r); 244 goto failure; 245 } 246 247 amd_camera_node = (const struct software_node *)acpi_dev->driver_data; 248 isp4_node = software_node_find_by_name(amd_camera_node, "isp4"); 249 250 /* initialize isp platform data */ 251 isp->isp_pdata->adev = (void *)adev; 252 isp->isp_pdata->asic_type = adev->asic_type; 253 isp->isp_pdata->base_rmmio_size = adev->rmmio_size; 254 255 isp->isp_res[0].name = "isp_4_1_1_reg"; 256 isp->isp_res[0].flags = IORESOURCE_MEM; 257 isp->isp_res[0].start = isp_base; 258 isp->isp_res[0].end = isp_base + ISP_REGS_OFFSET_END; 259 260 isp->isp_res[1].name = "isp_4_1_1_phy0_reg"; 261 isp->isp_res[1].flags = IORESOURCE_MEM; 262 isp->isp_res[1].start = isp_base + ISP411_PHY0_OFFSET; 263 isp->isp_res[1].end = isp_base + ISP411_PHY0_OFFSET + ISP411_PHY0_SIZE; 264 265 for (idx = MAX_ISP411_MEM_RES, int_idx = 0; idx < num_res; idx++, int_idx++) { 266 isp->isp_res[idx].name = "isp_4_1_1_irq"; 267 isp->isp_res[idx].flags = IORESOURCE_IRQ; 268 isp->isp_res[idx].start = 269 amdgpu_irq_create_mapping(adev, isp_4_1_1_int_srcid[int_idx]); 270 isp->isp_res[idx].end = 271 isp->isp_res[idx].start; 272 } 273 274 isp->isp_cell[0].name = "amd_isp_capture"; 275 isp->isp_cell[0].num_resources = num_res; 276 isp->isp_cell[0].resources = &isp->isp_res[0]; 277 isp->isp_cell[0].platform_data = isp->isp_pdata; 278 isp->isp_cell[0].swnode = isp4_node; 279 isp->isp_cell[0].pdata_size = sizeof(struct isp_platform_data); 280 281 /* initialize isp i2c platform data */ 282 isp->isp_i2c_res = kcalloc(1, sizeof(struct resource), GFP_KERNEL); 283 if (!isp->isp_i2c_res) { 284 r = -ENOMEM; 285 drm_err(&adev->ddev, "isp mfd res alloc failed (%d)\n", r); 286 goto failure; 287 } 288 289 isp->isp_i2c_res[0].name = "isp_i2c0_reg"; 290 isp->isp_i2c_res[0].flags = IORESOURCE_MEM; 291 isp->isp_i2c_res[0].start = isp_base + ISP411_I2C0_OFFSET; 292 isp->isp_i2c_res[0].end = isp_base + ISP411_I2C0_OFFSET + ISP411_I2C0_SIZE; 293 294 isp->isp_cell[1].name = "amd_isp_i2c_designware"; 295 isp->isp_cell[1].num_resources = 1; 296 isp->isp_cell[1].resources = &isp->isp_i2c_res[0]; 297 isp->isp_cell[1].platform_data = isp->isp_pdata; 298 isp->isp_cell[1].pdata_size = sizeof(struct isp_platform_data); 299 300 /* initialize isp gpiochip platform data */ 301 isp->isp_gpio_res = kcalloc(1, sizeof(struct resource), GFP_KERNEL); 302 if (!isp->isp_gpio_res) { 303 r = -ENOMEM; 304 drm_err(&adev->ddev, "isp gpio resource alloc failed (%d)\n", r); 305 goto failure; 306 } 307 308 isp->isp_gpio_res[0].name = "isp_gpio_reg"; 309 isp->isp_gpio_res[0].flags = IORESOURCE_MEM; 310 isp->isp_gpio_res[0].start = isp_base + ISP411_GPIO_SENSOR_OFFSET; 311 isp->isp_gpio_res[0].end = isp_base + ISP411_GPIO_SENSOR_OFFSET + 312 ISP411_GPIO_SENSOR_SIZE; 313 314 isp->isp_cell[2].name = "amdisp-pinctrl"; 315 isp->isp_cell[2].num_resources = 1; 316 isp->isp_cell[2].resources = &isp->isp_gpio_res[0]; 317 isp->isp_cell[2].platform_data = isp->isp_pdata; 318 isp->isp_cell[2].pdata_size = sizeof(struct isp_platform_data); 319 320 /* add only amd_isp_capture and amd_isp_i2c_designware to genpd */ 321 r = mfd_add_hotplug_devices(isp->parent, isp->isp_cell, 2); 322 if (r) { 323 drm_err(&adev->ddev, "add mfd hotplug device failed (%d)\n", r); 324 goto failure; 325 } 326 327 r = device_for_each_child(isp->parent, &isp->ispgpd, 328 isp_genpd_add_device); 329 if (r) { 330 drm_err(&adev->ddev, "failed to add devices to genpd (%d)\n", r); 331 goto failure; 332 } 333 334 r = mfd_add_hotplug_devices(isp->parent, &isp->isp_cell[2], 1); 335 if (r) { 336 drm_err(&adev->ddev, "add pinctl hotplug device failed (%d)\n", r); 337 goto failure; 338 } 339 340 return 0; 341 342 failure: 343 344 kfree(isp->isp_pdata); 345 kfree(isp->isp_res); 346 kfree(isp->isp_cell); 347 kfree(isp->isp_i2c_res); 348 kfree(isp->isp_gpio_res); 349 350 return r; 351 } 352 353 static int isp_v4_1_1_hw_fini(struct amdgpu_isp *isp) 354 { 355 device_for_each_child(isp->parent, NULL, 356 isp_genpd_remove_device); 357 358 mfd_remove_devices(isp->parent); 359 360 kfree(isp->isp_res); 361 kfree(isp->isp_cell); 362 kfree(isp->isp_pdata); 363 kfree(isp->isp_i2c_res); 364 kfree(isp->isp_gpio_res); 365 366 return 0; 367 } 368 369 static const struct isp_funcs isp_v4_1_1_funcs = { 370 .hw_init = isp_v4_1_1_hw_init, 371 .hw_fini = isp_v4_1_1_hw_fini, 372 }; 373 374 void isp_v4_1_1_set_isp_funcs(struct amdgpu_isp *isp) 375 { 376 isp->funcs = &isp_v4_1_1_funcs; 377 } 378