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