Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ There are 4 repositories that provide the complete setup:


## Content of this repository
- IPU7 kernel driver
- IPU7 kernel driver (support IPU8 by adding KCFLAGS="-DIPU8_INSYS_NEW_ABI" to make command)
- Kernel patches needed

## Dependencies
Expand All @@ -26,7 +26,7 @@ Three ways are available:
3. Build and install by dkms (DKMS build)

### 1. In-tree build
- Tested with kernel v6.8 and v6.10
- Tested with kernel v6.8 to v6.17
1. Check out kernel source code
2. Patch kernel source code, using patches under `patch/<kernel-version>` and `patch/<kernel-version>/in-tree-build` depending on what you need.
3. Copy `drivers` and `include` folders to kernel source code.
Expand Down
16 changes: 10 additions & 6 deletions drivers/media/pci/intel/ipu7/abi/ipu7_fw_boot_abi.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,14 +113,18 @@ struct ia_gofo_secondary_boot_config {
#define IA_GOFO_DOUBLE_EXCEPTION_ERR 0xdead0806U
#define IA_GOFO_BIST_DMEM_FAULT_DETECTION_ERR 0xdead1000U
#define IA_GOFO_BIST_DATA_INTEGRITY_FAILURE 0xdead1010U

#define IA_GOFO_BOOT_STATE_UNINIT 0x57a7e000U
#define IA_GOFO_BOOT_STATE_STARTING_0 0x57a7d000U
#define IA_GOFO_BOOT_STATE_CACHE_INIT_DONE 0x57a7d010U
#define IA_GOFO_BOOT_STATE_MEM_INIT_DONE 0x57a7d020U
#define IA_GOFO_BOOT_STATE_STACK_INIT_DONE 0x57a7d030U
enum ia_gofo_boot_state {
IA_GOFO_FW_BOOT_STATE_SECONDARY_BOOT_CONFIG_READY = 0x57a7b000U,
IA_GOFO_FW_BOOT_STATE_UNINIT = 0x57a7e000U,
IA_GOFO_FW_BOOT_STATE_STARTING_0 = 0x57a7d000U,
IA_GOFO_FW_BOOT_STATE_CACHE_INIT_DONE = 0x57a7d010U,
IA_GOFO_FW_BOOT_STATE_MEM_INIT_DONE = 0x57a7d020U,
IA_GOFO_FW_BOOT_STATE_STACK_INIT_DONE = 0x57a7d030U,
IA_GOFO_FW_BOOT_STATE_UNINIT = IA_GOFO_BOOT_STATE_UNINIT,
IA_GOFO_FW_BOOT_STATE_STARTING_0 = IA_GOFO_BOOT_STATE_STARTING_0,
IA_GOFO_FW_BOOT_STATE_CACHE_INIT_DONE = IA_GOFO_BOOT_STATE_CACHE_INIT_DONE,
IA_GOFO_FW_BOOT_STATE_MEM_INIT_DONE = IA_GOFO_BOOT_STATE_MEM_INIT_DONE,
IA_GOFO_FW_BOOT_STATE_STACK_INIT_DONE = IA_GOFO_BOOT_STATE_STACK_INIT_DONE,
IA_GOFO_FW_BOOT_STATE_EARLY_BOOT_DONE = 0x57a7d100U,
IA_GOFO_FW_BOOT_STATE_BOOT_CONFIG_START = 0x57a7d200U,
IA_GOFO_FW_BOOT_STATE_QUEUE_INIT_DONE = 0x57a7d300U,
Expand Down
13 changes: 13 additions & 0 deletions drivers/media/pci/intel/ipu7/abi/ipu7_fw_isys_abi.h
Original file line number Diff line number Diff line change
Expand Up @@ -356,13 +356,18 @@ struct ipu7_insys_resp {
struct ipu7_insys_capture_output_pin_payload pin;
struct ia_gofo_msg_err error_info;
u32 timestamp[2];
#ifdef IPU8_INSYS_NEW_ABI
u16 mipi_fn;
#endif
u8 type;
u8 msg_link_streaming_mode;
u8 stream_id;
u8 pin_id;
u8 frame_id;
u8 skip_frame;
#ifndef IPU8_INSYS_NEW_ABI
u16 mipi_fn;
#endif
};

struct ipu7_insys_resp_queue_token {
Expand Down Expand Up @@ -419,6 +424,14 @@ enum insys_msg_err_stream {
INSYS_MSG_ERR_STREAM_INSUFFICIENT_RESOURCES_OUTPUT = 36,
INSYS_MSG_ERR_STREAM_WIDTH_OUTPUT_SIZE = 37,
INSYS_MSG_ERR_STREAM_CLOSED = 38,
#ifdef IPU8_INSYS_NEW_ABI
INSYS_MSG_ERR_STREAM_BINNING_FACTOR_NOT_SUPPORTED = 39,
INSYS_MSG_ERR_STREAM_CFA_DIM_NOT_SUPPORTED = 40,
INSYS_MSG_ERR_STREAM_INVALID_UPIPE_ENABLE = 41,
INSYS_MSG_ERR_STREAM_INVALID_UPIPE_UOB_SINGLE = 42,
INSYS_MSG_ERR_STREAM_INVALID_UPIPE_UOB_SHARED = 43,
INSYS_MSG_ERR_STREAM_INVALID_UPIPE_OPAQUE_PIN_CFG = 44,
#endif
INSYS_MSG_ERR_STREAM_N
};

Expand Down
12 changes: 10 additions & 2 deletions drivers/media/pci/intel/ipu7/ipu7-buttress.c
Original file line number Diff line number Diff line change
Expand Up @@ -343,14 +343,22 @@ irqreturn_t ipu_buttress_isr(int irq, void *isp_ptr)
u32 disable_irqs = 0;
u32 irq_status;
unsigned int i;
int active;

pm_runtime_get_noresume(dev);
active = pm_runtime_get_if_active(dev);
if (active <= 0)
return IRQ_NONE;

pb_irq = readl(isp->pb_base + INTERRUPT_STATUS);
writel(pb_irq, isp->pb_base + INTERRUPT_STATUS);

/* check btrs ATS, CFI and IMR errors, BIT(0) is unused for IPU */
pb_local_irq = readl(isp->pb_base + BTRS_LOCAL_INTERRUPT_MASK);
if (WARN_ON_ONCE(pb_local_irq == 0xffffffff)) {
pm_runtime_put_noidle(dev);
return IRQ_NONE;
}

if (pb_local_irq & ~BIT(0)) {
dev_warn(dev, "PB interrupt status 0x%x local 0x%x\n", pb_irq,
pb_local_irq);
Expand All @@ -366,7 +374,7 @@ irqreturn_t ipu_buttress_isr(int irq, void *isp_ptr)
}

irq_status = readl(isp->base + BUTTRESS_REG_IRQ_STATUS);
if (!irq_status) {
if (!irq_status || WARN_ON_ONCE(irq_status == 0xffffffff)) {
pm_runtime_put_noidle(dev);
return IRQ_NONE;
}
Expand Down
3 changes: 1 addition & 2 deletions drivers/media/pci/intel/ipu7/ipu7-isys-queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -477,14 +477,13 @@ static int ipu7_isys_link_fmt_validate(struct ipu7_isys_queue *aq)
media_pad_remote_pad_first(av->vdev.entity.pads);
struct v4l2_mbus_framefmt format;
struct v4l2_subdev *sd;
u32 r_stream, code;
u32 r_stream = 0, code;
int ret;

if (!remote_pad)
return -ENOTCONN;

sd = media_entity_to_v4l2_subdev(remote_pad->entity);
r_stream = ipu7_isys_get_src_stream_by_src_pad(sd, remote_pad->index);

ret = ipu7_isys_get_stream_pad_fmt(sd, remote_pad->index, r_stream,
&format);
Expand Down
35 changes: 10 additions & 25 deletions drivers/media/pci/intel/ipu7/ipu7-isys-subdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,13 +194,22 @@ static int subdev_set_routing(struct v4l2_subdev *sd,
.code = MEDIA_BUS_FMT_SGRBG10_1X10,
.field = V4L2_FIELD_NONE,
};
struct v4l2_subdev_route *route;
int ret;

ret = v4l2_subdev_routing_validate(sd, routing,
V4L2_SUBDEV_ROUTING_ONLY_1_TO_1);
V4L2_SUBDEV_ROUTING_ONLY_1_TO_1 |
V4L2_SUBDEV_ROUTING_NO_SOURCE_MULTIPLEXING);
if (ret)
return ret;

/*
* The device doesn't support source multiplexing, set all source
* streams to 0 to simplify stream handling through the driver.
*/
for_each_active_route(routing, route)
route->source_stream = 0;

return v4l2_subdev_set_routing_with_fmt(sd, state, routing, &fmt);
}

Expand All @@ -222,30 +231,6 @@ int ipu7_isys_get_stream_pad_fmt(struct v4l2_subdev *sd, u32 pad, u32 stream,
return fmt ? 0 : -EINVAL;
}

u32 ipu7_isys_get_src_stream_by_src_pad(struct v4l2_subdev *sd, u32 pad)
{
struct v4l2_subdev_state *state;
struct v4l2_subdev_route *routes;
u32 source_stream = 0;
unsigned int i;

state = v4l2_subdev_lock_and_get_active_state(sd);
if (!state)
return 0;

routes = state->routing.routes;
for (i = 0; i < state->routing.num_routes; i++) {
if (routes[i].source_pad == pad) {
source_stream = routes[i].source_stream;
break;
}
}

v4l2_subdev_unlock_state(state);

return source_stream;
}

static int ipu7_isys_subdev_init_state(struct v4l2_subdev *sd,
struct v4l2_subdev_state *state)
{
Expand Down
1 change: 0 additions & 1 deletion drivers/media/pci/intel/ipu7/ipu7-isys-subdev.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ int ipu7_isys_subdev_enum_mbus_code(struct v4l2_subdev *sd,
struct v4l2_subdev_state *state,
struct v4l2_subdev_mbus_code_enum
*code);
u32 ipu7_isys_get_src_stream_by_src_pad(struct v4l2_subdev *sd, u32 pad);
int ipu7_isys_get_stream_pad_fmt(struct v4l2_subdev *sd, u32 pad, u32 stream,
struct v4l2_mbus_framefmt *format);
int ipu7_isys_subdev_set_routing(struct v4l2_subdev *sd,
Expand Down
33 changes: 3 additions & 30 deletions drivers/media/pci/intel/ipu7/ipu7-isys-video.c
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ static int link_validate(struct media_link *link)
struct v4l2_mbus_framefmt *s_fmt;
struct v4l2_subdev *s_sd;
struct media_pad *s_pad;
u32 s_stream, code;
u32 s_stream = 0, code;
int ret = -EPIPE;

if (!link->source->entity)
Expand All @@ -344,7 +344,6 @@ static int link_validate(struct media_link *link)
link->sink->entity->name);

s_pad = media_pad_remote_pad_first(&av->pad);
s_stream = ipu7_isys_get_src_stream_by_src_pad(s_sd, s_pad->index);

v4l2_subdev_lock_state(s_state);

Expand Down Expand Up @@ -407,10 +406,9 @@ static int ipu7_isys_fw_pin_cfg(struct ipu7_isys_video *av,
struct device *dev = &isys->adev->auxdev.dev;
struct v4l2_mbus_framefmt fmt;
int output_pins;
u32 src_stream;
u32 src_stream = 0;
int ret;

src_stream = ipu7_isys_get_src_stream_by_src_pad(sd, src_pad->index);
ret = ipu7_isys_get_stream_pad_fmt(sd, src_pad->index, src_stream,
&fmt);
if (ret < 0) {
Expand Down Expand Up @@ -860,38 +858,14 @@ ipu7_isys_query_stream_by_source(struct ipu7_isys *isys, int source, u8 vc)
return stream;
}

static u32 get_remote_pad_stream(struct media_pad *r_pad)
{
struct v4l2_subdev_state *state;
struct v4l2_subdev *sd;
struct v4l2_subdev_route *route;
u32 stream_id = 0;

sd = media_entity_to_v4l2_subdev(r_pad->entity);
state = v4l2_subdev_lock_and_get_active_state(sd);
if (!state)
return 0;

for_each_active_route(&state->routing, route) {
if (route->source_pad == r_pad->index) {
stream_id = route->source_stream;
break;
}
}

v4l2_subdev_unlock_state(state);

return stream_id;
}

int ipu7_isys_video_set_streaming(struct ipu7_isys_video *av, int state,
struct ipu7_isys_buffer_list *bl)
{
struct ipu7_isys_stream *stream = av->stream;
struct device *dev = &av->isys->adev->auxdev.dev;
struct media_pad *r_pad;
struct v4l2_subdev *sd;
u32 r_stream;
u32 r_stream = 0;
int ret = 0;

dev_dbg(dev, "set stream: %d\n", state);
Expand All @@ -901,7 +875,6 @@ int ipu7_isys_video_set_streaming(struct ipu7_isys_video *av, int state,

sd = &stream->asd->sd;
r_pad = media_pad_remote_pad_first(&av->pad);
r_stream = get_remote_pad_stream(r_pad);
if (!state) {
stop_streaming_firmware(av);

Expand Down
2 changes: 1 addition & 1 deletion drivers/media/pci/intel/ipu7/ipu7.c
Original file line number Diff line number Diff line change
Expand Up @@ -2713,7 +2713,7 @@ static int ipu7_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (!IS_ERR_OR_NULL(isp->isys) && !IS_ERR_OR_NULL(isp->isys->mmu))
ipu7_mmu_cleanup(isp->isys->mmu);
if (!IS_ERR_OR_NULL(isp->psys))
pm_runtime_put(&isp->psys->auxdev.dev);
pm_runtime_put_sync(&isp->psys->auxdev.dev);
ipu7_bus_del_devices(pdev);
release_firmware(isp->cpd_fw);
buttress_exit:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
From 63f2c63dc869a4e6a2e7e58040739b31c7894b6b Mon Sep 17 00:00:00 2001
From: linya14x <linx.yang@intel.com>
Date: Fri, 24 Oct 2025 12:44:25 +0800
Subject: [PATCH 1/6] staging: ipu7: Use DPHY as the default PHY mode

Signed-off-by: Bingbu Cao <bingbu.cao@intel.com>
---
drivers/staging/media/ipu7/ipu7-isys.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/media/ipu7/ipu7-isys.c b/drivers/staging/media/ipu7/ipu7-isys.c
index cb2f49f3e0fa..dd481f9d848d 100644
--- a/drivers/staging/media/ipu7/ipu7-isys.c
+++ b/drivers/staging/media/ipu7/ipu7-isys.c
@@ -81,10 +81,10 @@ isys_complete_ext_device_registration(struct ipu7_isys *isys,
}

isys->csi2[csi2->port].nlanes = csi2->nlanes;
- if (csi2->bus_type == V4L2_MBUS_CSI2_DPHY)
- isys->csi2[csi2->port].phy_mode = PHY_MODE_DPHY;
- else
+ if (csi2->bus_type == V4L2_MBUS_CSI2_CPHY)
isys->csi2[csi2->port].phy_mode = PHY_MODE_CPHY;
+ else
+ isys->csi2[csi2->port].phy_mode = PHY_MODE_DPHY;

return 0;

--
2.43.0

Loading