Skip to content

Commit

Permalink
drm/amdgpu: Add MFD support for ISP I2C bus
Browse files Browse the repository at this point in the history
ISP I2C bus device can't be enumerated via ACPI mechanism
since it shares the memory map with the AMDGPU.
So use the MFD mechanism for registering the ISP I2C device
and add the required resources.

Signed-off-by: Venkata Narendra Kumar Gutta <vengutta@amd.com>
Acked-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
  • Loading branch information
Venkata Narendra Kumar Gutta authored and Alex Deucher committed Jul 27, 2024
1 parent fbfb5f0 commit 25dd25f
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 24 deletions.
1 change: 1 addition & 0 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_isp.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ struct amdgpu_isp {
const struct isp_funcs *funcs;
struct mfd_cell *isp_cell;
struct resource *isp_res;
struct resource *isp_i2c_res;
struct isp_platform_data *isp_pdata;
unsigned int harvest_config;
const struct firmware *fw;
Expand Down
57 changes: 45 additions & 12 deletions drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,23 +42,23 @@ static const unsigned int isp_4_1_0_int_srcid[MAX_ISP410_INT_SRC] = {
static int isp_v4_1_0_hw_init(struct amdgpu_isp *isp)
{
struct amdgpu_device *adev = isp->adev;
int idx, int_idx, num_res, r;
u64 isp_base;
int int_idx;
int r;

if (adev->rmmio_size == 0 || adev->rmmio_size < 0x5289)
return -EINVAL;

isp_base = adev->rmmio_base;

isp->isp_cell = kcalloc(1, sizeof(struct mfd_cell), GFP_KERNEL);
isp->isp_cell = kcalloc(2, sizeof(struct mfd_cell), GFP_KERNEL);
if (!isp->isp_cell) {
r = -ENOMEM;
DRM_ERROR("%s: isp mfd cell alloc failed\n", __func__);
goto failure;
}

isp->isp_res = kcalloc(MAX_ISP410_INT_SRC + 1, sizeof(struct resource),
num_res = MAX_ISP410_MEM_RES + MAX_ISP410_SENSOR_RES + MAX_ISP410_INT_SRC;
isp->isp_res = kcalloc(num_res, sizeof(struct resource),
GFP_KERNEL);
if (!isp->isp_res) {
r = -ENOMEM;
Expand All @@ -83,22 +83,53 @@ static int isp_v4_1_0_hw_init(struct amdgpu_isp *isp)
isp->isp_res[0].start = isp_base;
isp->isp_res[0].end = isp_base + ISP_REGS_OFFSET_END;

for (int_idx = 0; int_idx < MAX_ISP410_INT_SRC; int_idx++) {
isp->isp_res[int_idx + 1].name = "isp_4_1_0_irq";
isp->isp_res[int_idx + 1].flags = IORESOURCE_IRQ;
isp->isp_res[int_idx + 1].start =
isp->isp_res[1].name = "isp_4_1_phy0_reg";
isp->isp_res[1].flags = IORESOURCE_MEM;
isp->isp_res[1].start = isp_base + ISP410_PHY0_OFFSET;
isp->isp_res[1].end = isp_base + ISP410_PHY0_OFFSET + ISP410_PHY0_SIZE;

isp->isp_res[2].name = "isp_gpio_sensor0_reg";
isp->isp_res[2].flags = IORESOURCE_MEM;
isp->isp_res[2].start = isp_base + ISP410_GPIO_SENSOR0_OFFSET;
isp->isp_res[2].end = isp_base + ISP410_GPIO_SENSOR0_OFFSET +
ISP410_GPIO_SENSOR0_SIZE;

for (idx = MAX_ISP410_MEM_RES + MAX_ISP410_SENSOR_RES, int_idx = 0;
idx < num_res; idx++, int_idx++) {
isp->isp_res[idx].name = "isp_4_1_0_irq";
isp->isp_res[idx].flags = IORESOURCE_IRQ;
isp->isp_res[idx].start =
amdgpu_irq_create_mapping(adev, isp_4_1_0_int_srcid[int_idx]);
isp->isp_res[int_idx + 1].end =
isp->isp_res[int_idx + 1].start;
isp->isp_res[idx].end =
isp->isp_res[idx].start;
}

isp->isp_cell[0].name = "amd_isp_capture";
isp->isp_cell[0].num_resources = MAX_ISP410_INT_SRC + 1;
isp->isp_cell[0].num_resources = num_res;
isp->isp_cell[0].resources = &isp->isp_res[0];
isp->isp_cell[0].platform_data = isp->isp_pdata;
isp->isp_cell[0].pdata_size = sizeof(struct isp_platform_data);

r = mfd_add_hotplug_devices(isp->parent, isp->isp_cell, 1);
isp->isp_i2c_res = kcalloc(1, sizeof(struct resource),
GFP_KERNEL);
if (!isp->isp_i2c_res) {
r = -ENOMEM;
DRM_ERROR("%s: isp mfd res alloc failed\n", __func__);
goto failure;
}

isp->isp_i2c_res[0].name = "isp_i2c0_reg";
isp->isp_i2c_res[0].flags = IORESOURCE_MEM;
isp->isp_i2c_res[0].start = isp_base + ISP410_I2C0_OFFSET;
isp->isp_i2c_res[0].end = isp_base + ISP410_I2C0_OFFSET + ISP410_I2C0_SIZE;

isp->isp_cell[1].name = "amd_isp_i2c_designware";
isp->isp_cell[1].num_resources = 1;
isp->isp_cell[1].resources = &isp->isp_i2c_res[0];
isp->isp_cell[1].platform_data = isp->isp_pdata;
isp->isp_cell[1].pdata_size = sizeof(struct isp_platform_data);

r = mfd_add_hotplug_devices(isp->parent, isp->isp_cell, 2);
if (r) {
DRM_ERROR("%s: add mfd hotplug device failed\n", __func__);
goto failure;
Expand All @@ -111,6 +142,7 @@ static int isp_v4_1_0_hw_init(struct amdgpu_isp *isp)
kfree(isp->isp_pdata);
kfree(isp->isp_res);
kfree(isp->isp_cell);
kfree(isp->isp_i2c_res);

return r;
}
Expand All @@ -122,6 +154,7 @@ static int isp_v4_1_0_hw_fini(struct amdgpu_isp *isp)
kfree(isp->isp_res);
kfree(isp->isp_cell);
kfree(isp->isp_pdata);
kfree(isp->isp_i2c_res);

return 0;
}
Expand Down
11 changes: 11 additions & 0 deletions drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,19 @@

#include "ivsrcid/isp/irqsrcs_isp_4_1.h"

#define MAX_ISP410_MEM_RES 2
#define MAX_ISP410_SENSOR_RES 1
#define MAX_ISP410_INT_SRC 8

#define ISP410_PHY0_OFFSET 0x66700
#define ISP410_PHY0_SIZE 0xD30

#define ISP410_I2C0_OFFSET 0x66400
#define ISP410_I2C0_SIZE 0x100

#define ISP410_GPIO_SENSOR0_OFFSET 0x6613C
#define ISP410_GPIO_SENSOR0_SIZE 0x4

void isp_v4_1_0_set_isp_funcs(struct amdgpu_isp *isp);

#endif
57 changes: 45 additions & 12 deletions drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,23 +42,24 @@ static const unsigned int isp_4_1_1_int_srcid[MAX_ISP411_INT_SRC] = {
static int isp_v4_1_1_hw_init(struct amdgpu_isp *isp)
{
struct amdgpu_device *adev = isp->adev;
int idx, int_idx, num_res, r;
u64 isp_base;
int int_idx;
int r;

if (adev->rmmio_size == 0 || adev->rmmio_size < 0x5289)
return -EINVAL;

isp_base = adev->rmmio_base;

isp->isp_cell = kcalloc(1, sizeof(struct mfd_cell), GFP_KERNEL);
isp->isp_cell = kcalloc(2, sizeof(struct mfd_cell), GFP_KERNEL);
if (!isp->isp_cell) {
r = -ENOMEM;
DRM_ERROR("%s: isp mfd cell alloc failed\n", __func__);
goto failure;
}

isp->isp_res = kcalloc(MAX_ISP411_INT_SRC + 1, sizeof(struct resource),
num_res = MAX_ISP411_MEM_RES + MAX_ISP411_SENSOR_RES + MAX_ISP411_INT_SRC;

isp->isp_res = kcalloc(num_res, sizeof(struct resource),
GFP_KERNEL);
if (!isp->isp_res) {
r = -ENOMEM;
Expand All @@ -83,22 +84,52 @@ static int isp_v4_1_1_hw_init(struct amdgpu_isp *isp)
isp->isp_res[0].start = isp_base;
isp->isp_res[0].end = isp_base + ISP_REGS_OFFSET_END;

for (int_idx = 0; int_idx < MAX_ISP411_INT_SRC; int_idx++) {
isp->isp_res[int_idx + 1].name = "isp_4_1_1_irq";
isp->isp_res[int_idx + 1].flags = IORESOURCE_IRQ;
isp->isp_res[int_idx + 1].start =
isp->isp_res[1].name = "isp_4_1_1_phy0_reg";
isp->isp_res[1].flags = IORESOURCE_MEM;
isp->isp_res[1].start = isp_base + ISP411_PHY0_OFFSET;
isp->isp_res[1].end = isp_base + ISP411_PHY0_OFFSET + ISP411_PHY0_SIZE;

isp->isp_res[2].name = "isp_4_1_1_sensor0_reg";
isp->isp_res[2].flags = IORESOURCE_MEM;
isp->isp_res[2].start = isp_base + ISP411_GPIO_SENSOR0_OFFSET;
isp->isp_res[2].end = isp_base + ISP411_GPIO_SENSOR0_OFFSET +
ISP411_GPIO_SENSOR0_SIZE;

for (idx = MAX_ISP411_MEM_RES + MAX_ISP411_SENSOR_RES, int_idx = 0;
idx < num_res; idx++, int_idx++) {
isp->isp_res[idx].name = "isp_4_1_1_irq";
isp->isp_res[idx].flags = IORESOURCE_IRQ;
isp->isp_res[idx].start =
amdgpu_irq_create_mapping(adev, isp_4_1_1_int_srcid[int_idx]);
isp->isp_res[int_idx + 1].end =
isp->isp_res[int_idx + 1].start;
isp->isp_res[idx].end =
isp->isp_res[idx].start;
}

isp->isp_cell[0].name = "amd_isp_capture";
isp->isp_cell[0].num_resources = MAX_ISP411_INT_SRC + 1;
isp->isp_cell[0].num_resources = num_res;
isp->isp_cell[0].resources = &isp->isp_res[0];
isp->isp_cell[0].platform_data = isp->isp_pdata;
isp->isp_cell[0].pdata_size = sizeof(struct isp_platform_data);

r = mfd_add_hotplug_devices(isp->parent, isp->isp_cell, 1);
isp->isp_i2c_res = kcalloc(1, sizeof(struct resource), GFP_KERNEL);
if (!isp->isp_i2c_res) {
r = -ENOMEM;
DRM_ERROR("%s: isp mfd res alloc failed\n", __func__);
goto failure;
}

isp->isp_i2c_res[0].name = "isp_i2c0_reg";
isp->isp_i2c_res[0].flags = IORESOURCE_MEM;
isp->isp_i2c_res[0].start = isp_base + ISP411_I2C0_OFFSET;
isp->isp_i2c_res[0].end = isp_base + ISP411_I2C0_OFFSET + ISP411_I2C0_SIZE;

isp->isp_cell[1].name = "amd_isp_i2c_designware";
isp->isp_cell[1].num_resources = 1;
isp->isp_cell[1].resources = &isp->isp_i2c_res[0];
isp->isp_cell[1].platform_data = isp->isp_pdata;
isp->isp_cell[1].pdata_size = sizeof(struct isp_platform_data);

r = mfd_add_hotplug_devices(isp->parent, isp->isp_cell, 2);
if (r) {
DRM_ERROR("%s: add mfd hotplug device failed\n", __func__);
goto failure;
Expand All @@ -111,6 +142,7 @@ static int isp_v4_1_1_hw_init(struct amdgpu_isp *isp)
kfree(isp->isp_pdata);
kfree(isp->isp_res);
kfree(isp->isp_cell);
kfree(isp->isp_i2c_res);

return r;
}
Expand All @@ -122,6 +154,7 @@ static int isp_v4_1_1_hw_fini(struct amdgpu_isp *isp)
kfree(isp->isp_res);
kfree(isp->isp_cell);
kfree(isp->isp_pdata);
kfree(isp->isp_i2c_res);

return 0;
}
Expand Down
11 changes: 11 additions & 0 deletions drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,19 @@

#include "ivsrcid/isp/irqsrcs_isp_4_1.h"

#define MAX_ISP411_MEM_RES 2
#define MAX_ISP411_SENSOR_RES 1
#define MAX_ISP411_INT_SRC 8

#define ISP411_PHY0_OFFSET 0x66700
#define ISP411_PHY0_SIZE 0xD30

#define ISP411_I2C0_OFFSET 0x66400
#define ISP411_I2C0_SIZE 0x100

#define ISP411_GPIO_SENSOR0_OFFSET 0x6613C
#define ISP411_GPIO_SENSOR0_SIZE 0x4

void isp_v4_1_1_set_isp_funcs(struct amdgpu_isp *isp);

#endif

0 comments on commit 25dd25f

Please sign in to comment.