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 static const unsigned int isp_4_1_1_int_srcid[MAX_ISP411_INT_SRC] = { 33 ISP_4_1__SRCID__ISP_RINGBUFFER_WPT9, 34 ISP_4_1__SRCID__ISP_RINGBUFFER_WPT10, 35 ISP_4_1__SRCID__ISP_RINGBUFFER_WPT11, 36 ISP_4_1__SRCID__ISP_RINGBUFFER_WPT12, 37 ISP_4_1__SRCID__ISP_RINGBUFFER_WPT13, 38 ISP_4_1__SRCID__ISP_RINGBUFFER_WPT14, 39 ISP_4_1__SRCID__ISP_RINGBUFFER_WPT15, 40 ISP_4_1__SRCID__ISP_RINGBUFFER_WPT16 41 }; 42 43 static struct gpiod_lookup_table isp_gpio_table = { 44 .dev_id = "amd_isp_capture", 45 .table = { 46 GPIO_LOOKUP("AMDI0030:00", 85, "enable_isp", GPIO_ACTIVE_HIGH), 47 { } 48 }, 49 }; 50 51 static struct gpiod_lookup_table isp_sensor_gpio_table = { 52 .dev_id = "i2c-ov05c10", 53 .table = { 54 GPIO_LOOKUP("amdisp-pinctrl", 0, "enable", GPIO_ACTIVE_HIGH), 55 { } 56 }, 57 }; 58 59 static int isp_v4_1_1_hw_init(struct amdgpu_isp *isp) 60 { 61 struct amdgpu_device *adev = isp->adev; 62 int idx, int_idx, num_res, r; 63 u8 isp_dev_hid[ACPI_ID_LEN]; 64 u64 isp_base; 65 66 if (adev->rmmio_size == 0 || adev->rmmio_size < 0x5289) 67 return -EINVAL; 68 69 r = amdgpu_acpi_get_isp4_dev_hid(&isp_dev_hid); 70 if (r) { 71 drm_dbg(&adev->ddev, "Invalid isp platform detected (%d)", r); 72 /* allow GPU init to progress */ 73 return 0; 74 } 75 76 /* add GPIO resources required for OMNI5C10 sensor */ 77 if (!strcmp("OMNI5C10", isp_dev_hid)) { 78 gpiod_add_lookup_table(&isp_gpio_table); 79 gpiod_add_lookup_table(&isp_sensor_gpio_table); 80 } 81 82 isp_base = adev->rmmio_base; 83 84 isp->isp_cell = kcalloc(3, sizeof(struct mfd_cell), GFP_KERNEL); 85 if (!isp->isp_cell) { 86 r = -ENOMEM; 87 drm_err(&adev->ddev, 88 "%s: isp mfd cell alloc failed\n", __func__); 89 goto failure; 90 } 91 92 num_res = MAX_ISP411_MEM_RES + MAX_ISP411_INT_SRC; 93 94 isp->isp_res = kcalloc(num_res, sizeof(struct resource), 95 GFP_KERNEL); 96 if (!isp->isp_res) { 97 r = -ENOMEM; 98 drm_err(&adev->ddev, 99 "%s: isp mfd res alloc failed\n", __func__); 100 goto failure; 101 } 102 103 isp->isp_pdata = kzalloc(sizeof(*isp->isp_pdata), GFP_KERNEL); 104 if (!isp->isp_pdata) { 105 r = -ENOMEM; 106 drm_err(&adev->ddev, 107 "%s: isp platform data alloc failed\n", __func__); 108 goto failure; 109 } 110 111 /* initialize isp platform data */ 112 isp->isp_pdata->adev = (void *)adev; 113 isp->isp_pdata->asic_type = adev->asic_type; 114 isp->isp_pdata->base_rmmio_size = adev->rmmio_size; 115 116 isp->isp_res[0].name = "isp_4_1_1_reg"; 117 isp->isp_res[0].flags = IORESOURCE_MEM; 118 isp->isp_res[0].start = isp_base; 119 isp->isp_res[0].end = isp_base + ISP_REGS_OFFSET_END; 120 121 isp->isp_res[1].name = "isp_4_1_1_phy0_reg"; 122 isp->isp_res[1].flags = IORESOURCE_MEM; 123 isp->isp_res[1].start = isp_base + ISP411_PHY0_OFFSET; 124 isp->isp_res[1].end = isp_base + ISP411_PHY0_OFFSET + ISP411_PHY0_SIZE; 125 126 for (idx = MAX_ISP411_MEM_RES, int_idx = 0; idx < num_res; idx++, int_idx++) { 127 isp->isp_res[idx].name = "isp_4_1_1_irq"; 128 isp->isp_res[idx].flags = IORESOURCE_IRQ; 129 isp->isp_res[idx].start = 130 amdgpu_irq_create_mapping(adev, isp_4_1_1_int_srcid[int_idx]); 131 isp->isp_res[idx].end = 132 isp->isp_res[idx].start; 133 } 134 135 isp->isp_cell[0].name = "amd_isp_capture"; 136 isp->isp_cell[0].num_resources = num_res; 137 isp->isp_cell[0].resources = &isp->isp_res[0]; 138 isp->isp_cell[0].platform_data = isp->isp_pdata; 139 isp->isp_cell[0].pdata_size = sizeof(struct isp_platform_data); 140 141 /* initialize isp i2c platform data */ 142 isp->isp_i2c_res = kcalloc(1, sizeof(struct resource), GFP_KERNEL); 143 if (!isp->isp_i2c_res) { 144 r = -ENOMEM; 145 drm_err(&adev->ddev, 146 "%s: isp mfd res alloc failed\n", __func__); 147 goto failure; 148 } 149 150 isp->isp_i2c_res[0].name = "isp_i2c0_reg"; 151 isp->isp_i2c_res[0].flags = IORESOURCE_MEM; 152 isp->isp_i2c_res[0].start = isp_base + ISP411_I2C0_OFFSET; 153 isp->isp_i2c_res[0].end = isp_base + ISP411_I2C0_OFFSET + ISP411_I2C0_SIZE; 154 155 isp->isp_cell[1].name = "amd_isp_i2c_designware"; 156 isp->isp_cell[1].num_resources = 1; 157 isp->isp_cell[1].resources = &isp->isp_i2c_res[0]; 158 isp->isp_cell[1].platform_data = isp->isp_pdata; 159 isp->isp_cell[1].pdata_size = sizeof(struct isp_platform_data); 160 161 /* initialize isp gpiochip platform data */ 162 isp->isp_gpio_res = kcalloc(1, sizeof(struct resource), GFP_KERNEL); 163 if (!isp->isp_gpio_res) { 164 r = -ENOMEM; 165 drm_err(&adev->ddev, 166 "%s: isp gpio res alloc failed\n", __func__); 167 goto failure; 168 } 169 170 isp->isp_gpio_res[0].name = "isp_gpio_reg"; 171 isp->isp_gpio_res[0].flags = IORESOURCE_MEM; 172 isp->isp_gpio_res[0].start = isp_base + ISP411_GPIO_SENSOR_OFFSET; 173 isp->isp_gpio_res[0].end = isp_base + ISP411_GPIO_SENSOR_OFFSET + 174 ISP411_GPIO_SENSOR_SIZE; 175 176 isp->isp_cell[2].name = "amdisp-pinctrl"; 177 isp->isp_cell[2].num_resources = 1; 178 isp->isp_cell[2].resources = &isp->isp_gpio_res[0]; 179 isp->isp_cell[2].platform_data = isp->isp_pdata; 180 isp->isp_cell[2].pdata_size = sizeof(struct isp_platform_data); 181 182 r = mfd_add_hotplug_devices(isp->parent, isp->isp_cell, 3); 183 if (r) { 184 drm_err(&adev->ddev, 185 "%s: add mfd hotplug device failed\n", __func__); 186 goto failure; 187 } 188 189 return 0; 190 191 failure: 192 193 kfree(isp->isp_pdata); 194 kfree(isp->isp_res); 195 kfree(isp->isp_cell); 196 kfree(isp->isp_i2c_res); 197 kfree(isp->isp_gpio_res); 198 199 return r; 200 } 201 202 static int isp_v4_1_1_hw_fini(struct amdgpu_isp *isp) 203 { 204 mfd_remove_devices(isp->parent); 205 206 kfree(isp->isp_res); 207 kfree(isp->isp_cell); 208 kfree(isp->isp_pdata); 209 kfree(isp->isp_i2c_res); 210 kfree(isp->isp_gpio_res); 211 212 return 0; 213 } 214 215 static const struct isp_funcs isp_v4_1_1_funcs = { 216 .hw_init = isp_v4_1_1_hw_init, 217 .hw_fini = isp_v4_1_1_hw_fini, 218 }; 219 220 void isp_v4_1_1_set_isp_funcs(struct amdgpu_isp *isp) 221 { 222 isp->funcs = &isp_v4_1_1_funcs; 223 } 224