mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-19 05:38:00 +00:00
bcm27xx: update to latest RPi patches
The patches were generated from the RPi repo with the following command: git format-patch v6.6.44..rpi-6.6.y Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
This commit is contained in:
parent
ef8c1adb61
commit
0171157d45
@ -23,6 +23,7 @@
|
|||||||
# CONFIG_RASPBERRYPI_GPIOMEM is not set
|
# CONFIG_RASPBERRYPI_GPIOMEM is not set
|
||||||
# CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_V2 is not set
|
# CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_V2 is not set
|
||||||
# CONFIG_SENSORS_RP1_ADC is not set
|
# CONFIG_SENSORS_RP1_ADC is not set
|
||||||
|
# CONFIG_SPI_RP2040_GPIO_BRIDGE is not set
|
||||||
# CONFIG_VIDEO_AD5398 is not set
|
# CONFIG_VIDEO_AD5398 is not set
|
||||||
# CONFIG_VIDEO_ARDUCAM_64MP is not set
|
# CONFIG_VIDEO_ARDUCAM_64MP is not set
|
||||||
# CONFIG_VIDEO_ARDUCAM_PIVARIETY is not set
|
# CONFIG_VIDEO_ARDUCAM_PIVARIETY is not set
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
From 6aab06ff9f81e186b1a02b53b514e691472e5a61 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Phil Elwell <phil@raspberrypi.com>
|
|
||||||
Date: Tue, 7 Nov 2023 14:49:47 +0000
|
|
||||||
Subject: [PATCH 0714/1085] spi: dw-dma: Get the last DMA scoop out of the FIFO
|
|
||||||
|
|
||||||
With a DMA FIFO threshold greater than 1 (encoded as 0), it is possible
|
|
||||||
for data in the FIFO to be inaccessible, causing the transfer to fail
|
|
||||||
after a timeout. If the transfer includes a transmission, reduce the
|
|
||||||
RX threshold when the TX completes, otherwise use 1 for the whole
|
|
||||||
transfer (inefficient, but not catastrophic at SPI data rates).
|
|
||||||
|
|
||||||
See: https://github.com/raspberrypi/linux/issues/5696
|
|
||||||
|
|
||||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
|
||||||
---
|
|
||||||
drivers/spi/spi-dw-dma.c | 6 +++++-
|
|
||||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
--- a/drivers/spi/spi-dw-dma.c
|
|
||||||
+++ b/drivers/spi/spi-dw-dma.c
|
|
||||||
@@ -315,8 +315,10 @@ static void dw_spi_dma_tx_done(void *arg
|
|
||||||
struct dw_spi *dws = arg;
|
|
||||||
|
|
||||||
clear_bit(DW_SPI_TX_BUSY, &dws->dma_chan_busy);
|
|
||||||
- if (test_bit(DW_SPI_RX_BUSY, &dws->dma_chan_busy))
|
|
||||||
+ if (test_bit(DW_SPI_RX_BUSY, &dws->dma_chan_busy)) {
|
|
||||||
+ dw_writel(dws, DW_SPI_DMARDLR, 0);
|
|
||||||
return;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
complete(&dws->dma_completion);
|
|
||||||
}
|
|
||||||
@@ -642,6 +644,8 @@ static int dw_spi_dma_transfer(struct dw
|
|
||||||
|
|
||||||
nents = max(xfer->tx_sg.nents, xfer->rx_sg.nents);
|
|
||||||
|
|
||||||
+ dw_writel(dws, DW_SPI_DMARDLR, xfer->tx_buf ? (dws->rxburst - 1) : 0);
|
|
||||||
+
|
|
||||||
/*
|
|
||||||
* Execute normal DMA-based transfer (which submits the Rx and Tx SG
|
|
||||||
* lists directly to the DMA engine at once) if either full hardware
|
|
@ -0,0 +1,260 @@
|
|||||||
|
From 65fddc7301f52470fd846acede96d240a1902e67 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jonathan Bell <jonathan@raspberrypi.com>
|
||||||
|
Date: Fri, 5 Jul 2024 14:00:38 +0100
|
||||||
|
Subject: [PATCH 1146/1215] drivers: dwc_otg: use C11 style variable array
|
||||||
|
declarations
|
||||||
|
|
||||||
|
The kernel C standard changed in 5.18.
|
||||||
|
|
||||||
|
Remove a layer of indirection around the FIQ bounce buffers, be consistent
|
||||||
|
with pointers to FIQ bounce buffers, and remove open-coded 32-bit clamping
|
||||||
|
of DMA addresses.
|
||||||
|
|
||||||
|
Also remove a pointless fiq_state initialisation loop.
|
||||||
|
|
||||||
|
Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
|
||||||
|
---
|
||||||
|
drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c | 12 ++++----
|
||||||
|
drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h | 8 ++---
|
||||||
|
drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 34 ++++++++++-----------
|
||||||
|
drivers/usb/host/dwc_otg/dwc_otg_hcd.h | 4 +--
|
||||||
|
drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 4 +--
|
||||||
|
5 files changed, 28 insertions(+), 34 deletions(-)
|
||||||
|
|
||||||
|
--- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
|
||||||
|
+++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
|
||||||
|
@@ -240,8 +240,8 @@ static int notrace fiq_increment_dma_buf
|
||||||
|
hcdma_data_t hcdma;
|
||||||
|
int i = st->channel[n].dma_info.index;
|
||||||
|
int len;
|
||||||
|
- struct fiq_dma_blob *blob =
|
||||||
|
- (struct fiq_dma_blob *)(uintptr_t)st->dma_base;
|
||||||
|
+ struct fiq_dma_channel *split_dma =
|
||||||
|
+ (struct fiq_dma_channel *)(uintptr_t)st->dma_base;
|
||||||
|
|
||||||
|
len = fiq_get_xfer_len(st, n);
|
||||||
|
fiq_print(FIQDBG_INT, st, "LEN: %03d", len);
|
||||||
|
@@ -250,7 +250,7 @@ static int notrace fiq_increment_dma_buf
|
||||||
|
if (i > 6)
|
||||||
|
BUG();
|
||||||
|
|
||||||
|
- hcdma.d32 = (u32)(uintptr_t)&blob->channel[n].index[i].buf[0];
|
||||||
|
+ hcdma.d32 = lower_32_bits((uintptr_t)&split_dma[n].index[i].buf[0]);
|
||||||
|
FIQ_WRITE(st->dwc_regs_base + HC_START + (HC_OFFSET * n) + HC_DMA, hcdma.d32);
|
||||||
|
st->channel[n].dma_info.index = i;
|
||||||
|
return 0;
|
||||||
|
@@ -290,8 +290,8 @@ static int notrace fiq_iso_out_advance(s
|
||||||
|
hcsplt_data_t hcsplt;
|
||||||
|
hctsiz_data_t hctsiz;
|
||||||
|
hcdma_data_t hcdma;
|
||||||
|
- struct fiq_dma_blob *blob =
|
||||||
|
- (struct fiq_dma_blob *)(uintptr_t)st->dma_base;
|
||||||
|
+ struct fiq_dma_channel *split_dma =
|
||||||
|
+ (struct fiq_dma_channel *)(uintptr_t)st->dma_base;
|
||||||
|
int last = 0;
|
||||||
|
int i = st->channel[n].dma_info.index;
|
||||||
|
|
||||||
|
@@ -303,7 +303,7 @@ static int notrace fiq_iso_out_advance(s
|
||||||
|
last = 1;
|
||||||
|
|
||||||
|
/* New DMA address - address of bounce buffer referred to in index */
|
||||||
|
- hcdma.d32 = (u32)(uintptr_t)blob->channel[n].index[i].buf;
|
||||||
|
+ hcdma.d32 = lower_32_bits((uintptr_t)&split_dma[n].index[i].buf[0]);
|
||||||
|
//hcdma.d32 = FIQ_READ(st->dwc_regs_base + HC_START + (HC_OFFSET * n) + HC_DMA);
|
||||||
|
//hcdma.d32 += st->channel[n].dma_info.slot_len[i];
|
||||||
|
fiq_print(FIQDBG_INT, st, "LAST: %01d ", last);
|
||||||
|
--- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h
|
||||||
|
+++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h
|
||||||
|
@@ -263,10 +263,6 @@ struct fiq_dma_channel {
|
||||||
|
struct fiq_split_dma_slot index[6];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
-struct fiq_dma_blob {
|
||||||
|
- struct fiq_dma_channel channel[0];
|
||||||
|
-} __attribute__((packed));
|
||||||
|
-
|
||||||
|
/**
|
||||||
|
* struct fiq_hs_isoc_info - USB2.0 isochronous data
|
||||||
|
* @iso_frame: Pointer to the array of OTG URB iso_frame_descs.
|
||||||
|
@@ -352,7 +348,7 @@ struct fiq_state {
|
||||||
|
mphi_regs_t mphi_regs;
|
||||||
|
void *dwc_regs_base;
|
||||||
|
dma_addr_t dma_base;
|
||||||
|
- struct fiq_dma_blob *fiq_dmab;
|
||||||
|
+ struct fiq_dma_channel *fiq_dmab;
|
||||||
|
void *dummy_send;
|
||||||
|
dma_addr_t dummy_send_dma;
|
||||||
|
gintmsk_data_t gintmsk_saved;
|
||||||
|
@@ -365,7 +361,7 @@ struct fiq_state {
|
||||||
|
char * buffer;
|
||||||
|
unsigned int bufsiz;
|
||||||
|
#endif
|
||||||
|
- struct fiq_channel_state channel[0];
|
||||||
|
+ struct fiq_channel_state channel[];
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_ARM64
|
||||||
|
--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
|
||||||
|
+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
|
||||||
|
@@ -58,6 +58,7 @@ static int last_sel_trans_num_avail_hc_a
|
||||||
|
static int last_sel_trans_num_avail_hc_at_end = 0;
|
||||||
|
#endif /* DEBUG_HOST_CHANNELS */
|
||||||
|
|
||||||
|
+static_assert(FIQ_PASSTHROUGH == 0);
|
||||||
|
|
||||||
|
dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void)
|
||||||
|
{
|
||||||
|
@@ -876,7 +877,7 @@ void dwc_otg_hcd_power_up(void *ptr)
|
||||||
|
void dwc_otg_cleanup_fiq_channel(dwc_otg_hcd_t *hcd, uint32_t num)
|
||||||
|
{
|
||||||
|
struct fiq_channel_state *st = &hcd->fiq_state->channel[num];
|
||||||
|
- struct fiq_dma_blob *blob = hcd->fiq_dmab;
|
||||||
|
+ struct fiq_dma_channel *split_dma = hcd->fiq_dmab;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
st->fsm = FIQ_PASSTHROUGH;
|
||||||
|
@@ -898,7 +899,7 @@ void dwc_otg_cleanup_fiq_channel(dwc_otg
|
||||||
|
st->hs_isoc_info.iso_desc = NULL;
|
||||||
|
st->hs_isoc_info.nrframes = 0;
|
||||||
|
|
||||||
|
- DWC_MEMSET(&blob->channel[num].index[0], 0x6b, 1128);
|
||||||
|
+ DWC_MEMSET(&split_dma[num].index[0], 0x6b, 1128);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@@ -1045,9 +1046,6 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd
|
||||||
|
spin_lock_init(&hcd->fiq_state->lock);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
- for (i = 0; i < num_channels; i++) {
|
||||||
|
- hcd->fiq_state->channel[i].fsm = FIQ_PASSTHROUGH;
|
||||||
|
- }
|
||||||
|
hcd->fiq_state->dummy_send = DWC_DMA_ALLOC_ATOMIC(dev, 16,
|
||||||
|
&hcd->fiq_state->dummy_send_dma);
|
||||||
|
|
||||||
|
@@ -1561,7 +1559,7 @@ int fiq_fsm_setup_periodic_dma(dwc_otg_h
|
||||||
|
int frame_length, i = 0;
|
||||||
|
uint8_t *ptr = NULL;
|
||||||
|
dwc_hc_t *hc = qh->channel;
|
||||||
|
- struct fiq_dma_blob *blob;
|
||||||
|
+ struct fiq_dma_channel *split_dma;
|
||||||
|
struct dwc_otg_hcd_iso_packet_desc *frame_desc;
|
||||||
|
|
||||||
|
for (i = 0; i < 6; i++) {
|
||||||
|
@@ -1576,10 +1574,10 @@ int fiq_fsm_setup_periodic_dma(dwc_otg_h
|
||||||
|
* Pointer arithmetic on hcd->fiq_state->dma_base (a dma_addr_t)
|
||||||
|
* to point it to the correct offset in the allocated buffers.
|
||||||
|
*/
|
||||||
|
- blob = (struct fiq_dma_blob *)
|
||||||
|
+ split_dma = (struct fiq_dma_channel *)
|
||||||
|
(uintptr_t)hcd->fiq_state->dma_base;
|
||||||
|
- st->hcdma_copy.d32 =(u32)(uintptr_t)
|
||||||
|
- blob->channel[hc->hc_num].index[0].buf;
|
||||||
|
+ st->hcdma_copy.d32 = lower_32_bits((uintptr_t)
|
||||||
|
+ &split_dma[hc->hc_num].index[0].buf[0]);
|
||||||
|
|
||||||
|
/* Calculate the max number of CSPLITS such that the FIQ can time out
|
||||||
|
* a transaction if it fails.
|
||||||
|
@@ -1600,7 +1598,7 @@ int fiq_fsm_setup_periodic_dma(dwc_otg_h
|
||||||
|
frame_length = frame_desc->length;
|
||||||
|
|
||||||
|
/* Virtual address for bounce buffers */
|
||||||
|
- blob = hcd->fiq_dmab;
|
||||||
|
+ split_dma = hcd->fiq_dmab;
|
||||||
|
|
||||||
|
ptr = qtd->urb->buf + frame_desc->offset;
|
||||||
|
if (frame_length == 0) {
|
||||||
|
@@ -1613,11 +1611,11 @@ int fiq_fsm_setup_periodic_dma(dwc_otg_h
|
||||||
|
} else {
|
||||||
|
do {
|
||||||
|
if (frame_length <= 188) {
|
||||||
|
- dwc_memcpy(&blob->channel[hc->hc_num].index[i].buf[0], ptr, frame_length);
|
||||||
|
+ dwc_memcpy(&split_dma[hc->hc_num].index[i].buf[0], ptr, frame_length);
|
||||||
|
st->dma_info.slot_len[i] = frame_length;
|
||||||
|
ptr += frame_length;
|
||||||
|
} else {
|
||||||
|
- dwc_memcpy(&blob->channel[hc->hc_num].index[i].buf[0], ptr, 188);
|
||||||
|
+ dwc_memcpy(&split_dma[hc->hc_num].index[i].buf[0], ptr, 188);
|
||||||
|
st->dma_info.slot_len[i] = 188;
|
||||||
|
ptr += 188;
|
||||||
|
}
|
||||||
|
@@ -1634,10 +1632,10 @@ int fiq_fsm_setup_periodic_dma(dwc_otg_h
|
||||||
|
* dma_addr_t) to point it to the correct offset in the
|
||||||
|
* allocated buffers.
|
||||||
|
*/
|
||||||
|
- blob = (struct fiq_dma_blob *)
|
||||||
|
+ split_dma = (struct fiq_dma_channel *)
|
||||||
|
(uintptr_t)hcd->fiq_state->dma_base;
|
||||||
|
- st->hcdma_copy.d32 = (u32)(uintptr_t)
|
||||||
|
- blob->channel[hc->hc_num].index[0].buf;
|
||||||
|
+ st->hcdma_copy.d32 = lower_32_bits((uintptr_t)
|
||||||
|
+ &split_dma[hc->hc_num].index[0].buf[0]);
|
||||||
|
|
||||||
|
/* fixup xfersize to the actual packet size */
|
||||||
|
st->hctsiz_copy.b.pid = 0;
|
||||||
|
@@ -1917,14 +1915,14 @@ int fiq_fsm_queue_split_transaction(dwc_
|
||||||
|
if (hc->align_buff) {
|
||||||
|
st->hcdma_copy.d32 = hc->align_buff;
|
||||||
|
} else {
|
||||||
|
- st->hcdma_copy.d32 = ((unsigned long) hc->xfer_buff & 0xFFFFFFFF);
|
||||||
|
+ st->hcdma_copy.d32 = lower_32_bits((uintptr_t)hc->xfer_buff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (hc->align_buff) {
|
||||||
|
st->hcdma_copy.d32 = hc->align_buff;
|
||||||
|
} else {
|
||||||
|
- st->hcdma_copy.d32 = ((unsigned long) hc->xfer_buff & 0xFFFFFFFF);
|
||||||
|
+ st->hcdma_copy.d32 = lower_32_bits((uintptr_t)hc->xfer_buff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* The FIQ depends upon no other interrupts being enabled except channel halt.
|
||||||
|
@@ -1944,7 +1942,7 @@ int fiq_fsm_queue_split_transaction(dwc_
|
||||||
|
if (hc->align_buff) {
|
||||||
|
st->hcdma_copy.d32 = hc->align_buff;
|
||||||
|
} else {
|
||||||
|
- st->hcdma_copy.d32 = ((unsigned long) hc->xfer_buff & 0xFFFFFFFF);
|
||||||
|
+ st->hcdma_copy.d32 = lower_32_bits((uintptr_t)hc->xfer_buff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DWC_WRITE_REG32(&hc_regs->hcdma, st->hcdma_copy.d32);
|
||||||
|
--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h
|
||||||
|
+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h
|
||||||
|
@@ -88,7 +88,7 @@ struct dwc_otg_hcd_urb {
|
||||||
|
uint32_t flags;
|
||||||
|
uint16_t interval;
|
||||||
|
struct dwc_otg_hcd_pipe_info pipe_info;
|
||||||
|
- struct dwc_otg_hcd_iso_packet_desc iso_descs[0];
|
||||||
|
+ struct dwc_otg_hcd_iso_packet_desc iso_descs[];
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline uint8_t dwc_otg_hcd_get_ep_num(struct dwc_otg_hcd_pipe_info *pipe)
|
||||||
|
@@ -592,7 +592,7 @@ struct dwc_otg_hcd {
|
||||||
|
struct fiq_state *fiq_state;
|
||||||
|
|
||||||
|
/** Virtual address for split transaction DMA bounce buffers */
|
||||||
|
- struct fiq_dma_blob *fiq_dmab;
|
||||||
|
+ struct fiq_dma_channel *fiq_dmab;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
uint32_t frrem_samples;
|
||||||
|
--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
|
||||||
|
+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
|
||||||
|
@@ -2332,7 +2332,7 @@ void dwc_otg_fiq_unmangle_isoc(dwc_otg_h
|
||||||
|
int dwc_otg_fiq_unsetup_per_dma(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh, dwc_otg_qtd_t *qtd, uint32_t num)
|
||||||
|
{
|
||||||
|
dwc_hc_t *hc = qh->channel;
|
||||||
|
- struct fiq_dma_blob *blob = hcd->fiq_dmab;
|
||||||
|
+ struct fiq_dma_channel *split_dma = hcd->fiq_dmab;
|
||||||
|
struct fiq_channel_state *st = &hcd->fiq_state->channel[num];
|
||||||
|
uint8_t *ptr = NULL;
|
||||||
|
int index = 0, len = 0;
|
||||||
|
@@ -2352,7 +2352,7 @@ int dwc_otg_fiq_unsetup_per_dma(dwc_otg_
|
||||||
|
|
||||||
|
for (i = 0; i < st->dma_info.index; i++) {
|
||||||
|
len += st->dma_info.slot_len[i];
|
||||||
|
- dwc_memcpy(ptr, &blob->channel[num].index[i].buf[0], st->dma_info.slot_len[i]);
|
||||||
|
+ dwc_memcpy(ptr, &split_dma[num].index[i].buf[0], st->dma_info.slot_len[i]);
|
||||||
|
ptr += st->dma_info.slot_len[i];
|
||||||
|
}
|
||||||
|
return len;
|
@ -0,0 +1,27 @@
|
|||||||
|
From 8dea9155ab081289edd618f8373d5f980d5bb664 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
|
||||||
|
Date: Fri, 23 Feb 2024 10:40:47 +0100
|
||||||
|
Subject: [PATCH 1147/1215] media: uapi: pixfmt-luma: Document MIPI CSI-2
|
||||||
|
packing
|
||||||
|
|
||||||
|
The Y10P, Y12P and Y14P format variants are packed according to
|
||||||
|
the RAW10, RAW12 and RAW14 formats as defined by the MIPI CSI-2
|
||||||
|
specification. Document it.
|
||||||
|
|
||||||
|
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
|
||||||
|
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||||
|
Reviewed-by: Naushir Patuck <naush@raspberrypi.com>
|
||||||
|
---
|
||||||
|
Documentation/userspace-api/media/v4l/pixfmt-yuv-luma.rst | 4 ++++
|
||||||
|
1 file changed, 4 insertions(+)
|
||||||
|
|
||||||
|
--- a/Documentation/userspace-api/media/v4l/pixfmt-yuv-luma.rst
|
||||||
|
+++ b/Documentation/userspace-api/media/v4l/pixfmt-yuv-luma.rst
|
||||||
|
@@ -161,3 +161,7 @@ are often referred to as greyscale forma
|
||||||
|
For Y012 and Y12 formats, Y012 places its data in the 12 high bits, with
|
||||||
|
padding zeros in the 4 low bits, in contrast to the Y12 format, which has
|
||||||
|
its padding located in the most significant bits of the 16 bit word.
|
||||||
|
+
|
||||||
|
+ The 'P' variations of the Y10, Y12 and Y14 formats are packed according to
|
||||||
|
+ the RAW10, RAW12 and RAW14 packing scheme as defined by the MIPI CSI-2
|
||||||
|
+ specification.
|
@ -0,0 +1,101 @@
|
|||||||
|
From 814c088cb7183f79ba68c8f9459505e2ac4dde3a Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
|
||||||
|
Date: Fri, 26 Jan 2024 15:03:18 +0100
|
||||||
|
Subject: [PATCH 1148/1215] media: uapi: Add a pixel format for BGR48 and RGB48
|
||||||
|
|
||||||
|
Add BGR48 and RGB48 16-bit per component image formats.
|
||||||
|
|
||||||
|
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
|
||||||
|
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
|
||||||
|
Reviewed-by: Naushir Patuck <naush@raspberrypi.com>
|
||||||
|
---
|
||||||
|
.../userspace-api/media/v4l/pixfmt-rgb.rst | 54 +++++++++++++++++++
|
||||||
|
drivers/media/v4l2-core/v4l2-common.c | 2 +
|
||||||
|
include/uapi/linux/videodev2.h | 2 +
|
||||||
|
3 files changed, 58 insertions(+)
|
||||||
|
|
||||||
|
--- a/Documentation/userspace-api/media/v4l/pixfmt-rgb.rst
|
||||||
|
+++ b/Documentation/userspace-api/media/v4l/pixfmt-rgb.rst
|
||||||
|
@@ -996,6 +996,60 @@ arranged in little endian order.
|
||||||
|
|
||||||
|
\normalsize
|
||||||
|
|
||||||
|
+16 Bits Per Component
|
||||||
|
+=====================
|
||||||
|
+
|
||||||
|
+These formats store an RGB triplet in six bytes, with 16 bits per component
|
||||||
|
+stored in memory in little endian byte order. They are named based on the order
|
||||||
|
+of the RGB components as stored in memory. For instance, RGB48 stores R\
|
||||||
|
+:sub:`7:0` and R\ :sub:`15:8` in bytes 0 and 1 respectively. This differs from
|
||||||
|
+the DRM format nomenclature that instead uses the order of components as seen in
|
||||||
|
+the 48-bits little endian word.
|
||||||
|
+
|
||||||
|
+.. raw:: latex
|
||||||
|
+
|
||||||
|
+ \small
|
||||||
|
+
|
||||||
|
+.. flat-table:: RGB Formats With 16 Bits Per Component
|
||||||
|
+ :header-rows: 1
|
||||||
|
+
|
||||||
|
+ * - Identifier
|
||||||
|
+ - Code
|
||||||
|
+ - Byte 0
|
||||||
|
+ - Byte 1
|
||||||
|
+ - Byte 2
|
||||||
|
+ - Byte 3
|
||||||
|
+ - Byte 4
|
||||||
|
+ - Byte 5
|
||||||
|
+
|
||||||
|
+ * .. _V4L2-PIX-FMT-BGR48:
|
||||||
|
+
|
||||||
|
+ - ``V4L2_PIX_FMT_BGR48``
|
||||||
|
+ - 'BGR6'
|
||||||
|
+
|
||||||
|
+ - B\ :sub:`7-0`
|
||||||
|
+ - B\ :sub:`15-8`
|
||||||
|
+ - G\ :sub:`7-0`
|
||||||
|
+ - G\ :sub:`15-8`
|
||||||
|
+ - R\ :sub:`7-0`
|
||||||
|
+ - R\ :sub:`15-8`
|
||||||
|
+
|
||||||
|
+ * .. _V4L2-PIX-FMT-RGB48:
|
||||||
|
+
|
||||||
|
+ - ``V4L2_PIX_FMT_RGB48``
|
||||||
|
+ - 'RGB6'
|
||||||
|
+
|
||||||
|
+ - R\ :sub:`7-0`
|
||||||
|
+ - R\ :sub:`15-8`
|
||||||
|
+ - G\ :sub:`7-0`
|
||||||
|
+ - G\ :sub:`15-8`
|
||||||
|
+ - B\ :sub:`7-0`
|
||||||
|
+ - B\ :sub:`15-8`
|
||||||
|
+
|
||||||
|
+.. raw:: latex
|
||||||
|
+
|
||||||
|
+ \normalsize
|
||||||
|
+
|
||||||
|
Deprecated RGB Formats
|
||||||
|
======================
|
||||||
|
|
||||||
|
--- a/drivers/media/v4l2-core/v4l2-common.c
|
||||||
|
+++ b/drivers/media/v4l2-core/v4l2-common.c
|
||||||
|
@@ -253,6 +253,8 @@ const struct v4l2_format_info *v4l2_form
|
||||||
|
{ .format = V4L2_PIX_FMT_RGB555, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
|
||||||
|
{ .format = V4L2_PIX_FMT_BGR666, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
|
||||||
|
{ .format = V4L2_PIX_FMT_BGR48_12, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 6, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
|
||||||
|
+ { .format = V4L2_PIX_FMT_BGR48, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 6, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
|
||||||
|
+ { .format = V4L2_PIX_FMT_RGB48, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 6, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
|
||||||
|
{ .format = V4L2_PIX_FMT_ABGR64_12, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 8, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 },
|
||||||
|
|
||||||
|
/* YUV packed formats */
|
||||||
|
--- a/include/uapi/linux/videodev2.h
|
||||||
|
+++ b/include/uapi/linux/videodev2.h
|
||||||
|
@@ -587,6 +587,8 @@ struct v4l2_pix_format {
|
||||||
|
|
||||||
|
/* RGB formats (6 or 8 bytes per pixel) */
|
||||||
|
#define V4L2_PIX_FMT_BGR48_12 v4l2_fourcc('B', '3', '1', '2') /* 48 BGR 12-bit per component */
|
||||||
|
+#define V4L2_PIX_FMT_BGR48 v4l2_fourcc('B', 'G', 'R', '6') /* 48 BGR 16-bit per component */
|
||||||
|
+#define V4L2_PIX_FMT_RGB48 v4l2_fourcc('R', 'G', 'B', '6') /* 48 RGB 16-bit per component */
|
||||||
|
#define V4L2_PIX_FMT_ABGR64_12 v4l2_fourcc('B', '4', '1', '2') /* 64 BGRA 12-bit per component */
|
||||||
|
|
||||||
|
/* RGB formats (6 bytes per pixel) */
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,86 @@
|
|||||||
|
From 7ca73020a5b26599d539083e413784e79891107e Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
|
||||||
|
Date: Fri, 26 Jan 2024 15:04:59 +0100
|
||||||
|
Subject: [PATCH 1150/1215] media: uapi: Document meta pixel format for PiSP BE
|
||||||
|
config
|
||||||
|
|
||||||
|
Add format description for the PiSP Back End configuration parameter
|
||||||
|
buffer.
|
||||||
|
|
||||||
|
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
|
||||||
|
Reviewed-by: Naushir Patuck <naush@raspberrypi.com>
|
||||||
|
---
|
||||||
|
.../userspace-api/media/v4l/meta-formats.rst | 1 +
|
||||||
|
.../media/v4l/metafmt-pisp-be.rst | 56 +++++++++++++++++++
|
||||||
|
2 files changed, 57 insertions(+)
|
||||||
|
create mode 100644 Documentation/userspace-api/media/v4l/metafmt-pisp-be.rst
|
||||||
|
|
||||||
|
--- a/Documentation/userspace-api/media/v4l/meta-formats.rst
|
||||||
|
+++ b/Documentation/userspace-api/media/v4l/meta-formats.rst
|
||||||
|
@@ -15,6 +15,7 @@ These formats are used for the :ref:`met
|
||||||
|
metafmt-bcm2835-isp-stats
|
||||||
|
metafmt-d4xx
|
||||||
|
metafmt-intel-ipu3
|
||||||
|
+ metafmt-pisp-be
|
||||||
|
metafmt-rkisp1
|
||||||
|
metafmt-sensor-data
|
||||||
|
metafmt-uvc
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/Documentation/userspace-api/media/v4l/metafmt-pisp-be.rst
|
||||||
|
@@ -0,0 +1,56 @@
|
||||||
|
+.. SPDX-License-Identifier: GPL-2.0
|
||||||
|
+
|
||||||
|
+.. _v4l2-meta-fmt-rpi-be-cfg:
|
||||||
|
+
|
||||||
|
+************************
|
||||||
|
+V4L2_META_FMT_RPI_BE_CFG
|
||||||
|
+************************
|
||||||
|
+
|
||||||
|
+Raspberry Pi PiSP Back End configuration format
|
||||||
|
+===============================================
|
||||||
|
+
|
||||||
|
+The Raspberry Pi PiSP Back End memory-to-memory image signal processor is
|
||||||
|
+configured by userspace by providing a buffer of configuration parameters
|
||||||
|
+to the `pispbe-config` output video device node using the
|
||||||
|
+:c:type:`v4l2_meta_format` interface.
|
||||||
|
+
|
||||||
|
+The PiSP Back End processes images in tiles, and its configuration requires
|
||||||
|
+specifying two different sets of parameters by populating the members of
|
||||||
|
+:c:type:`pisp_be_tiles_config` defined in the ``pisp_be_config.h`` header file.
|
||||||
|
+
|
||||||
|
+The `Raspberry Pi PiSP technical specification
|
||||||
|
+<https://datasheets.raspberrypi.com/camera/raspberry-pi-image-signal-processor-specification.pdf>`_
|
||||||
|
+provide detailed description of the ISP back end configuration and programming
|
||||||
|
+model.
|
||||||
|
+
|
||||||
|
+Global configuration data
|
||||||
|
+-------------------------
|
||||||
|
+
|
||||||
|
+The global configuration data describe how the pixels in a particular image are
|
||||||
|
+to be processed and is therefore shared across all the tiles of the image. So
|
||||||
|
+for example, LSC (Lens Shading Correction) or Denoise parameters would be common
|
||||||
|
+across all tiles from the same frame.
|
||||||
|
+
|
||||||
|
+Global configuration data are passed to the ISP by populating the member of
|
||||||
|
+:c:type:`pisp_be_config`.
|
||||||
|
+
|
||||||
|
+Tile parameters
|
||||||
|
+---------------
|
||||||
|
+
|
||||||
|
+As the ISP processes images in tiles, each set of tiles parameters describe how
|
||||||
|
+a single tile in an image is going to be processed. A single set of tile
|
||||||
|
+parameters consist of 160 bytes of data and to process a batch of tiles several
|
||||||
|
+sets of tiles parameters are required.
|
||||||
|
+
|
||||||
|
+Tiles parameters are passed to the ISP by populating the member of
|
||||||
|
+``pisp_tile`` and the ``num_tiles`` fields of :c:type:`pisp_be_tiles_config`.
|
||||||
|
+
|
||||||
|
+Raspberry Pi PiSP Back End uAPI data types
|
||||||
|
+==========================================
|
||||||
|
+
|
||||||
|
+This section describes the data types exposed to userspace by the Raspberry Pi
|
||||||
|
+PiSP Back End. The section is informative only, for a detailed description of
|
||||||
|
+each field refer to the `Raspberry Pi PiSP technical specification
|
||||||
|
+<https://datasheets.raspberrypi.com/camera/raspberry-pi-image-signal-processor-specification.pdf>`_.
|
||||||
|
+
|
||||||
|
+.. kernel-doc:: include/uapi/linux/media/raspberrypi/pisp_be_config.h
|
@ -0,0 +1,106 @@
|
|||||||
|
From 5d6318f242cce5f9b5677baedde736a2b81061df Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
|
||||||
|
Date: Wed, 17 Jan 2024 11:21:50 +0200
|
||||||
|
Subject: [PATCH 1151/1215] media: uapi: Document PiSP Compressed RAW Bayer
|
||||||
|
formats
|
||||||
|
|
||||||
|
Document the Raspberry Pi compressed RAW Bayer formats.
|
||||||
|
|
||||||
|
The compression algorithm description is provided by Nick Hollinghurst
|
||||||
|
<nick.hollinghurst@raspberrypi.com> from Raspberry Pi.
|
||||||
|
|
||||||
|
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
|
||||||
|
Reviewed-by: Naushir Patuck <naush@raspberrypi.com>
|
||||||
|
---
|
||||||
|
.../userspace-api/media/v4l/pixfmt-bayer.rst | 1 +
|
||||||
|
.../media/v4l/pixfmt-srggb8-pisp-comp.rst | 74 +++++++++++++++++++
|
||||||
|
2 files changed, 75 insertions(+)
|
||||||
|
create mode 100644 Documentation/userspace-api/media/v4l/pixfmt-srggb8-pisp-comp.rst
|
||||||
|
|
||||||
|
--- a/Documentation/userspace-api/media/v4l/pixfmt-bayer.rst
|
||||||
|
+++ b/Documentation/userspace-api/media/v4l/pixfmt-bayer.rst
|
||||||
|
@@ -20,6 +20,7 @@ orders. See also `the Wikipedia article
|
||||||
|
:maxdepth: 1
|
||||||
|
|
||||||
|
pixfmt-srggb8
|
||||||
|
+ pixfmt-srggb8-pisp-comp
|
||||||
|
pixfmt-srggb10
|
||||||
|
pixfmt-srggb10p
|
||||||
|
pixfmt-srggb10alaw8
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/Documentation/userspace-api/media/v4l/pixfmt-srggb8-pisp-comp.rst
|
||||||
|
@@ -0,0 +1,74 @@
|
||||||
|
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
|
||||||
|
+
|
||||||
|
+.. _v4l2-pix-fmt-pisp-comp1-rggb:
|
||||||
|
+.. _v4l2-pix-fmt-pisp-comp1-grbg:
|
||||||
|
+.. _v4l2-pix-fmt-pisp-comp1-gbrg:
|
||||||
|
+.. _v4l2-pix-fmt-pisp-comp1-bggr:
|
||||||
|
+.. _v4l2-pix-fmt-pisp-comp1-mono:
|
||||||
|
+.. _v4l2-pix-fmt-pisp-comp2-rggb:
|
||||||
|
+.. _v4l2-pix-fmt-pisp-comp2-grbg:
|
||||||
|
+.. _v4l2-pix-fmt-pisp-comp2-gbrg:
|
||||||
|
+.. _v4l2-pix-fmt-pisp-comp2-bggr:
|
||||||
|
+.. _v4l2-pix-fmt-pisp-comp2-mono:
|
||||||
|
+
|
||||||
|
+**************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
|
||||||
|
+V4L2_PIX_FMT_PISP_COMP1_RGGB ('PC1R'), V4L2_PIX_FMT_PISP_COMP1_GRBG ('PC1G'), V4L2_PIX_FMT_PISP_COMP1_GBRG ('PC1g'), V4L2_PIX_FMT_PISP_COMP1_BGGR ('PC1B), V4L2_PIX_FMT_PISP_COMP1_MONO ('PC1M'), V4L2_PIX_FMT_PISP_COMP2_RGGB ('PC2R'), V4L2_PIX_FMT_PISP_COMP2_GRBG ('PC2G'), V4L2_PIX_FMT_PISP_COMP2_GBRG ('PC2g'), V4L2_PIX_FMT_PISP_COMP2_BGGR ('PC2B), V4L2_PIX_FMT_PISP_COMP2_MONO ('PC2M')
|
||||||
|
+**************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
|
||||||
|
+
|
||||||
|
+================================================
|
||||||
|
+Raspberry Pi PiSP compressed 8-bit Bayer formats
|
||||||
|
+================================================
|
||||||
|
+
|
||||||
|
+Description
|
||||||
|
+===========
|
||||||
|
+
|
||||||
|
+The Raspberry Pi ISP (PiSP) uses a family of three fixed-rate compressed Bayer
|
||||||
|
+formats. A black-level offset may be subtracted to improve compression
|
||||||
|
+efficiency; the nominal black level and amount of offset must be signalled out
|
||||||
|
+of band. Each scanline is padded to a multiple of 8 pixels wide, and each block
|
||||||
|
+of 8 horizontally-contiguous pixels is coded using 8 bytes.
|
||||||
|
+
|
||||||
|
+Mode 1 uses a quantization and delta-based coding scheme which preserves up to
|
||||||
|
+12 significant bits. Mode 2 is a simple sqrt-like companding scheme with 6 PWL
|
||||||
|
+chords, preserving up to 12 significant bits. Mode 3 combines both companding
|
||||||
|
+(with 4 chords) and the delta scheme, preserving up to 14 significant bits.
|
||||||
|
+
|
||||||
|
+The remainder of this description applies to Modes 1 and 3.
|
||||||
|
+
|
||||||
|
+Each block of 8 pixels is separated into even and odd phases of 4 pixels,
|
||||||
|
+coded independently by 32-bit words at successive locations in memory.
|
||||||
|
+The two LS bits of each 32-bit word give its "quantization mode".
|
||||||
|
+
|
||||||
|
+In quantization mode 0, the lowest 321 quantization levels are multiples of
|
||||||
|
+FSD/4096 and the remaining levels are successive multiples of FSD/2048.
|
||||||
|
+Quantization modes 1 and 2 use linear quantization with step sizes of
|
||||||
|
+FSD/1024 and FSD/512 respectively. Each of the four pixels is quantized
|
||||||
|
+independently, with rounding to the nearest level.
|
||||||
|
+In quantization mode 2 where the middle two samples have quantized values
|
||||||
|
+(q1,q2) both in the range [384..511], they are coded using 9 bits for q1
|
||||||
|
+followed by 7 bits for (q2 & 127). Otherwise, for quantization modes
|
||||||
|
+0, 1 and 2: a 9-bit field encodes MIN(q1,q2) which must be in the range
|
||||||
|
+[0..511] and a 7-bit field encodes (q2-q1+64) which must be in [0..127].
|
||||||
|
+
|
||||||
|
+Each of the outer samples (q0,q3) is encoded using a 7-bit field based
|
||||||
|
+on its inner neighbour q1 or q2. In quantization mode 2 where the inner
|
||||||
|
+sample has a quantized value in the range [448..511], the field value is
|
||||||
|
+(q0-384). Otherwise for quantization modes 0, 1 and 2: The outer sample
|
||||||
|
+is encoded as (q0-MAX(0,q1-64)). q3 is likewise coded based on q2.
|
||||||
|
+Each of these values must be in the range [0..127]. All these fields
|
||||||
|
+of 2, 9, 7, 7, 7 bits respectively are packed in little-endian order
|
||||||
|
+to give a 32-bit word with LE byte order.
|
||||||
|
+
|
||||||
|
+Quantization mode 3 has a "7.5-bit" escape, used when none of the above
|
||||||
|
+encodings will fit. Each pixel value is quantized to the nearest of 176
|
||||||
|
+levels, where the lowest 95 levels are multiples of FSD/256 and the
|
||||||
|
+remaining levels are multiples of FSD/128 (level 175 represents values
|
||||||
|
+very close to FSD and may require saturating arithmetic to decode).
|
||||||
|
+
|
||||||
|
+Each pair of quantized pixels (q0,q1) or (q2,q3) is jointly coded
|
||||||
|
+by a 15-bit field: 2816*(q0>>4) + 16*q1 + (q0&15).
|
||||||
|
+Three fields of 2, 15, 15 bits are packed in LE order {15,15,2}.
|
||||||
|
+
|
||||||
|
+An implementation of a software decoder of compressed formats is available
|
||||||
|
+in `Raspberry Pi camera applications code base
|
||||||
|
+<https://github.com/raspberrypi/rpicam-apps/blob/main/image/dng.cpp>`_.
|
@ -0,0 +1,97 @@
|
|||||||
|
From c38a898c6877c6722ebfecea99f42e5a84c3e453 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
|
||||||
|
Date: Thu, 25 Jan 2024 16:42:33 +0100
|
||||||
|
Subject: [PATCH 1152/1215] media: dt-bindings: Add bindings for Raspberry Pi
|
||||||
|
PiSP Back End
|
||||||
|
|
||||||
|
Add bindings for the Raspberry Pi PiSP Back End memory-to-memory image
|
||||||
|
signal processor.
|
||||||
|
|
||||||
|
Datasheet:
|
||||||
|
https://datasheets.raspberrypi.com/camera/raspberry-pi-image-signal-processor-specification.pdf
|
||||||
|
|
||||||
|
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
|
||||||
|
Reviewed-by: Rob Herring <robh@kernel.org>
|
||||||
|
Reviewed-by: Naushir Patuck <naush@raspberrypi.com>
|
||||||
|
---
|
||||||
|
.../bindings/media/raspberrypi,pispbe.yaml | 63 +++++++++++++++++++
|
||||||
|
MAINTAINERS | 1 +
|
||||||
|
2 files changed, 64 insertions(+)
|
||||||
|
create mode 100644 Documentation/devicetree/bindings/media/raspberrypi,pispbe.yaml
|
||||||
|
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/Documentation/devicetree/bindings/media/raspberrypi,pispbe.yaml
|
||||||
|
@@ -0,0 +1,63 @@
|
||||||
|
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
+%YAML 1.2
|
||||||
|
+---
|
||||||
|
+$id: http://devicetree.org/schemas/media/raspberrypi,pispbe.yaml#
|
||||||
|
+$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
+
|
||||||
|
+title: Raspberry Pi PiSP Image Signal Processor (ISP) Back End
|
||||||
|
+
|
||||||
|
+maintainers:
|
||||||
|
+ - Raspberry Pi Kernel Maintenance <kernel-list@raspberrypi.com>
|
||||||
|
+ - Jacopo Mondi <jacopo.mondi@ideasonboard.com>
|
||||||
|
+
|
||||||
|
+description: |
|
||||||
|
+ The Raspberry Pi PiSP Image Signal Processor (ISP) Back End is an image
|
||||||
|
+ processor that fetches images in Bayer or Grayscale format from DRAM memory
|
||||||
|
+ in tiles and produces images consumable by applications.
|
||||||
|
+
|
||||||
|
+ The full ISP documentation is available at
|
||||||
|
+ https://datasheets.raspberrypi.com/camera/raspberry-pi-image-signal-processor-specification.pdf
|
||||||
|
+
|
||||||
|
+properties:
|
||||||
|
+ compatible:
|
||||||
|
+ items:
|
||||||
|
+ - enum:
|
||||||
|
+ - brcm,bcm2712-pispbe
|
||||||
|
+ - const: raspberrypi,pispbe
|
||||||
|
+
|
||||||
|
+ reg:
|
||||||
|
+ maxItems: 1
|
||||||
|
+
|
||||||
|
+ interrupts:
|
||||||
|
+ maxItems: 1
|
||||||
|
+
|
||||||
|
+ clocks:
|
||||||
|
+ maxItems: 1
|
||||||
|
+
|
||||||
|
+ iommus:
|
||||||
|
+ maxItems: 1
|
||||||
|
+
|
||||||
|
+required:
|
||||||
|
+ - compatible
|
||||||
|
+ - reg
|
||||||
|
+ - interrupts
|
||||||
|
+ - clocks
|
||||||
|
+
|
||||||
|
+additionalProperties: false
|
||||||
|
+
|
||||||
|
+examples:
|
||||||
|
+ - |
|
||||||
|
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||||
|
+
|
||||||
|
+ soc {
|
||||||
|
+ #address-cells = <2>;
|
||||||
|
+ #size-cells = <2>;
|
||||||
|
+
|
||||||
|
+ isp@880000 {
|
||||||
|
+ compatible = "brcm,bcm2712-pispbe", "raspberrypi,pispbe";
|
||||||
|
+ reg = <0x10 0x00880000 0x0 0x4000>;
|
||||||
|
+ interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
+ clocks = <&firmware_clocks 7>;
|
||||||
|
+ iommus = <&iommu2>;
|
||||||
|
+ };
|
||||||
|
+ };
|
||||||
|
--- a/MAINTAINERS
|
||||||
|
+++ b/MAINTAINERS
|
||||||
|
@@ -18037,6 +18037,7 @@ M: Jacopo Mondi <jacopo.mondi@ideasonboa
|
||||||
|
L: Raspberry Pi Kernel Maintenance <kernel-list@raspberrypi.com>
|
||||||
|
L: linux-media@vger.kernel.org
|
||||||
|
S: Maintained
|
||||||
|
+F: Documentation/devicetree/bindings/media/raspberrypi,pispbe.yaml
|
||||||
|
F: include/uapi/linux/media/raspberrypi/
|
||||||
|
|
||||||
|
RC-CORE / LIRC FRAMEWORK
|
@ -0,0 +1,162 @@
|
|||||||
|
From d68e76260316002869aea1b0edf4be399bb592b8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
|
||||||
|
Date: Mon, 29 Jan 2024 17:23:55 +0100
|
||||||
|
Subject: [PATCH 1153/1215] media: admin-guide: Document the Raspberry Pi PiSP
|
||||||
|
BE
|
||||||
|
|
||||||
|
Add documentation for the PiSP Back End memory-to-memory ISP.
|
||||||
|
|
||||||
|
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
|
||||||
|
---
|
||||||
|
.../admin-guide/media/raspberrypi-pisp-be.dot | 20 ++++
|
||||||
|
.../admin-guide/media/raspberrypi-pisp-be.rst | 109 ++++++++++++++++++
|
||||||
|
.../admin-guide/media/v4l-drivers.rst | 1 +
|
||||||
|
3 files changed, 130 insertions(+)
|
||||||
|
create mode 100644 Documentation/admin-guide/media/raspberrypi-pisp-be.dot
|
||||||
|
create mode 100644 Documentation/admin-guide/media/raspberrypi-pisp-be.rst
|
||||||
|
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/Documentation/admin-guide/media/raspberrypi-pisp-be.dot
|
||||||
|
@@ -0,0 +1,20 @@
|
||||||
|
+digraph board {
|
||||||
|
+ rankdir=TB
|
||||||
|
+ n00000001 [label="{{<port0> 0 | <port1> 1 | <port2> 2 | <port7> 7} | pispbe\n | {<port3> 3 | <port4> 4 | <port5> 5 | <port6> 6}}", shape=Mrecord, style=filled, fillcolor=green]
|
||||||
|
+ n00000001:port3 -> n0000001c [style=bold]
|
||||||
|
+ n00000001:port4 -> n00000022 [style=bold]
|
||||||
|
+ n00000001:port5 -> n00000028 [style=bold]
|
||||||
|
+ n00000001:port6 -> n0000002e [style=bold]
|
||||||
|
+ n0000000a [label="pispbe-input\n/dev/video0", shape=box, style=filled, fillcolor=yellow]
|
||||||
|
+ n0000000a -> n00000001:port0 [style=bold]
|
||||||
|
+ n00000010 [label="pispbe-tdn_input\n/dev/video1", shape=box, style=filled, fillcolor=yellow]
|
||||||
|
+ n00000010 -> n00000001:port1 [style=bold]
|
||||||
|
+ n00000016 [label="pispbe-stitch_input\n/dev/video2", shape=box, style=filled, fillcolor=yellow]
|
||||||
|
+ n00000016 -> n00000001:port2 [style=bold]
|
||||||
|
+ n0000001c [label="pispbe-output0\n/dev/video3", shape=box, style=filled, fillcolor=yellow]
|
||||||
|
+ n00000022 [label="pispbe-output1\n/dev/video4", shape=box, style=filled, fillcolor=yellow]
|
||||||
|
+ n00000028 [label="pispbe-tdn_output\n/dev/video5", shape=box, style=filled, fillcolor=yellow]
|
||||||
|
+ n0000002e [label="pispbe-stitch_output\n/dev/video6", shape=box, style=filled, fillcolor=yellow]
|
||||||
|
+ n00000034 [label="pispbe-config\n/dev/video7", shape=box, style=filled, fillcolor=yellow]
|
||||||
|
+ n00000034 -> n00000001:port7 [style=bold]
|
||||||
|
+}
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/Documentation/admin-guide/media/raspberrypi-pisp-be.rst
|
||||||
|
@@ -0,0 +1,109 @@
|
||||||
|
+.. SPDX-License-Identifier: GPL-2.0
|
||||||
|
+
|
||||||
|
+=========================================================
|
||||||
|
+Raspberry Pi PiSP Back End Memory-to-Memory ISP (pisp-be)
|
||||||
|
+=========================================================
|
||||||
|
+
|
||||||
|
+The PiSP Back End
|
||||||
|
+=================
|
||||||
|
+
|
||||||
|
+The PiSP Back End is a memory-to-memory Image Signal Processor (ISP) which reads
|
||||||
|
+image data from DRAM memory and performs image processing as specified by the
|
||||||
|
+application through the parameters in a configuration buffer, before writing
|
||||||
|
+pixel data back to memory through two distinct output channels.
|
||||||
|
+
|
||||||
|
+The ISP registers and programming model are documented in the `Raspberry Pi
|
||||||
|
+Image Signal Processor (PiSP) Specification document`_
|
||||||
|
+
|
||||||
|
+The PiSP Back End ISP processes images in tiles. The handling of image
|
||||||
|
+tessellation and the computation of low-level configuration parameters is
|
||||||
|
+realized by a free software library called `libpisp
|
||||||
|
+<https://github.com/raspberrypi/libpisp>`_.
|
||||||
|
+
|
||||||
|
+The full image processing pipeline, which involves capturing RAW Bayer data from
|
||||||
|
+an image sensor through a MIPI CSI-2 compatible capture interface, storing them
|
||||||
|
+in DRAM memory and processing them in the PiSP Back End to obtain images usable
|
||||||
|
+by an application is implemented in `libcamera <https://libcamera.org>`_ as
|
||||||
|
+part of the Raspberry Pi platform support.
|
||||||
|
+
|
||||||
|
+The pisp-be driver
|
||||||
|
+==================
|
||||||
|
+
|
||||||
|
+The Raspberry Pi PiSP Back End (pisp-be) driver is located under
|
||||||
|
+drivers/media/platform/raspberrypi/pisp-be. It uses the `V4L2 API` to register
|
||||||
|
+a number of video capture and output devices, the `V4L2 subdev API` to register
|
||||||
|
+a subdevice for the ISP that connects the video devices in a single media graph
|
||||||
|
+realized using the `Media Controller (MC) API`.
|
||||||
|
+
|
||||||
|
+The media topology registered by the `pisp-be` driver is represented below:
|
||||||
|
+
|
||||||
|
+.. _pips-be-topology:
|
||||||
|
+
|
||||||
|
+.. kernel-figure:: raspberrypi-pisp-be.dot
|
||||||
|
+ :alt: Diagram of the default media pipeline topology
|
||||||
|
+ :align: center
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+The media graph registers the following video device nodes:
|
||||||
|
+
|
||||||
|
+- pispbe-input: output device for images to be submitted to the ISP for
|
||||||
|
+ processing.
|
||||||
|
+- pispbe-tdn_input: output device for temporal denoise.
|
||||||
|
+- pispbe-stitch_input: output device for image stitching (HDR).
|
||||||
|
+- pispbe-output0: first capture device for processed images.
|
||||||
|
+- pispbe-output1: second capture device for processed images.
|
||||||
|
+- pispbe-tdn_output: capture device for temporal denoise.
|
||||||
|
+- pispbe-stitch_output: capture device for image stitching (HDR).
|
||||||
|
+- pispbe-config: output device for ISP configuration parameters.
|
||||||
|
+
|
||||||
|
+pispbe-input
|
||||||
|
+------------
|
||||||
|
+
|
||||||
|
+Images to be processed by the ISP are queued to the `pispbe-input` output device
|
||||||
|
+node. For a list of image formats supported as input to the ISP refer to the
|
||||||
|
+`Raspberry Pi Image Signal Processor (PiSP) Specification document`_.
|
||||||
|
+
|
||||||
|
+pispbe-tdn_input, pispbe-tdn_output
|
||||||
|
+-----------------------------------
|
||||||
|
+
|
||||||
|
+The `pispbe-tdn_input` output video device receives images to be processed by
|
||||||
|
+the temporal denoise block which are captured from the `pispbe-tdn_output`
|
||||||
|
+capture video device. Userspace is responsible for maintaining queues on both
|
||||||
|
+devices, and ensuring that buffers completed on the output are queued to the
|
||||||
|
+input.
|
||||||
|
+
|
||||||
|
+pispbe-stitch_input, pispbe-stitch_output
|
||||||
|
+-----------------------------------------
|
||||||
|
+
|
||||||
|
+To realize HDR (high dynamic range) image processing the image stitching and
|
||||||
|
+tonemapping blocks are used. The `pispbe-stitch_output` writes images to memory
|
||||||
|
+and the `pispbe-stitch_input` receives the previously written frame to process
|
||||||
|
+it along with the current input image. Userspace is responsible for maintaining
|
||||||
|
+queues on both devices, and ensuring that buffers completed on the output are
|
||||||
|
+queued to the input.
|
||||||
|
+
|
||||||
|
+pispbe-output0, pispbe-output1
|
||||||
|
+------------------------------
|
||||||
|
+
|
||||||
|
+The two capture devices write to memory the pixel data as processed by the ISP.
|
||||||
|
+
|
||||||
|
+pispbe-config
|
||||||
|
+-------------
|
||||||
|
+
|
||||||
|
+The `pispbe-config` output video devices receives a buffer of configuration
|
||||||
|
+parameters that define the desired image processing to be performed by the ISP.
|
||||||
|
+
|
||||||
|
+The format of the ISP configuration parameter is defined by
|
||||||
|
+:c:type:`pisp_be_tiles_config` C structure and the meaning of each parameter is
|
||||||
|
+described in the `Raspberry Pi Image Signal Processor (PiSP) Specification
|
||||||
|
+document`_.
|
||||||
|
+
|
||||||
|
+ISP configuration
|
||||||
|
+=================
|
||||||
|
+
|
||||||
|
+The ISP configuration is described solely by the content of the parameters
|
||||||
|
+buffer. The only parameter that userspace needs to configure using the V4L2 API
|
||||||
|
+is the image format on the output and capture video devices for validation of
|
||||||
|
+the content of the parameters buffer.
|
||||||
|
+
|
||||||
|
+.. _Raspberry Pi Image Signal Processor (PiSP) Specification document: https://datasheets.raspberrypi.com/camera/raspberry-pi-image-signal-processor-specification.pdf
|
||||||
|
--- a/Documentation/admin-guide/media/v4l-drivers.rst
|
||||||
|
+++ b/Documentation/admin-guide/media/v4l-drivers.rst
|
||||||
|
@@ -21,6 +21,7 @@ Video4Linux (V4L) driver-specific docume
|
||||||
|
omap4_camera
|
||||||
|
philips
|
||||||
|
qcom_camss
|
||||||
|
+ raspberrypi-pisp-be
|
||||||
|
rcar-fdp1
|
||||||
|
rkisp1
|
||||||
|
saa7134
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,29 @@
|
|||||||
|
From b58aeea7e2e3afd4fb3b6dcbe5e382b2244b33a4 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
|
||||||
|
Date: Thu, 27 Jun 2024 13:40:29 +0200
|
||||||
|
Subject: [PATCH 1155/1215] media: uapi: pisp_be_config: Drop BIT() from uAPI
|
||||||
|
|
||||||
|
The pisp_be_config.h uAPI header file contains a bit-field definition
|
||||||
|
that uses the BIT() helper macro.
|
||||||
|
|
||||||
|
As the BIT() identifier is not defined in userspace, drop it from the
|
||||||
|
uAPI header.
|
||||||
|
|
||||||
|
Fixes: c6c49bac8770 ("media: uapi: Add Raspberry Pi PiSP Back End uAPI")
|
||||||
|
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
|
||||||
|
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
|
||||||
|
---
|
||||||
|
include/uapi/linux/media/raspberrypi/pisp_be_config.h | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
--- a/include/uapi/linux/media/raspberrypi/pisp_be_config.h
|
||||||
|
+++ b/include/uapi/linux/media/raspberrypi/pisp_be_config.h
|
||||||
|
@@ -146,7 +146,7 @@ struct pisp_be_dpc_config {
|
||||||
|
*/
|
||||||
|
struct pisp_be_geq_config {
|
||||||
|
__u16 offset;
|
||||||
|
-#define PISP_BE_GEQ_SHARPER BIT(15)
|
||||||
|
+#define PISP_BE_GEQ_SHARPER (1U << 15)
|
||||||
|
#define PISP_BE_GEQ_SLOPE ((1 << 10) - 1)
|
||||||
|
/* top bit is the "sharper" flag, slope value is bottom 10 bits */
|
||||||
|
__u16 slope_sharper;
|
@ -0,0 +1,32 @@
|
|||||||
|
From 7c36a1feb61d964055bee777efc1db60790aa215 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
|
||||||
|
Date: Thu, 27 Jun 2024 16:07:43 +0200
|
||||||
|
Subject: [PATCH 1156/1215] media: uapi: pisp_common: Add 32 bpp format test
|
||||||
|
|
||||||
|
Add definition and test for 32-bits image formats to the pisp_common.h
|
||||||
|
uAPI header.
|
||||||
|
|
||||||
|
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
|
||||||
|
---
|
||||||
|
include/uapi/linux/media/raspberrypi/pisp_common.h | 3 +++
|
||||||
|
1 file changed, 3 insertions(+)
|
||||||
|
|
||||||
|
--- a/include/uapi/linux/media/raspberrypi/pisp_common.h
|
||||||
|
+++ b/include/uapi/linux/media/raspberrypi/pisp_common.h
|
||||||
|
@@ -72,6 +72,8 @@ enum pisp_image_format {
|
||||||
|
PISP_IMAGE_FORMAT_SHIFT_8 = 0x00080000,
|
||||||
|
PISP_IMAGE_FORMAT_SHIFT_MASK = 0x000f0000,
|
||||||
|
|
||||||
|
+ PISP_IMAGE_FORMAT_BPP_32 = 0x00100000,
|
||||||
|
+
|
||||||
|
PISP_IMAGE_FORMAT_UNCOMPRESSED = 0x00000000,
|
||||||
|
PISP_IMAGE_FORMAT_COMPRESSION_MODE_1 = 0x01000000,
|
||||||
|
PISP_IMAGE_FORMAT_COMPRESSION_MODE_2 = 0x02000000,
|
||||||
|
@@ -134,6 +136,7 @@ enum pisp_image_format {
|
||||||
|
PISP_IMAGE_FORMAT_PLANARITY_PLANAR)
|
||||||
|
#define PISP_IMAGE_FORMAT_wallpaper(fmt) \
|
||||||
|
((fmt) & PISP_IMAGE_FORMAT_WALLPAPER_ROLL)
|
||||||
|
+#define PISP_IMAGE_FORMAT_bpp_32(fmt) ((fmt) & PISP_IMAGE_FORMAT_BPP_32)
|
||||||
|
#define PISP_IMAGE_FORMAT_HOG(fmt) \
|
||||||
|
((fmt) & \
|
||||||
|
(PISP_IMAGE_FORMAT_HOG_SIGNED | PISP_IMAGE_FORMAT_HOG_UNSIGNED))
|
@ -0,0 +1,89 @@
|
|||||||
|
From 20a3671be178fd98aac08931d809e689eaa7a9d9 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
|
||||||
|
Date: Fri, 28 Jun 2024 10:10:10 +0200
|
||||||
|
Subject: [PATCH 1157/1215] media: uapi: Capitalize all macros
|
||||||
|
|
||||||
|
The macro used to inspect an image format characteristic use a mixture
|
||||||
|
of capitalized and non-capitalized letters, which is rather unusual for
|
||||||
|
the Linux kernel style.
|
||||||
|
|
||||||
|
Capitalize all identifiers.
|
||||||
|
|
||||||
|
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
|
||||||
|
---
|
||||||
|
.../linux/media/raspberrypi/pisp_common.h | 38 +++++++++----------
|
||||||
|
1 file changed, 19 insertions(+), 19 deletions(-)
|
||||||
|
|
||||||
|
--- a/include/uapi/linux/media/raspberrypi/pisp_common.h
|
||||||
|
+++ b/include/uapi/linux/media/raspberrypi/pisp_common.h
|
||||||
|
@@ -92,51 +92,51 @@ enum pisp_image_format {
|
||||||
|
PISP_IMAGE_FORMAT_THREE_CHANNEL
|
||||||
|
};
|
||||||
|
|
||||||
|
-#define PISP_IMAGE_FORMAT_bps_8(fmt) \
|
||||||
|
+#define PISP_IMAGE_FORMAT_BPS_8(fmt) \
|
||||||
|
(((fmt) & PISP_IMAGE_FORMAT_BPS_MASK) == PISP_IMAGE_FORMAT_BPS_8)
|
||||||
|
-#define PISP_IMAGE_FORMAT_bps_10(fmt) \
|
||||||
|
+#define PISP_IMAGE_FORMAT_BPS_10(fmt) \
|
||||||
|
(((fmt) & PISP_IMAGE_FORMAT_BPS_MASK) == PISP_IMAGE_FORMAT_BPS_10)
|
||||||
|
-#define PISP_IMAGE_FORMAT_bps_12(fmt) \
|
||||||
|
+#define PISP_IMAGE_FORMAT_BPS_12(fmt) \
|
||||||
|
(((fmt) & PISP_IMAGE_FORMAT_BPS_MASK) == PISP_IMAGE_FORMAT_BPS_12)
|
||||||
|
-#define PISP_IMAGE_FORMAT_bps_16(fmt) \
|
||||||
|
+#define PISP_IMAGE_FORMAT_BPS_16(fmt) \
|
||||||
|
(((fmt) & PISP_IMAGE_FORMAT_BPS_MASK) == PISP_IMAGE_FORMAT_BPS_16)
|
||||||
|
-#define PISP_IMAGE_FORMAT_bps(fmt) \
|
||||||
|
+#define PISP_IMAGE_FORMAT_BPS(fmt) \
|
||||||
|
(((fmt) & PISP_IMAGE_FORMAT_BPS_MASK) ? \
|
||||||
|
8 + (2 << (((fmt) & PISP_IMAGE_FORMAT_BPS_MASK) - 1)) : 8)
|
||||||
|
-#define PISP_IMAGE_FORMAT_shift(fmt) \
|
||||||
|
+#define PISP_IMAGE_FORMAT_SHIFT(fmt) \
|
||||||
|
(((fmt) & PISP_IMAGE_FORMAT_SHIFT_MASK) / PISP_IMAGE_FORMAT_SHIFT_1)
|
||||||
|
-#define PISP_IMAGE_FORMAT_three_channel(fmt) \
|
||||||
|
+#define PISP_IMAGE_FORMAT_THREE_CHANNEL(fmt) \
|
||||||
|
((fmt) & PISP_IMAGE_FORMAT_THREE_CHANNEL)
|
||||||
|
-#define PISP_IMAGE_FORMAT_single_channel(fmt) \
|
||||||
|
+#define PISP_IMAGE_FORMAT_SINGLE_CHANNEL(fmt) \
|
||||||
|
(!((fmt) & PISP_IMAGE_FORMAT_THREE_CHANNEL))
|
||||||
|
-#define PISP_IMAGE_FORMAT_compressed(fmt) \
|
||||||
|
+#define PISP_IMAGE_FORMAT_COMPRESSED(fmt) \
|
||||||
|
(((fmt) & PISP_IMAGE_FORMAT_COMPRESSION_MASK) != \
|
||||||
|
PISP_IMAGE_FORMAT_UNCOMPRESSED)
|
||||||
|
-#define PISP_IMAGE_FORMAT_sampling_444(fmt) \
|
||||||
|
+#define PISP_IMAGE_FORMAT_SAMPLING_444(fmt) \
|
||||||
|
(((fmt) & PISP_IMAGE_FORMAT_SAMPLING_MASK) == \
|
||||||
|
PISP_IMAGE_FORMAT_SAMPLING_444)
|
||||||
|
-#define PISP_IMAGE_FORMAT_sampling_422(fmt) \
|
||||||
|
+#define PISP_IMAGE_FORMAT_SAMPLING_422(fmt) \
|
||||||
|
(((fmt) & PISP_IMAGE_FORMAT_SAMPLING_MASK) == \
|
||||||
|
PISP_IMAGE_FORMAT_SAMPLING_422)
|
||||||
|
-#define PISP_IMAGE_FORMAT_sampling_420(fmt) \
|
||||||
|
+#define PISP_IMAGE_FORMAT_SAMPLING_420(fmt) \
|
||||||
|
(((fmt) & PISP_IMAGE_FORMAT_SAMPLING_MASK) == \
|
||||||
|
PISP_IMAGE_FORMAT_SAMPLING_420)
|
||||||
|
-#define PISP_IMAGE_FORMAT_order_normal(fmt) \
|
||||||
|
+#define PISP_IMAGE_FORMAT_ORDER_NORMAL(fmt) \
|
||||||
|
(!((fmt) & PISP_IMAGE_FORMAT_ORDER_SWAPPED))
|
||||||
|
-#define PISP_IMAGE_FORMAT_order_swapped(fmt) \
|
||||||
|
+#define PISP_IMAGE_FORMAT_ORDER_SWAPPED(fmt) \
|
||||||
|
((fmt) & PISP_IMAGE_FORMAT_ORDER_SWAPPED)
|
||||||
|
-#define PISP_IMAGE_FORMAT_interleaved(fmt) \
|
||||||
|
+#define PISP_IMAGE_FORMAT_INTERLEAVED(fmt) \
|
||||||
|
(((fmt) & PISP_IMAGE_FORMAT_PLANARITY_MASK) == \
|
||||||
|
PISP_IMAGE_FORMAT_PLANARITY_INTERLEAVED)
|
||||||
|
-#define PISP_IMAGE_FORMAT_semiplanar(fmt) \
|
||||||
|
+#define PISP_IMAGE_FORMAT_SEMIPLANAR(fmt) \
|
||||||
|
(((fmt) & PISP_IMAGE_FORMAT_PLANARITY_MASK) == \
|
||||||
|
PISP_IMAGE_FORMAT_PLANARITY_SEMI_PLANAR)
|
||||||
|
-#define PISP_IMAGE_FORMAT_planar(fmt) \
|
||||||
|
+#define PISP_IMAGE_FORMAT_PLANAR(fmt) \
|
||||||
|
(((fmt) & PISP_IMAGE_FORMAT_PLANARITY_MASK) == \
|
||||||
|
PISP_IMAGE_FORMAT_PLANARITY_PLANAR)
|
||||||
|
-#define PISP_IMAGE_FORMAT_wallpaper(fmt) \
|
||||||
|
+#define PISP_IMAGE_FORMAT_WALLPAPER(fmt) \
|
||||||
|
((fmt) & PISP_IMAGE_FORMAT_WALLPAPER_ROLL)
|
||||||
|
-#define PISP_IMAGE_FORMAT_bpp_32(fmt) ((fmt) & PISP_IMAGE_FORMAT_BPP_32)
|
||||||
|
+#define PISP_IMAGE_FORMAT_BPP_32(fmt) ((fmt) & PISP_IMAGE_FORMAT_BPP_32)
|
||||||
|
#define PISP_IMAGE_FORMAT_HOG(fmt) \
|
||||||
|
((fmt) & \
|
||||||
|
(PISP_IMAGE_FORMAT_HOG_SIGNED | PISP_IMAGE_FORMAT_HOG_UNSIGNED))
|
@ -0,0 +1,30 @@
|
|||||||
|
From ce89955e44f3ab41262b02d8e1e65c3455d66c4d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
|
||||||
|
Date: Fri, 28 Jun 2024 13:59:40 +0200
|
||||||
|
Subject: [PATCH 1158/1215] media: uapi: pisp_be_config: Re-sort
|
||||||
|
pisp_be_tiles_config
|
||||||
|
|
||||||
|
The order of the members of pisp_be_tiles_config is relevant
|
||||||
|
as the driver logic assumes 'config' to be at offset 0.
|
||||||
|
|
||||||
|
Re-sort the member to match the driver's expectations.
|
||||||
|
|
||||||
|
Fixes: c6c49bac8770 ("media: uapi: Add Raspberry Pi PiSP Back End uAPI")
|
||||||
|
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
|
||||||
|
---
|
||||||
|
include/uapi/linux/media/raspberrypi/pisp_be_config.h | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
--- a/include/uapi/linux/media/raspberrypi/pisp_be_config.h
|
||||||
|
+++ b/include/uapi/linux/media/raspberrypi/pisp_be_config.h
|
||||||
|
@@ -919,9 +919,9 @@ struct pisp_tile {
|
||||||
|
* @config: PiSP Back End configuration
|
||||||
|
*/
|
||||||
|
struct pisp_be_tiles_config {
|
||||||
|
+ struct pisp_be_config config;
|
||||||
|
struct pisp_tile tiles[PISP_BACK_END_NUM_TILES];
|
||||||
|
__u32 num_tiles;
|
||||||
|
- struct pisp_be_config config;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
#endif /* _UAPI_PISP_BE_CONFIG_H_ */
|
@ -0,0 +1,82 @@
|
|||||||
|
From abf30420f943d03cc28fec38612d2c5f5e6edf1f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
|
||||||
|
Date: Fri, 28 Jun 2024 14:11:14 +0200
|
||||||
|
Subject: [PATCH 1159/1215] media: uapi: pisp_be_config: Add extra config
|
||||||
|
fields
|
||||||
|
|
||||||
|
Complete the pisp_be_config strcture by adding fields that even if not
|
||||||
|
written to the HW are relevant to complete the uAPI and put it in par
|
||||||
|
with the BSP driver.
|
||||||
|
|
||||||
|
Fixes: c6c49bac8770 ("media: uapi: Add Raspberry Pi PiSP Back End uAPI")
|
||||||
|
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
|
||||||
|
---
|
||||||
|
.../linux/media/raspberrypi/pisp_be_config.h | 41 +++++++++++++++++++
|
||||||
|
1 file changed, 41 insertions(+)
|
||||||
|
|
||||||
|
--- a/include/uapi/linux/media/raspberrypi/pisp_be_config.h
|
||||||
|
+++ b/include/uapi/linux/media/raspberrypi/pisp_be_config.h
|
||||||
|
@@ -716,6 +716,13 @@ struct pisp_be_hog_buffer_config {
|
||||||
|
/**
|
||||||
|
* struct pisp_be_config - RaspberryPi PiSP Back End Processing configuration
|
||||||
|
*
|
||||||
|
+ * @input_buffer: Input buffer addresses
|
||||||
|
+ * @tdn_input_buffer: TDN input buffer addresses
|
||||||
|
+ * @stitch_input_buffer: Stitch input buffer addresses
|
||||||
|
+ * @tdn_output_buffer: TDN output buffer addresses
|
||||||
|
+ * @stitch_output_buffer: Stitch output buffer addresses
|
||||||
|
+ * @output_buffer: Output buffers addresses
|
||||||
|
+ * @hog_buffer: HOG buffer addresses
|
||||||
|
* @global: Global PiSP configuration
|
||||||
|
* @input_format: Input image format
|
||||||
|
* @decompress: Decompress configuration
|
||||||
|
@@ -753,8 +760,30 @@ struct pisp_be_hog_buffer_config {
|
||||||
|
* @resample: Resampling configuration
|
||||||
|
* @output_format: Output format configuration
|
||||||
|
* @hog: HOG configuration
|
||||||
|
+ * @axi: AXI bus configuration
|
||||||
|
+ * @lsc_extra: LSC extra info
|
||||||
|
+ * @cac_extra: CAC extra info
|
||||||
|
+ * @downscale_extra: Downscaler extra info
|
||||||
|
+ * @resample_extra: Resample extra info
|
||||||
|
+ * @crop: Crop configuration
|
||||||
|
+ * @hog_format: HOG format info
|
||||||
|
+ * @dirty_flags_bayer: Bayer enable dirty flags
|
||||||
|
+ * (:c:type:`pisp_be_bayer_enable`)
|
||||||
|
+ * @dirty_flags_rgb: RGB enable dirty flags
|
||||||
|
+ * (:c:type:`pisp_be_rgb_enable`)
|
||||||
|
+ * @dirty_flags_extra: Extra dirty flags
|
||||||
|
*/
|
||||||
|
struct pisp_be_config {
|
||||||
|
+ /* I/O configuration: */
|
||||||
|
+ struct pisp_be_input_buffer_config input_buffer;
|
||||||
|
+ struct pisp_be_tdn_input_buffer_config tdn_input_buffer;
|
||||||
|
+ struct pisp_be_stitch_input_buffer_config stitch_input_buffer;
|
||||||
|
+ struct pisp_be_tdn_output_buffer_config tdn_output_buffer;
|
||||||
|
+ struct pisp_be_stitch_output_buffer_config stitch_output_buffer;
|
||||||
|
+ struct pisp_be_output_buffer_config
|
||||||
|
+ output_buffer[PISP_BACK_END_NUM_OUTPUTS];
|
||||||
|
+ struct pisp_be_hog_buffer_config hog_buffer;
|
||||||
|
+ /* Processing configuration: */
|
||||||
|
struct pisp_be_global_config global;
|
||||||
|
struct pisp_image_format_config input_format;
|
||||||
|
struct pisp_decompress_config decompress;
|
||||||
|
@@ -793,6 +822,18 @@ struct pisp_be_config {
|
||||||
|
struct pisp_be_output_format_config
|
||||||
|
output_format[PISP_BACK_END_NUM_OUTPUTS];
|
||||||
|
struct pisp_be_hog_config hog;
|
||||||
|
+ struct pisp_be_axi_config axi;
|
||||||
|
+ /* Non-register fields: */
|
||||||
|
+ struct pisp_be_lsc_extra lsc_extra;
|
||||||
|
+ struct pisp_be_cac_extra cac_extra;
|
||||||
|
+ struct pisp_be_downscale_extra
|
||||||
|
+ downscale_extra[PISP_BACK_END_NUM_OUTPUTS];
|
||||||
|
+ struct pisp_be_resample_extra resample_extra[PISP_BACK_END_NUM_OUTPUTS];
|
||||||
|
+ struct pisp_be_crop_config crop;
|
||||||
|
+ struct pisp_image_format_config hog_format;
|
||||||
|
+ __u32 dirty_flags_bayer; /* these use pisp_be_bayer_enable */
|
||||||
|
+ __u32 dirty_flags_rgb; /* use pisp_be_rgb_enable */
|
||||||
|
+ __u32 dirty_flags_extra; /* these use pisp_be_dirty_t */
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
/**
|
@ -0,0 +1,886 @@
|
|||||||
|
From 033e037013f2c092501a03bb1bf5bbf7b4045aa0 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
|
||||||
|
Date: Fri, 28 Jun 2024 17:26:26 +0200
|
||||||
|
Subject: [PATCH 1160/1215] media: pisp_be: Re-introduce multi-context support
|
||||||
|
|
||||||
|
Re-introduce multi-context support that was dropped from the
|
||||||
|
mainline driver version.
|
||||||
|
|
||||||
|
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
|
||||||
|
---
|
||||||
|
.../platform/raspberrypi/pisp_be/pisp_be.c | 355 ++++++++++--------
|
||||||
|
1 file changed, 208 insertions(+), 147 deletions(-)
|
||||||
|
|
||||||
|
--- a/drivers/media/platform/raspberrypi/pisp_be/pisp_be.c
|
||||||
|
+++ b/drivers/media/platform/raspberrypi/pisp_be/pisp_be.c
|
||||||
|
@@ -24,6 +24,14 @@
|
||||||
|
/* Maximum number of config buffers possible */
|
||||||
|
#define PISP_BE_NUM_CONFIG_BUFFERS VB2_MAX_FRAME
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * We want to support 2 independent instances allowing 2 simultaneous users
|
||||||
|
+ * of the ISP-BE (of course they share hardware, platform resources and mutex).
|
||||||
|
+ * Each such instance comprises a group of device nodes representing input
|
||||||
|
+ * and output queues, and a media controller device node to describe them.
|
||||||
|
+ */
|
||||||
|
+#define PISPBE_NUM_NODE_GROUPS 2
|
||||||
|
+
|
||||||
|
#define PISPBE_NAME "pispbe"
|
||||||
|
|
||||||
|
/* Some ISP-BE registers */
|
||||||
|
@@ -156,7 +164,7 @@ struct pispbe_node {
|
||||||
|
struct media_pad pad;
|
||||||
|
struct media_intf_devnode *intf_devnode;
|
||||||
|
struct media_link *intf_link;
|
||||||
|
- struct pispbe_dev *pispbe;
|
||||||
|
+ struct pispbe_node_group *node_group;
|
||||||
|
/* Video device lock */
|
||||||
|
struct mutex node_lock;
|
||||||
|
/* vb2_queue lock */
|
||||||
|
@@ -173,9 +181,27 @@ struct pispbe_node {
|
||||||
|
#define NODE_NAME(node) \
|
||||||
|
(node_desc[(node)->id].ent_name + sizeof(PISPBE_NAME))
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * Node group structure, which comprises all the input and output nodes that a
|
||||||
|
+ * single PiSP client will need, along with its own v4l2 and media devices.
|
||||||
|
+ */
|
||||||
|
+struct pispbe_node_group {
|
||||||
|
+ unsigned int id;
|
||||||
|
+ struct v4l2_device v4l2_dev;
|
||||||
|
+ struct v4l2_subdev sd;
|
||||||
|
+ struct pispbe_dev *pispbe;
|
||||||
|
+ struct media_device mdev;
|
||||||
|
+ struct pispbe_node node[PISPBE_NUM_NODES];
|
||||||
|
+ u32 streaming_map; /* bitmap of which nodes are streaming */
|
||||||
|
+ struct media_pad pad[PISPBE_NUM_NODES]; /* output pads first */
|
||||||
|
+ struct pisp_be_tiles_config *config;
|
||||||
|
+ dma_addr_t config_dma_addr;
|
||||||
|
+ unsigned int sequence;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
/* Records details of the jobs currently running or queued on the h/w. */
|
||||||
|
struct pispbe_job {
|
||||||
|
- bool valid;
|
||||||
|
+ struct pispbe_node_group *node_group;
|
||||||
|
/*
|
||||||
|
* An array of buffer pointers - remember it's source buffers first,
|
||||||
|
* then captures, then metadata last.
|
||||||
|
@@ -198,22 +224,13 @@ struct pispbe_job_descriptor {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Structure representing the entire PiSP Back End device, comprising several
|
||||||
|
- * nodes which share platform resources and a mutex for the actual HW.
|
||||||
|
+ * nodes groups which share platform resources and a mutex for the actual HW.
|
||||||
|
*/
|
||||||
|
struct pispbe_dev {
|
||||||
|
struct device *dev;
|
||||||
|
- struct pispbe_dev *pispbe;
|
||||||
|
- struct pisp_be_tiles_config *config;
|
||||||
|
void __iomem *be_reg_base;
|
||||||
|
struct clk *clk;
|
||||||
|
- struct v4l2_device v4l2_dev;
|
||||||
|
- struct v4l2_subdev sd;
|
||||||
|
- struct media_device mdev;
|
||||||
|
- struct media_pad pad[PISPBE_NUM_NODES]; /* output pads first */
|
||||||
|
- struct pispbe_node node[PISPBE_NUM_NODES];
|
||||||
|
- dma_addr_t config_dma_addr;
|
||||||
|
- unsigned int sequence;
|
||||||
|
- u32 streaming_map;
|
||||||
|
+ struct pispbe_node_group node_group[PISPBE_NUM_NODE_GROUPS];
|
||||||
|
struct pispbe_job queued_job, running_job;
|
||||||
|
spinlock_t hw_lock; /* protects "hw_busy" flag and streaming_map */
|
||||||
|
bool hw_busy; /* non-zero if a job is queued or is being started */
|
||||||
|
@@ -348,9 +365,9 @@ static dma_addr_t pispbe_get_addr(struct
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void pispbe_xlate_addrs(struct pispbe_dev *pispbe,
|
||||||
|
- struct pispbe_job_descriptor *job,
|
||||||
|
- struct pispbe_buffer *buf[PISPBE_NUM_NODES])
|
||||||
|
+static void pispbe_xlate_addrs(struct pispbe_job_descriptor *job,
|
||||||
|
+ struct pispbe_buffer *buf[PISPBE_NUM_NODES],
|
||||||
|
+ struct pispbe_node_group *node_group)
|
||||||
|
{
|
||||||
|
struct pispbe_hw_enables *hw_en = &job->hw_enables;
|
||||||
|
struct pisp_be_tiles_config *config = job->config;
|
||||||
|
@@ -366,13 +383,13 @@ static void pispbe_xlate_addrs(struct pi
|
||||||
|
* to 3 planes.
|
||||||
|
*/
|
||||||
|
ret = pispbe_get_planes_addr(addrs, buf[MAIN_INPUT_NODE],
|
||||||
|
- &pispbe->node[MAIN_INPUT_NODE]);
|
||||||
|
+ &node_group->node[MAIN_INPUT_NODE]);
|
||||||
|
if (ret <= 0) {
|
||||||
|
/*
|
||||||
|
* This shouldn't happen; pispbe_schedule_internal should insist
|
||||||
|
* on an input.
|
||||||
|
*/
|
||||||
|
- dev_warn(pispbe->dev, "ISP-BE missing input\n");
|
||||||
|
+ dev_warn(node_group->pispbe->dev, "ISP-BE missing input\n");
|
||||||
|
hw_en->bayer_enables = 0;
|
||||||
|
hw_en->rgb_enables = 0;
|
||||||
|
return;
|
||||||
|
@@ -427,7 +444,7 @@ static void pispbe_xlate_addrs(struct pi
|
||||||
|
for (unsigned int i = 0; i < PISP_BACK_END_NUM_OUTPUTS; i++) {
|
||||||
|
ret = pispbe_get_planes_addr(addrs + 7 + 3 * i,
|
||||||
|
buf[OUTPUT0_NODE + i],
|
||||||
|
- &pispbe->node[OUTPUT0_NODE + i]);
|
||||||
|
+ &node_group->node[OUTPUT0_NODE + i]);
|
||||||
|
if (ret <= 0)
|
||||||
|
hw_en->rgb_enables &= ~(PISP_BE_RGB_ENABLE_OUTPUT0 << i);
|
||||||
|
}
|
||||||
|
@@ -447,10 +464,11 @@ static void pispbe_xlate_addrs(struct pi
|
||||||
|
*
|
||||||
|
* Returns 0 if a job has been successfully prepared, < 0 otherwise.
|
||||||
|
*/
|
||||||
|
-static int pispbe_prepare_job(struct pispbe_dev *pispbe,
|
||||||
|
+static int pispbe_prepare_job(struct pispbe_node_group *node_group,
|
||||||
|
struct pispbe_job_descriptor *job)
|
||||||
|
{
|
||||||
|
struct pispbe_buffer *buf[PISPBE_NUM_NODES] = {};
|
||||||
|
+ struct pispbe_dev *pispbe = node_group->pispbe;
|
||||||
|
unsigned int config_index;
|
||||||
|
struct pispbe_node *node;
|
||||||
|
unsigned long flags;
|
||||||
|
@@ -460,11 +478,11 @@ static int pispbe_prepare_job(struct pis
|
||||||
|
memset(job, 0, sizeof(struct pispbe_job_descriptor));
|
||||||
|
|
||||||
|
if (((BIT(CONFIG_NODE) | BIT(MAIN_INPUT_NODE)) &
|
||||||
|
- pispbe->streaming_map) !=
|
||||||
|
+ node_group->streaming_map) !=
|
||||||
|
(BIT(CONFIG_NODE) | BIT(MAIN_INPUT_NODE)))
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
- node = &pispbe->node[CONFIG_NODE];
|
||||||
|
+ node = &node_group->node[CONFIG_NODE];
|
||||||
|
spin_lock_irqsave(&node->ready_lock, flags);
|
||||||
|
buf[CONFIG_NODE] = list_first_entry_or_null(&node->ready_queue,
|
||||||
|
struct pispbe_buffer,
|
||||||
|
@@ -480,8 +498,8 @@ static int pispbe_prepare_job(struct pis
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
config_index = buf[CONFIG_NODE]->vb.vb2_buf.index;
|
||||||
|
- job->config = &pispbe->config[config_index];
|
||||||
|
- job->tiles = pispbe->config_dma_addr +
|
||||||
|
+ job->config = &node_group->config[config_index];
|
||||||
|
+ job->tiles = node_group->config_dma_addr +
|
||||||
|
config_index * sizeof(struct pisp_be_tiles_config) +
|
||||||
|
offsetof(struct pisp_be_tiles_config, tiles);
|
||||||
|
|
||||||
|
@@ -498,7 +516,7 @@ static int pispbe_prepare_job(struct pis
|
||||||
|
continue;
|
||||||
|
|
||||||
|
buf[i] = NULL;
|
||||||
|
- if (!(pispbe->streaming_map & BIT(i)))
|
||||||
|
+ if (!(node_group->streaming_map & BIT(i)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ((!(rgb_en & PISP_BE_RGB_ENABLE_OUTPUT0) &&
|
||||||
|
@@ -522,7 +540,7 @@ static int pispbe_prepare_job(struct pis
|
||||||
|
ignore_buffers = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
- node = &pispbe->node[i];
|
||||||
|
+ node = &node_group->node[i];
|
||||||
|
|
||||||
|
/* Pull a buffer from each V4L2 queue to form the queued job */
|
||||||
|
spin_lock_irqsave(&node->ready_lock, flags);
|
||||||
|
@@ -539,16 +557,16 @@ static int pispbe_prepare_job(struct pis
|
||||||
|
goto err_return_buffers;
|
||||||
|
}
|
||||||
|
|
||||||
|
- pispbe->queued_job.valid = true;
|
||||||
|
+ pispbe->queued_job.node_group = node_group;
|
||||||
|
|
||||||
|
/* Convert buffers to DMA addresses for the hardware */
|
||||||
|
- pispbe_xlate_addrs(pispbe, job, buf);
|
||||||
|
+ pispbe_xlate_addrs(job, buf, node_group);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_return_buffers:
|
||||||
|
for (unsigned int i = 0; i < PISPBE_NUM_NODES; i++) {
|
||||||
|
- struct pispbe_node *n = &pispbe->node[i];
|
||||||
|
+ struct pispbe_node *n = &node_group->node[i];
|
||||||
|
|
||||||
|
if (!buf[i])
|
||||||
|
continue;
|
||||||
|
@@ -564,11 +582,12 @@ err_return_buffers:
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void pispbe_schedule(struct pispbe_dev *pispbe, bool clear_hw_busy)
|
||||||
|
+static void pispbe_schedule(struct pispbe_dev *pispbe,
|
||||||
|
+ struct pispbe_node_group *node_group,
|
||||||
|
+ bool clear_hw_busy)
|
||||||
|
{
|
||||||
|
struct pispbe_job_descriptor job;
|
||||||
|
unsigned long flags;
|
||||||
|
- int ret;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&pispbe->hw_lock, flags);
|
||||||
|
|
||||||
|
@@ -578,40 +597,53 @@ static void pispbe_schedule(struct pispb
|
||||||
|
if (pispbe->hw_busy)
|
||||||
|
goto unlock_and_return;
|
||||||
|
|
||||||
|
- ret = pispbe_prepare_job(pispbe, &job);
|
||||||
|
- if (ret)
|
||||||
|
- goto unlock_and_return;
|
||||||
|
+ for (unsigned int i = 0; i < PISPBE_NUM_NODE_GROUPS; i++) {
|
||||||
|
+ int ret;
|
||||||
|
|
||||||
|
- /*
|
||||||
|
- * We can kick the job off without the hw_lock, as this can
|
||||||
|
- * never run again until hw_busy is cleared, which will happen
|
||||||
|
- * only when the following job has been queued and an interrupt
|
||||||
|
- * is rised.
|
||||||
|
- */
|
||||||
|
- pispbe->hw_busy = true;
|
||||||
|
- spin_unlock_irqrestore(&pispbe->hw_lock, flags);
|
||||||
|
+ /* Schedule jobs only for a specific group. */
|
||||||
|
+ if (node_group && &pispbe->node_group[i] != node_group)
|
||||||
|
+ continue;
|
||||||
|
|
||||||
|
- if (job.config->num_tiles <= 0 ||
|
||||||
|
- job.config->num_tiles > PISP_BACK_END_NUM_TILES ||
|
||||||
|
- !((job.hw_enables.bayer_enables | job.hw_enables.rgb_enables) &
|
||||||
|
- PISP_BE_BAYER_ENABLE_INPUT)) {
|
||||||
|
/*
|
||||||
|
- * Bad job. We can't let it proceed as it could lock up
|
||||||
|
- * the hardware, or worse!
|
||||||
|
- *
|
||||||
|
- * For now, just force num_tiles to 0, which causes the
|
||||||
|
- * H/W to do something bizarre but survivable. It
|
||||||
|
- * increments (started,done) counters by more than 1,
|
||||||
|
- * but we seem to survive...
|
||||||
|
+ * Prepare a job for this group, if the group is not ready
|
||||||
|
+ * continue and try with the next one.
|
||||||
|
*/
|
||||||
|
- dev_dbg(pispbe->dev, "Bad job: invalid number of tiles: %u\n",
|
||||||
|
- job.config->num_tiles);
|
||||||
|
- job.config->num_tiles = 0;
|
||||||
|
- }
|
||||||
|
+ ret = pispbe_prepare_job(&pispbe->node_group[i], &job);
|
||||||
|
+ if (ret)
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * We can kick the job off without the hw_lock, as this can
|
||||||
|
+ * never run again until hw_busy is cleared, which will happen
|
||||||
|
+ * only when the following job has been queued and an interrupt
|
||||||
|
+ * is rised.
|
||||||
|
+ */
|
||||||
|
+ pispbe->hw_busy = true;
|
||||||
|
+ spin_unlock_irqrestore(&pispbe->hw_lock, flags);
|
||||||
|
+
|
||||||
|
+ if (job.config->num_tiles <= 0 ||
|
||||||
|
+ job.config->num_tiles > PISP_BACK_END_NUM_TILES ||
|
||||||
|
+ !((job.hw_enables.bayer_enables |
|
||||||
|
+ job.hw_enables.rgb_enables) &
|
||||||
|
+ PISP_BE_BAYER_ENABLE_INPUT)) {
|
||||||
|
+ /*
|
||||||
|
+ * Bad job. We can't let it proceed as it could lock up
|
||||||
|
+ * the hardware, or worse!
|
||||||
|
+ *
|
||||||
|
+ * For now, just force num_tiles to 0, which causes the
|
||||||
|
+ * H/W to do something bizarre but survivable. It
|
||||||
|
+ * increments (started,done) counters by more than 1,
|
||||||
|
+ * but we seem to survive...
|
||||||
|
+ */
|
||||||
|
+ dev_dbg(pispbe->dev, "Bad job: invalid number of tiles: %u\n",
|
||||||
|
+ job.config->num_tiles);
|
||||||
|
+ job.config->num_tiles = 0;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- pispbe_queue_job(pispbe, &job);
|
||||||
|
+ pispbe_queue_job(pispbe, &job);
|
||||||
|
|
||||||
|
- return;
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
unlock_and_return:
|
||||||
|
/* No job has been queued, just release the lock and return. */
|
||||||
|
@@ -627,13 +659,13 @@ static void pispbe_isr_jobdone(struct pi
|
||||||
|
for (unsigned int i = 0; i < PISPBE_NUM_NODES; i++) {
|
||||||
|
if (buf[i]) {
|
||||||
|
buf[i]->vb.vb2_buf.timestamp = ts;
|
||||||
|
- buf[i]->vb.sequence = pispbe->sequence;
|
||||||
|
+ buf[i]->vb.sequence = job->node_group->sequence;
|
||||||
|
vb2_buffer_done(&buf[i]->vb.vb2_buf,
|
||||||
|
VB2_BUF_STATE_DONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- pispbe->sequence++;
|
||||||
|
+ job->node_group->sequence++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static irqreturn_t pispbe_isr(int irq, void *dev)
|
||||||
|
@@ -657,7 +689,7 @@ static irqreturn_t pispbe_isr(int irq, v
|
||||||
|
* we previously saw "start" now finishes, and we then queued a new job
|
||||||
|
* which we see both start and finish "simultaneously".
|
||||||
|
*/
|
||||||
|
- if (pispbe->running_job.valid && pispbe->done != done) {
|
||||||
|
+ if (pispbe->running_job.node_group && pispbe->done != done) {
|
||||||
|
pispbe_isr_jobdone(pispbe, &pispbe->running_job);
|
||||||
|
memset(&pispbe->running_job, 0, sizeof(pispbe->running_job));
|
||||||
|
pispbe->done++;
|
||||||
|
@@ -667,7 +699,7 @@ static irqreturn_t pispbe_isr(int irq, v
|
||||||
|
pispbe->started++;
|
||||||
|
can_queue_another = 1;
|
||||||
|
|
||||||
|
- if (pispbe->done != done && pispbe->queued_job.valid) {
|
||||||
|
+ if (pispbe->done != done && pispbe->queued_job.node_group) {
|
||||||
|
pispbe_isr_jobdone(pispbe, &pispbe->queued_job);
|
||||||
|
pispbe->done++;
|
||||||
|
} else {
|
||||||
|
@@ -686,17 +718,17 @@ static irqreturn_t pispbe_isr(int irq, v
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if there's more to do before going to sleep */
|
||||||
|
- pispbe_schedule(pispbe, can_queue_another);
|
||||||
|
+ pispbe_schedule(pispbe, NULL, can_queue_another);
|
||||||
|
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int pisp_be_validate_config(struct pispbe_dev *pispbe,
|
||||||
|
+static int pisp_be_validate_config(struct pispbe_node_group *node_group,
|
||||||
|
struct pisp_be_tiles_config *config)
|
||||||
|
{
|
||||||
|
u32 bayer_enables = config->config.global.bayer_enables;
|
||||||
|
u32 rgb_enables = config->config.global.rgb_enables;
|
||||||
|
- struct device *dev = pispbe->dev;
|
||||||
|
+ struct device *dev = node_group->pispbe->dev;
|
||||||
|
struct v4l2_format *fmt;
|
||||||
|
unsigned int bpl, size;
|
||||||
|
|
||||||
|
@@ -707,7 +739,7 @@ static int pisp_be_validate_config(struc
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure output config strides and buffer sizes match the V4L2 formats. */
|
||||||
|
- fmt = &pispbe->node[TDN_OUTPUT_NODE].format;
|
||||||
|
+ fmt = &node_group->node[TDN_OUTPUT_NODE].format;
|
||||||
|
if (bayer_enables & PISP_BE_BAYER_ENABLE_TDN_OUTPUT) {
|
||||||
|
bpl = config->config.tdn_output_format.stride;
|
||||||
|
size = bpl * config->config.tdn_output_format.height;
|
||||||
|
@@ -725,7 +757,7 @@ static int pisp_be_validate_config(struc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- fmt = &pispbe->node[STITCH_OUTPUT_NODE].format;
|
||||||
|
+ fmt = &node_group->node[STITCH_OUTPUT_NODE].format;
|
||||||
|
if (bayer_enables & PISP_BE_BAYER_ENABLE_STITCH_OUTPUT) {
|
||||||
|
bpl = config->config.stitch_output_format.stride;
|
||||||
|
size = bpl * config->config.stitch_output_format.height;
|
||||||
|
@@ -751,7 +783,7 @@ static int pisp_be_validate_config(struc
|
||||||
|
PISP_IMAGE_FORMAT_WALLPAPER_ROLL)
|
||||||
|
continue; /* TODO: Size checks for wallpaper formats */
|
||||||
|
|
||||||
|
- fmt = &pispbe->node[OUTPUT0_NODE + j].format;
|
||||||
|
+ fmt = &node_group->node[OUTPUT0_NODE + j].format;
|
||||||
|
for (unsigned int i = 0; i < fmt->fmt.pix_mp.num_planes; i++) {
|
||||||
|
bpl = !i ? config->config.output_format[j].image.stride
|
||||||
|
: config->config.output_format[j].image.stride2;
|
||||||
|
@@ -783,7 +815,7 @@ static int pispbe_node_queue_setup(struc
|
||||||
|
struct device *alloc_devs[])
|
||||||
|
{
|
||||||
|
struct pispbe_node *node = vb2_get_drv_priv(q);
|
||||||
|
- struct pispbe_dev *pispbe = node->pispbe;
|
||||||
|
+ struct pispbe_dev *pispbe = node->node_group->pispbe;
|
||||||
|
unsigned int num_planes = NODE_IS_MPLANE(node) ?
|
||||||
|
node->format.fmt.pix_mp.num_planes : 1;
|
||||||
|
|
||||||
|
@@ -821,7 +853,7 @@ static int pispbe_node_queue_setup(struc
|
||||||
|
static int pispbe_node_buffer_prepare(struct vb2_buffer *vb)
|
||||||
|
{
|
||||||
|
struct pispbe_node *node = vb2_get_drv_priv(vb->vb2_queue);
|
||||||
|
- struct pispbe_dev *pispbe = node->pispbe;
|
||||||
|
+ struct pispbe_dev *pispbe = node->node_group->pispbe;
|
||||||
|
unsigned int num_planes = NODE_IS_MPLANE(node) ?
|
||||||
|
node->format.fmt.pix_mp.num_planes : 1;
|
||||||
|
|
||||||
|
@@ -841,12 +873,12 @@ static int pispbe_node_buffer_prepare(st
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node->id == CONFIG_NODE) {
|
||||||
|
- void *dst = &node->pispbe->config[vb->index];
|
||||||
|
+ void *dst = &node->node_group->config[vb->index];
|
||||||
|
void *src = vb2_plane_vaddr(vb, 0);
|
||||||
|
|
||||||
|
memcpy(dst, src, sizeof(struct pisp_be_tiles_config));
|
||||||
|
|
||||||
|
- return pisp_be_validate_config(pispbe, dst);
|
||||||
|
+ return pisp_be_validate_config(node->node_group, dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
@@ -859,7 +891,8 @@ static void pispbe_node_buffer_queue(str
|
||||||
|
struct pispbe_buffer *buffer =
|
||||||
|
container_of(vbuf, struct pispbe_buffer, vb);
|
||||||
|
struct pispbe_node *node = vb2_get_drv_priv(buf->vb2_queue);
|
||||||
|
- struct pispbe_dev *pispbe = node->pispbe;
|
||||||
|
+ struct pispbe_node_group *node_group = node->node_group;
|
||||||
|
+ struct pispbe_dev *pispbe = node->node_group->pispbe;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
dev_dbg(pispbe->dev, "%s: for node %s\n", __func__, NODE_NAME(node));
|
||||||
|
@@ -869,15 +902,16 @@ static void pispbe_node_buffer_queue(str
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Every time we add a buffer, check if there's now some work for the hw
|
||||||
|
- * to do.
|
||||||
|
+ * to do, but only for this client.
|
||||||
|
*/
|
||||||
|
- pispbe_schedule(pispbe, false);
|
||||||
|
+ pispbe_schedule(node_group->pispbe, node_group, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pispbe_node_start_streaming(struct vb2_queue *q, unsigned int count)
|
||||||
|
{
|
||||||
|
struct pispbe_node *node = vb2_get_drv_priv(q);
|
||||||
|
- struct pispbe_dev *pispbe = node->pispbe;
|
||||||
|
+ struct pispbe_node_group *node_group = node->node_group;
|
||||||
|
+ struct pispbe_dev *pispbe = node_group->pispbe;
|
||||||
|
struct pispbe_buffer *buf, *tmp;
|
||||||
|
unsigned long flags;
|
||||||
|
int ret;
|
||||||
|
@@ -887,17 +921,17 @@ static int pispbe_node_start_streaming(s
|
||||||
|
goto err_return_buffers;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&pispbe->hw_lock, flags);
|
||||||
|
- node->pispbe->streaming_map |= BIT(node->id);
|
||||||
|
- node->pispbe->sequence = 0;
|
||||||
|
+ node->node_group->streaming_map |= BIT(node->id);
|
||||||
|
+ node->node_group->sequence = 0;
|
||||||
|
spin_unlock_irqrestore(&pispbe->hw_lock, flags);
|
||||||
|
|
||||||
|
dev_dbg(pispbe->dev, "%s: for node %s (count %u)\n",
|
||||||
|
__func__, NODE_NAME(node), count);
|
||||||
|
- dev_dbg(pispbe->dev, "Nodes streaming now 0x%x\n",
|
||||||
|
- node->pispbe->streaming_map);
|
||||||
|
+ dev_dbg(pispbe->dev, "Nodes streaming for this group now 0x%x\n",
|
||||||
|
+ node->node_group->streaming_map);
|
||||||
|
|
||||||
|
/* Maybe we're ready to run. */
|
||||||
|
- pispbe_schedule(pispbe, false);
|
||||||
|
+ pispbe_schedule(node_group->pispbe, node_group, false);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
@@ -915,7 +949,8 @@ err_return_buffers:
|
||||||
|
static void pispbe_node_stop_streaming(struct vb2_queue *q)
|
||||||
|
{
|
||||||
|
struct pispbe_node *node = vb2_get_drv_priv(q);
|
||||||
|
- struct pispbe_dev *pispbe = node->pispbe;
|
||||||
|
+ struct pispbe_node_group *node_group = node->node_group;
|
||||||
|
+ struct pispbe_dev *pispbe = node_group->pispbe;
|
||||||
|
struct pispbe_buffer *buf;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
@@ -948,14 +983,14 @@ static void pispbe_node_stop_streaming(s
|
||||||
|
vb2_wait_for_all_buffers(&node->queue);
|
||||||
|
|
||||||
|
spin_lock_irqsave(&pispbe->hw_lock, flags);
|
||||||
|
- pispbe->streaming_map &= ~BIT(node->id);
|
||||||
|
+ node_group->streaming_map &= ~BIT(node->id);
|
||||||
|
spin_unlock_irqrestore(&pispbe->hw_lock, flags);
|
||||||
|
|
||||||
|
pm_runtime_mark_last_busy(pispbe->dev);
|
||||||
|
pm_runtime_put_autosuspend(pispbe->dev);
|
||||||
|
|
||||||
|
- dev_dbg(pispbe->dev, "Nodes streaming now 0x%x\n",
|
||||||
|
- pispbe->streaming_map);
|
||||||
|
+ dev_dbg(pispbe->dev, "Nodes streaming for this group now 0x%x\n",
|
||||||
|
+ node_group->streaming_map);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct vb2_ops pispbe_node_queue_ops = {
|
||||||
|
@@ -979,7 +1014,7 @@ static int pispbe_node_querycap(struct f
|
||||||
|
struct v4l2_capability *cap)
|
||||||
|
{
|
||||||
|
struct pispbe_node *node = video_drvdata(file);
|
||||||
|
- struct pispbe_dev *pispbe = node->pispbe;
|
||||||
|
+ struct pispbe_dev *pispbe = node->node_group->pispbe;
|
||||||
|
|
||||||
|
strscpy(cap->driver, PISPBE_NAME, sizeof(cap->driver));
|
||||||
|
strscpy(cap->card, PISPBE_NAME, sizeof(cap->card));
|
||||||
|
@@ -995,7 +1030,7 @@ static int pispbe_node_g_fmt_vid_cap(str
|
||||||
|
struct v4l2_format *f)
|
||||||
|
{
|
||||||
|
struct pispbe_node *node = video_drvdata(file);
|
||||||
|
- struct pispbe_dev *pispbe = node->pispbe;
|
||||||
|
+ struct pispbe_dev *pispbe = node->node_group->pispbe;
|
||||||
|
|
||||||
|
if (!NODE_IS_CAPTURE(node) || NODE_IS_META(node)) {
|
||||||
|
dev_dbg(pispbe->dev,
|
||||||
|
@@ -1015,7 +1050,7 @@ static int pispbe_node_g_fmt_vid_out(str
|
||||||
|
struct v4l2_format *f)
|
||||||
|
{
|
||||||
|
struct pispbe_node *node = video_drvdata(file);
|
||||||
|
- struct pispbe_dev *pispbe = node->pispbe;
|
||||||
|
+ struct pispbe_dev *pispbe = node->node_group->pispbe;
|
||||||
|
|
||||||
|
if (NODE_IS_CAPTURE(node) || NODE_IS_META(node)) {
|
||||||
|
dev_dbg(pispbe->dev,
|
||||||
|
@@ -1035,7 +1070,7 @@ static int pispbe_node_g_fmt_meta_out(st
|
||||||
|
struct v4l2_format *f)
|
||||||
|
{
|
||||||
|
struct pispbe_node *node = video_drvdata(file);
|
||||||
|
- struct pispbe_dev *pispbe = node->pispbe;
|
||||||
|
+ struct pispbe_dev *pispbe = node->node_group->pispbe;
|
||||||
|
|
||||||
|
if (!NODE_IS_META(node) || NODE_IS_CAPTURE(node)) {
|
||||||
|
dev_dbg(pispbe->dev,
|
||||||
|
@@ -1092,7 +1127,7 @@ static void pispbe_set_plane_params(stru
|
||||||
|
|
||||||
|
static void pispbe_try_format(struct v4l2_format *f, struct pispbe_node *node)
|
||||||
|
{
|
||||||
|
- struct pispbe_dev *pispbe = node->pispbe;
|
||||||
|
+ struct pispbe_dev *pispbe = node->node_group->pispbe;
|
||||||
|
u32 pixfmt = f->fmt.pix_mp.pixelformat;
|
||||||
|
const struct pisp_be_format *fmt;
|
||||||
|
bool is_rgb;
|
||||||
|
@@ -1156,7 +1191,7 @@ static int pispbe_node_try_fmt_vid_cap(s
|
||||||
|
struct v4l2_format *f)
|
||||||
|
{
|
||||||
|
struct pispbe_node *node = video_drvdata(file);
|
||||||
|
- struct pispbe_dev *pispbe = node->pispbe;
|
||||||
|
+ struct pispbe_dev *pispbe = node->node_group->pispbe;
|
||||||
|
|
||||||
|
if (!NODE_IS_CAPTURE(node) || NODE_IS_META(node)) {
|
||||||
|
dev_dbg(pispbe->dev,
|
||||||
|
@@ -1174,7 +1209,7 @@ static int pispbe_node_try_fmt_vid_out(s
|
||||||
|
struct v4l2_format *f)
|
||||||
|
{
|
||||||
|
struct pispbe_node *node = video_drvdata(file);
|
||||||
|
- struct pispbe_dev *pispbe = node->pispbe;
|
||||||
|
+ struct pispbe_dev *pispbe = node->node_group->pispbe;
|
||||||
|
|
||||||
|
if (!NODE_IS_OUTPUT(node) || NODE_IS_META(node)) {
|
||||||
|
dev_dbg(pispbe->dev,
|
||||||
|
@@ -1192,7 +1227,7 @@ static int pispbe_node_try_fmt_meta_out(
|
||||||
|
struct v4l2_format *f)
|
||||||
|
{
|
||||||
|
struct pispbe_node *node = video_drvdata(file);
|
||||||
|
- struct pispbe_dev *pispbe = node->pispbe;
|
||||||
|
+ struct pispbe_dev *pispbe = node->node_group->pispbe;
|
||||||
|
|
||||||
|
if (!NODE_IS_META(node) || NODE_IS_CAPTURE(node)) {
|
||||||
|
dev_dbg(pispbe->dev,
|
||||||
|
@@ -1211,7 +1246,7 @@ static int pispbe_node_s_fmt_vid_cap(str
|
||||||
|
struct v4l2_format *f)
|
||||||
|
{
|
||||||
|
struct pispbe_node *node = video_drvdata(file);
|
||||||
|
- struct pispbe_dev *pispbe = node->pispbe;
|
||||||
|
+ struct pispbe_dev *pispbe = node->node_group->pispbe;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = pispbe_node_try_fmt_vid_cap(file, priv, f);
|
||||||
|
@@ -1234,7 +1269,7 @@ static int pispbe_node_s_fmt_vid_out(str
|
||||||
|
struct v4l2_format *f)
|
||||||
|
{
|
||||||
|
struct pispbe_node *node = video_drvdata(file);
|
||||||
|
- struct pispbe_dev *pispbe = node->pispbe;
|
||||||
|
+ struct pispbe_dev *pispbe = node->node_group->pispbe;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = pispbe_node_try_fmt_vid_out(file, priv, f);
|
||||||
|
@@ -1257,7 +1292,7 @@ static int pispbe_node_s_fmt_meta_out(st
|
||||||
|
struct v4l2_format *f)
|
||||||
|
{
|
||||||
|
struct pispbe_node *node = video_drvdata(file);
|
||||||
|
- struct pispbe_dev *pispbe = node->pispbe;
|
||||||
|
+ struct pispbe_dev *pispbe = node->node_group->pispbe;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = pispbe_node_try_fmt_meta_out(file, priv, f);
|
||||||
|
@@ -1306,7 +1341,7 @@ static int pispbe_enum_framesizes(struct
|
||||||
|
struct v4l2_frmsizeenum *fsize)
|
||||||
|
{
|
||||||
|
struct pispbe_node *node = video_drvdata(file);
|
||||||
|
- struct pispbe_dev *pispbe = node->pispbe;
|
||||||
|
+ struct pispbe_dev *pispbe = node->node_group->pispbe;
|
||||||
|
|
||||||
|
if (NODE_IS_META(node) || fsize->index)
|
||||||
|
return -EINVAL;
|
||||||
|
@@ -1391,17 +1426,19 @@ static void pispbe_node_def_fmt(struct p
|
||||||
|
* Initialise a struct pispbe_node and register it as /dev/video<N>
|
||||||
|
* to represent one of the PiSP Back End's input or output streams.
|
||||||
|
*/
|
||||||
|
-static int pispbe_init_node(struct pispbe_dev *pispbe, unsigned int id)
|
||||||
|
+static int pispbe_init_node(struct pispbe_node_group *node_group,
|
||||||
|
+ unsigned int id)
|
||||||
|
{
|
||||||
|
bool output = NODE_DESC_IS_OUTPUT(&node_desc[id]);
|
||||||
|
- struct pispbe_node *node = &pispbe->node[id];
|
||||||
|
+ struct pispbe_node *node = &node_group->node[id];
|
||||||
|
struct media_entity *entity = &node->vfd.entity;
|
||||||
|
+ struct pispbe_dev *pispbe = node_group->pispbe;
|
||||||
|
struct video_device *vdev = &node->vfd;
|
||||||
|
struct vb2_queue *q = &node->queue;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
node->id = id;
|
||||||
|
- node->pispbe = pispbe;
|
||||||
|
+ node->node_group = node_group;
|
||||||
|
node->buf_type = node_desc[id].buf_type;
|
||||||
|
|
||||||
|
mutex_init(&node->node_lock);
|
||||||
|
@@ -1419,7 +1456,7 @@ static int pispbe_init_node(struct pispb
|
||||||
|
q->ops = &pispbe_node_queue_ops;
|
||||||
|
q->buf_struct_size = sizeof(struct pispbe_buffer);
|
||||||
|
q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
|
||||||
|
- q->dev = pispbe->dev;
|
||||||
|
+ q->dev = node->node_group->pispbe->dev;
|
||||||
|
/* get V4L2 to handle node->queue locking */
|
||||||
|
q->lock = &node->queue_lock;
|
||||||
|
|
||||||
|
@@ -1431,7 +1468,7 @@ static int pispbe_init_node(struct pispb
|
||||||
|
|
||||||
|
*vdev = pispbe_videodev; /* default initialization */
|
||||||
|
strscpy(vdev->name, node_desc[id].ent_name, sizeof(vdev->name));
|
||||||
|
- vdev->v4l2_dev = &pispbe->v4l2_dev;
|
||||||
|
+ vdev->v4l2_dev = &node_group->v4l2_dev;
|
||||||
|
vdev->vfl_dir = output ? VFL_DIR_TX : VFL_DIR_RX;
|
||||||
|
/* get V4L2 to serialise our ioctls */
|
||||||
|
vdev->lock = &node->node_lock;
|
||||||
|
@@ -1457,11 +1494,11 @@ static int pispbe_init_node(struct pispb
|
||||||
|
video_set_drvdata(vdev, node);
|
||||||
|
|
||||||
|
if (output)
|
||||||
|
- ret = media_create_pad_link(entity, 0, &pispbe->sd.entity,
|
||||||
|
+ ret = media_create_pad_link(entity, 0, &node_group->sd.entity,
|
||||||
|
id, MEDIA_LNK_FL_IMMUTABLE |
|
||||||
|
MEDIA_LNK_FL_ENABLED);
|
||||||
|
else
|
||||||
|
- ret = media_create_pad_link(&pispbe->sd.entity, id, entity,
|
||||||
|
+ ret = media_create_pad_link(&node_group->sd.entity, id, entity,
|
||||||
|
0, MEDIA_LNK_FL_IMMUTABLE |
|
||||||
|
MEDIA_LNK_FL_ENABLED);
|
||||||
|
if (ret)
|
||||||
|
@@ -1490,9 +1527,10 @@ static const struct v4l2_subdev_ops pisp
|
||||||
|
.pad = &pispbe_pad_ops,
|
||||||
|
};
|
||||||
|
|
||||||
|
-static int pispbe_init_subdev(struct pispbe_dev *pispbe)
|
||||||
|
+static int pispbe_init_subdev(struct pispbe_node_group *node_group)
|
||||||
|
{
|
||||||
|
- struct v4l2_subdev *sd = &pispbe->sd;
|
||||||
|
+ struct pispbe_dev *pispbe = node_group->pispbe;
|
||||||
|
+ struct v4l2_subdev *sd = &node_group->sd;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
v4l2_subdev_init(sd, &pispbe_sd_ops);
|
||||||
|
@@ -1502,16 +1540,16 @@ static int pispbe_init_subdev(struct pis
|
||||||
|
strscpy(sd->name, PISPBE_NAME, sizeof(sd->name));
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < PISPBE_NUM_NODES; i++)
|
||||||
|
- pispbe->pad[i].flags =
|
||||||
|
+ node_group->pad[i].flags =
|
||||||
|
NODE_DESC_IS_OUTPUT(&node_desc[i]) ?
|
||||||
|
MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE;
|
||||||
|
|
||||||
|
ret = media_entity_pads_init(&sd->entity, PISPBE_NUM_NODES,
|
||||||
|
- pispbe->pad);
|
||||||
|
+ node_group->pad);
|
||||||
|
if (ret)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
- ret = v4l2_device_register_subdev(&pispbe->v4l2_dev, sd);
|
||||||
|
+ ret = v4l2_device_register_subdev(&node_group->v4l2_dev, sd);
|
||||||
|
if (ret)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
@@ -1522,36 +1560,43 @@ error:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int pispbe_init_devices(struct pispbe_dev *pispbe)
|
||||||
|
+static int pispbe_init_group(struct pispbe_dev *pispbe, unsigned int id)
|
||||||
|
{
|
||||||
|
+ struct pispbe_node_group *node_group = &pispbe->node_group[id];
|
||||||
|
struct v4l2_device *v4l2_dev;
|
||||||
|
struct media_device *mdev;
|
||||||
|
unsigned int num_regist;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
+ node_group->id = id;
|
||||||
|
+ node_group->pispbe = pispbe;
|
||||||
|
+ node_group->streaming_map = 0;
|
||||||
|
+
|
||||||
|
+ dev_dbg(pispbe->dev, "Register nodes for group %u\n", id);
|
||||||
|
+
|
||||||
|
/* Register v4l2_device and media_device */
|
||||||
|
- mdev = &pispbe->mdev;
|
||||||
|
- mdev->hw_revision = pispbe->hw_version;
|
||||||
|
- mdev->dev = pispbe->dev;
|
||||||
|
+ mdev = &node_group->mdev;
|
||||||
|
+ mdev->hw_revision = node_group->pispbe->hw_version;
|
||||||
|
+ mdev->dev = node_group->pispbe->dev;
|
||||||
|
strscpy(mdev->model, PISPBE_NAME, sizeof(mdev->model));
|
||||||
|
media_device_init(mdev);
|
||||||
|
|
||||||
|
- v4l2_dev = &pispbe->v4l2_dev;
|
||||||
|
- v4l2_dev->mdev = &pispbe->mdev;
|
||||||
|
+ v4l2_dev = &node_group->v4l2_dev;
|
||||||
|
+ v4l2_dev->mdev = &node_group->mdev;
|
||||||
|
strscpy(v4l2_dev->name, PISPBE_NAME, sizeof(v4l2_dev->name));
|
||||||
|
|
||||||
|
- ret = v4l2_device_register(pispbe->dev, v4l2_dev);
|
||||||
|
+ ret = v4l2_device_register(pispbe->dev, &node_group->v4l2_dev);
|
||||||
|
if (ret)
|
||||||
|
goto err_media_dev_cleanup;
|
||||||
|
|
||||||
|
/* Register the PISPBE subdevice. */
|
||||||
|
- ret = pispbe_init_subdev(pispbe);
|
||||||
|
+ ret = pispbe_init_subdev(node_group);
|
||||||
|
if (ret)
|
||||||
|
goto err_unregister_v4l2;
|
||||||
|
|
||||||
|
/* Create device video nodes */
|
||||||
|
for (num_regist = 0; num_regist < PISPBE_NUM_NODES; num_regist++) {
|
||||||
|
- ret = pispbe_init_node(pispbe, num_regist);
|
||||||
|
+ ret = pispbe_init_node(node_group, num_regist);
|
||||||
|
if (ret)
|
||||||
|
goto err_unregister_nodes;
|
||||||
|
}
|
||||||
|
@@ -1560,12 +1605,12 @@ static int pispbe_init_devices(struct pi
|
||||||
|
if (ret)
|
||||||
|
goto err_unregister_nodes;
|
||||||
|
|
||||||
|
- pispbe->config =
|
||||||
|
+ node_group->config =
|
||||||
|
dma_alloc_coherent(pispbe->dev,
|
||||||
|
sizeof(struct pisp_be_tiles_config) *
|
||||||
|
PISP_BE_NUM_CONFIG_BUFFERS,
|
||||||
|
- &pispbe->config_dma_addr, GFP_KERNEL);
|
||||||
|
- if (!pispbe->config) {
|
||||||
|
+ &node_group->config_dma_addr, GFP_KERNEL);
|
||||||
|
+ if (!node_group->config) {
|
||||||
|
dev_err(pispbe->dev, "Unable to allocate cached config buffers.\n");
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto err_unregister_mdev;
|
||||||
|
@@ -1577,11 +1622,11 @@ err_unregister_mdev:
|
||||||
|
media_device_unregister(mdev);
|
||||||
|
err_unregister_nodes:
|
||||||
|
while (num_regist-- > 0) {
|
||||||
|
- video_unregister_device(&pispbe->node[num_regist].vfd);
|
||||||
|
- vb2_queue_release(&pispbe->node[num_regist].queue);
|
||||||
|
+ video_unregister_device(&node_group->node[num_regist].vfd);
|
||||||
|
+ vb2_queue_release(&node_group->node[num_regist].queue);
|
||||||
|
}
|
||||||
|
- v4l2_device_unregister_subdev(&pispbe->sd);
|
||||||
|
- media_entity_cleanup(&pispbe->sd.entity);
|
||||||
|
+ v4l2_device_unregister_subdev(&node_group->sd);
|
||||||
|
+ media_entity_cleanup(&node_group->sd.entity);
|
||||||
|
err_unregister_v4l2:
|
||||||
|
v4l2_device_unregister(v4l2_dev);
|
||||||
|
err_media_dev_cleanup:
|
||||||
|
@@ -1589,31 +1634,33 @@ err_media_dev_cleanup:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void pispbe_destroy_devices(struct pispbe_dev *pispbe)
|
||||||
|
+static void pispbe_destroy_node_group(struct pispbe_node_group *node_group)
|
||||||
|
{
|
||||||
|
- if (pispbe->config) {
|
||||||
|
- dma_free_coherent(pispbe->dev,
|
||||||
|
+ struct pispbe_dev *pispbe = node_group->pispbe;
|
||||||
|
+
|
||||||
|
+ if (node_group->config) {
|
||||||
|
+ dma_free_coherent(node_group->pispbe->dev,
|
||||||
|
sizeof(struct pisp_be_tiles_config) *
|
||||||
|
PISP_BE_NUM_CONFIG_BUFFERS,
|
||||||
|
- pispbe->config,
|
||||||
|
- pispbe->config_dma_addr);
|
||||||
|
+ node_group->config,
|
||||||
|
+ node_group->config_dma_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
dev_dbg(pispbe->dev, "Unregister from media controller\n");
|
||||||
|
|
||||||
|
- v4l2_device_unregister_subdev(&pispbe->sd);
|
||||||
|
- media_entity_cleanup(&pispbe->sd.entity);
|
||||||
|
- media_device_unregister(&pispbe->mdev);
|
||||||
|
+ v4l2_device_unregister_subdev(&node_group->sd);
|
||||||
|
+ media_entity_cleanup(&node_group->sd.entity);
|
||||||
|
+ media_device_unregister(&node_group->mdev);
|
||||||
|
|
||||||
|
for (int i = PISPBE_NUM_NODES - 1; i >= 0; i--) {
|
||||||
|
- video_unregister_device(&pispbe->node[i].vfd);
|
||||||
|
- vb2_queue_release(&pispbe->node[i].queue);
|
||||||
|
- mutex_destroy(&pispbe->node[i].node_lock);
|
||||||
|
- mutex_destroy(&pispbe->node[i].queue_lock);
|
||||||
|
+ video_unregister_device(&node_group->node[i].vfd);
|
||||||
|
+ vb2_queue_release(&node_group->node[i].queue);
|
||||||
|
+ mutex_destroy(&node_group->node[i].node_lock);
|
||||||
|
+ mutex_destroy(&node_group->node[i].queue_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
- media_device_cleanup(&pispbe->mdev);
|
||||||
|
- v4l2_device_unregister(&pispbe->v4l2_dev);
|
||||||
|
+ media_device_cleanup(&node_group->mdev);
|
||||||
|
+ v4l2_device_unregister(&node_group->v4l2_dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pispbe_runtime_suspend(struct device *dev)
|
||||||
|
@@ -1681,9 +1728,13 @@ static int pispbe_hw_init(struct pispbe_
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-/* Probe the ISP-BE hardware block, as a single platform device. */
|
||||||
|
+/*
|
||||||
|
+ * Probe the ISP-BE hardware block, as a single platform device.
|
||||||
|
+ * This will instantiate multiple "node groups" each with many device nodes.
|
||||||
|
+ */
|
||||||
|
static int pispbe_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
+ unsigned int num_groups = 0;
|
||||||
|
struct pispbe_dev *pispbe;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
@@ -1738,17 +1789,26 @@ static int pispbe_probe(struct platform_
|
||||||
|
if (ret)
|
||||||
|
goto pm_runtime_suspend_err;
|
||||||
|
|
||||||
|
- ret = pispbe_init_devices(pispbe);
|
||||||
|
- if (ret)
|
||||||
|
- goto disable_devs_err;
|
||||||
|
+ /*
|
||||||
|
+ * Initialise and register devices for each node_group, including media
|
||||||
|
+ * device
|
||||||
|
+ */
|
||||||
|
+ for (num_groups = 0;
|
||||||
|
+ num_groups < PISPBE_NUM_NODE_GROUPS;
|
||||||
|
+ num_groups++) {
|
||||||
|
+ ret = pispbe_init_group(pispbe, num_groups);
|
||||||
|
+ if (ret)
|
||||||
|
+ goto disable_nodes_err;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
pm_runtime_mark_last_busy(pispbe->dev);
|
||||||
|
pm_runtime_put_autosuspend(pispbe->dev);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
-disable_devs_err:
|
||||||
|
- pispbe_destroy_devices(pispbe);
|
||||||
|
+disable_nodes_err:
|
||||||
|
+ while (num_groups-- > 0)
|
||||||
|
+ pispbe_destroy_node_group(&pispbe->node_group[num_groups]);
|
||||||
|
pm_runtime_suspend_err:
|
||||||
|
pispbe_runtime_suspend(pispbe->dev);
|
||||||
|
pm_runtime_disable_err:
|
||||||
|
@@ -1762,7 +1822,8 @@ static int pispbe_remove(struct platform
|
||||||
|
{
|
||||||
|
struct pispbe_dev *pispbe = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
|
- pispbe_destroy_devices(pispbe);
|
||||||
|
+ for (int i = PISPBE_NUM_NODE_GROUPS - 1; i >= 0; i--)
|
||||||
|
+ pispbe_destroy_node_group(&pispbe->node_group[i]);
|
||||||
|
|
||||||
|
pispbe_runtime_suspend(pispbe->dev);
|
||||||
|
pm_runtime_dont_use_autosuspend(pispbe->dev);
|
@ -0,0 +1,36 @@
|
|||||||
|
From f372f2854279828a33b9b3debc233d366fb4c124 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Naushir Patuck <naush@raspberrypi.com>
|
||||||
|
Date: Mon, 8 Jul 2024 11:47:49 +0100
|
||||||
|
Subject: [PATCH 1161/1215] media: pisp_be: Re-introduce video node offset
|
||||||
|
|
||||||
|
Offset the backend dev-nodes starting at /dev/video20
|
||||||
|
onwards to maintain backward compatibility with the
|
||||||
|
pre-upstreamed kernel driver.
|
||||||
|
|
||||||
|
Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
|
||||||
|
---
|
||||||
|
drivers/media/platform/raspberrypi/pisp_be/pisp_be.c | 6 +++++-
|
||||||
|
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
--- a/drivers/media/platform/raspberrypi/pisp_be/pisp_be.c
|
||||||
|
+++ b/drivers/media/platform/raspberrypi/pisp_be/pisp_be.c
|
||||||
|
@@ -21,6 +21,9 @@
|
||||||
|
|
||||||
|
#include "pisp_be_formats.h"
|
||||||
|
|
||||||
|
+/* Offset to use when registering the /dev/videoX node */
|
||||||
|
+#define PISPBE_VIDEO_NODE_OFFSET 20
|
||||||
|
+
|
||||||
|
/* Maximum number of config buffers possible */
|
||||||
|
#define PISP_BE_NUM_CONFIG_BUFFERS VB2_MAX_FRAME
|
||||||
|
|
||||||
|
@@ -1484,7 +1487,8 @@ static int pispbe_init_node(struct pispb
|
||||||
|
goto err_unregister_queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
- ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
|
||||||
|
+ ret = video_register_device(vdev, VFL_TYPE_VIDEO,
|
||||||
|
+ PISPBE_VIDEO_NODE_OFFSET);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(pispbe->dev,
|
||||||
|
"Failed to register video %s device node\n",
|
@ -0,0 +1,158 @@
|
|||||||
|
From 6e4ad40811170653431fc40a6fdc3f486863b40f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
||||||
|
Date: Thu, 4 Jul 2024 18:15:00 +0100
|
||||||
|
Subject: [PATCH 1163/1215] dts: Make camN_reg and camN_reg_gpio overrides
|
||||||
|
generic
|
||||||
|
|
||||||
|
The camera regulator GPIO can be used for other purposes,
|
||||||
|
so the camN_reg override to allow disabling is potentially
|
||||||
|
useful on any platform.
|
||||||
|
camN_gpio is less useful, but isn't invalid.
|
||||||
|
|
||||||
|
Move these overrides from the CM dt files to bcm270x-rpi.dtsi
|
||||||
|
and bcm2712-rpi.dtsi.
|
||||||
|
|
||||||
|
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
||||||
|
---
|
||||||
|
.../arm/boot/dts/broadcom/bcm2708-rpi-cm.dtsi | 4 ----
|
||||||
|
.../arm/boot/dts/broadcom/bcm2709-rpi-cm2.dts | 4 ----
|
||||||
|
arch/arm/boot/dts/broadcom/bcm270x-rpi.dtsi | 7 +++++++
|
||||||
|
.../arm/boot/dts/broadcom/bcm2710-rpi-cm3.dts | 4 ----
|
||||||
|
.../arm/boot/dts/broadcom/bcm2711-rpi-cm4.dts | 7 -------
|
||||||
|
.../boot/dts/broadcom/bcm2711-rpi-cm4s.dts | 5 -----
|
||||||
|
arch/arm/boot/dts/broadcom/bcm2712-rpi.dtsi | 8 ++++++++
|
||||||
|
arch/arm/boot/dts/overlays/README | 20 +++++++++----------
|
||||||
|
8 files changed, 25 insertions(+), 34 deletions(-)
|
||||||
|
|
||||||
|
--- a/arch/arm/boot/dts/broadcom/bcm2708-rpi-cm.dtsi
|
||||||
|
+++ b/arch/arm/boot/dts/broadcom/bcm2708-rpi-cm.dtsi
|
||||||
|
@@ -19,9 +19,5 @@ i2c_vc: &i2c0 {
|
||||||
|
act_led_gpio = <&led_act>,"gpios:4";
|
||||||
|
act_led_activelow = <&led_act>,"gpios:8";
|
||||||
|
act_led_trigger = <&led_act>,"linux,default-trigger";
|
||||||
|
- cam0_reg = <&cam0_reg>,"status";
|
||||||
|
- cam0_reg_gpio = <&cam0_reg>,"gpio:4";
|
||||||
|
- cam1_reg = <&cam1_reg>,"status";
|
||||||
|
- cam1_reg_gpio = <&cam1_reg>,"gpio:4";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
--- a/arch/arm/boot/dts/broadcom/bcm2709-rpi-cm2.dts
|
||||||
|
+++ b/arch/arm/boot/dts/broadcom/bcm2709-rpi-cm2.dts
|
||||||
|
@@ -211,9 +211,5 @@ i2c_csi_dsi0: &i2c0 {
|
||||||
|
act_led_gpio = <&led_act>,"gpios:4";
|
||||||
|
act_led_activelow = <&led_act>,"gpios:8";
|
||||||
|
act_led_trigger = <&led_act>,"linux,default-trigger";
|
||||||
|
- cam0_reg = <&cam0_reg>,"status";
|
||||||
|
- cam0_reg_gpio = <&cam0_reg>,"gpio:4";
|
||||||
|
- cam1_reg = <&cam1_reg>,"status";
|
||||||
|
- cam1_reg_gpio = <&cam1_reg>,"gpio:4";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
--- a/arch/arm/boot/dts/broadcom/bcm270x-rpi.dtsi
|
||||||
|
+++ b/arch/arm/boot/dts/broadcom/bcm270x-rpi.dtsi
|
||||||
|
@@ -111,6 +111,13 @@
|
||||||
|
<&csi0>, "sync-gpios:4",
|
||||||
|
<&csi0>, "sync-gpios:8=", <GPIO_ACTIVE_LOW>;
|
||||||
|
|
||||||
|
+ cam0_reg = <&cam0_reg>,"status";
|
||||||
|
+ cam0_reg_gpio = <&cam0_reg>,"gpio:4",
|
||||||
|
+ <&cam0_reg>,"gpio:0=", <&gpio>;
|
||||||
|
+ cam1_reg = <&cam1_reg>,"status";
|
||||||
|
+ cam1_reg_gpio = <&cam1_reg>,"gpio:4",
|
||||||
|
+ <&cam1_reg>,"gpio:0=", <&gpio>;
|
||||||
|
+
|
||||||
|
strict_gpiod = <&chosen>, "bootargs=pinctrl_bcm2835.persist_gpio_outputs=n";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
--- a/arch/arm/boot/dts/broadcom/bcm2710-rpi-cm3.dts
|
||||||
|
+++ b/arch/arm/boot/dts/broadcom/bcm2710-rpi-cm3.dts
|
||||||
|
@@ -211,9 +211,5 @@ i2c_csi_dsi0: &i2c0 {
|
||||||
|
act_led_gpio = <&led_act>,"gpios:4";
|
||||||
|
act_led_activelow = <&led_act>,"gpios:8";
|
||||||
|
act_led_trigger = <&led_act>,"linux,default-trigger";
|
||||||
|
- cam0_reg = <&cam0_reg>,"status";
|
||||||
|
- cam0_reg_gpio = <&cam0_reg>,"gpio:4";
|
||||||
|
- cam1_reg = <&cam1_reg>,"status";
|
||||||
|
- cam1_reg_gpio = <&cam1_reg>,"gpio:4";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
--- a/arch/arm/boot/dts/broadcom/bcm2711-rpi-cm4.dts
|
||||||
|
+++ b/arch/arm/boot/dts/broadcom/bcm2711-rpi-cm4.dts
|
||||||
|
@@ -498,13 +498,6 @@ i2c_csi_dsi0: &i2c0 {
|
||||||
|
<&ant2>, "output-high?=off",
|
||||||
|
<&ant2>, "output-low?=on";
|
||||||
|
|
||||||
|
- cam0_reg = <&cam0_reg>,"status";
|
||||||
|
- cam0_reg_gpio = <&cam0_reg>,"gpio:4",
|
||||||
|
- <&cam0_reg>,"gpio:0=", <&gpio>;
|
||||||
|
- cam1_reg = <&cam1_reg>,"status";
|
||||||
|
- cam1_reg_gpio = <&cam1_reg>,"gpio:4",
|
||||||
|
- <&cam1_reg>,"gpio:0=", <&gpio>;
|
||||||
|
-
|
||||||
|
pcie_tperst_clk_ms = <&pcie0>,"brcm,tperst-clk-ms:0";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
--- a/arch/arm/boot/dts/broadcom/bcm2711-rpi-cm4s.dts
|
||||||
|
+++ b/arch/arm/boot/dts/broadcom/bcm2711-rpi-cm4s.dts
|
||||||
|
@@ -289,10 +289,5 @@ i2c_csi_dsi0: &i2c0 {
|
||||||
|
act_led_gpio = <&led_act>,"gpios:4";
|
||||||
|
act_led_activelow = <&led_act>,"gpios:8";
|
||||||
|
act_led_trigger = <&led_act>,"linux,default-trigger";
|
||||||
|
-
|
||||||
|
- cam0_reg = <&cam0_reg>,"status";
|
||||||
|
- cam0_reg_gpio = <&cam0_reg>,"gpio:4";
|
||||||
|
- cam1_reg = <&cam1_reg>,"status";
|
||||||
|
- cam1_reg_gpio = <&cam1_reg>,"gpio:4";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
--- a/arch/arm/boot/dts/broadcom/bcm2712-rpi.dtsi
|
||||||
|
+++ b/arch/arm/boot/dts/broadcom/bcm2712-rpi.dtsi
|
||||||
|
@@ -106,6 +106,14 @@
|
||||||
|
nvmem_priv_rw = <&nvmem_priv>,"rw?";
|
||||||
|
nvmem_mac_rw = <&nvmem_mac>,"rw?";
|
||||||
|
strict_gpiod = <&chosen>, "bootargs=pinctrl_rp1.persist_gpio_outputs=n";
|
||||||
|
+
|
||||||
|
+ cam0_reg = <&cam0_reg>,"status";
|
||||||
|
+ cam0_reg_gpio = <&cam0_reg>,"gpio:4",
|
||||||
|
+ <&cam0_reg>,"gpio:0=", <&gpio>;
|
||||||
|
+ cam1_reg = <&cam1_reg>,"status";
|
||||||
|
+ cam1_reg_gpio = <&cam1_reg>,"gpio:4",
|
||||||
|
+ <&cam1_reg>,"gpio:0=", <&gpio>;
|
||||||
|
+
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
--- a/arch/arm/boot/dts/overlays/README
|
||||||
|
+++ b/arch/arm/boot/dts/overlays/README
|
||||||
|
@@ -171,21 +171,21 @@ Params:
|
||||||
|
button_debounce Set the debounce delay (in ms) on the power/
|
||||||
|
shutdown button (default 50ms)
|
||||||
|
|
||||||
|
- cam0_reg Enables CAM 0 regulator.
|
||||||
|
- Only required on CM1 & 3.
|
||||||
|
+ cam0_reg Controls CAM 0 regulator.
|
||||||
|
+ Disabled by default on CM1 & 3.
|
||||||
|
+ Enabled by default on all other boards.
|
||||||
|
|
||||||
|
cam0_reg_gpio Set GPIO for CAM 0 regulator.
|
||||||
|
- Default 31 on CM1, 3, and 4S.
|
||||||
|
- Default of GPIO expander 5 on CM4, but override
|
||||||
|
- switches to normal GPIO.
|
||||||
|
+ NB override switches to the normal GPIO driver,
|
||||||
|
+ even if the original was on the GPIO expander.
|
||||||
|
|
||||||
|
- cam1_reg Enables CAM 1 regulator.
|
||||||
|
- Only required on CM1 & 3.
|
||||||
|
+ cam1_reg Controls CAM 1 regulator.
|
||||||
|
+ Disabled by default on CM1 & 3.
|
||||||
|
+ Enabled by default on all other boards.
|
||||||
|
|
||||||
|
cam1_reg_gpio Set GPIO for CAM 1 regulator.
|
||||||
|
- Default 3 on CM1, 3, and 4S.
|
||||||
|
- Default of GPIO expander 5 on CM4, but override
|
||||||
|
- switches to normal GPIO.
|
||||||
|
+ NB override switches to the normal GPIO driver,
|
||||||
|
+ even if the original was on the GPIO expander.
|
||||||
|
|
||||||
|
cam0_sync Enable a GPIO to reflect frame sync from CSI0,
|
||||||
|
going high on frame start, and low on frame end.
|
@ -0,0 +1,108 @@
|
|||||||
|
From afd949f5f64d224cf7a016ef933257842bc170ab Mon Sep 17 00:00:00 2001
|
||||||
|
From: Richard Oliver <richard.oliver@raspberrypi.com>
|
||||||
|
Date: Fri, 24 May 2024 10:34:45 +0100
|
||||||
|
Subject: [PATCH 1164/1215] spi: dt-bindings: Add RPI RP2040 GPIO Bridge
|
||||||
|
|
||||||
|
Add YAML device tree bindings for the Raspberry Pi RP2040 GPIO Bridge.
|
||||||
|
|
||||||
|
Signed-off-by: Richard Oliver <richard.oliver@raspberrypi.com>
|
||||||
|
---
|
||||||
|
.../spi/raspberrypi,rp2040-gpio-bridge.yaml | 77 +++++++++++++++++++
|
||||||
|
MAINTAINERS | 5 ++
|
||||||
|
2 files changed, 82 insertions(+)
|
||||||
|
create mode 100644 Documentation/devicetree/bindings/spi/raspberrypi,rp2040-gpio-bridge.yaml
|
||||||
|
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/Documentation/devicetree/bindings/spi/raspberrypi,rp2040-gpio-bridge.yaml
|
||||||
|
@@ -0,0 +1,77 @@
|
||||||
|
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
+%YAML 1.2
|
||||||
|
+---
|
||||||
|
+$id: http://devicetree.org/schemas/spi/raspberrypi,rp2040-gpio-bridge.yaml#
|
||||||
|
+$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
+
|
||||||
|
+title: Raspberry Pi RP2040 GPIO Bridge
|
||||||
|
+
|
||||||
|
+maintainers:
|
||||||
|
+ - Raspberry Pi <kernel-list@raspberrypi.com>
|
||||||
|
+
|
||||||
|
+description: |-
|
||||||
|
+ The Raspberry Pi PR2040 GPIO bridge can be used as a GPIO expander and
|
||||||
|
+ Tx-only SPI master.
|
||||||
|
+
|
||||||
|
+properties:
|
||||||
|
+ reg:
|
||||||
|
+ description: I2C slave address
|
||||||
|
+ const: 0x40
|
||||||
|
+
|
||||||
|
+ compatible:
|
||||||
|
+ const: raspberrypi,rp2040-gpio-bridge
|
||||||
|
+
|
||||||
|
+ power-supply:
|
||||||
|
+ description: Phandle to the regulator that powers the RP2040.
|
||||||
|
+
|
||||||
|
+ '#address-cells':
|
||||||
|
+ const: 1
|
||||||
|
+
|
||||||
|
+ '#size-cells':
|
||||||
|
+ const: 0
|
||||||
|
+
|
||||||
|
+ '#gpio-cells':
|
||||||
|
+ const: 2
|
||||||
|
+
|
||||||
|
+ gpio-controller: true
|
||||||
|
+
|
||||||
|
+ fast_xfer_requires_i2c_lock:
|
||||||
|
+ description: Set if I2C bus should be locked during fast transfer.
|
||||||
|
+
|
||||||
|
+ fast_xfer_recv_gpio_base:
|
||||||
|
+ description: RP2040 GPIO base for fast transfer pair.
|
||||||
|
+
|
||||||
|
+ fast_xfer-gpios:
|
||||||
|
+ description: RP1 GPIOs to use for fast transfer clock and data.
|
||||||
|
+
|
||||||
|
+required:
|
||||||
|
+ - reg
|
||||||
|
+ - compatible
|
||||||
|
+ - power-supply
|
||||||
|
+ - '#gpio-cells'
|
||||||
|
+ - gpio-controller
|
||||||
|
+
|
||||||
|
+additionalProperties: false
|
||||||
|
+
|
||||||
|
+examples:
|
||||||
|
+ - |
|
||||||
|
+ i2c {
|
||||||
|
+ #address-cells = <1>;
|
||||||
|
+ #size-cells = <0>;
|
||||||
|
+
|
||||||
|
+ spi@40 {
|
||||||
|
+ reg = <0x40>;
|
||||||
|
+ compatible = "raspberrypi,rp2040-gpio-bridge";
|
||||||
|
+ status = "disabled";
|
||||||
|
+ #address-cells = <1>;
|
||||||
|
+ #size-cells = <0>;
|
||||||
|
+
|
||||||
|
+ power-supply = <&cam_dummy_reg>;
|
||||||
|
+
|
||||||
|
+ #gpio-cells = <2>;
|
||||||
|
+ gpio-controller;
|
||||||
|
+ };
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+...
|
||||||
|
+
|
||||||
|
--- a/MAINTAINERS
|
||||||
|
+++ b/MAINTAINERS
|
||||||
|
@@ -18027,6 +18027,11 @@ F: drivers/ras/
|
||||||
|
F: include/linux/ras.h
|
||||||
|
F: include/ras/ras_event.h
|
||||||
|
|
||||||
|
+RASPBERRY PI RP2040 GPIO BRIDGE DRIVER
|
||||||
|
+M: Raspberry Pi Kernel Maintenance <kernel-list@raspberrypi.com>
|
||||||
|
+S: Maintained
|
||||||
|
+F: Documentation/devicetree/bindings/spi/raspberrypi,rp2040-gpio-bridge.yaml
|
||||||
|
+
|
||||||
|
RAYLINK/WEBGEAR 802.11 WIRELESS LAN DRIVER
|
||||||
|
L: linux-wireless@vger.kernel.org
|
||||||
|
S: Orphan
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,52 @@
|
|||||||
|
From 475cddaba6b02584157e1c128a5a6858770a3d06 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Phil Elwell <phil@raspberrypi.com>
|
||||||
|
Date: Wed, 10 Jul 2024 14:47:17 +0100
|
||||||
|
Subject: [PATCH 1166/1215] dmaengine: dw-axi-dmac: Honour snps,block-size
|
||||||
|
|
||||||
|
The snps,block-size DT property declares the maximum block size for each
|
||||||
|
channel of the dw-axi-dmac. However, the driver ignores these when
|
||||||
|
setting max_seg_size and uses MAX_BLOCK_SIZE (4096) instead.
|
||||||
|
|
||||||
|
To take advantage of the efficiencies of larger blocks, calculate the
|
||||||
|
minimum block size across all channels and use that instead.
|
||||||
|
|
||||||
|
See: https://github.com/raspberrypi/linux/issues/6256
|
||||||
|
|
||||||
|
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||||
|
---
|
||||||
|
drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c | 15 ++++++++++++++-
|
||||||
|
1 file changed, 14 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
|
||||||
|
+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
|
||||||
|
@@ -1470,6 +1470,7 @@ static int dw_probe(struct platform_devi
|
||||||
|
struct dw_axi_dma *dw;
|
||||||
|
struct dw_axi_dma_hcfg *hdata;
|
||||||
|
struct reset_control *resets;
|
||||||
|
+ unsigned int max_seg_size;
|
||||||
|
unsigned int flags;
|
||||||
|
u32 i;
|
||||||
|
int ret;
|
||||||
|
@@ -1585,9 +1586,21 @@ static int dw_probe(struct platform_devi
|
||||||
|
* Synopsis DesignWare AxiDMA datasheet mentioned Maximum
|
||||||
|
* supported blocks is 1024. Device register width is 4 bytes.
|
||||||
|
* Therefore, set constraint to 1024 * 4.
|
||||||
|
+ * However, if all channels specify a greater value, use that instead.
|
||||||
|
*/
|
||||||
|
+
|
||||||
|
dw->dma.dev->dma_parms = &dw->dma_parms;
|
||||||
|
- dma_set_max_seg_size(&pdev->dev, MAX_BLOCK_SIZE);
|
||||||
|
+ max_seg_size = UINT_MAX;
|
||||||
|
+ for (i = 0; i < dw->hdata->nr_channels; i++) {
|
||||||
|
+ unsigned int block_size = chip->dw->hdata->block_size[i];
|
||||||
|
+
|
||||||
|
+ if (!block_size)
|
||||||
|
+ block_size = MAX_BLOCK_SIZE;
|
||||||
|
+ max_seg_size = min(block_size, max_seg_size);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ dma_set_max_seg_size(&pdev->dev, max_seg_size);
|
||||||
|
+
|
||||||
|
platform_set_drvdata(pdev, chip);
|
||||||
|
|
||||||
|
pm_runtime_enable(chip->dev);
|
@ -0,0 +1,157 @@
|
|||||||
|
From e6c1e862b2b8150a419f4208e5bd7749662b16a1 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jonathan Bell <jonathan@raspberrypi.com>
|
||||||
|
Date: Thu, 20 Jun 2024 14:31:20 +0100
|
||||||
|
Subject: [PATCH 1167/1215] mmc: restrict posted write counts for SD cards in
|
||||||
|
CQ mode
|
||||||
|
|
||||||
|
Command Queueing requires Write Cache and Power off Notification support
|
||||||
|
from the card - but using the write cache forms a contract with the host
|
||||||
|
whereby the card expects to be told about impending power-down.
|
||||||
|
|
||||||
|
The implication is that (for performance) the card can do unsafe things
|
||||||
|
with pending write data - including reordering what gets committed to
|
||||||
|
nonvolatile storage at what time.
|
||||||
|
|
||||||
|
Exposed SD slots and platforms powered by hotpluggable means (i.e.
|
||||||
|
Raspberry Pis) can't guarantee that surprise removal won't happen.
|
||||||
|
|
||||||
|
To limit the scope for cards to invent new ways to trash filesystems,
|
||||||
|
limit pending writes to 1 (equivalent to the non-CQ behaviour).
|
||||||
|
|
||||||
|
Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
|
||||||
|
---
|
||||||
|
drivers/mmc/core/block.c | 11 +++++++++--
|
||||||
|
drivers/mmc/core/mmc.c | 1 +
|
||||||
|
drivers/mmc/core/queue.c | 9 +++++++++
|
||||||
|
drivers/mmc/core/queue.h | 1 +
|
||||||
|
drivers/mmc/core/sd.c | 8 ++++++++
|
||||||
|
include/linux/mmc/card.h | 2 ++
|
||||||
|
6 files changed, 30 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
--- a/drivers/mmc/core/block.c
|
||||||
|
+++ b/drivers/mmc/core/block.c
|
||||||
|
@@ -1555,6 +1555,8 @@ static void mmc_blk_cqe_complete_rq(stru
|
||||||
|
|
||||||
|
spin_lock_irqsave(&mq->lock, flags);
|
||||||
|
|
||||||
|
+ if (req_op(req) == REQ_OP_WRITE)
|
||||||
|
+ mq->pending_writes--;
|
||||||
|
mq->in_flight[issue_type] -= 1;
|
||||||
|
|
||||||
|
put_card = (mmc_tot_in_flight(mq) == 0);
|
||||||
|
@@ -2071,6 +2073,8 @@ static void mmc_blk_mq_complete_rq(struc
|
||||||
|
struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req);
|
||||||
|
unsigned int nr_bytes = mqrq->brq.data.bytes_xfered;
|
||||||
|
|
||||||
|
+ if (req_op(req) == REQ_OP_WRITE)
|
||||||
|
+ mq->pending_writes--;
|
||||||
|
if (nr_bytes) {
|
||||||
|
if (blk_update_request(req, BLK_STS_OK, nr_bytes))
|
||||||
|
blk_mq_requeue_request(req, true);
|
||||||
|
@@ -2165,13 +2169,16 @@ static void mmc_blk_mq_poll_completion(s
|
||||||
|
mmc_blk_urgent_bkops(mq, mqrq);
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void mmc_blk_mq_dec_in_flight(struct mmc_queue *mq, enum mmc_issue_type issue_type)
|
||||||
|
+static void mmc_blk_mq_dec_in_flight(struct mmc_queue *mq, enum mmc_issue_type issue_type,
|
||||||
|
+ struct request *req)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
bool put_card;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&mq->lock, flags);
|
||||||
|
|
||||||
|
+ if (req_op(req) == REQ_OP_WRITE)
|
||||||
|
+ mq->pending_writes--;
|
||||||
|
mq->in_flight[issue_type] -= 1;
|
||||||
|
|
||||||
|
put_card = (mmc_tot_in_flight(mq) == 0);
|
||||||
|
@@ -2205,7 +2212,7 @@ static void mmc_blk_mq_post_req(struct m
|
||||||
|
blk_mq_complete_request(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
- mmc_blk_mq_dec_in_flight(mq, issue_type);
|
||||||
|
+ mmc_blk_mq_dec_in_flight(mq, issue_type, req);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mmc_blk_mq_recovery(struct mmc_queue *mq)
|
||||||
|
--- a/drivers/mmc/core/mmc.c
|
||||||
|
+++ b/drivers/mmc/core/mmc.c
|
||||||
|
@@ -1922,6 +1922,7 @@ static int mmc_init_card(struct mmc_host
|
||||||
|
pr_info("%s: Host Software Queue enabled\n",
|
||||||
|
mmc_hostname(host));
|
||||||
|
}
|
||||||
|
+ card->max_posted_writes = card->ext_csd.cmdq_depth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
--- a/drivers/mmc/core/queue.c
|
||||||
|
+++ b/drivers/mmc/core/queue.c
|
||||||
|
@@ -268,6 +268,11 @@ static blk_status_t mmc_mq_queue_rq(stru
|
||||||
|
spin_unlock_irq(&mq->lock);
|
||||||
|
return BLK_STS_RESOURCE;
|
||||||
|
}
|
||||||
|
+ if (host->cqe_enabled && req_op(req) == REQ_OP_WRITE &&
|
||||||
|
+ mq->pending_writes >= card->max_posted_writes) {
|
||||||
|
+ spin_unlock_irq(&mq->lock);
|
||||||
|
+ return BLK_STS_RESOURCE;
|
||||||
|
+ }
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/*
|
||||||
|
@@ -284,6 +289,8 @@ static blk_status_t mmc_mq_queue_rq(stru
|
||||||
|
/* Parallel dispatch of requests is not supported at the moment */
|
||||||
|
mq->busy = true;
|
||||||
|
|
||||||
|
+ if (req_op(req) == REQ_OP_WRITE)
|
||||||
|
+ mq->pending_writes++;
|
||||||
|
mq->in_flight[issue_type] += 1;
|
||||||
|
get_card = (mmc_tot_in_flight(mq) == 1);
|
||||||
|
cqe_retune_ok = (mmc_cqe_qcnt(mq) == 1);
|
||||||
|
@@ -323,6 +330,8 @@ static blk_status_t mmc_mq_queue_rq(stru
|
||||||
|
bool put_card = false;
|
||||||
|
|
||||||
|
spin_lock_irq(&mq->lock);
|
||||||
|
+ if (req_op(req) == REQ_OP_WRITE)
|
||||||
|
+ mq->pending_writes--;
|
||||||
|
mq->in_flight[issue_type] -= 1;
|
||||||
|
if (mmc_tot_in_flight(mq) == 0)
|
||||||
|
put_card = true;
|
||||||
|
--- a/drivers/mmc/core/queue.h
|
||||||
|
+++ b/drivers/mmc/core/queue.h
|
||||||
|
@@ -79,6 +79,7 @@ struct mmc_queue {
|
||||||
|
struct request_queue *queue;
|
||||||
|
spinlock_t lock;
|
||||||
|
int in_flight[MMC_ISSUE_MAX];
|
||||||
|
+ int pending_writes;
|
||||||
|
unsigned int cqe_busy;
|
||||||
|
#define MMC_CQE_DCMD_BUSY BIT(0)
|
||||||
|
bool busy;
|
||||||
|
--- a/drivers/mmc/core/sd.c
|
||||||
|
+++ b/drivers/mmc/core/sd.c
|
||||||
|
@@ -1104,6 +1104,14 @@ static int sd_parse_ext_reg_perf(struct
|
||||||
|
pr_debug("%s: Command Queue supported depth %u\n",
|
||||||
|
mmc_hostname(card->host),
|
||||||
|
card->ext_csd.cmdq_depth);
|
||||||
|
+ /*
|
||||||
|
+ * If CQ is enabled, there is a contract between host and card such that VDD will
|
||||||
|
+ * be maintained and removed only if a power off notification is provided.
|
||||||
|
+ * An SD card in an accessible slot means surprise removal is a possibility.
|
||||||
|
+ * As a middle ground, limit max posted writes to 1 unless the card is "hardwired".
|
||||||
|
+ */
|
||||||
|
+ if (mmc_card_is_removable(card->host))
|
||||||
|
+ card->max_posted_writes = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
card->ext_perf.fno = fno;
|
||||||
|
--- a/include/linux/mmc/card.h
|
||||||
|
+++ b/include/linux/mmc/card.h
|
||||||
|
@@ -343,6 +343,8 @@ struct mmc_card {
|
||||||
|
unsigned int nr_parts;
|
||||||
|
|
||||||
|
struct workqueue_struct *complete_wq; /* Private workqueue */
|
||||||
|
+
|
||||||
|
+ unsigned int max_posted_writes; /* command queue posted write limit */
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline bool mmc_large_sector(struct mmc_card *card)
|
@ -0,0 +1,70 @@
|
|||||||
|
From 19682239a60c1b53cad8319eaeb58e71d4213cee Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jonathan Bell <jonathan@raspberrypi.com>
|
||||||
|
Date: Mon, 15 Jul 2024 13:38:38 +0100
|
||||||
|
Subject: [PATCH 1168/1215] fixup: mmc: restrict posted write counts for SD
|
||||||
|
cards in CQ mode
|
||||||
|
|
||||||
|
Leaving card->max_posted_writes unintialised was a bad thing to do.
|
||||||
|
|
||||||
|
Also, cqe_enable is 1 if hsq is enabled as hsq substitutes the cqhci
|
||||||
|
implementation with its own.
|
||||||
|
|
||||||
|
Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
|
||||||
|
---
|
||||||
|
drivers/mmc/core/mmc.c | 1 +
|
||||||
|
drivers/mmc/core/queue.c | 2 +-
|
||||||
|
drivers/mmc/core/sd.c | 14 ++++++++------
|
||||||
|
3 files changed, 10 insertions(+), 7 deletions(-)
|
||||||
|
|
||||||
|
--- a/drivers/mmc/core/mmc.c
|
||||||
|
+++ b/drivers/mmc/core/mmc.c
|
||||||
|
@@ -1663,6 +1663,7 @@ static int mmc_init_card(struct mmc_host
|
||||||
|
card->ocr = ocr;
|
||||||
|
card->type = MMC_TYPE_MMC;
|
||||||
|
card->rca = 1;
|
||||||
|
+ card->max_posted_writes = 1;
|
||||||
|
memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
|
||||||
|
}
|
||||||
|
|
||||||
|
--- a/drivers/mmc/core/queue.c
|
||||||
|
+++ b/drivers/mmc/core/queue.c
|
||||||
|
@@ -268,7 +268,7 @@ static blk_status_t mmc_mq_queue_rq(stru
|
||||||
|
spin_unlock_irq(&mq->lock);
|
||||||
|
return BLK_STS_RESOURCE;
|
||||||
|
}
|
||||||
|
- if (host->cqe_enabled && req_op(req) == REQ_OP_WRITE &&
|
||||||
|
+ if (!host->hsq_enabled && host->cqe_enabled && req_op(req) == REQ_OP_WRITE &&
|
||||||
|
mq->pending_writes >= card->max_posted_writes) {
|
||||||
|
spin_unlock_irq(&mq->lock);
|
||||||
|
return BLK_STS_RESOURCE;
|
||||||
|
--- a/drivers/mmc/core/sd.c
|
||||||
|
+++ b/drivers/mmc/core/sd.c
|
||||||
|
@@ -1105,13 +1105,14 @@ static int sd_parse_ext_reg_perf(struct
|
||||||
|
mmc_hostname(card->host),
|
||||||
|
card->ext_csd.cmdq_depth);
|
||||||
|
/*
|
||||||
|
- * If CQ is enabled, there is a contract between host and card such that VDD will
|
||||||
|
- * be maintained and removed only if a power off notification is provided.
|
||||||
|
- * An SD card in an accessible slot means surprise removal is a possibility.
|
||||||
|
- * As a middle ground, limit max posted writes to 1 unless the card is "hardwired".
|
||||||
|
+ * If CQ is enabled, there is a contract between host and card such that
|
||||||
|
+ * VDD will be maintained and removed only if a power off notification
|
||||||
|
+ * is provided. An SD card in an accessible slot means surprise removal
|
||||||
|
+ * is a possibility. As a middle ground, keep the default maximum of 1
|
||||||
|
+ * posted write unless the card is "hardwired".
|
||||||
|
*/
|
||||||
|
- if (mmc_card_is_removable(card->host))
|
||||||
|
- card->max_posted_writes = 1;
|
||||||
|
+ if (!mmc_card_is_removable(card->host))
|
||||||
|
+ card->max_posted_writes = card->ext_csd.cmdq_depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
card->ext_perf.fno = fno;
|
||||||
|
@@ -1383,6 +1384,7 @@ retry:
|
||||||
|
|
||||||
|
card->ocr = ocr;
|
||||||
|
card->type = MMC_TYPE_SD;
|
||||||
|
+ card->max_posted_writes = 1;
|
||||||
|
memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
|||||||
|
From 1abc413af44652d6a76d5b5c2afe90788595008e Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jonathan Bell <jonathan@raspberrypi.com>
|
||||||
|
Date: Mon, 15 Jul 2024 13:57:01 +0100
|
||||||
|
Subject: [PATCH 1169/1215] mmc: brcmstb: don't squash card-busy detection on
|
||||||
|
bcm2712
|
||||||
|
|
||||||
|
Commit 485d9421719b ("mmc: sdhci-brcmstb: check R1_STATUS for
|
||||||
|
erase/trim/discard") introduced a new flag and defaulted to disabling
|
||||||
|
card busy detection across all platforms with this controller.
|
||||||
|
|
||||||
|
This is required for IO voltage switching, as the card drives CMD low
|
||||||
|
while the switch is in progress.
|
||||||
|
|
||||||
|
Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
|
||||||
|
---
|
||||||
|
drivers/mmc/host/sdhci-brcmstb.c | 1 +
|
||||||
|
1 file changed, 1 insertion(+)
|
||||||
|
|
||||||
|
--- a/drivers/mmc/host/sdhci-brcmstb.c
|
||||||
|
+++ b/drivers/mmc/host/sdhci-brcmstb.c
|
||||||
|
@@ -430,6 +430,7 @@ static const struct brcmstb_match_priv m
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct brcmstb_match_priv match_priv_2712 = {
|
||||||
|
+ .flags = BRCMSTB_MATCH_FLAGS_USE_CARD_BUSY,
|
||||||
|
.hs400es = sdhci_brcmstb_hs400es,
|
||||||
|
.cfginit = sdhci_brcmstb_cfginit_2712,
|
||||||
|
.ops = &sdhci_brcmstb_ops_2712,
|
@ -0,0 +1,25 @@
|
|||||||
|
From 31eb43be8cad2818b4458cf1fd2dfa60031ee5f4 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Matthew <sirfragles@gmail.com>
|
||||||
|
Date: Tue, 16 Jul 2024 11:20:54 +0200
|
||||||
|
Subject: [PATCH 1172/1215] Revert "Update DAC8x to support 384khz (#6187)"
|
||||||
|
|
||||||
|
This reverts commit dd7a15472b18d4bce738bb9213443c140473833b.
|
||||||
|
---
|
||||||
|
sound/soc/bcm/rpi-simple-soundcard.c | 4 ++--
|
||||||
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
--- a/sound/soc/bcm/rpi-simple-soundcard.c
|
||||||
|
+++ b/sound/soc/bcm/rpi-simple-soundcard.c
|
||||||
|
@@ -324,10 +324,10 @@ static int hifiberry_dac8x_init(struct s
|
||||||
|
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
|
||||||
|
|
||||||
|
/* override the defaults to reflect 4 x PCM5102A on the card
|
||||||
|
- * and limit the sample rate to 384ksps
|
||||||
|
+ * and limit the sample rate to 192ksps
|
||||||
|
*/
|
||||||
|
codec_dai->driver->playback.channels_max = 8;
|
||||||
|
- codec_dai->driver->playback.rates = SNDRV_PCM_RATE_8000_384000;
|
||||||
|
+ codec_dai->driver->playback.rates = SNDRV_PCM_RATE_8000_192000;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
From 3224569a3e279bbeae4e975dfa1a890f3f595239 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Nick Hollinghurst <nick.hollinghurst@raspberrypi.com>
|
||||||
|
Date: Fri, 10 May 2024 15:18:44 +0100
|
||||||
|
Subject: [PATCH 1176/1215] dt-bindings: clk: rp1: Add clocks representing MIPI
|
||||||
|
DSI byteclock
|
||||||
|
|
||||||
|
Define two new RP1 clocks, representing the MIPI DSI byteclock
|
||||||
|
sources for the dividers used to generate MIPI[01] DPI pixel clocks.
|
||||||
|
(Previously they were represented by "fake" fixed clocks sources).
|
||||||
|
|
||||||
|
Signed-off-by: Nick Hollinghurst <nick.hollinghurst@raspberrypi.com>
|
||||||
|
---
|
||||||
|
include/dt-bindings/clock/rp1.h | 4 ++++
|
||||||
|
1 file changed, 4 insertions(+)
|
||||||
|
|
||||||
|
--- a/include/dt-bindings/clock/rp1.h
|
||||||
|
+++ b/include/dt-bindings/clock/rp1.h
|
||||||
|
@@ -54,3 +54,7 @@
|
||||||
|
/* Extra PLL output channels - RP1B0 only */
|
||||||
|
#define RP1_PLL_VIDEO_PRI_PH 43
|
||||||
|
#define RP1_PLL_AUDIO_TERN 44
|
||||||
|
+
|
||||||
|
+/* MIPI clocks managed by the DSI driver */
|
||||||
|
+#define RP1_CLK_MIPI0_DSI_BYTECLOCK 45
|
||||||
|
+#define RP1_CLK_MIPI1_DSI_BYTECLOCK 46
|
@ -0,0 +1,132 @@
|
|||||||
|
From 126560c909f38f00c08dd5f35f50c981d5e25e1f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Nick Hollinghurst <nick.hollinghurst@raspberrypi.com>
|
||||||
|
Date: Fri, 10 May 2024 15:30:44 +0100
|
||||||
|
Subject: [PATCH 1177/1215] clk: clk-rp1: Add "varsrc" clocks to represent MIPI
|
||||||
|
byte clocks
|
||||||
|
|
||||||
|
Add a new class of clocks to RP1 to represent clock sources whose
|
||||||
|
frequency changes at run-time as a side-effect of some other driver.
|
||||||
|
Specifically this is for the two MIPI DSI byte-clock sources.
|
||||||
|
|
||||||
|
Signed-off-by: Nick Hollinghurst <nick.hollinghurst@raspberrypi.com>
|
||||||
|
---
|
||||||
|
drivers/clk/clk-rp1.c | 73 +++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
1 file changed, 73 insertions(+)
|
||||||
|
|
||||||
|
--- a/drivers/clk/clk-rp1.c
|
||||||
|
+++ b/drivers/clk/clk-rp1.c
|
||||||
|
@@ -394,6 +394,11 @@ struct rp1_clock {
|
||||||
|
unsigned long cached_rate;
|
||||||
|
};
|
||||||
|
|
||||||
|
+struct rp1_varsrc {
|
||||||
|
+ struct clk_hw hw;
|
||||||
|
+ struct rp1_clockman *clockman;
|
||||||
|
+ unsigned long rate;
|
||||||
|
+};
|
||||||
|
|
||||||
|
struct rp1_clk_change {
|
||||||
|
struct clk_hw *hw;
|
||||||
|
@@ -1414,6 +1419,34 @@ static void rp1_clk_debug_init(struct cl
|
||||||
|
rp1_debugfs_regset(clockman, 0, regs, i, dentry);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int rp1_varsrc_set_rate(struct clk_hw *hw,
|
||||||
|
+ unsigned long rate, unsigned long parent_rate)
|
||||||
|
+{
|
||||||
|
+ struct rp1_varsrc *varsrc = container_of(hw, struct rp1_varsrc, hw);
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * "varsrc" exists purely to let clock dividers know the frequency
|
||||||
|
+ * of an externally-managed clock source (such as MIPI DSI byte-clock)
|
||||||
|
+ * which may change at run-time as a side-effect of some other driver.
|
||||||
|
+ */
|
||||||
|
+ varsrc->rate = rate;
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static unsigned long rp1_varsrc_recalc_rate(struct clk_hw *hw,
|
||||||
|
+ unsigned long parent_rate)
|
||||||
|
+{
|
||||||
|
+ struct rp1_varsrc *varsrc = container_of(hw, struct rp1_varsrc, hw);
|
||||||
|
+
|
||||||
|
+ return varsrc->rate;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static long rp1_varsrc_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
|
+ unsigned long *parent_rate)
|
||||||
|
+{
|
||||||
|
+ return rate;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static const struct clk_ops rp1_pll_core_ops = {
|
||||||
|
.is_prepared = rp1_pll_core_is_on,
|
||||||
|
.prepare = rp1_pll_core_on,
|
||||||
|
@@ -1464,6 +1497,12 @@ static const struct clk_ops rp1_clk_ops
|
||||||
|
.debug_init = rp1_clk_debug_init,
|
||||||
|
};
|
||||||
|
|
||||||
|
+static const struct clk_ops rp1_varsrc_ops = {
|
||||||
|
+ .set_rate = rp1_varsrc_set_rate,
|
||||||
|
+ .recalc_rate = rp1_varsrc_recalc_rate,
|
||||||
|
+ .round_rate = rp1_varsrc_round_rate,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
static bool rp1_clk_is_claimed(const char *name);
|
||||||
|
|
||||||
|
static struct clk_hw *rp1_register_pll_core(struct rp1_clockman *clockman,
|
||||||
|
@@ -1647,6 +1686,35 @@ static struct clk_hw *rp1_register_clock
|
||||||
|
return &clock->hw;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static struct clk_hw *rp1_register_varsrc(struct rp1_clockman *clockman,
|
||||||
|
+ const void *data)
|
||||||
|
+{
|
||||||
|
+ const char *name = *(char const * const *)data;
|
||||||
|
+ struct rp1_varsrc *clock;
|
||||||
|
+ struct clk_init_data init;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ memset(&init, 0, sizeof(init));
|
||||||
|
+ init.parent_names = &ref_clock;
|
||||||
|
+ init.num_parents = 1;
|
||||||
|
+ init.name = name;
|
||||||
|
+ init.flags = CLK_IGNORE_UNUSED;
|
||||||
|
+ init.ops = &rp1_varsrc_ops;
|
||||||
|
+
|
||||||
|
+ clock = devm_kzalloc(clockman->dev, sizeof(*clock), GFP_KERNEL);
|
||||||
|
+ if (!clock)
|
||||||
|
+ return NULL;
|
||||||
|
+
|
||||||
|
+ clock->clockman = clockman;
|
||||||
|
+ clock->hw.init = &init;
|
||||||
|
+
|
||||||
|
+ ret = devm_clk_hw_register(clockman->dev, &clock->hw);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ERR_PTR(ret);
|
||||||
|
+
|
||||||
|
+ return &clock->hw;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
struct rp1_clk_desc {
|
||||||
|
struct clk_hw *(*clk_register)(struct rp1_clockman *clockman,
|
||||||
|
const void *data);
|
||||||
|
@@ -1676,6 +1744,8 @@ struct rp1_clk_desc {
|
||||||
|
&(struct rp1_clock_data) \
|
||||||
|
{__VA_ARGS__})
|
||||||
|
|
||||||
|
+#define REGISTER_VARSRC(n) _REGISTER(&rp1_register_varsrc, &(const char *){n})
|
||||||
|
+
|
||||||
|
static const struct rp1_clk_desc clk_desc_array[] = {
|
||||||
|
[RP1_PLL_SYS_CORE] = REGISTER_PLL_CORE(
|
||||||
|
.name = "pll_sys_core",
|
||||||
|
@@ -2318,6 +2388,9 @@ static const struct rp1_clk_desc clk_des
|
||||||
|
.max_freq = 200 * MHz,
|
||||||
|
.fc0_src = FC_NUM(3, 6),
|
||||||
|
),
|
||||||
|
+
|
||||||
|
+ [RP1_CLK_MIPI0_DSI_BYTECLOCK] = REGISTER_VARSRC("clksrc_mipi0_dsi_byteclk"),
|
||||||
|
+ [RP1_CLK_MIPI1_DSI_BYTECLOCK] = REGISTER_VARSRC("clksrc_mipi1_dsi_byteclk"),
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool rp1_clk_claimed[ARRAY_SIZE(clk_desc_array)];
|
@ -0,0 +1,92 @@
|
|||||||
|
From 9a108c82b6f6526e0aa8a19befa1ed3f31f8fe52 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Nick Hollinghurst <nick.hollinghurst@raspberrypi.com>
|
||||||
|
Date: Fri, 10 May 2024 15:42:29 +0100
|
||||||
|
Subject: [PATCH 1178/1215] dts: rp1: DSI drivers to use newly defined MIPI
|
||||||
|
byte source clocks.
|
||||||
|
|
||||||
|
Remove the "dummy" 72MHz fixed clock sources and associate DSI driver
|
||||||
|
with the new "variable" clock sources now defined in RP1 clocks.
|
||||||
|
|
||||||
|
Also add PLLSYS clock to DSI, which it will need as an alternative
|
||||||
|
clock source in those cases where DPI pixclock > DSI byteclock.
|
||||||
|
|
||||||
|
Signed-off-by: Nick Hollinghurst <nick.hollinghurst@raspberrypi.com>
|
||||||
|
---
|
||||||
|
arch/arm/boot/dts/broadcom/rp1.dtsi | 50 +++++++++--------------------
|
||||||
|
1 file changed, 15 insertions(+), 35 deletions(-)
|
||||||
|
|
||||||
|
--- a/arch/arm/boot/dts/broadcom/rp1.dtsi
|
||||||
|
+++ b/arch/arm/boot/dts/broadcom/rp1.dtsi
|
||||||
|
@@ -1109,16 +1109,15 @@
|
||||||
|
|
||||||
|
interrupts = <RP1_INT_MIPI0 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
|
||||||
|
- clocks = <&rp1_clocks RP1_CLK_MIPI0_CFG>, // required, config bus clock
|
||||||
|
- <&rp1_clocks RP1_CLK_MIPI0_DPI>, // required, pixel clock
|
||||||
|
- <&clksrc_mipi0_dsi_byteclk>, // internal, parent for divide
|
||||||
|
- <&clk_xosc>; // hardwired to DSI "refclk"
|
||||||
|
- clock-names = "cfgclk", "dpiclk", "byteclk", "refclk";
|
||||||
|
+ clocks = <&rp1_clocks RP1_CLK_MIPI0_CFG>,
|
||||||
|
+ <&rp1_clocks RP1_CLK_MIPI0_DPI>,
|
||||||
|
+ <&rp1_clocks RP1_CLK_MIPI0_DSI_BYTECLOCK>,
|
||||||
|
+ <&clk_xosc>, // hardwired to DSI "refclk"
|
||||||
|
+ <&rp1_clocks RP1_PLL_SYS>; // alternate parent for divide
|
||||||
|
+ clock-names = "cfgclk", "dpiclk", "byteclk", "refclk", "pllsys";
|
||||||
|
|
||||||
|
- assigned-clocks = <&rp1_clocks RP1_CLK_MIPI0_CFG>,
|
||||||
|
- <&rp1_clocks RP1_CLK_MIPI0_DPI>;
|
||||||
|
+ assigned-clocks = <&rp1_clocks RP1_CLK_MIPI0_CFG>;
|
||||||
|
assigned-clock-rates = <25000000>;
|
||||||
|
- assigned-clock-parents = <0>, <&clksrc_mipi0_dsi_byteclk>;
|
||||||
|
};
|
||||||
|
|
||||||
|
rp1_dsi1: dsi@128000 {
|
||||||
|
@@ -1130,16 +1129,15 @@
|
||||||
|
|
||||||
|
interrupts = <RP1_INT_MIPI1 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
|
||||||
|
- clocks = <&rp1_clocks RP1_CLK_MIPI1_CFG>, // required, config bus clock
|
||||||
|
- <&rp1_clocks RP1_CLK_MIPI1_DPI>, // required, pixel clock
|
||||||
|
- <&clksrc_mipi1_dsi_byteclk>, // internal, parent for divide
|
||||||
|
- <&clk_xosc>; // hardwired to DSI "refclk"
|
||||||
|
- clock-names = "cfgclk", "dpiclk", "byteclk", "refclk";
|
||||||
|
+ clocks = <&rp1_clocks RP1_CLK_MIPI1_CFG>,
|
||||||
|
+ <&rp1_clocks RP1_CLK_MIPI1_DPI>,
|
||||||
|
+ <&rp1_clocks RP1_CLK_MIPI1_DSI_BYTECLOCK>,
|
||||||
|
+ <&clk_xosc>, // hardwired to DSI "refclk"
|
||||||
|
+ <&rp1_clocks RP1_PLL_SYS>; // alternate parent for divide
|
||||||
|
+ clock-names = "cfgclk", "dpiclk", "byteclk", "refclk", "pllsys";
|
||||||
|
|
||||||
|
- assigned-clocks = <&rp1_clocks RP1_CLK_MIPI1_CFG>,
|
||||||
|
- <&rp1_clocks RP1_CLK_MIPI1_DPI>;
|
||||||
|
+ assigned-clocks = <&rp1_clocks RP1_CLK_MIPI1_CFG>;
|
||||||
|
assigned-clock-rates = <25000000>;
|
||||||
|
- assigned-clock-parents = <0>, <&clksrc_mipi1_dsi_byteclk>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* VEC and DPI both need to control PLL_VIDEO and cannot work together; */
|
||||||
|
@@ -1216,24 +1214,6 @@
|
||||||
|
clock-output-names = "core";
|
||||||
|
clock-frequency = <50000000>;
|
||||||
|
};
|
||||||
|
- clksrc_mipi0_dsi_byteclk: clksrc_mipi0_dsi_byteclk {
|
||||||
|
- // This clock is synthesized by MIPI0 D-PHY, when DSI is running.
|
||||||
|
- // Its frequency is not known a priori (until a panel driver attaches)
|
||||||
|
- // so assign a made-up frequency of 72MHz so it can be divided for DPI.
|
||||||
|
- compatible = "fixed-clock";
|
||||||
|
- #clock-cells = <0>;
|
||||||
|
- clock-output-names = "clksrc_mipi0_dsi_byteclk";
|
||||||
|
- clock-frequency = <72000000>;
|
||||||
|
- };
|
||||||
|
- clksrc_mipi1_dsi_byteclk: clksrc_mipi1_dsi_byteclk {
|
||||||
|
- // This clock is synthesized by MIPI1 D-PHY, when DSI is running.
|
||||||
|
- // Its frequency is not known a priori (until a panel driver attaches)
|
||||||
|
- // so assign a made-up frequency of 72MHz so it can be divided for DPI.
|
||||||
|
- compatible = "fixed-clock";
|
||||||
|
- #clock-cells = <0>;
|
||||||
|
- clock-output-names = "clksrc_mipi1_dsi_byteclk";
|
||||||
|
- clock-frequency = <72000000>;
|
||||||
|
- };
|
||||||
|
/* GPIO derived clock sources. Each GPIO with a GPCLK function
|
||||||
|
* can drive its output from the respective GPCLK
|
||||||
|
* generator, and provide a clock source to other internal
|
@ -0,0 +1,313 @@
|
|||||||
|
From f5de8d46da4b40f2180be502c1e547fe8c9b2ac2 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Nick Hollinghurst <nick.hollinghurst@raspberrypi.com>
|
||||||
|
Date: Fri, 10 May 2024 15:48:15 +0100
|
||||||
|
Subject: [PATCH 1179/1215] drm: rp1: rp1-dsi: Switch to PLL_SYS source for DPI
|
||||||
|
when 8 * lanes > bpp
|
||||||
|
|
||||||
|
To support 4 lanes, re-parent DPI clock source between DSI byteclock
|
||||||
|
(using the new "variable sources" defined in clk-rp1) and PLL_SYS.
|
||||||
|
This is to cover cases in which byteclock < pixclock <= 200MHz.
|
||||||
|
|
||||||
|
Tidying: All frequencies now in Hz (not kHz), where DSI speed is now
|
||||||
|
represented by byteclock to simplify arithmetic. Clamp DPI and byte
|
||||||
|
clocks to their legal ranges; fix up HSTX timeout to avoid an unsafe
|
||||||
|
assumption that it would return to LP state for every scanline.
|
||||||
|
|
||||||
|
Because of RP1's clock topology, the ratio between DSI and DPI clocks
|
||||||
|
may not be exact with 3 or 4 lanes, leading to slightly irregular
|
||||||
|
timings each time DSI switches between HS and LP states. Tweak to
|
||||||
|
inhibit LP during Horizontal BP when sync pulses were requested.
|
||||||
|
|
||||||
|
Signed-off-by: Nick Hollinghurst <nick.hollinghurst@raspberrypi.com>
|
||||||
|
---
|
||||||
|
drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi.c | 3 +-
|
||||||
|
drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi.h | 3 +-
|
||||||
|
drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi_dsi.c | 130 +++++++++++++---------
|
||||||
|
3 files changed, 80 insertions(+), 56 deletions(-)
|
||||||
|
|
||||||
|
--- a/drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi.c
|
||||||
|
+++ b/drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi.c
|
||||||
|
@@ -54,6 +54,7 @@ static void rp1_dsi_bridge_pre_enable(st
|
||||||
|
struct rp1_dsi *dsi = bridge_to_rp1_dsi(bridge);
|
||||||
|
|
||||||
|
rp1dsi_dsi_setup(dsi, &dsi->pipe.crtc.state->adjusted_mode);
|
||||||
|
+ dsi->dsi_running = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rp1_dsi_bridge_enable(struct drm_bridge *bridge,
|
||||||
|
@@ -443,7 +444,7 @@ static int rp1dsi_platform_probe(struct
|
||||||
|
/* Hardware resources */
|
||||||
|
for (i = 0; i < RP1DSI_NUM_CLOCKS; i++) {
|
||||||
|
static const char * const myclocknames[RP1DSI_NUM_CLOCKS] = {
|
||||||
|
- "cfgclk", "dpiclk", "byteclk", "refclk"
|
||||||
|
+ "cfgclk", "dpiclk", "byteclk", "refclk", "pllsys"
|
||||||
|
};
|
||||||
|
dsi->clocks[i] = devm_clk_get(dev, myclocknames[i]);
|
||||||
|
if (IS_ERR(dsi->clocks[i])) {
|
||||||
|
--- a/drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi.h
|
||||||
|
+++ b/drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi.h
|
||||||
|
@@ -30,7 +30,8 @@
|
||||||
|
#define RP1DSI_CLOCK_DPI 1
|
||||||
|
#define RP1DSI_CLOCK_BYTE 2
|
||||||
|
#define RP1DSI_CLOCK_REF 3
|
||||||
|
-#define RP1DSI_NUM_CLOCKS 4
|
||||||
|
+#define RP1DSI_CLOCK_PLLSYS 4
|
||||||
|
+#define RP1DSI_NUM_CLOCKS 5
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
--- a/drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi_dsi.c
|
||||||
|
+++ b/drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi_dsi.c
|
||||||
|
@@ -7,6 +7,7 @@
|
||||||
|
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
+#include <linux/math64.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/rp1_platform.h>
|
||||||
|
#include "drm/drm_print.h"
|
||||||
|
@@ -1111,7 +1112,7 @@ static void dphy_transaction(struct rp1_
|
||||||
|
DSI_WRITE(DSI_PHY_TST_CTRL0, DPHY_CTRL0_PHY_TESTCLK_BITS);
|
||||||
|
}
|
||||||
|
|
||||||
|
-static uint8_t dphy_get_div(u32 refclk_khz, u32 vco_freq_khz, u32 *ptr_m, u32 *ptr_n)
|
||||||
|
+static u64 dphy_get_div(u32 refclk, u64 vco_freq, u32 *ptr_m, u32 *ptr_n)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* See pg 77-78 of dphy databook
|
||||||
|
@@ -1124,19 +1125,23 @@ static uint8_t dphy_get_div(u32 refclk_k
|
||||||
|
* In practice, given a 50MHz reference clock, it can produce any
|
||||||
|
* multiple of 10MHz, 11.1111MHz, 12.5MHz, 14.286MHz or 16.667MHz
|
||||||
|
* with < 1% error for all frequencies above 495MHz.
|
||||||
|
+ *
|
||||||
|
+ * vco_freq should be set to the lane bit rate (not the MIPI clock
|
||||||
|
+ * which is half of this). These frequencies are now measured in Hz.
|
||||||
|
+ * They should fit within u32, but u64 is needed for calculations.
|
||||||
|
*/
|
||||||
|
|
||||||
|
- static const u32 REF_DIVN_MAX = 40000u;
|
||||||
|
- static const u32 REF_DIVN_MIN = 5000u;
|
||||||
|
- u32 best_n, best_m, best_err = 0x7fffffff;
|
||||||
|
- unsigned int n;
|
||||||
|
+ static const u32 REF_DIVN_MAX = 40000000;
|
||||||
|
+ static const u32 REF_DIVN_MIN = 5000000;
|
||||||
|
+ u32 n, best_n, best_m;
|
||||||
|
+ u64 best_err = vco_freq;
|
||||||
|
|
||||||
|
- for (n = 1 + refclk_khz / REF_DIVN_MAX; n * REF_DIVN_MIN <= refclk_khz && n < 100; ++n) {
|
||||||
|
- u32 half_m = (n * vco_freq_khz + refclk_khz) / (2 * refclk_khz);
|
||||||
|
+ for (n = 1 + refclk / REF_DIVN_MAX; n * REF_DIVN_MIN <= refclk && n < 100; ++n) {
|
||||||
|
+ u32 half_m = DIV_U64_ROUND_CLOSEST(n * vco_freq, 2 * refclk);
|
||||||
|
|
||||||
|
if (half_m < 150) {
|
||||||
|
- u32 f = (2 * half_m * refclk_khz) / n;
|
||||||
|
- u32 err = (f > vco_freq_khz) ? f - vco_freq_khz : vco_freq_khz - f;
|
||||||
|
+ u64 f = div_u64(mul_u32_u32(2 * half_m, refclk), n);
|
||||||
|
+ u64 err = (f > vco_freq) ? f - vco_freq : vco_freq - f;
|
||||||
|
|
||||||
|
if (err < best_err) {
|
||||||
|
best_n = n;
|
||||||
|
@@ -1148,12 +1153,12 @@ static uint8_t dphy_get_div(u32 refclk_k
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (64 * best_err < vco_freq_khz) { /* tolerate small error */
|
||||||
|
- *ptr_n = best_n;
|
||||||
|
- *ptr_m = best_m;
|
||||||
|
- return 1;
|
||||||
|
- }
|
||||||
|
- return 0;
|
||||||
|
+ if (64 * best_err >= vco_freq)
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ *ptr_n = best_n;
|
||||||
|
+ *ptr_m = best_m;
|
||||||
|
+ return div_u64(mul_u32_u32(best_m, refclk), best_n);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct hsfreq_range {
|
||||||
|
@@ -1226,13 +1231,14 @@ static void dphy_set_hsfreqrange(struct
|
||||||
|
hsfreq_table[i].hsfreqrange << 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void dphy_configure_pll(struct rp1_dsi *dsi, u32 refclk_khz, u32 vco_freq_khz)
|
||||||
|
+static u32 dphy_configure_pll(struct rp1_dsi *dsi, u32 refclk, u32 vco_freq)
|
||||||
|
{
|
||||||
|
u32 m = 0;
|
||||||
|
u32 n = 0;
|
||||||
|
+ u32 actual_vco_freq = dphy_get_div(refclk, vco_freq, &m, &n);
|
||||||
|
|
||||||
|
- if (dphy_get_div(refclk_khz, vco_freq_khz, &m, &n)) {
|
||||||
|
- dphy_set_hsfreqrange(dsi, vco_freq_khz / 1000);
|
||||||
|
+ if (actual_vco_freq) {
|
||||||
|
+ dphy_set_hsfreqrange(dsi, actual_vco_freq / 1000000);
|
||||||
|
/* Program m,n from registers */
|
||||||
|
dphy_transaction(dsi, DPHY_PLL_DIV_CTRL_OFFSET, 0x30);
|
||||||
|
/* N (program N-1) */
|
||||||
|
@@ -1242,18 +1248,21 @@ static void dphy_configure_pll(struct rp
|
||||||
|
/* M[4:0] (program M-1) */
|
||||||
|
dphy_transaction(dsi, DPHY_PLL_LOOP_DIV_OFFSET, ((m - 1) & 0x1F));
|
||||||
|
drm_dbg_driver(dsi->drm,
|
||||||
|
- "DPHY: vco freq want %dkHz got %dkHz = %d * (%dkHz / %d), hsfreqrange = 0x%02x\r\n",
|
||||||
|
- vco_freq_khz, refclk_khz * m / n, m, refclk_khz,
|
||||||
|
- n, hsfreq_table[dsi->hsfreq_index].hsfreqrange);
|
||||||
|
+ "DPHY: vco freq want %uHz got %uHz = %d * (%uHz / %d), hsfreqrange = 0x%02x\n",
|
||||||
|
+ vco_freq, actual_vco_freq, m, refclk, n,
|
||||||
|
+ hsfreq_table[dsi->hsfreq_index].hsfreqrange);
|
||||||
|
} else {
|
||||||
|
- drm_info(dsi->drm,
|
||||||
|
- "rp1dsi: Error configuring DPHY PLL! %dkHz = %d * (%dkHz / %d)\r\n",
|
||||||
|
- vco_freq_khz, m, refclk_khz, n);
|
||||||
|
+ drm_warn(dsi->drm,
|
||||||
|
+ "rp1dsi: Error configuring DPHY PLL %uHz\n", vco_freq);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ return actual_vco_freq;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void dphy_init_khz(struct rp1_dsi *dsi, u32 ref_freq, u32 vco_freq)
|
||||||
|
+static u32 dphy_init(struct rp1_dsi *dsi, u32 ref_freq, u32 vco_freq)
|
||||||
|
{
|
||||||
|
+ u32 actual_vco_freq;
|
||||||
|
+
|
||||||
|
/* Reset the PHY */
|
||||||
|
DSI_WRITE(DSI_PHYRSTZ, 0);
|
||||||
|
DSI_WRITE(DSI_PHY_TST_CTRL0, DPHY_CTRL0_PHY_TESTCLK_BITS);
|
||||||
|
@@ -1263,13 +1272,15 @@ static void dphy_init_khz(struct rp1_dsi
|
||||||
|
DSI_WRITE(DSI_PHY_TST_CTRL0, DPHY_CTRL0_PHY_TESTCLK_BITS);
|
||||||
|
udelay(1);
|
||||||
|
/* Since we are in DSI (not CSI2) mode here, start the PLL */
|
||||||
|
- dphy_configure_pll(dsi, ref_freq, vco_freq);
|
||||||
|
+ actual_vco_freq = dphy_configure_pll(dsi, ref_freq, vco_freq);
|
||||||
|
udelay(1);
|
||||||
|
/* Unreset */
|
||||||
|
DSI_WRITE(DSI_PHYRSTZ, DSI_PHYRSTZ_SHUTDOWNZ_BITS);
|
||||||
|
udelay(1);
|
||||||
|
DSI_WRITE(DSI_PHYRSTZ, (DSI_PHYRSTZ_SHUTDOWNZ_BITS | DSI_PHYRSTZ_RSTZ_BITS));
|
||||||
|
udelay(1); /* so we can see PLL coming up? */
|
||||||
|
+
|
||||||
|
+ return actual_vco_freq;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rp1dsi_mipicfg_setup(struct rp1_dsi *dsi)
|
||||||
|
@@ -1290,23 +1301,30 @@ static unsigned long rp1dsi_refclk_freq(
|
||||||
|
return u;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void rp1dsi_dpiclk_start(struct rp1_dsi *dsi, unsigned int bpp, unsigned int lanes)
|
||||||
|
+static void rp1dsi_dpiclk_start(struct rp1_dsi *dsi, u32 byte_clock,
|
||||||
|
+ unsigned int bpp, unsigned int lanes)
|
||||||
|
{
|
||||||
|
- unsigned long u;
|
||||||
|
-
|
||||||
|
- if (dsi->clocks[RP1DSI_CLOCK_DPI]) {
|
||||||
|
- u = (dsi->clocks[RP1DSI_CLOCK_BYTE]) ?
|
||||||
|
- clk_get_rate(dsi->clocks[RP1DSI_CLOCK_BYTE]) : 0;
|
||||||
|
- drm_info(dsi->drm,
|
||||||
|
- "rp1dsi: Nominal byte clock %lu; scale by %u/%u",
|
||||||
|
- u, 4 * lanes, (bpp >> 1));
|
||||||
|
- if (u < 1 || u >= (1ul << 28))
|
||||||
|
- u = 72000000ul; /* default DUMMY frequency for byteclock */
|
||||||
|
+ /* Dummy clk_set_rate() to declare the actual DSI byte-clock rate */
|
||||||
|
+ clk_set_rate(dsi->clocks[RP1DSI_CLOCK_BYTE], byte_clock);
|
||||||
|
|
||||||
|
+ /*
|
||||||
|
+ * Prefer the DSI byte-clock source where possible, so that DSI and DPI
|
||||||
|
+ * clocks will be in an exact ratio and downstream devices can recover
|
||||||
|
+ * perfect timings. But when DPI clock is faster, fall back on PLL_SYS.
|
||||||
|
+ * To defeat rounding errors, specify explicitly which source to use.
|
||||||
|
+ */
|
||||||
|
+ if (bpp >= 8 * lanes)
|
||||||
|
clk_set_parent(dsi->clocks[RP1DSI_CLOCK_DPI], dsi->clocks[RP1DSI_CLOCK_BYTE]);
|
||||||
|
- clk_set_rate(dsi->clocks[RP1DSI_CLOCK_DPI], (4 * lanes * u) / (bpp >> 1));
|
||||||
|
- clk_prepare_enable(dsi->clocks[RP1DSI_CLOCK_DPI]);
|
||||||
|
- }
|
||||||
|
+ else if (dsi->clocks[RP1DSI_CLOCK_PLLSYS])
|
||||||
|
+ clk_set_parent(dsi->clocks[RP1DSI_CLOCK_DPI], dsi->clocks[RP1DSI_CLOCK_PLLSYS]);
|
||||||
|
+
|
||||||
|
+ clk_set_rate(dsi->clocks[RP1DSI_CLOCK_DPI], (4 * lanes * byte_clock) / (bpp >> 1));
|
||||||
|
+ clk_prepare_enable(dsi->clocks[RP1DSI_CLOCK_DPI]);
|
||||||
|
+ drm_info(dsi->drm,
|
||||||
|
+ "rp1dsi: Nominal Byte clock %u DPI clock %lu (parent rate %lu)",
|
||||||
|
+ byte_clock,
|
||||||
|
+ clk_get_rate(dsi->clocks[RP1DSI_CLOCK_DPI]),
|
||||||
|
+ clk_get_rate(clk_get_parent(dsi->clocks[RP1DSI_CLOCK_DPI])));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rp1dsi_dpiclk_stop(struct rp1_dsi *dsi)
|
||||||
|
@@ -1336,18 +1354,21 @@ static u32 get_colorcode(enum mipi_dsi_p
|
||||||
|
return 0x005;
|
||||||
|
}
|
||||||
|
|
||||||
|
-/* Maximum frequency for LP escape clock (20MHz), and some magic numbers */
|
||||||
|
-#define RP1DSI_ESC_CLK_KHZ 20000
|
||||||
|
-#define RP1DSI_TO_CLK_DIV 5
|
||||||
|
-#define RP1DSI_HSTX_TO_MIN 0x200
|
||||||
|
-#define RP1DSI_LPRX_TO_VAL 0x400
|
||||||
|
+/* Frequency limits for DPI, HS and LP clocks, and some magic numbers */
|
||||||
|
+#define RP1DSI_DPI_MAX_KHZ 200000
|
||||||
|
+#define RP1DSI_BYTE_CLK_MIN 10000000
|
||||||
|
+#define RP1DSI_BYTE_CLK_MAX 187500000
|
||||||
|
+#define RP1DSI_ESC_CLK_MAX 20000000
|
||||||
|
+#define RP1DSI_TO_CLK_DIV 0x50
|
||||||
|
+#define RP1DSI_LPRX_TO_VAL 0x40
|
||||||
|
#define RP1DSI_BTA_TO_VAL 0xd00
|
||||||
|
|
||||||
|
void rp1dsi_dsi_setup(struct rp1_dsi *dsi, struct drm_display_mode const *mode)
|
||||||
|
{
|
||||||
|
u32 timeout, mask, vid_mode_cfg;
|
||||||
|
- int lane_kbps;
|
||||||
|
unsigned int bpp = mipi_dsi_pixel_format_to_bpp(dsi->display_format);
|
||||||
|
+ u32 byte_clock = clamp((bpp * 125 * min(mode->clock, RP1DSI_DPI_MAX_KHZ)) / dsi->lanes,
|
||||||
|
+ RP1DSI_BYTE_CLK_MIN, RP1DSI_BYTE_CLK_MAX);
|
||||||
|
|
||||||
|
DSI_WRITE(DSI_PHY_IF_CFG, dsi->lanes - 1);
|
||||||
|
DSI_WRITE(DSI_DPI_CFG_POL, 0);
|
||||||
|
@@ -1360,6 +1381,8 @@ void rp1dsi_dsi_setup(struct rp1_dsi *ds
|
||||||
|
vid_mode_cfg = 0xbf00;
|
||||||
|
if (!(dsi->display_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE))
|
||||||
|
vid_mode_cfg |= 0x01;
|
||||||
|
+ else if (8 * dsi->lanes > bpp)
|
||||||
|
+ vid_mode_cfg &= ~0x400; /* PULSE && inexact DPICLK => fix HBP time */
|
||||||
|
if (dsi->display_flags & MIPI_DSI_MODE_VIDEO_BURST)
|
||||||
|
vid_mode_cfg |= 0x02;
|
||||||
|
DSI_WRITE(DSI_VID_MODE_CFG, vid_mode_cfg);
|
||||||
|
@@ -1369,15 +1392,14 @@ void rp1dsi_dsi_setup(struct rp1_dsi *ds
|
||||||
|
DSI_WRITE(DSI_MODE_CFG, 1);
|
||||||
|
|
||||||
|
/* Set timeouts and clock dividers */
|
||||||
|
- DSI_WRITE(DSI_TO_CNT_CFG,
|
||||||
|
- (max((bpp * mode->htotal) / (7 * RP1DSI_TO_CLK_DIV * dsi->lanes),
|
||||||
|
- RP1DSI_HSTX_TO_MIN) << 16) |
|
||||||
|
- RP1DSI_LPRX_TO_VAL);
|
||||||
|
+ timeout = (bpp * mode->htotal * mode->vdisplay) / (7 * RP1DSI_TO_CLK_DIV * dsi->lanes);
|
||||||
|
+ if (timeout > 0xFFFFu)
|
||||||
|
+ timeout = 0;
|
||||||
|
+ DSI_WRITE(DSI_TO_CNT_CFG, (timeout << 16) | RP1DSI_LPRX_TO_VAL);
|
||||||
|
DSI_WRITE(DSI_BTA_TO_CNT, RP1DSI_BTA_TO_VAL);
|
||||||
|
- lane_kbps = (bpp * mode->clock) / dsi->lanes;
|
||||||
|
DSI_WRITE(DSI_CLKMGR_CFG,
|
||||||
|
(RP1DSI_TO_CLK_DIV << 8) |
|
||||||
|
- max(2, lane_kbps / (8 * RP1DSI_ESC_CLK_KHZ) + 1));
|
||||||
|
+ max(2u, 1u + byte_clock / RP1DSI_ESC_CLK_MAX));
|
||||||
|
|
||||||
|
/* Configure video timings */
|
||||||
|
DSI_WRITE(DSI_VID_PKT_SIZE, mode->hdisplay);
|
||||||
|
@@ -1394,7 +1416,7 @@ void rp1dsi_dsi_setup(struct rp1_dsi *ds
|
||||||
|
DSI_WRITE(DSI_VID_VACTIVE_LINES, mode->vdisplay);
|
||||||
|
|
||||||
|
/* Init PHY */
|
||||||
|
- dphy_init_khz(dsi, rp1dsi_refclk_freq(dsi) / 1000, lane_kbps);
|
||||||
|
+ byte_clock = dphy_init(dsi, rp1dsi_refclk_freq(dsi), 8 * byte_clock) >> 3;
|
||||||
|
|
||||||
|
DSI_WRITE(DSI_PHY_TMR_LPCLK_CFG,
|
||||||
|
(hsfreq_table[dsi->hsfreq_index].clk_lp2hs << DSI_PHY_TMR_LP2HS_LSB) |
|
||||||
|
@@ -1418,7 +1440,7 @@ void rp1dsi_dsi_setup(struct rp1_dsi *ds
|
||||||
|
DSI_WRITE(DSI_PWR_UP, 0x1); /* power up */
|
||||||
|
|
||||||
|
/* Now it should be safe to start the external DPI clock divider */
|
||||||
|
- rp1dsi_dpiclk_start(dsi, bpp, dsi->lanes);
|
||||||
|
+ rp1dsi_dpiclk_start(dsi, byte_clock, bpp, dsi->lanes);
|
||||||
|
|
||||||
|
/* Wait for all lane(s) to be in Stopstate */
|
||||||
|
mask = (1 << 4);
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,92 @@
|
|||||||
|
From 4de4f56af7d803fa7dd9ffe42d4719b428d73e6c Mon Sep 17 00:00:00 2001
|
||||||
|
From: Phil Elwell <phil@raspberrypi.com>
|
||||||
|
Date: Wed, 17 Jul 2024 17:31:58 +0100
|
||||||
|
Subject: [PATCH 1181/1215] arm64: dts: Add cm5l files
|
||||||
|
|
||||||
|
CM5 Lite DTBs require minor changes compared to the "heavy" variants.
|
||||||
|
|
||||||
|
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||||
|
---
|
||||||
|
arch/arm64/boot/dts/broadcom/Makefile | 2 ++
|
||||||
|
.../dts/broadcom/bcm2712-rpi-cm5l-cm4io.dts | 20 ++++++++++++++++
|
||||||
|
.../dts/broadcom/bcm2712-rpi-cm5l-cm5io.dts | 10 ++++++++
|
||||||
|
.../boot/dts/broadcom/bcm2712-rpi-cm5l.dtsi | 24 +++++++++++++++++++
|
||||||
|
4 files changed, 56 insertions(+)
|
||||||
|
create mode 100644 arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5l-cm4io.dts
|
||||||
|
create mode 100644 arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5l-cm5io.dts
|
||||||
|
create mode 100644 arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5l.dtsi
|
||||||
|
|
||||||
|
--- a/arch/arm64/boot/dts/broadcom/Makefile
|
||||||
|
+++ b/arch/arm64/boot/dts/broadcom/Makefile
|
||||||
|
@@ -24,6 +24,8 @@ dtb-$(CONFIG_ARCH_BCM2835) += bcm2712-rp
|
||||||
|
dtb-$(CONFIG_ARCH_BCM2835) += bcm2712d0-rpi-5-b.dtb
|
||||||
|
dtb-$(CONFIG_ARCH_BCM2835) += bcm2712-rpi-cm5-cm5io.dtb
|
||||||
|
dtb-$(CONFIG_ARCH_BCM2835) += bcm2712-rpi-cm5-cm4io.dtb
|
||||||
|
+dtb-$(CONFIG_ARCH_BCM2835) += bcm2712-rpi-cm5l-cm5io.dtb
|
||||||
|
+dtb-$(CONFIG_ARCH_BCM2835) += bcm2712-rpi-cm5l-cm4io.dtb
|
||||||
|
|
||||||
|
subdir-y += bcmbca
|
||||||
|
subdir-y += northstar2
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5l-cm4io.dts
|
||||||
|
@@ -0,0 +1,20 @@
|
||||||
|
+// SPDX-License-Identifier: GPL-2.0
|
||||||
|
+/dts-v1/;
|
||||||
|
+
|
||||||
|
+#include "bcm2712-rpi-cm5l.dtsi"
|
||||||
|
+
|
||||||
|
+// The RP1 USB3 interfaces are not usable on CM4IO
|
||||||
|
+
|
||||||
|
+&rp1_usb0 {
|
||||||
|
+ status = "disabled";
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+&rp1_usb1 {
|
||||||
|
+ status = "disabled";
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/ {
|
||||||
|
+ __overrides__ {
|
||||||
|
+ i2c_csi_dsi = <&i2c_csi_dsi>, "status";
|
||||||
|
+ };
|
||||||
|
+};
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5l-cm5io.dts
|
||||||
|
@@ -0,0 +1,10 @@
|
||||||
|
+// SPDX-License-Identifier: GPL-2.0
|
||||||
|
+/dts-v1/;
|
||||||
|
+
|
||||||
|
+#include "bcm2712-rpi-cm5l.dtsi"
|
||||||
|
+
|
||||||
|
+/ {
|
||||||
|
+ __overrides__ {
|
||||||
|
+ i2c_csi_dsi = <&i2c_csi_dsi>, "status";
|
||||||
|
+ };
|
||||||
|
+};
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5l.dtsi
|
||||||
|
@@ -0,0 +1,24 @@
|
||||||
|
+// SPDX-License-Identifier: GPL-2.0
|
||||||
|
+/dts-v1/;
|
||||||
|
+
|
||||||
|
+#include "bcm2712-rpi-cm5.dtsi"
|
||||||
|
+
|
||||||
|
+/ {
|
||||||
|
+ __overrides__ {
|
||||||
|
+ i2c_csi_dsi = <&i2c_csi_dsi>, "status";
|
||||||
|
+ };
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+&sd_io_1v8_reg {
|
||||||
|
+ compatible = "regulator-gpio";
|
||||||
|
+ regulator-max-microvolt = <3300000>;
|
||||||
|
+ regulator-settling-time-us = <5000>;
|
||||||
|
+ gpios = <&gio_aon 3 GPIO_ACTIVE_HIGH>;
|
||||||
|
+ states = <1800000 0x1
|
||||||
|
+ 3300000 0x0>;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+&sdio1 {
|
||||||
|
+ /delete-property/ mmc-hs400-1_8v;
|
||||||
|
+ /delete-property/ mmc-hs400-enhanced-strobe;
|
||||||
|
+};
|
@ -0,0 +1,408 @@
|
|||||||
|
From e1c56acf3355cd539447511fdc1b886e5eb5cca3 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Phil Elwell <phil@raspberrypi.com>
|
||||||
|
Date: Thu, 2 May 2024 16:57:31 +0100
|
||||||
|
Subject: [PATCH 1182/1215] dts: bcm2712: Dedup the aliases and overrides
|
||||||
|
|
||||||
|
Move the aliases and overrrides shared by Pi 5 and CM5 into
|
||||||
|
bcm2712-rpi.dtsi.
|
||||||
|
|
||||||
|
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||||
|
---
|
||||||
|
.../boot/dts/broadcom/bcm2712-rpi-5-b.dts | 115 -----------------
|
||||||
|
.../boot/dts/broadcom/bcm2712-rpi-cm5.dtsi | 114 -----------------
|
||||||
|
arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi | 117 +++++++++++++++++-
|
||||||
|
3 files changed, 113 insertions(+), 233 deletions(-)
|
||||||
|
|
||||||
|
--- a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts
|
||||||
|
+++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts
|
||||||
|
@@ -746,122 +746,7 @@ spi10_cs_pins: &spi10_cs_gpio1 {};
|
||||||
|
};
|
||||||
|
|
||||||
|
/ {
|
||||||
|
- aliases: aliases {
|
||||||
|
- blconfig = &blconfig;
|
||||||
|
- blpubkey = &blpubkey;
|
||||||
|
- bluetooth = &bluetooth;
|
||||||
|
- console = &uart10;
|
||||||
|
- ethernet0 = &rp1_eth;
|
||||||
|
- wifi0 = &wifi;
|
||||||
|
- fb = &fb;
|
||||||
|
- mailbox = &mailbox;
|
||||||
|
- mmc0 = &sdio1;
|
||||||
|
- uart0 = &uart0;
|
||||||
|
- uart1 = &uart1;
|
||||||
|
- uart2 = &uart2;
|
||||||
|
- uart3 = &uart3;
|
||||||
|
- uart4 = &uart4;
|
||||||
|
- uart10 = &uart10;
|
||||||
|
- serial0 = &uart0;
|
||||||
|
- serial1 = &uart1;
|
||||||
|
- serial2 = &uart2;
|
||||||
|
- serial3 = &uart3;
|
||||||
|
- serial4 = &uart4;
|
||||||
|
- serial10 = &uart10;
|
||||||
|
- i2c = &i2c_arm;
|
||||||
|
- i2c0 = &i2c0;
|
||||||
|
- i2c1 = &i2c1;
|
||||||
|
- i2c2 = &i2c2;
|
||||||
|
- i2c3 = &i2c3;
|
||||||
|
- i2c4 = &i2c4;
|
||||||
|
- i2c5 = &i2c5;
|
||||||
|
- i2c6 = &i2c6;
|
||||||
|
- i2c10 = &i2c_rp1boot;
|
||||||
|
- // Bit-bashed i2c_gpios start at 10
|
||||||
|
- spi0 = &spi0;
|
||||||
|
- spi1 = &spi1;
|
||||||
|
- spi2 = &spi2;
|
||||||
|
- spi3 = &spi3;
|
||||||
|
- spi4 = &spi4;
|
||||||
|
- spi5 = &spi5;
|
||||||
|
- spi10 = &spi10;
|
||||||
|
- gpio0 = &gpio;
|
||||||
|
- gpio1 = &gio;
|
||||||
|
- gpio2 = &gio_aon;
|
||||||
|
- gpio3 = &pinctrl;
|
||||||
|
- gpio4 = &pinctrl_aon;
|
||||||
|
- usb0 = &rp1_usb0;
|
||||||
|
- usb1 = &rp1_usb1;
|
||||||
|
- drm-dsi1 = &dsi0;
|
||||||
|
- drm-dsi2 = &dsi1;
|
||||||
|
- };
|
||||||
|
-
|
||||||
|
__overrides__ {
|
||||||
|
- bdaddr = <&bluetooth>, "local-bd-address[";
|
||||||
|
- button_debounce = <&pwr_key>, "debounce-interval:0";
|
||||||
|
- cooling_fan = <&fan>, "status", <&rp1_pwm1>, "status";
|
||||||
|
- uart0_console = <&uart0>,"status", <&aliases>, "console=",&uart0;
|
||||||
|
- i2c0 = <&i2c0>, "status";
|
||||||
|
- i2c1 = <&i2c1>, "status";
|
||||||
|
- i2c = <&i2c1>, "status";
|
||||||
|
- i2c_arm = <&i2c_arm>, "status";
|
||||||
|
- i2c_vc = <&i2c_vc>, "status";
|
||||||
|
- i2c_csi_dsi = <&i2c_csi_dsi>, "status";
|
||||||
|
- i2c_csi_dsi0 = <&i2c_csi_dsi0>, "status";
|
||||||
|
- i2c_csi_dsi1 = <&i2c_csi_dsi1>, "status";
|
||||||
|
- i2c0_baudrate = <&i2c0>, "clock-frequency:0";
|
||||||
|
- i2c1_baudrate = <&i2c1>, "clock-frequency:0";
|
||||||
|
- i2c_baudrate = <&i2c_arm>, "clock-frequency:0";
|
||||||
|
- i2c_arm_baudrate = <&i2c_arm>, "clock-frequency:0";
|
||||||
|
- i2c_vc_baudrate = <&i2c_vc>, "clock-frequency:0";
|
||||||
|
- krnbt = <&bluetooth>, "status";
|
||||||
|
- nvme = <&pciex1>, "status";
|
||||||
|
- pciex1 = <&pciex1>, "status";
|
||||||
|
- pciex1_gen = <&pciex1> , "max-link-speed:0";
|
||||||
|
- pciex1_no_l0s = <&pciex1>, "aspm-no-l0s?";
|
||||||
|
- pciex1_tperst_clk_ms = <&pciex1>, "brcm,tperst-clk-ms:0";
|
||||||
|
- pcie_tperst_clk_ms = <&pciex1>, "brcm,tperst-clk-ms:0";
|
||||||
|
- random = <&random>, "status";
|
||||||
|
- rtc = <&rpi_rtc>, "status";
|
||||||
|
- rtc_bbat_vchg = <&rpi_rtc>, "trickle-charge-microvolt:0";
|
||||||
|
sd_cqe = <&sdio1>, "supports-cqe?";
|
||||||
|
- spi = <&spi0>, "status";
|
||||||
|
- suspend = <&pwr_key>, "linux,code:0=205";
|
||||||
|
- uart0 = <&uart0>, "status";
|
||||||
|
- wifiaddr = <&wifi>, "local-mac-address[";
|
||||||
|
-
|
||||||
|
- act_led_gpio = <&led_act>,"gpios:4",<&led_act>,"gpios:0=",<&gpio>;
|
||||||
|
- act_led_activelow = <&led_act>,"gpios:8";
|
||||||
|
- act_led_trigger = <&led_act>, "linux,default-trigger";
|
||||||
|
- pwr_led_gpio = <&led_pwr>,"gpios:4";
|
||||||
|
- pwr_led_activelow = <&led_pwr>, "gpios:8";
|
||||||
|
- pwr_led_trigger = <&led_pwr>, "linux,default-trigger";
|
||||||
|
- eth_led0 = <&phy1>,"led-modes:0";
|
||||||
|
- eth_led1 = <&phy1>,"led-modes:4";
|
||||||
|
- drm_fb0_rp1_dsi0 = <&aliases>, "drm-fb0=",&dsi0;
|
||||||
|
- drm_fb0_rp1_dsi1 = <&aliases>, "drm-fb0=",&dsi1;
|
||||||
|
- drm_fb0_rp1_dpi = <&aliases>, "drm-fb0=",&dpi;
|
||||||
|
- drm_fb0_vc4 = <&aliases>, "drm-fb0=",&vc4;
|
||||||
|
- drm_fb1_rp1_dsi0 = <&aliases>, "drm-fb1=",&dsi0;
|
||||||
|
- drm_fb1_rp1_dsi1 = <&aliases>, "drm-fb1=",&dsi1;
|
||||||
|
- drm_fb1_rp1_dpi = <&aliases>, "drm-fb1=",&dpi;
|
||||||
|
- drm_fb1_vc4 = <&aliases>, "drm-fb1=",&vc4;
|
||||||
|
- drm_fb2_rp1_dsi0 = <&aliases>, "drm-fb2=",&dsi0;
|
||||||
|
- drm_fb2_rp1_dsi1 = <&aliases>, "drm-fb2=",&dsi1;
|
||||||
|
- drm_fb2_rp1_dpi = <&aliases>, "drm-fb2=",&dpi;
|
||||||
|
- drm_fb2_vc4 = <&aliases>, "drm-fb2=",&vc4;
|
||||||
|
-
|
||||||
|
- fan_temp0 = <&cpu_tepid>,"temperature:0";
|
||||||
|
- fan_temp1 = <&cpu_warm>,"temperature:0";
|
||||||
|
- fan_temp2 = <&cpu_hot>,"temperature:0";
|
||||||
|
- fan_temp3 = <&cpu_vhot>,"temperature:0";
|
||||||
|
- fan_temp0_hyst = <&cpu_tepid>,"hysteresis:0";
|
||||||
|
- fan_temp1_hyst = <&cpu_warm>,"hysteresis:0";
|
||||||
|
- fan_temp2_hyst = <&cpu_hot>,"hysteresis:0";
|
||||||
|
- fan_temp3_hyst = <&cpu_vhot>,"hysteresis:0";
|
||||||
|
- fan_temp0_speed = <&fan>, "cooling-levels:4";
|
||||||
|
- fan_temp1_speed = <&fan>, "cooling-levels:8";
|
||||||
|
- fan_temp2_speed = <&fan>, "cooling-levels:12";
|
||||||
|
- fan_temp3_speed = <&fan>, "cooling-levels:16";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
--- a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5.dtsi
|
||||||
|
+++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5.dtsi
|
||||||
|
@@ -753,108 +753,7 @@ spi10_cs_pins: &spi10_cs_gpio1 {};
|
||||||
|
};
|
||||||
|
|
||||||
|
/ {
|
||||||
|
- aliases: aliases {
|
||||||
|
- blconfig = &blconfig;
|
||||||
|
- blpubkey = &blpubkey;
|
||||||
|
- bluetooth = &bluetooth;
|
||||||
|
- console = &uart10;
|
||||||
|
- ethernet0 = &rp1_eth;
|
||||||
|
- wifi0 = &wifi;
|
||||||
|
- fb = &fb;
|
||||||
|
- mailbox = &mailbox;
|
||||||
|
- mmc0 = &sdio1;
|
||||||
|
- uart0 = &uart0;
|
||||||
|
- uart1 = &uart1;
|
||||||
|
- uart2 = &uart2;
|
||||||
|
- uart3 = &uart3;
|
||||||
|
- uart4 = &uart4;
|
||||||
|
- uart10 = &uart10;
|
||||||
|
- serial0 = &uart0;
|
||||||
|
- serial1 = &uart1;
|
||||||
|
- serial2 = &uart2;
|
||||||
|
- serial3 = &uart3;
|
||||||
|
- serial4 = &uart4;
|
||||||
|
- serial10 = &uart10;
|
||||||
|
- i2c = &i2c_arm;
|
||||||
|
- i2c0 = &i2c0;
|
||||||
|
- i2c1 = &i2c1;
|
||||||
|
- i2c2 = &i2c2;
|
||||||
|
- i2c3 = &i2c3;
|
||||||
|
- i2c4 = &i2c4;
|
||||||
|
- i2c5 = &i2c5;
|
||||||
|
- i2c6 = &i2c6;
|
||||||
|
- i2c10 = &i2c_rp1boot;
|
||||||
|
- // Bit-bashed i2c_gpios start at 10
|
||||||
|
- spi0 = &spi0;
|
||||||
|
- spi1 = &spi1;
|
||||||
|
- spi2 = &spi2;
|
||||||
|
- spi3 = &spi3;
|
||||||
|
- spi4 = &spi4;
|
||||||
|
- spi5 = &spi5;
|
||||||
|
- spi10 = &spi10;
|
||||||
|
- gpio0 = &gpio;
|
||||||
|
- gpio1 = &gio;
|
||||||
|
- gpio2 = &gio_aon;
|
||||||
|
- gpio3 = &pinctrl;
|
||||||
|
- gpio4 = &pinctrl_aon;
|
||||||
|
- usb0 = &rp1_usb0;
|
||||||
|
- usb1 = &rp1_usb1;
|
||||||
|
- drm-dsi1 = &dsi0;
|
||||||
|
- drm-dsi2 = &dsi1;
|
||||||
|
- };
|
||||||
|
-
|
||||||
|
__overrides__ {
|
||||||
|
- bdaddr = <&bluetooth>, "local-bd-address[";
|
||||||
|
- button_debounce = <&pwr_key>, "debounce-interval:0";
|
||||||
|
- cooling_fan = <&fan>, "status", <&rp1_pwm1>, "status";
|
||||||
|
- uart0_console = <&uart0>,"status", <&aliases>, "console=",&uart0;
|
||||||
|
- i2c0 = <&i2c0>, "status";
|
||||||
|
- i2c1 = <&i2c1>, "status";
|
||||||
|
- i2c = <&i2c1>, "status";
|
||||||
|
- i2c_arm = <&i2c_arm>, "status";
|
||||||
|
- i2c_vc = <&i2c_vc>, "status";
|
||||||
|
- i2c_csi_dsi = <&i2c_csi_dsi>, "status";
|
||||||
|
- i2c_csi_dsi0 = <&i2c_csi_dsi0>, "status";
|
||||||
|
- i2c_csi_dsi1 = <&i2c_csi_dsi1>, "status";
|
||||||
|
- i2c0_baudrate = <&i2c0>, "clock-frequency:0";
|
||||||
|
- i2c1_baudrate = <&i2c1>, "clock-frequency:0";
|
||||||
|
- i2c_baudrate = <&i2c_arm>, "clock-frequency:0";
|
||||||
|
- i2c_arm_baudrate = <&i2c_arm>, "clock-frequency:0";
|
||||||
|
- i2c_vc_baudrate = <&i2c_vc>, "clock-frequency:0";
|
||||||
|
- krnbt = <&bluetooth>, "status";
|
||||||
|
- nvme = <&pciex1>, "status";
|
||||||
|
- pciex1 = <&pciex1>, "status";
|
||||||
|
- pciex1_gen = <&pciex1> , "max-link-speed:0";
|
||||||
|
- pciex1_no_l0s = <&pciex1>, "aspm-no-l0s?";
|
||||||
|
- pciex1_tperst_clk_ms = <&pciex1>, "brcm,tperst-clk-ms:0";
|
||||||
|
- pcie_tperst_clk_ms = <&pciex1>, "brcm,tperst-clk-ms:0";
|
||||||
|
- random = <&random>, "status";
|
||||||
|
- rtc = <&rpi_rtc>, "status";
|
||||||
|
- rtc_bbat_vchg = <&rpi_rtc>, "trickle-charge-microvolt:0";
|
||||||
|
- spi = <&spi0>, "status";
|
||||||
|
- suspend = <&pwr_key>, "linux,code:0=205";
|
||||||
|
- uart0 = <&uart0>, "status";
|
||||||
|
- wifiaddr = <&wifi>, "local-mac-address[";
|
||||||
|
-
|
||||||
|
- act_led_activelow = <&led_act>, "active-low?";
|
||||||
|
- act_led_trigger = <&led_act>, "linux,default-trigger";
|
||||||
|
- pwr_led_activelow = <&led_pwr>, "gpios:8";
|
||||||
|
- pwr_led_trigger = <&led_pwr>, "linux,default-trigger";
|
||||||
|
- eth_led0 = <&phy1>,"led-modes:0";
|
||||||
|
- eth_led1 = <&phy1>,"led-modes:4";
|
||||||
|
- drm_fb0_rp1_dsi0 = <&aliases>, "drm-fb0=",&dsi0;
|
||||||
|
- drm_fb0_rp1_dsi1 = <&aliases>, "drm-fb0=",&dsi1;
|
||||||
|
- drm_fb0_rp1_dpi = <&aliases>, "drm-fb0=",&dpi;
|
||||||
|
- drm_fb0_vc4 = <&aliases>, "drm-fb0=",&vc4;
|
||||||
|
- drm_fb1_rp1_dsi0 = <&aliases>, "drm-fb1=",&dsi0;
|
||||||
|
- drm_fb1_rp1_dsi1 = <&aliases>, "drm-fb1=",&dsi1;
|
||||||
|
- drm_fb1_rp1_dpi = <&aliases>, "drm-fb1=",&dpi;
|
||||||
|
- drm_fb1_vc4 = <&aliases>, "drm-fb1=",&vc4;
|
||||||
|
- drm_fb2_rp1_dsi0 = <&aliases>, "drm-fb2=",&dsi0;
|
||||||
|
- drm_fb2_rp1_dsi1 = <&aliases>, "drm-fb2=",&dsi1;
|
||||||
|
- drm_fb2_rp1_dpi = <&aliases>, "drm-fb2=",&dpi;
|
||||||
|
- drm_fb2_vc4 = <&aliases>, "drm-fb2=",&vc4;
|
||||||
|
-
|
||||||
|
ant1 = <&ant1>,"output-high?=on",
|
||||||
|
<&ant1>, "output-low?=off",
|
||||||
|
<&ant2>, "output-high?=off",
|
||||||
|
@@ -867,18 +766,5 @@ spi10_cs_pins: &spi10_cs_gpio1 {};
|
||||||
|
<&ant1>, "output-low?=on",
|
||||||
|
<&ant2>, "output-high?=off",
|
||||||
|
<&ant2>, "output-low?=on";
|
||||||
|
-
|
||||||
|
- fan_temp0 = <&cpu_tepid>,"temperature:0";
|
||||||
|
- fan_temp1 = <&cpu_warm>,"temperature:0";
|
||||||
|
- fan_temp2 = <&cpu_hot>,"temperature:0";
|
||||||
|
- fan_temp3 = <&cpu_vhot>,"temperature:0";
|
||||||
|
- fan_temp0_hyst = <&cpu_tepid>,"hysteresis:0";
|
||||||
|
- fan_temp1_hyst = <&cpu_warm>,"hysteresis:0";
|
||||||
|
- fan_temp2_hyst = <&cpu_hot>,"hysteresis:0";
|
||||||
|
- fan_temp3_hyst = <&cpu_vhot>,"hysteresis:0";
|
||||||
|
- fan_temp0_speed = <&fan>, "cooling-levels:4";
|
||||||
|
- fan_temp1_speed = <&fan>, "cooling-levels:8";
|
||||||
|
- fan_temp2_speed = <&fan>, "cooling-levels:12";
|
||||||
|
- fan_temp3_speed = <&fan>, "cooling-levels:16";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
--- a/arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi
|
||||||
|
+++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi
|
||||||
|
@@ -98,14 +98,124 @@
|
||||||
|
};
|
||||||
|
|
||||||
|
/ {
|
||||||
|
+ aliases: aliases {
|
||||||
|
+ blconfig = &blconfig;
|
||||||
|
+ blpubkey = &blpubkey;
|
||||||
|
+ bluetooth = &bluetooth;
|
||||||
|
+ console = &uart10;
|
||||||
|
+ drm-dsi1 = &dsi0;
|
||||||
|
+ drm-dsi2 = &dsi1;
|
||||||
|
+ ethernet0 = &rp1_eth;
|
||||||
|
+ fb = &fb;
|
||||||
|
+ gpio0 = &gpio;
|
||||||
|
+ gpio1 = &gio;
|
||||||
|
+ gpio2 = &gio_aon;
|
||||||
|
+ gpio3 = &pinctrl;
|
||||||
|
+ gpio4 = &pinctrl_aon;
|
||||||
|
+ i2c = &i2c_arm;
|
||||||
|
+ i2c0 = &i2c0;
|
||||||
|
+ i2c1 = &i2c1;
|
||||||
|
+ i2c10 = &i2c_rp1boot;
|
||||||
|
+ i2c2 = &i2c2;
|
||||||
|
+ i2c3 = &i2c3;
|
||||||
|
+ i2c4 = &i2c4;
|
||||||
|
+ i2c5 = &i2c5;
|
||||||
|
+ i2c6 = &i2c6;
|
||||||
|
+ mailbox = &mailbox;
|
||||||
|
+ mmc0 = &sdio1;
|
||||||
|
+ serial0 = &uart0;
|
||||||
|
+ serial1 = &uart1;
|
||||||
|
+ serial10 = &uart10;
|
||||||
|
+ serial2 = &uart2;
|
||||||
|
+ serial3 = &uart3;
|
||||||
|
+ serial4 = &uart4;
|
||||||
|
+ spi0 = &spi0;
|
||||||
|
+ spi1 = &spi1;
|
||||||
|
+ spi10 = &spi10;
|
||||||
|
+ spi2 = &spi2;
|
||||||
|
+ spi3 = &spi3;
|
||||||
|
+ spi4 = &spi4;
|
||||||
|
+ spi5 = &spi5;
|
||||||
|
+ uart0 = &uart0;
|
||||||
|
+ uart1 = &uart1;
|
||||||
|
+ uart10 = &uart10;
|
||||||
|
+ uart2 = &uart2;
|
||||||
|
+ uart3 = &uart3;
|
||||||
|
+ uart4 = &uart4;
|
||||||
|
+ usb0 = &rp1_usb0;
|
||||||
|
+ usb1 = &rp1_usb1;
|
||||||
|
+ wifi0 = &wifi;
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
__overrides__ {
|
||||||
|
- arm_freq;
|
||||||
|
+ act_led_gpio = <&led_act>,"gpios:4",<&led_act>,"gpios:0=",<&gpio>;
|
||||||
|
+ act_led_activelow = <&led_act>, "gpios:8";
|
||||||
|
+ act_led_trigger = <&led_act>, "linux,default-trigger";
|
||||||
|
axiperf = <&axiperf>,"status";
|
||||||
|
-
|
||||||
|
+ bdaddr = <&bluetooth>, "local-bd-address[";
|
||||||
|
+ button_debounce = <&pwr_key>, "debounce-interval:0";
|
||||||
|
+ cooling_fan = <&fan>, "status", <&rp1_pwm1>, "status";
|
||||||
|
+ drm_fb0_rp1_dpi = <&aliases>, "drm-fb0=",&dpi;
|
||||||
|
+ drm_fb0_rp1_dsi0 = <&aliases>, "drm-fb0=",&dsi0;
|
||||||
|
+ drm_fb0_rp1_dsi1 = <&aliases>, "drm-fb0=",&dsi1;
|
||||||
|
+ drm_fb0_vc4 = <&aliases>, "drm-fb0=",&vc4;
|
||||||
|
+ drm_fb1_rp1_dpi = <&aliases>, "drm-fb1=",&dpi;
|
||||||
|
+ drm_fb1_rp1_dsi0 = <&aliases>, "drm-fb1=",&dsi0;
|
||||||
|
+ drm_fb1_rp1_dsi1 = <&aliases>, "drm-fb1=",&dsi1;
|
||||||
|
+ drm_fb1_vc4 = <&aliases>, "drm-fb1=",&vc4;
|
||||||
|
+ drm_fb2_rp1_dpi = <&aliases>, "drm-fb2=",&dpi;
|
||||||
|
+ drm_fb2_rp1_dsi0 = <&aliases>, "drm-fb2=",&dsi0;
|
||||||
|
+ drm_fb2_rp1_dsi1 = <&aliases>, "drm-fb2=",&dsi1;
|
||||||
|
+ drm_fb2_vc4 = <&aliases>, "drm-fb2=",&vc4;
|
||||||
|
+ eth_led0 = <&phy1>,"led-modes:0";
|
||||||
|
+ eth_led1 = <&phy1>,"led-modes:4";
|
||||||
|
+ fan_temp0 = <&cpu_tepid>,"temperature:0";
|
||||||
|
+ fan_temp0_hyst = <&cpu_tepid>,"hysteresis:0";
|
||||||
|
+ fan_temp0_speed = <&fan>, "cooling-levels:4";
|
||||||
|
+ fan_temp1 = <&cpu_warm>,"temperature:0";
|
||||||
|
+ fan_temp1_hyst = <&cpu_warm>,"hysteresis:0";
|
||||||
|
+ fan_temp1_speed = <&fan>, "cooling-levels:8";
|
||||||
|
+ fan_temp2 = <&cpu_hot>,"temperature:0";
|
||||||
|
+ fan_temp2_hyst = <&cpu_hot>,"hysteresis:0";
|
||||||
|
+ fan_temp2_speed = <&fan>, "cooling-levels:12";
|
||||||
|
+ fan_temp3 = <&cpu_vhot>,"temperature:0";
|
||||||
|
+ fan_temp3_hyst = <&cpu_vhot>,"hysteresis:0";
|
||||||
|
+ fan_temp3_speed = <&fan>, "cooling-levels:16";
|
||||||
|
+ i2c = <&i2c1>, "status";
|
||||||
|
+ i2c_arm = <&i2c_arm>, "status";
|
||||||
|
+ i2c_arm_baudrate = <&i2c_arm>, "clock-frequency:0";
|
||||||
|
+ i2c_baudrate = <&i2c_arm>, "clock-frequency:0";
|
||||||
|
+ i2c_csi_dsi = <&i2c_csi_dsi>, "status";
|
||||||
|
+ i2c_csi_dsi0 = <&i2c_csi_dsi0>, "status";
|
||||||
|
+ i2c_csi_dsi1 = <&i2c_csi_dsi1>, "status";
|
||||||
|
+ i2c_vc = <&i2c_vc>, "status";
|
||||||
|
+ i2c_vc_baudrate = <&i2c_vc>, "clock-frequency:0";
|
||||||
|
+ i2c0 = <&i2c0>, "status";
|
||||||
|
+ i2c0_baudrate = <&i2c0>, "clock-frequency:0";
|
||||||
|
+ i2c1 = <&i2c1>, "status";
|
||||||
|
+ i2c1_baudrate = <&i2c1>, "clock-frequency:0";
|
||||||
|
+ krnbt = <&bluetooth>, "status";
|
||||||
|
+ nvme = <&pciex1>, "status";
|
||||||
|
nvmem_cust_rw = <&nvmem_cust>,"rw?";
|
||||||
|
- nvmem_priv_rw = <&nvmem_priv>,"rw?";
|
||||||
|
nvmem_mac_rw = <&nvmem_mac>,"rw?";
|
||||||
|
+ nvmem_priv_rw = <&nvmem_priv>,"rw?";
|
||||||
|
+ pcie_tperst_clk_ms = <&pciex1>, "brcm,tperst-clk-ms:0";
|
||||||
|
+ pciex1 = <&pciex1>, "status";
|
||||||
|
+ pciex1_gen = <&pciex1> , "max-link-speed:0";
|
||||||
|
+ pciex1_no_l0s = <&pciex1>, "aspm-no-l0s?";
|
||||||
|
+ pciex1_tperst_clk_ms = <&pciex1>, "brcm,tperst-clk-ms:0";
|
||||||
|
+ pwr_led_gpio = <&led_pwr>, "gpios:4";
|
||||||
|
+ pwr_led_activelow = <&led_pwr>, "gpios:8";
|
||||||
|
+ pwr_led_trigger = <&led_pwr>, "linux,default-trigger";
|
||||||
|
+ random = <&random>, "status";
|
||||||
|
+ rtc = <&rpi_rtc>, "status";
|
||||||
|
+ rtc_bbat_vchg = <&rpi_rtc>, "trickle-charge-microvolt:0";
|
||||||
|
+ spi = <&spi0>, "status";
|
||||||
|
strict_gpiod = <&chosen>, "bootargs=pinctrl_rp1.persist_gpio_outputs=n";
|
||||||
|
+ suspend = <&pwr_key>, "linux,code:0=205";
|
||||||
|
+ uart0 = <&uart0>, "status";
|
||||||
|
+ uart0_console = <&uart0>,"status", <&aliases>, "console=",&uart0;
|
||||||
|
+ wifiaddr = <&wifi>, "local-mac-address[";
|
||||||
|
|
||||||
|
cam0_reg = <&cam0_reg>,"status";
|
||||||
|
cam0_reg_gpio = <&cam0_reg>,"gpio:4",
|
||||||
|
@@ -113,7 +223,6 @@
|
||||||
|
cam1_reg = <&cam1_reg>,"status";
|
||||||
|
cam1_reg_gpio = <&cam1_reg>,"gpio:4",
|
||||||
|
<&cam1_reg>,"gpio:0=", <&gpio>;
|
||||||
|
-
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,24 @@
|
|||||||
|
From ad110e5ff36de6096e1b9d7e0fe125326f45ed7d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Phil Elwell <phil@raspberrypi.com>
|
||||||
|
Date: Fri, 19 Jul 2024 13:18:47 +0100
|
||||||
|
Subject: [PATCH 1183/1215] arm64: dts: Give cm5l its own model name
|
||||||
|
|
||||||
|
The bootloader patches the DT with the correct model string, but it
|
||||||
|
is better not to rely on that by setting it from the start.
|
||||||
|
|
||||||
|
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||||
|
---
|
||||||
|
arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5l.dtsi | 2 ++
|
||||||
|
1 file changed, 2 insertions(+)
|
||||||
|
|
||||||
|
--- a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5l.dtsi
|
||||||
|
+++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5l.dtsi
|
||||||
|
@@ -4,6 +4,8 @@
|
||||||
|
#include "bcm2712-rpi-cm5.dtsi"
|
||||||
|
|
||||||
|
/ {
|
||||||
|
+ model = "Raspberry Pi Compute Module 5 Lite";
|
||||||
|
+
|
||||||
|
__overrides__ {
|
||||||
|
i2c_csi_dsi = <&i2c_csi_dsi>, "status";
|
||||||
|
};
|
@ -0,0 +1,288 @@
|
|||||||
|
From d24229dcef58e0162780ceffa02eb5f6a01b9a4d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jonathan Bell <jonathan@raspberrypi.com>
|
||||||
|
Date: Tue, 16 Jul 2024 16:47:08 +0100
|
||||||
|
Subject: [PATCH 1185/1215] pinctrl: rp1: jump through hoops to avoid PCIe
|
||||||
|
latency issues
|
||||||
|
|
||||||
|
Automatic link power saving plus the ability of a root complex to buffer
|
||||||
|
pending posted write transfers (and consider them complete before being
|
||||||
|
transmitted on the wire) causes compression of updates to GPIO state.
|
||||||
|
|
||||||
|
The large bandwidth of a Gen 2 x4 link means the writes toggle state
|
||||||
|
inside RP1 as fast as it can go (~20MHz), which is bad for applications
|
||||||
|
wanting bitbash with at least a few microseconds of delay between
|
||||||
|
updates.
|
||||||
|
|
||||||
|
By tailoring IO access patterns to a special Root Complex register,
|
||||||
|
writes to GPIOs can be stalled until the link wakes - meaning all writes
|
||||||
|
end up with a reasonably consistent minimum pacing (~200ns).
|
||||||
|
|
||||||
|
Additionally, write barriers have no effect other than to arbitrarily
|
||||||
|
delay some writes by a small, variable amount - so remove the vast
|
||||||
|
majority of these in areas that could be hot-paths.
|
||||||
|
|
||||||
|
Although the IO memory is mapped with Device strongly-ordered semantics,
|
||||||
|
this doesn't prevent the splitter inside BCM2712 from letting an MMIO
|
||||||
|
read request to a GPIO register get ahead of the pacing writes to the
|
||||||
|
Root Complex register. So each pin state read must flush writes out to
|
||||||
|
the Outer-Shareable domain.
|
||||||
|
|
||||||
|
Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
|
||||||
|
---
|
||||||
|
drivers/pinctrl/pinctrl-rp1.c | 120 +++++++++++++++++++++++++++++-----
|
||||||
|
1 file changed, 105 insertions(+), 15 deletions(-)
|
||||||
|
|
||||||
|
--- a/drivers/pinctrl/pinctrl-rp1.c
|
||||||
|
+++ b/drivers/pinctrl/pinctrl-rp1.c
|
||||||
|
@@ -197,6 +197,7 @@ struct rp1_pin_info {
|
||||||
|
void __iomem *inte;
|
||||||
|
void __iomem *ints;
|
||||||
|
void __iomem *pad;
|
||||||
|
+ void __iomem *dummy;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum funcs {
|
||||||
|
@@ -276,6 +277,7 @@ struct rp1_pinctrl {
|
||||||
|
void __iomem *gpio_base;
|
||||||
|
void __iomem *rio_base;
|
||||||
|
void __iomem *pads_base;
|
||||||
|
+ void __iomem *dummy_base;
|
||||||
|
int irq[RP1_NUM_BANKS];
|
||||||
|
struct rp1_pin_info pins[RP1_NUM_GPIOS];
|
||||||
|
|
||||||
|
@@ -577,6 +579,42 @@ static bool persist_gpio_outputs = true;
|
||||||
|
module_param(persist_gpio_outputs, bool, 0644);
|
||||||
|
MODULE_PARM_DESC(persist_gpio_outputs, "Enable GPIO_OUT persistence when pin is freed");
|
||||||
|
|
||||||
|
+static bool pace_pin_updates = true;
|
||||||
|
+module_param(pace_pin_updates, bool, 0644);
|
||||||
|
+MODULE_PARM_DESC(pace_pin_updates, "Update pin states with guaranteed monotonicity if PCIe ASPM is enabled");
|
||||||
|
+
|
||||||
|
+static inline void rp1_pin_writel(u32 val, void __iomem *dummy, void __iomem *reg)
|
||||||
|
+{
|
||||||
|
+ unsigned long flags;
|
||||||
|
+
|
||||||
|
+ local_irq_save(flags);
|
||||||
|
+ /*
|
||||||
|
+ * Issuing 6 pipelined writes to the RC's Slot Control register will stall the
|
||||||
|
+ * peripheral bus inside 2712 if the link is in L1. This acts as a lightweight
|
||||||
|
+ * "fence" operation preventing back-to-back writes arriving at RP1 on a wake.
|
||||||
|
+ */
|
||||||
|
+ if (dummy) {
|
||||||
|
+ writel_relaxed(0, dummy);
|
||||||
|
+ writel_relaxed(0, dummy);
|
||||||
|
+ writel_relaxed(0, dummy);
|
||||||
|
+ writel_relaxed(0, dummy);
|
||||||
|
+ writel_relaxed(0, dummy);
|
||||||
|
+ writel_relaxed(0, dummy);
|
||||||
|
+ }
|
||||||
|
+ writel_relaxed(val, reg);
|
||||||
|
+ local_irq_restore(flags);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline u32 rp1_pin_readl(const void __iomem *ioaddr)
|
||||||
|
+{
|
||||||
|
+ /*
|
||||||
|
+ * Prior posted writes may not yet have been emitted by the CPU - do a store-flush
|
||||||
|
+ * before reading GPIO state, as this will serialise writes versus the next issued read.
|
||||||
|
+ */
|
||||||
|
+ __dma_wmb();
|
||||||
|
+ return readl(ioaddr);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int rp1_pinconf_set(struct pinctrl_dev *pctldev,
|
||||||
|
unsigned int offset, unsigned long *configs,
|
||||||
|
unsigned int num_configs);
|
||||||
|
@@ -603,12 +641,12 @@ static struct rp1_pin_info *rp1_get_pin_
|
||||||
|
|
||||||
|
static void rp1_pad_update(struct rp1_pin_info *pin, u32 clr, u32 set)
|
||||||
|
{
|
||||||
|
- u32 padctrl = readl(pin->pad);
|
||||||
|
+ u32 padctrl = rp1_pin_readl(pin->pad);
|
||||||
|
|
||||||
|
padctrl &= ~clr;
|
||||||
|
padctrl |= set;
|
||||||
|
|
||||||
|
- writel(padctrl, pin->pad);
|
||||||
|
+ rp1_pin_writel(padctrl, pin->dummy, pin->pad);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rp1_input_enable(struct rp1_pin_info *pin, int value)
|
||||||
|
@@ -625,7 +663,7 @@ static void rp1_output_enable(struct rp1
|
||||||
|
|
||||||
|
static u32 rp1_get_fsel(struct rp1_pin_info *pin)
|
||||||
|
{
|
||||||
|
- u32 ctrl = readl(pin->gpio + RP1_GPIO_CTRL);
|
||||||
|
+ u32 ctrl = rp1_pin_readl(pin->gpio + RP1_GPIO_CTRL);
|
||||||
|
u32 oeover = FLD_GET(ctrl, RP1_GPIO_CTRL_OEOVER);
|
||||||
|
u32 fsel = FLD_GET(ctrl, RP1_GPIO_CTRL_FUNCSEL);
|
||||||
|
|
||||||
|
@@ -637,7 +675,7 @@ static u32 rp1_get_fsel(struct rp1_pin_i
|
||||||
|
|
||||||
|
static void rp1_set_fsel(struct rp1_pin_info *pin, u32 fsel)
|
||||||
|
{
|
||||||
|
- u32 ctrl = readl(pin->gpio + RP1_GPIO_CTRL);
|
||||||
|
+ u32 ctrl = rp1_pin_readl(pin->gpio + RP1_GPIO_CTRL);
|
||||||
|
|
||||||
|
if (fsel >= RP1_FSEL_COUNT)
|
||||||
|
fsel = RP1_FSEL_NONE_HW;
|
||||||
|
@@ -652,12 +690,12 @@ static void rp1_set_fsel(struct rp1_pin_
|
||||||
|
FLD_SET(ctrl, RP1_GPIO_CTRL_OEOVER, RP1_OEOVER_PERI);
|
||||||
|
}
|
||||||
|
FLD_SET(ctrl, RP1_GPIO_CTRL_FUNCSEL, fsel);
|
||||||
|
- writel(ctrl, pin->gpio + RP1_GPIO_CTRL);
|
||||||
|
+ rp1_pin_writel(ctrl, pin->dummy, pin->gpio + RP1_GPIO_CTRL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rp1_get_dir(struct rp1_pin_info *pin)
|
||||||
|
{
|
||||||
|
- return !(readl(pin->rio + RP1_RIO_OE) & (1 << pin->offset)) ?
|
||||||
|
+ return !(rp1_pin_readl(pin->rio + RP1_RIO_OE) & (1 << pin->offset)) ?
|
||||||
|
RP1_DIR_INPUT : RP1_DIR_OUTPUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -665,19 +703,19 @@ static void rp1_set_dir(struct rp1_pin_i
|
||||||
|
{
|
||||||
|
int offset = is_input ? RP1_CLR_OFFSET : RP1_SET_OFFSET;
|
||||||
|
|
||||||
|
- writel(1 << pin->offset, pin->rio + RP1_RIO_OE + offset);
|
||||||
|
+ rp1_pin_writel(1 << pin->offset, pin->dummy, pin->rio + RP1_RIO_OE + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rp1_get_value(struct rp1_pin_info *pin)
|
||||||
|
{
|
||||||
|
- return !!(readl(pin->rio + RP1_RIO_IN) & (1 << pin->offset));
|
||||||
|
+ return !!(rp1_pin_readl(pin->rio + RP1_RIO_IN) & (1 << pin->offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rp1_set_value(struct rp1_pin_info *pin, int value)
|
||||||
|
{
|
||||||
|
/* Assume the pin is already an output */
|
||||||
|
- writel(1 << pin->offset,
|
||||||
|
- pin->rio + RP1_RIO_OUT + (value ? RP1_SET_OFFSET : RP1_CLR_OFFSET));
|
||||||
|
+ rp1_pin_writel(1 << pin->offset, pin->dummy,
|
||||||
|
+ pin->rio + RP1_RIO_OUT + (value ? RP1_SET_OFFSET : RP1_CLR_OFFSET));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rp1_gpio_get(struct gpio_chip *chip, unsigned offset)
|
||||||
|
@@ -1298,7 +1336,7 @@ static const struct pinmux_ops rp1_pmx_o
|
||||||
|
|
||||||
|
static void rp1_pull_config_set(struct rp1_pin_info *pin, unsigned int arg)
|
||||||
|
{
|
||||||
|
- u32 padctrl = readl(pin->pad);
|
||||||
|
+ u32 padctrl = rp1_pin_readl(pin->pad);
|
||||||
|
|
||||||
|
FLD_SET(padctrl, RP1_PAD_PULL, arg & 0x3);
|
||||||
|
|
||||||
|
@@ -1398,7 +1436,7 @@ static int rp1_pinconf_get(struct pinctr
|
||||||
|
if (!pin)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
- padctrl = readl(pin->pad);
|
||||||
|
+ padctrl = rp1_pin_readl(pin->pad);
|
||||||
|
|
||||||
|
switch (param) {
|
||||||
|
case PIN_CONFIG_INPUT_ENABLE:
|
||||||
|
@@ -1493,6 +1531,7 @@ static int rp1_pinctrl_probe(struct plat
|
||||||
|
{
|
||||||
|
struct device *dev = &pdev->dev;
|
||||||
|
struct device_node *np = dev->of_node;
|
||||||
|
+ struct device_node *rp1_node = NULL;
|
||||||
|
struct rp1_pinctrl *pc;
|
||||||
|
struct gpio_irq_chip *girq;
|
||||||
|
int err, i;
|
||||||
|
@@ -1528,6 +1567,40 @@ static int rp1_pinctrl_probe(struct plat
|
||||||
|
pc->gpio_chip = rp1_gpio_chip;
|
||||||
|
pc->gpio_chip.parent = dev;
|
||||||
|
|
||||||
|
+ /*
|
||||||
|
+ * Workaround for the vagaries of PCIe on BCM2712
|
||||||
|
+ *
|
||||||
|
+ * If the link to RP1 is in L1, then the BRCMSTB RC will buffer many
|
||||||
|
+ * outbound writes - and generate write responses for them, despite the
|
||||||
|
+ * fact that the link is not yet active. This has the effect of compressing
|
||||||
|
+ * multiple writes to GPIOs together, destroying any pacing that an application
|
||||||
|
+ * may require in the 1-10us range.
|
||||||
|
+ *
|
||||||
|
+ * The RC Slot Control configuration register is special. It emits a
|
||||||
|
+ * MsgD for every write to it, will stall further writes until the message
|
||||||
|
+ * goes out on the wire. This can be (ab)used to force CPU stalls when the
|
||||||
|
+ * link is inactive, at the cost of a small amount of downstream bandwidth
|
||||||
|
+ * and some 200ns of added latency for each write.
|
||||||
|
+ *
|
||||||
|
+ * Several back-to-back configuration writes are necessary to "fill the pipe",
|
||||||
|
+ * otherwise the outbound MAC can consume a pending MMIO write and reorder
|
||||||
|
+ * it with respect to the config writes - undoing the intent.
|
||||||
|
+ *
|
||||||
|
+ * of_iomap() is used directly here as the address overlaps with the RC driver's
|
||||||
|
+ * usage.
|
||||||
|
+ */
|
||||||
|
+ rp1_node = of_find_node_by_name(NULL, "rp1");
|
||||||
|
+ if (!rp1_node)
|
||||||
|
+ dev_err(&pdev->dev, "failed to find RP1 DT node\n");
|
||||||
|
+ else if (pace_pin_updates &&
|
||||||
|
+ of_device_is_compatible(rp1_node->parent, "brcm,bcm2712-pcie")) {
|
||||||
|
+ pc->dummy_base = of_iomap(rp1_node->parent, 0);
|
||||||
|
+ if (IS_ERR(pc->dummy_base)) {
|
||||||
|
+ dev_warn(&pdev->dev, "could not map bcm2712 root complex registers\n");
|
||||||
|
+ pc->dummy_base = NULL;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
for (i = 0; i < RP1_NUM_BANKS; i++) {
|
||||||
|
const struct rp1_iobank_desc *bank = &rp1_iobanks[i];
|
||||||
|
int j;
|
||||||
|
@@ -1547,14 +1620,17 @@ static int rp1_pinctrl_probe(struct plat
|
||||||
|
pin->rio = pc->rio_base + bank->rio_offset;
|
||||||
|
pin->pad = pc->pads_base + bank->pads_offset +
|
||||||
|
j * sizeof(u32);
|
||||||
|
+ pin->dummy = pc->dummy_base ? pc->dummy_base + 0xc0 : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
raw_spin_lock_init(&pc->irq_lock[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pc->pctl_dev = devm_pinctrl_register(dev, &rp1_pinctrl_desc, pc);
|
||||||
|
- if (IS_ERR(pc->pctl_dev))
|
||||||
|
- return PTR_ERR(pc->pctl_dev);
|
||||||
|
+ if (IS_ERR(pc->pctl_dev)) {
|
||||||
|
+ err = PTR_ERR(pc->pctl_dev);
|
||||||
|
+ goto out_iounmap;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
girq = &pc->gpio_chip.irq;
|
||||||
|
girq->chip = &rp1_gpio_irq_chip;
|
||||||
|
@@ -1583,7 +1659,7 @@ static int rp1_pinctrl_probe(struct plat
|
||||||
|
err = devm_gpiochip_add_data(dev, &pc->gpio_chip, pc);
|
||||||
|
if (err) {
|
||||||
|
dev_err(dev, "could not add GPIO chip\n");
|
||||||
|
- return err;
|
||||||
|
+ goto out_iounmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
pc->gpio_range = rp1_pinctrl_gpio_range;
|
||||||
|
@@ -1592,10 +1668,24 @@ static int rp1_pinctrl_probe(struct plat
|
||||||
|
pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
+
|
||||||
|
+out_iounmap:
|
||||||
|
+ if (pc->dummy_base)
|
||||||
|
+ iounmap(pc->dummy_base);
|
||||||
|
+ return err;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void rp1_pinctrl_remove(struct platform_device *pdev)
|
||||||
|
+{
|
||||||
|
+ struct rp1_pinctrl *pc = platform_get_drvdata(pdev);
|
||||||
|
+
|
||||||
|
+ if (pc->dummy_base)
|
||||||
|
+ iounmap(pc->dummy_base);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct platform_driver rp1_pinctrl_driver = {
|
||||||
|
.probe = rp1_pinctrl_probe,
|
||||||
|
+ .remove_new = rp1_pinctrl_remove,
|
||||||
|
.driver = {
|
||||||
|
.name = MODULE_NAME,
|
||||||
|
.of_match_table = rp1_pinctrl_match,
|
@ -0,0 +1,36 @@
|
|||||||
|
From 43fa967811484afde0bbbee182ff8f29dc0550c2 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
||||||
|
Date: Fri, 5 Jul 2024 15:57:25 +0100
|
||||||
|
Subject: [PATCH 1186/1215] staging: bcm2835-codec: Disable HEADER_ON_OPEN for
|
||||||
|
video encode
|
||||||
|
|
||||||
|
Video encode can defer generating the header until the first
|
||||||
|
frame is presented, which allows it to take the colourspace
|
||||||
|
information from the frame rather than just the format.
|
||||||
|
|
||||||
|
Enable that for the V4L2 driver now that the firmware populates
|
||||||
|
all the parameters.
|
||||||
|
|
||||||
|
https://github.com/raspberrypi/firmware/issues/1885
|
||||||
|
|
||||||
|
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
||||||
|
---
|
||||||
|
.../vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c | 7 +++++++
|
||||||
|
1 file changed, 7 insertions(+)
|
||||||
|
|
||||||
|
--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
|
||||||
|
+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
|
||||||
|
@@ -2731,6 +2731,13 @@ static int bcm2835_codec_create_componen
|
||||||
|
¶ms,
|
||||||
|
sizeof(params));
|
||||||
|
|
||||||
|
+ } else if (dev->role == ENCODE) {
|
||||||
|
+ enable = 0;
|
||||||
|
+ vchiq_mmal_port_parameter_set(dev->instance,
|
||||||
|
+ &ctx->component->control,
|
||||||
|
+ MMAL_PARAMETER_VIDEO_ENCODE_HEADER_ON_OPEN,
|
||||||
|
+ &enable,
|
||||||
|
+ sizeof(enable));
|
||||||
|
} else if (dev->role == ENCODE_IMAGE) {
|
||||||
|
enable = 0;
|
||||||
|
vchiq_mmal_port_parameter_set(dev->instance,
|
@ -0,0 +1,36 @@
|
|||||||
|
From 31b9871b8895d7931ee88d7cda7861f829b21d63 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
||||||
|
Date: Wed, 17 Jul 2024 16:59:08 +0100
|
||||||
|
Subject: [PATCH 1188/1215] staging: bcm2835-codec: Add support for H264 level
|
||||||
|
5.0 and 5.1
|
||||||
|
|
||||||
|
We do NOT claim to support decoding in real-time for these levels,
|
||||||
|
but can transcode some content, and handle 1920x1200.
|
||||||
|
|
||||||
|
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
||||||
|
---
|
||||||
|
.../vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c | 6 ++++--
|
||||||
|
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
|
||||||
|
+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
|
||||||
|
@@ -3273,7 +3273,7 @@ static void dec_add_profile_ctrls(struct
|
||||||
|
case V4L2_PIX_FMT_H264:
|
||||||
|
ctrl = v4l2_ctrl_new_std_menu(hdl, &bcm2835_codec_ctrl_ops,
|
||||||
|
V4L2_CID_MPEG_VIDEO_H264_LEVEL,
|
||||||
|
- V4L2_MPEG_VIDEO_H264_LEVEL_4_2,
|
||||||
|
+ V4L2_MPEG_VIDEO_H264_LEVEL_5_1,
|
||||||
|
~(BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) |
|
||||||
|
BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) |
|
||||||
|
BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) |
|
||||||
|
@@ -3287,7 +3287,9 @@ static void dec_add_profile_ctrls(struct
|
||||||
|
BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) |
|
||||||
|
BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) |
|
||||||
|
BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) |
|
||||||
|
- BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2)),
|
||||||
|
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2) |
|
||||||
|
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_0) |
|
||||||
|
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_1)),
|
||||||
|
V4L2_MPEG_VIDEO_H264_LEVEL_4_0);
|
||||||
|
ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
|
||||||
|
ctrl = v4l2_ctrl_new_std_menu(hdl, &bcm2835_codec_ctrl_ops,
|
@ -0,0 +1,66 @@
|
|||||||
|
From 6014649de765a8a1f95c146ca72214ff0ba4ba89 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Phil Elwell <phil@raspberrypi.com>
|
||||||
|
Date: Mon, 1 Jul 2024 15:49:14 +0100
|
||||||
|
Subject: [PATCH 1189/1215] spi: dw: Save bandwidth with the TMOD_TO feature
|
||||||
|
|
||||||
|
TMOD_TO is the transmit-only mode that doesn't put data into the receive
|
||||||
|
FIFO. Using TMOD_TO when the user doesn't want the received data saves
|
||||||
|
CPU time and memory bandwidth.
|
||||||
|
|
||||||
|
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||||
|
---
|
||||||
|
drivers/spi/spi-dw-core.c | 27 +++++++++++++++++----------
|
||||||
|
1 file changed, 17 insertions(+), 10 deletions(-)
|
||||||
|
|
||||||
|
--- a/drivers/spi/spi-dw-core.c
|
||||||
|
+++ b/drivers/spi/spi-dw-core.c
|
||||||
|
@@ -225,12 +225,17 @@ static irqreturn_t dw_spi_transfer_handl
|
||||||
|
* final stage of the transfer. By doing so we'll get the next IRQ
|
||||||
|
* right when the leftover incoming data is received.
|
||||||
|
*/
|
||||||
|
- dw_reader(dws);
|
||||||
|
- if (!dws->rx_len) {
|
||||||
|
- dw_spi_mask_intr(dws, 0xff);
|
||||||
|
+ if (dws->rx_len) {
|
||||||
|
+ dw_reader(dws);
|
||||||
|
+ if (!dws->rx_len) {
|
||||||
|
+ dw_spi_mask_intr(dws, 0xff);
|
||||||
|
+ spi_finalize_current_transfer(dws->host);
|
||||||
|
+ } else if (dws->rx_len <= dw_readl(dws, DW_SPI_RXFTLR)) {
|
||||||
|
+ dw_writel(dws, DW_SPI_RXFTLR, dws->rx_len - 1);
|
||||||
|
+ }
|
||||||
|
+ } else if (!dws->tx_len) {
|
||||||
|
+ dw_spi_mask_intr(dws, DW_SPI_INT_TXEI);
|
||||||
|
spi_finalize_current_transfer(dws->host);
|
||||||
|
- } else if (dws->rx_len <= dw_readl(dws, DW_SPI_RXFTLR)) {
|
||||||
|
- dw_writel(dws, DW_SPI_RXFTLR, dws->rx_len - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -239,12 +244,9 @@ static irqreturn_t dw_spi_transfer_handl
|
||||||
|
* have the TXE IRQ flood at the final stage of the transfer.
|
||||||
|
*/
|
||||||
|
if (irq_status & DW_SPI_INT_TXEI) {
|
||||||
|
- dw_writer(dws);
|
||||||
|
- if (!dws->tx_len) {
|
||||||
|
+ if (!dws->tx_len)
|
||||||
|
dw_spi_mask_intr(dws, DW_SPI_INT_TXEI);
|
||||||
|
- if (!dws->rx_len)
|
||||||
|
- spi_finalize_current_transfer(dws->host);
|
||||||
|
- }
|
||||||
|
+ dw_writer(dws);
|
||||||
|
}
|
||||||
|
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
@@ -437,6 +439,11 @@ static int dw_spi_transfer_one(struct sp
|
||||||
|
dws->rx = transfer->rx_buf;
|
||||||
|
dws->rx_len = dws->tx_len;
|
||||||
|
|
||||||
|
+ if (!dws->rx) {
|
||||||
|
+ dws->rx_len = 0;
|
||||||
|
+ cfg.tmode = DW_SPI_CTRLR0_TMOD_TO;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/* Ensure the data above is visible for all CPUs */
|
||||||
|
smp_mb();
|
||||||
|
|
@ -0,0 +1,186 @@
|
|||||||
|
From cd9084ceb606a2f06c3429c2d3beae2d7c3ebd23 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Phil Elwell <phil@raspberrypi.com>
|
||||||
|
Date: Mon, 1 Jul 2024 16:41:04 +0100
|
||||||
|
Subject: [PATCH 1190/1215] spi: dw: Save bandwidth with the TMOD_RO feature
|
||||||
|
|
||||||
|
TMOD_RO is the receive-only mode that doesn't require data in the
|
||||||
|
transmit FIFO in order to generate clock cycles. Using TMOD_RO when the
|
||||||
|
device doesn't care about the data sent to it saves CPU time and memory
|
||||||
|
bandwidth.
|
||||||
|
|
||||||
|
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||||
|
---
|
||||||
|
drivers/spi/spi-dw-core.c | 31 +++++++++++++++++++++-------
|
||||||
|
drivers/spi/spi-dw-dma.c | 43 +++++++++++++++++++++++++--------------
|
||||||
|
2 files changed, 52 insertions(+), 22 deletions(-)
|
||||||
|
|
||||||
|
--- a/drivers/spi/spi-dw-core.c
|
||||||
|
+++ b/drivers/spi/spi-dw-core.c
|
||||||
|
@@ -367,18 +367,18 @@ static void dw_spi_irq_setup(struct dw_s
|
||||||
|
* will be adjusted at the final stage of the IRQ-based SPI transfer
|
||||||
|
* execution so not to lose the leftover of the incoming data.
|
||||||
|
*/
|
||||||
|
- level = min_t(unsigned int, dws->fifo_len / 2, dws->tx_len);
|
||||||
|
+ level = min_t(unsigned int, dws->fifo_len / 2, dws->tx_len ? dws->tx_len : dws->rx_len);
|
||||||
|
dw_writel(dws, DW_SPI_TXFTLR, level);
|
||||||
|
dw_writel(dws, DW_SPI_RXFTLR, level - 1);
|
||||||
|
|
||||||
|
dws->transfer_handler = dw_spi_transfer_handler;
|
||||||
|
|
||||||
|
- imask = 0;
|
||||||
|
- if (dws->tx_len)
|
||||||
|
- imask |= DW_SPI_INT_TXEI | DW_SPI_INT_TXOI;
|
||||||
|
+ imask = DW_SPI_INT_TXEI | DW_SPI_INT_TXOI;
|
||||||
|
if (dws->rx_len)
|
||||||
|
imask |= DW_SPI_INT_RXUI | DW_SPI_INT_RXOI | DW_SPI_INT_RXFI;
|
||||||
|
dw_spi_umask_intr(dws, imask);
|
||||||
|
+ if (!dws->tx_len)
|
||||||
|
+ dw_writel(dws, DW_SPI_DR, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -401,13 +401,18 @@ static int dw_spi_poll_transfer(struct d
|
||||||
|
delay.unit = SPI_DELAY_UNIT_SCK;
|
||||||
|
nbits = dws->n_bytes * BITS_PER_BYTE;
|
||||||
|
|
||||||
|
+ if (!dws->tx_len)
|
||||||
|
+ dw_writel(dws, DW_SPI_DR, 0);
|
||||||
|
+
|
||||||
|
do {
|
||||||
|
- dw_writer(dws);
|
||||||
|
+ if (dws->tx_len)
|
||||||
|
+ dw_writer(dws);
|
||||||
|
|
||||||
|
delay.value = nbits * (dws->rx_len - dws->tx_len);
|
||||||
|
spi_delay_exec(&delay, transfer);
|
||||||
|
|
||||||
|
- dw_reader(dws);
|
||||||
|
+ if (dws->rx_len)
|
||||||
|
+ dw_reader(dws);
|
||||||
|
|
||||||
|
ret = dw_spi_check_status(dws, true);
|
||||||
|
if (ret)
|
||||||
|
@@ -427,6 +432,7 @@ static int dw_spi_transfer_one(struct sp
|
||||||
|
.dfs = transfer->bits_per_word,
|
||||||
|
.freq = transfer->speed_hz,
|
||||||
|
};
|
||||||
|
+ int buswidth;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
dws->dma_mapped = 0;
|
||||||
|
@@ -444,6 +450,18 @@ static int dw_spi_transfer_one(struct sp
|
||||||
|
cfg.tmode = DW_SPI_CTRLR0_TMOD_TO;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (!dws->rx) {
|
||||||
|
+ dws->rx_len = 0;
|
||||||
|
+ cfg.tmode = DW_SPI_CTRLR0_TMOD_TO;
|
||||||
|
+ }
|
||||||
|
+ if (!dws->tx) {
|
||||||
|
+ dws->tx_len = 0;
|
||||||
|
+ cfg.tmode = DW_SPI_CTRLR0_TMOD_RO;
|
||||||
|
+ cfg.ndf = dws->rx_len;
|
||||||
|
+ }
|
||||||
|
+ buswidth = transfer->rx_buf ? transfer->rx_nbits :
|
||||||
|
+ (transfer->tx_buf ? transfer->tx_nbits : 1);
|
||||||
|
+
|
||||||
|
/* Ensure the data above is visible for all CPUs */
|
||||||
|
smp_mb();
|
||||||
|
|
||||||
|
@@ -961,7 +979,6 @@ int dw_spi_add_host(struct device *dev,
|
||||||
|
dev_warn(dev, "DMA init failed\n");
|
||||||
|
} else {
|
||||||
|
host->can_dma = dws->dma_ops->can_dma;
|
||||||
|
- host->flags |= SPI_CONTROLLER_MUST_TX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
--- a/drivers/spi/spi-dw-dma.c
|
||||||
|
+++ b/drivers/spi/spi-dw-dma.c
|
||||||
|
@@ -6,6 +6,7 @@
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/completion.h>
|
||||||
|
+#include <linux/delay.h>
|
||||||
|
#include <linux/dma-mapping.h>
|
||||||
|
#include <linux/dmaengine.h>
|
||||||
|
#include <linux/irqreturn.h>
|
||||||
|
@@ -470,13 +471,12 @@ static int dw_spi_dma_setup(struct dw_sp
|
||||||
|
u16 imr, dma_ctrl;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
- if (!xfer->tx_buf)
|
||||||
|
- return -EINVAL;
|
||||||
|
-
|
||||||
|
/* Setup DMA channels */
|
||||||
|
- ret = dw_spi_dma_config_tx(dws);
|
||||||
|
- if (ret)
|
||||||
|
- return ret;
|
||||||
|
+ if (xfer->tx_buf) {
|
||||||
|
+ ret = dw_spi_dma_config_tx(dws);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
if (xfer->rx_buf) {
|
||||||
|
ret = dw_spi_dma_config_rx(dws);
|
||||||
|
@@ -485,13 +485,17 @@ static int dw_spi_dma_setup(struct dw_sp
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the DMA handshaking interface */
|
||||||
|
- dma_ctrl = DW_SPI_DMACR_TDMAE;
|
||||||
|
+ dma_ctrl = 0;
|
||||||
|
+ if (xfer->tx_buf)
|
||||||
|
+ dma_ctrl |= DW_SPI_DMACR_TDMAE;
|
||||||
|
if (xfer->rx_buf)
|
||||||
|
dma_ctrl |= DW_SPI_DMACR_RDMAE;
|
||||||
|
dw_writel(dws, DW_SPI_DMACR, dma_ctrl);
|
||||||
|
|
||||||
|
/* Set the interrupt mask */
|
||||||
|
- imr = DW_SPI_INT_TXOI;
|
||||||
|
+ imr = 0;
|
||||||
|
+ if (xfer->tx_buf)
|
||||||
|
+ imr |= DW_SPI_INT_TXOI;
|
||||||
|
if (xfer->rx_buf)
|
||||||
|
imr |= DW_SPI_INT_RXUI | DW_SPI_INT_RXOI;
|
||||||
|
dw_spi_umask_intr(dws, imr);
|
||||||
|
@@ -508,15 +512,16 @@ static int dw_spi_dma_transfer_all(struc
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
- /* Submit the DMA Tx transfer */
|
||||||
|
- ret = dw_spi_dma_submit_tx(dws, xfer->tx_sg.sgl, xfer->tx_sg.nents);
|
||||||
|
- if (ret)
|
||||||
|
- goto err_clear_dmac;
|
||||||
|
+ /* Submit the DMA Tx transfer if required */
|
||||||
|
+ if (xfer->tx_buf) {
|
||||||
|
+ ret = dw_spi_dma_submit_tx(dws, xfer->tx_sg.sgl, xfer->tx_sg.nents);
|
||||||
|
+ if (ret)
|
||||||
|
+ goto err_clear_dmac;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
/* Submit the DMA Rx transfer if required */
|
||||||
|
if (xfer->rx_buf) {
|
||||||
|
- ret = dw_spi_dma_submit_rx(dws, xfer->rx_sg.sgl,
|
||||||
|
- xfer->rx_sg.nents);
|
||||||
|
+ ret = dw_spi_dma_submit_rx(dws, xfer->rx_sg.sgl, xfer->rx_sg.nents);
|
||||||
|
if (ret)
|
||||||
|
goto err_clear_dmac;
|
||||||
|
|
||||||
|
@@ -524,7 +529,15 @@ static int dw_spi_dma_transfer_all(struc
|
||||||
|
dma_async_issue_pending(dws->rxchan);
|
||||||
|
}
|
||||||
|
|
||||||
|
- dma_async_issue_pending(dws->txchan);
|
||||||
|
+ if (xfer->tx_buf) {
|
||||||
|
+ dma_async_issue_pending(dws->txchan);
|
||||||
|
+ } else {
|
||||||
|
+ /* Pause to allow DMA channel to fetch RX descriptor */
|
||||||
|
+ usleep_range(5, 10);
|
||||||
|
+
|
||||||
|
+ /* Write something to the TX FIFO to start the transfer */
|
||||||
|
+ dw_writel(dws, DW_SPI_DR, 0);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
ret = dw_spi_dma_wait(dws, xfer->len, xfer->effective_speed_hz);
|
||||||
|
|
@ -0,0 +1,41 @@
|
|||||||
|
From 3af7822df36e36b5a74d877df7654695c0e0d34a Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jonathan Bell <jonathan@raspberrypi.com>
|
||||||
|
Date: Mon, 22 Jul 2024 15:27:51 +0100
|
||||||
|
Subject: [PATCH 1191/1215] spi: dw: don't immediately kill DMA transfers if an
|
||||||
|
error occurs
|
||||||
|
|
||||||
|
Disabling the peripheral resets controller state which has a dangerous
|
||||||
|
side-effect of disabling the DMA handshake interface while it is active.
|
||||||
|
This can cause DMA channels to hang.
|
||||||
|
|
||||||
|
The error recovery pathway will wait for DMA to stop and reset the chip
|
||||||
|
anyway, so mask further FIFO interrupts and let the transfer finish
|
||||||
|
gracefully.
|
||||||
|
|
||||||
|
Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
|
||||||
|
---
|
||||||
|
drivers/spi/spi-dw-core.c | 13 ++++++++++++-
|
||||||
|
1 file changed, 12 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
--- a/drivers/spi/spi-dw-core.c
|
||||||
|
+++ b/drivers/spi/spi-dw-core.c
|
||||||
|
@@ -200,7 +200,18 @@ int dw_spi_check_status(struct dw_spi *d
|
||||||
|
|
||||||
|
/* Generically handle the erroneous situation */
|
||||||
|
if (ret) {
|
||||||
|
- dw_spi_reset_chip(dws);
|
||||||
|
+ /*
|
||||||
|
+ * Forcibly halting the controller can cause DMA to hang.
|
||||||
|
+ * Defer to dw_spi_handle_err outside of interrupt context
|
||||||
|
+ * and mask further interrupts for the current transfer.
|
||||||
|
+ */
|
||||||
|
+ if (dws->dma_mapped) {
|
||||||
|
+ dw_spi_mask_intr(dws, 0xff);
|
||||||
|
+ dw_readl(dws, DW_SPI_ICR);
|
||||||
|
+ } else {
|
||||||
|
+ dw_spi_reset_chip(dws);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (dws->host->cur_msg)
|
||||||
|
dws->host->cur_msg->status = ret;
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
From 4c1a665b465fa0e9d3369a467fc563ec812a47ce Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jonathan Bell <jonathan@raspberrypi.com>
|
||||||
|
Date: Fri, 19 Jul 2024 13:07:59 +0100
|
||||||
|
Subject: [PATCH 1192/1215] dts: rp1: hobble DMA AXI burst lengths
|
||||||
|
|
||||||
|
Channels 1-2 have a statically configured maximum MSIZE of 8, and
|
||||||
|
channels 3-8 have MSIZE set to 4. The DMAC "helpfully" silently
|
||||||
|
truncates bursts to the hardware supported maximum, so any FIFO read
|
||||||
|
operation with an oversized burst threshold will leave a residue of
|
||||||
|
threshold minus MSIZE rows.
|
||||||
|
|
||||||
|
As channel allocation is dynamic, this means every client needs to use a
|
||||||
|
maximum of 4 for burst length.
|
||||||
|
|
||||||
|
AXI AWLEN/ARLEN constraints aren't strictly related to MSIZE, except
|
||||||
|
that bursts won't be issued that are longer than MSIZE beats. Therefore,
|
||||||
|
it's a useful proxy to tell clients of the DMAC the hardware
|
||||||
|
limitations.
|
||||||
|
|
||||||
|
Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
|
||||||
|
---
|
||||||
|
arch/arm64/boot/dts/broadcom/rp1.dtsi | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
--- a/arch/arm64/boot/dts/broadcom/rp1.dtsi
|
||||||
|
+++ b/arch/arm64/boot/dts/broadcom/rp1.dtsi
|
||||||
|
@@ -1064,7 +1064,7 @@
|
||||||
|
snps,data-width = <4>; // (8 << 4) == 128 bits
|
||||||
|
snps,block-size = <0x40000 0x40000 0x40000 0x40000 0x40000 0x40000 0x40000 0x40000>;
|
||||||
|
snps,priority = <0 1 2 3 4 5 6 7>;
|
||||||
|
- snps,axi-max-burst-len = <8>;
|
||||||
|
+ snps,axi-max-burst-len = <4>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,124 @@
|
|||||||
|
From ce56098eb4dc2985f27f30ad7b7f5aed6bcf7fb1 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jonathan Bell <jonathan@raspberrypi.com>
|
||||||
|
Date: Fri, 19 Jul 2024 15:55:56 +0100
|
||||||
|
Subject: [PATCH 1193/1215] drivers: dw-axi-dmac: make more sensible choices
|
||||||
|
about memory accesses
|
||||||
|
|
||||||
|
There's no real need to constrain MEM access widths to 32-bit (or
|
||||||
|
narrower), as the DMAC is intelligent enough to size memory accesses
|
||||||
|
appropriately. Wider accesses are more efficient.
|
||||||
|
|
||||||
|
Similarly, MEM burst lengths don't need to be a function of DEV burst
|
||||||
|
lengths - the DMAC packs/unpacks data into/from its internal channel
|
||||||
|
FIFOs appropriately. Longer accesses are more efficient.
|
||||||
|
|
||||||
|
However, the DMAC doesn't have complete support for unaligned accesses,
|
||||||
|
and blocks are always defined in integer multiples of SRC_WIDTH, so odd
|
||||||
|
source lengths or buffer alignments will prevent wide accesses being
|
||||||
|
used, as before.
|
||||||
|
|
||||||
|
There is an implicit requirement to limit requested DEV read burst
|
||||||
|
lengths to less than the hardware's maximum configured MSIZE - otherwise
|
||||||
|
RX data will be left over at the end of a block. There is no config
|
||||||
|
register that reports this value, so the AXI burst length parameter is
|
||||||
|
used to produce a facsimile of it. Warn if such a request arrives that
|
||||||
|
doesn't respect this.
|
||||||
|
|
||||||
|
Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
|
||||||
|
---
|
||||||
|
.../dma/dw-axi-dmac/dw-axi-dmac-platform.c | 38 ++++++++++++-------
|
||||||
|
1 file changed, 25 insertions(+), 13 deletions(-)
|
||||||
|
|
||||||
|
--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
|
||||||
|
+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
|
||||||
|
@@ -261,6 +261,15 @@ static u32 axi_chan_get_xfer_width(struc
|
||||||
|
return __ffs(src | dst | len | BIT(max_width));
|
||||||
|
}
|
||||||
|
|
||||||
|
+static u32 axi_dma_encode_msize(u32 max_burst)
|
||||||
|
+{
|
||||||
|
+ if (max_burst <= 1)
|
||||||
|
+ return DWAXIDMAC_BURST_TRANS_LEN_1;
|
||||||
|
+ if (max_burst > 1024)
|
||||||
|
+ return DWAXIDMAC_BURST_TRANS_LEN_1024;
|
||||||
|
+ return fls(max_burst) - 2;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static inline const char *axi_chan_name(struct axi_dma_chan *chan)
|
||||||
|
{
|
||||||
|
return dma_chan_name(&chan->vc.chan);
|
||||||
|
@@ -685,41 +694,41 @@ static int dw_axi_dma_set_hw_desc(struct
|
||||||
|
size_t axi_block_ts;
|
||||||
|
size_t block_ts;
|
||||||
|
u32 ctllo, ctlhi;
|
||||||
|
- u32 burst_len;
|
||||||
|
+ u32 burst_len = 0, mem_burst_msize, reg_burst_msize;
|
||||||
|
|
||||||
|
axi_block_ts = chan->chip->dw->hdata->block_size[chan->id];
|
||||||
|
|
||||||
|
mem_width = __ffs(data_width | mem_addr | len);
|
||||||
|
- if (mem_width > DWAXIDMAC_TRANS_WIDTH_32)
|
||||||
|
- mem_width = DWAXIDMAC_TRANS_WIDTH_32;
|
||||||
|
|
||||||
|
if (!IS_ALIGNED(mem_addr, 4)) {
|
||||||
|
dev_err(chan->chip->dev, "invalid buffer alignment\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ /* Use a reasonable upper limit otherwise residue reporting granularity grows large */
|
||||||
|
+ mem_burst_msize = axi_dma_encode_msize(16);
|
||||||
|
+
|
||||||
|
switch (chan->direction) {
|
||||||
|
case DMA_MEM_TO_DEV:
|
||||||
|
+ reg_burst_msize = axi_dma_encode_msize(chan->config.dst_maxburst);
|
||||||
|
reg_width = __ffs(chan->config.dst_addr_width);
|
||||||
|
device_addr = phys_to_dma(chan->chip->dev, chan->config.dst_addr);
|
||||||
|
ctllo = reg_width << CH_CTL_L_DST_WIDTH_POS |
|
||||||
|
mem_width << CH_CTL_L_SRC_WIDTH_POS |
|
||||||
|
- DWAXIDMAC_BURST_TRANS_LEN_1 << CH_CTL_L_DST_MSIZE_POS |
|
||||||
|
- DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_SRC_MSIZE_POS |
|
||||||
|
+ reg_burst_msize << CH_CTL_L_DST_MSIZE_POS |
|
||||||
|
+ mem_burst_msize << CH_CTL_L_SRC_MSIZE_POS |
|
||||||
|
DWAXIDMAC_CH_CTL_L_NOINC << CH_CTL_L_DST_INC_POS |
|
||||||
|
DWAXIDMAC_CH_CTL_L_INC << CH_CTL_L_SRC_INC_POS;
|
||||||
|
block_ts = len >> mem_width;
|
||||||
|
break;
|
||||||
|
case DMA_DEV_TO_MEM:
|
||||||
|
+ reg_burst_msize = axi_dma_encode_msize(chan->config.src_maxburst);
|
||||||
|
reg_width = __ffs(chan->config.src_addr_width);
|
||||||
|
- /* Prevent partial access units getting lost */
|
||||||
|
- if (mem_width > reg_width)
|
||||||
|
- mem_width = reg_width;
|
||||||
|
device_addr = phys_to_dma(chan->chip->dev, chan->config.src_addr);
|
||||||
|
ctllo = reg_width << CH_CTL_L_SRC_WIDTH_POS |
|
||||||
|
mem_width << CH_CTL_L_DST_WIDTH_POS |
|
||||||
|
- DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_DST_MSIZE_POS |
|
||||||
|
- DWAXIDMAC_BURST_TRANS_LEN_1 << CH_CTL_L_SRC_MSIZE_POS |
|
||||||
|
+ mem_burst_msize << CH_CTL_L_DST_MSIZE_POS |
|
||||||
|
+ reg_burst_msize << CH_CTL_L_SRC_MSIZE_POS |
|
||||||
|
DWAXIDMAC_CH_CTL_L_INC << CH_CTL_L_DST_INC_POS |
|
||||||
|
DWAXIDMAC_CH_CTL_L_NOINC << CH_CTL_L_SRC_INC_POS;
|
||||||
|
block_ts = len >> reg_width;
|
||||||
|
@@ -760,6 +769,12 @@ static int dw_axi_dma_set_hw_desc(struct
|
||||||
|
set_desc_src_master(hw_desc);
|
||||||
|
|
||||||
|
hw_desc->len = len;
|
||||||
|
+
|
||||||
|
+ if (burst_len && (chan->config.src_maxburst > burst_len))
|
||||||
|
+ dev_warn_ratelimited(chan2dev(chan),
|
||||||
|
+ "%s: requested source burst length %u exceeds supported burst length %u - data may be lost\n",
|
||||||
|
+ axi_chan_name(chan), chan->config.src_maxburst, burst_len);
|
||||||
|
+
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -776,9 +791,6 @@ static size_t calculate_block_len(struct
|
||||||
|
case DMA_MEM_TO_DEV:
|
||||||
|
data_width = BIT(chan->chip->dw->hdata->m_data_width);
|
||||||
|
mem_width = __ffs(data_width | dma_addr | buf_len);
|
||||||
|
- if (mem_width > DWAXIDMAC_TRANS_WIDTH_32)
|
||||||
|
- mem_width = DWAXIDMAC_TRANS_WIDTH_32;
|
||||||
|
-
|
||||||
|
block_len = axi_block_ts << mem_width;
|
||||||
|
break;
|
||||||
|
case DMA_DEV_TO_MEM:
|
@ -0,0 +1,30 @@
|
|||||||
|
From f3cb675102a2a5a330038c4e748f02b02cec989e Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jonathan Bell <jonathan@raspberrypi.com>
|
||||||
|
Date: Mon, 22 Jul 2024 09:30:54 +0100
|
||||||
|
Subject: [PATCH 1195/1215] tty/serial: pl011: restrict RX burst FIFO threshold
|
||||||
|
|
||||||
|
If the associated DMA controller has lower burst length support than the
|
||||||
|
level the FIFO is set to, then bytes will be left in the RX FIFO at the
|
||||||
|
end of a DMA block - requiring a round-trip through the timeout interrupt
|
||||||
|
handler rather than an end-of-block DMA interrupt.
|
||||||
|
|
||||||
|
Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
|
||||||
|
---
|
||||||
|
drivers/tty/serial/amba-pl011.c | 6 ++++++
|
||||||
|
1 file changed, 6 insertions(+)
|
||||||
|
|
||||||
|
--- a/drivers/tty/serial/amba-pl011.c
|
||||||
|
+++ b/drivers/tty/serial/amba-pl011.c
|
||||||
|
@@ -487,6 +487,12 @@ static void pl011_dma_probe(struct uart_
|
||||||
|
"RX DMA disabled - no residue processing\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
+ /*
|
||||||
|
+ * DMA controllers with smaller burst capabilities than 1/4
|
||||||
|
+ * the FIFO depth will leave more bytes than expected in the
|
||||||
|
+ * RX FIFO if mismatched.
|
||||||
|
+ */
|
||||||
|
+ rx_conf.src_maxburst = min(caps.max_burst, rx_conf.src_maxburst);
|
||||||
|
}
|
||||||
|
dmaengine_slave_config(chan, &rx_conf);
|
||||||
|
uap->dmarx.chan = chan;
|
@ -0,0 +1,27 @@
|
|||||||
|
From 5112fd8cce4f1dc9bf43f0f90d35e273e1a0f555 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jonathan Bell <jonathan@raspberrypi.com>
|
||||||
|
Date: Mon, 22 Jul 2024 14:32:32 +0100
|
||||||
|
Subject: [PATCH 1196/1215] DT: bindings: add a dma-maxburst property to
|
||||||
|
snps,designware-i2s
|
||||||
|
|
||||||
|
Do an end-run around ASoC in lieu of not being able to easily find the
|
||||||
|
associated DMA controller capabilities.
|
||||||
|
|
||||||
|
Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
|
||||||
|
---
|
||||||
|
.../devicetree/bindings/sound/snps,designware-i2s.yaml | 4 ++++
|
||||||
|
1 file changed, 4 insertions(+)
|
||||||
|
|
||||||
|
--- a/Documentation/devicetree/bindings/sound/snps,designware-i2s.yaml
|
||||||
|
+++ b/Documentation/devicetree/bindings/sound/snps,designware-i2s.yaml
|
||||||
|
@@ -69,6 +69,10 @@ properties:
|
||||||
|
- description: RX DMA Channel
|
||||||
|
minItems: 1
|
||||||
|
|
||||||
|
+ dma-maxburst:
|
||||||
|
+ description: FIFO DMA burst threshold limit
|
||||||
|
+ maxItems: 1
|
||||||
|
+
|
||||||
|
dma-names:
|
||||||
|
items:
|
||||||
|
- const: tx
|
@ -0,0 +1,99 @@
|
|||||||
|
From b6b4260fa546d1dc7421c7cfed059052dae04227 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jonathan Bell <jonathan@raspberrypi.com>
|
||||||
|
Date: Thu, 18 Jul 2024 09:40:03 +0100
|
||||||
|
Subject: [PATCH 1197/1215] sound/soc: dwc-i2s: choose FIFO thresholds based on
|
||||||
|
DMA burst constraints
|
||||||
|
|
||||||
|
Valid ranges for the I2S peripheral's FIFO configuration include a depth
|
||||||
|
of 16 - unconditionally setting the burst length to 16 with a fifo
|
||||||
|
threshold of size/2 will cause under/overflows.
|
||||||
|
|
||||||
|
For DMA engines with restricted capabilities the requested burst length
|
||||||
|
and FIFO thresholds need to be adjusted downward accordingly.
|
||||||
|
|
||||||
|
Both the RX and TX FIFOs operate on "less-than" thresholds. Setting the
|
||||||
|
TX threshold to fifo_size minus burst means the FIFO is kept nearly-full.
|
||||||
|
|
||||||
|
Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
|
||||||
|
---
|
||||||
|
sound/soc/dwc/dwc-i2s.c | 21 ++++++++++++++++-----
|
||||||
|
sound/soc/dwc/local.h | 1 +
|
||||||
|
2 files changed, 17 insertions(+), 5 deletions(-)
|
||||||
|
|
||||||
|
--- a/sound/soc/dwc/dwc-i2s.c
|
||||||
|
+++ b/sound/soc/dwc/dwc-i2s.c
|
||||||
|
@@ -236,6 +236,8 @@ static void dw_i2s_config(struct dw_i2s_
|
||||||
|
u32 ch_reg;
|
||||||
|
struct i2s_clk_config_data *config = &dev->config;
|
||||||
|
u32 dmacr;
|
||||||
|
+ u32 comp1 = i2s_read_reg(dev->i2s_base, dev->i2s_reg_comp1);
|
||||||
|
+ u32 fifo_depth = 1 << (1 + COMP1_FIFO_DEPTH_GLOBAL(comp1));
|
||||||
|
|
||||||
|
i2s_disable_channels(dev, stream);
|
||||||
|
|
||||||
|
@@ -251,7 +253,7 @@ static void dw_i2s_config(struct dw_i2s_
|
||||||
|
i2s_write_reg(dev->i2s_base, TCR(ch_reg),
|
||||||
|
dev->xfer_resolution);
|
||||||
|
i2s_write_reg(dev->i2s_base, TFCR(ch_reg),
|
||||||
|
- dev->fifo_th - 1);
|
||||||
|
+ fifo_depth - dev->fifo_th - 1);
|
||||||
|
i2s_write_reg(dev->i2s_base, TER(ch_reg), TER_TXCHEN |
|
||||||
|
dev->tdm_mask << TER_TXSLOT_SHIFT);
|
||||||
|
dmacr |= (DMACR_DMAEN_TXCH0 << ch_reg);
|
||||||
|
@@ -783,8 +785,8 @@ static int dw_configure_dai_by_pd(struct
|
||||||
|
dev->capture_dma_data.pd.data = pdata->capture_dma_data;
|
||||||
|
dev->play_dma_data.pd.addr = res->start + I2S_TXDMA;
|
||||||
|
dev->capture_dma_data.pd.addr = res->start + I2S_RXDMA;
|
||||||
|
- dev->play_dma_data.pd.max_burst = 16;
|
||||||
|
- dev->capture_dma_data.pd.max_burst = 16;
|
||||||
|
+ dev->play_dma_data.pd.max_burst = dev->fifo_th;
|
||||||
|
+ dev->capture_dma_data.pd.max_burst = dev->fifo_th;
|
||||||
|
dev->play_dma_data.pd.addr_width = bus_widths[idx];
|
||||||
|
dev->capture_dma_data.pd.addr_width = bus_widths[idx];
|
||||||
|
dev->play_dma_data.pd.filter = pdata->filter;
|
||||||
|
@@ -815,7 +817,10 @@ static int dw_configure_dai_by_dt(struct
|
||||||
|
dev->play_dma_data.dt.addr = res->start + I2S_TXDMA;
|
||||||
|
dev->play_dma_data.dt.fifo_size = fifo_depth *
|
||||||
|
(fifo_width[idx2]) >> 8;
|
||||||
|
- dev->play_dma_data.dt.maxburst = 16;
|
||||||
|
+ if (dev->max_dma_burst)
|
||||||
|
+ dev->play_dma_data.dt.maxburst = dev->max_dma_burst;
|
||||||
|
+ else
|
||||||
|
+ dev->play_dma_data.dt.maxburst = fifo_depth / 2;
|
||||||
|
}
|
||||||
|
if (COMP1_RX_ENABLED(comp1)) {
|
||||||
|
idx2 = COMP2_RX_WORDSIZE_0(comp2);
|
||||||
|
@@ -824,9 +829,14 @@ static int dw_configure_dai_by_dt(struct
|
||||||
|
dev->capture_dma_data.dt.addr = res->start + I2S_RXDMA;
|
||||||
|
dev->capture_dma_data.dt.fifo_size = fifo_depth *
|
||||||
|
(fifo_width[idx2] >> 8);
|
||||||
|
- dev->capture_dma_data.dt.maxburst = 16;
|
||||||
|
+ if (dev->max_dma_burst)
|
||||||
|
+ dev->capture_dma_data.dt.maxburst = dev->max_dma_burst;
|
||||||
|
+ else
|
||||||
|
+ dev->capture_dma_data.dt.maxburst = fifo_depth / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (dev->max_dma_burst)
|
||||||
|
+ dev->fifo_th = min(dev->max_dma_burst, dev->fifo_th);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
@@ -1070,6 +1080,7 @@ static int dw_i2s_probe(struct platform_
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ of_property_read_u32(pdev->dev.of_node, "dma-maxburst", &dev->max_dma_burst);
|
||||||
|
dev->bclk_ratio = 0;
|
||||||
|
dev->i2s_reg_comp1 = I2S_COMP_PARAM_1;
|
||||||
|
dev->i2s_reg_comp2 = I2S_COMP_PARAM_2;
|
||||||
|
--- a/sound/soc/dwc/local.h
|
||||||
|
+++ b/sound/soc/dwc/local.h
|
||||||
|
@@ -133,6 +133,7 @@ struct dw_i2s_dev {
|
||||||
|
u32 ccr;
|
||||||
|
u32 xfer_resolution;
|
||||||
|
u32 fifo_th;
|
||||||
|
+ u32 max_dma_burst;
|
||||||
|
u32 l_reg;
|
||||||
|
u32 r_reg;
|
||||||
|
bool is_jh7110; /* Flag for StarFive JH7110 SoC */
|
@ -0,0 +1,30 @@
|
|||||||
|
From 062434ab3be76d4fa5973bb199ccfd5b68c11720 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jonathan Bell <jonathan@raspberrypi.com>
|
||||||
|
Date: Tue, 23 Jul 2024 11:21:47 +0100
|
||||||
|
Subject: [PATCH 1198/1215] dts: rp1: restrict i2s burst lengths to 4
|
||||||
|
|
||||||
|
The associated DMAC has channels that do not support longer bursts.
|
||||||
|
|
||||||
|
Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
|
||||||
|
---
|
||||||
|
arch/arm64/boot/dts/broadcom/rp1.dtsi | 2 ++
|
||||||
|
1 file changed, 2 insertions(+)
|
||||||
|
|
||||||
|
--- a/arch/arm64/boot/dts/broadcom/rp1.dtsi
|
||||||
|
+++ b/arch/arm64/boot/dts/broadcom/rp1.dtsi
|
||||||
|
@@ -400,6 +400,7 @@
|
||||||
|
#sound-dai-cells = <0>;
|
||||||
|
dmas = <&rp1_dma RP1_DMA_I2S0_TX>,<&rp1_dma RP1_DMA_I2S0_RX>;
|
||||||
|
dma-names = "tx", "rx";
|
||||||
|
+ dma-maxburst = <4>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -413,6 +414,7 @@
|
||||||
|
#sound-dai-cells = <0>;
|
||||||
|
dmas = <&rp1_dma RP1_DMA_I2S1_TX>,<&rp1_dma RP1_DMA_I2S1_RX>;
|
||||||
|
dma-names = "tx", "rx";
|
||||||
|
+ dma-maxburst = <4>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,204 @@
|
|||||||
|
From 485d11cfa7df2d2deb39c9b3455cebcb1a85cea2 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
||||||
|
Date: Thu, 25 Jul 2024 14:36:32 +0100
|
||||||
|
Subject: [PATCH 1199/1215] drm/vc4: Disable the 2pixel/clock odd timings
|
||||||
|
workaround for interlaced
|
||||||
|
|
||||||
|
Whilst BCM2712 does fix using odd horizontal timings, it doesn't
|
||||||
|
work with interlaced modes.
|
||||||
|
|
||||||
|
Drop the workaround for interlaced modes and revert to the same
|
||||||
|
behaviour as BCM2711.
|
||||||
|
|
||||||
|
https://github.com/raspberrypi/linux/issues/6281
|
||||||
|
|
||||||
|
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
||||||
|
---
|
||||||
|
drivers/gpu/drm/vc4/vc4_crtc.c | 20 +++++++++++++++++---
|
||||||
|
drivers/gpu/drm/vc4/vc4_drv.h | 2 ++
|
||||||
|
drivers/gpu/drm/vc4/vc4_hdmi.c | 8 +++++++-
|
||||||
|
drivers/gpu/drm/vc4/vc4_hdmi.h | 4 ++++
|
||||||
|
4 files changed, 30 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
|
||||||
|
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
|
||||||
|
@@ -378,7 +378,9 @@ static void vc4_crtc_config_pv(struct dr
|
||||||
|
bool is_dsi1 = vc4_encoder->type == VC4_ENCODER_TYPE_DSI1;
|
||||||
|
bool is_vec = vc4_encoder->type == VC4_ENCODER_TYPE_VEC;
|
||||||
|
u32 format = is_dsi1 ? PV_CONTROL_FORMAT_DSIV_24 : PV_CONTROL_FORMAT_24;
|
||||||
|
- u8 ppc = pv_data->pixels_per_clock;
|
||||||
|
+ u8 ppc = (mode->flags & DRM_MODE_FLAG_INTERLACE) ?
|
||||||
|
+ pv_data->pixels_per_clock_int :
|
||||||
|
+ pv_data->pixels_per_clock;
|
||||||
|
|
||||||
|
u16 vert_bp = mode->crtc_vtotal - mode->crtc_vsync_end;
|
||||||
|
u16 vert_sync = mode->crtc_vsync_end - mode->crtc_vsync_start;
|
||||||
|
@@ -443,7 +445,8 @@ static void vc4_crtc_config_pv(struct dr
|
||||||
|
*/
|
||||||
|
CRTC_WRITE(PV_V_CONTROL,
|
||||||
|
PV_VCONTROL_CONTINUOUS |
|
||||||
|
- (vc4->gen >= VC4_GEN_6 ? PV_VCONTROL_ODD_TIMING : 0) |
|
||||||
|
+ (vc4->gen >= VC4_GEN_6 && ppc == 1 ?
|
||||||
|
+ PV_VCONTROL_ODD_TIMING : 0) |
|
||||||
|
(is_dsi ? PV_VCONTROL_DSI : 0) |
|
||||||
|
PV_VCONTROL_INTERLACE |
|
||||||
|
(odd_field_first
|
||||||
|
@@ -455,7 +458,8 @@ static void vc4_crtc_config_pv(struct dr
|
||||||
|
} else {
|
||||||
|
CRTC_WRITE(PV_V_CONTROL,
|
||||||
|
PV_VCONTROL_CONTINUOUS |
|
||||||
|
- (vc4->gen >= VC4_GEN_6 ? PV_VCONTROL_ODD_TIMING : 0) |
|
||||||
|
+ (vc4->gen >= VC4_GEN_6 && ppc == 1 ?
|
||||||
|
+ PV_VCONTROL_ODD_TIMING : 0) |
|
||||||
|
(is_dsi ? PV_VCONTROL_DSI : 0));
|
||||||
|
CRTC_WRITE(PV_VSYNCD_EVEN, 0);
|
||||||
|
}
|
||||||
|
@@ -1223,6 +1227,7 @@ const struct vc4_pv_data bcm2835_pv0_dat
|
||||||
|
},
|
||||||
|
.fifo_depth = 64,
|
||||||
|
.pixels_per_clock = 1,
|
||||||
|
+ .pixels_per_clock_int = 1,
|
||||||
|
.encoder_types = {
|
||||||
|
[PV_CONTROL_CLK_SELECT_DSI] = VC4_ENCODER_TYPE_DSI0,
|
||||||
|
[PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_DPI,
|
||||||
|
@@ -1238,6 +1243,7 @@ const struct vc4_pv_data bcm2835_pv1_dat
|
||||||
|
},
|
||||||
|
.fifo_depth = 64,
|
||||||
|
.pixels_per_clock = 1,
|
||||||
|
+ .pixels_per_clock_int = 1,
|
||||||
|
.encoder_types = {
|
||||||
|
[PV_CONTROL_CLK_SELECT_DSI] = VC4_ENCODER_TYPE_DSI1,
|
||||||
|
[PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_SMI,
|
||||||
|
@@ -1253,6 +1259,7 @@ const struct vc4_pv_data bcm2835_pv2_dat
|
||||||
|
},
|
||||||
|
.fifo_depth = 64,
|
||||||
|
.pixels_per_clock = 1,
|
||||||
|
+ .pixels_per_clock_int = 1,
|
||||||
|
.encoder_types = {
|
||||||
|
[PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_HDMI0,
|
||||||
|
[PV_CONTROL_CLK_SELECT_VEC] = VC4_ENCODER_TYPE_VEC,
|
||||||
|
@@ -1268,6 +1275,7 @@ const struct vc4_pv_data bcm2711_pv0_dat
|
||||||
|
},
|
||||||
|
.fifo_depth = 64,
|
||||||
|
.pixels_per_clock = 1,
|
||||||
|
+ .pixels_per_clock_int = 1,
|
||||||
|
.encoder_types = {
|
||||||
|
[0] = VC4_ENCODER_TYPE_DSI0,
|
||||||
|
[1] = VC4_ENCODER_TYPE_DPI,
|
||||||
|
@@ -1283,6 +1291,7 @@ const struct vc4_pv_data bcm2711_pv1_dat
|
||||||
|
},
|
||||||
|
.fifo_depth = 64,
|
||||||
|
.pixels_per_clock = 1,
|
||||||
|
+ .pixels_per_clock_int = 1,
|
||||||
|
.encoder_types = {
|
||||||
|
[0] = VC4_ENCODER_TYPE_DSI1,
|
||||||
|
[1] = VC4_ENCODER_TYPE_SMI,
|
||||||
|
@@ -1298,6 +1307,7 @@ const struct vc4_pv_data bcm2711_pv2_dat
|
||||||
|
},
|
||||||
|
.fifo_depth = 256,
|
||||||
|
.pixels_per_clock = 2,
|
||||||
|
+ .pixels_per_clock_int = 2,
|
||||||
|
.encoder_types = {
|
||||||
|
[0] = VC4_ENCODER_TYPE_HDMI0,
|
||||||
|
},
|
||||||
|
@@ -1312,6 +1322,7 @@ const struct vc4_pv_data bcm2711_pv3_dat
|
||||||
|
},
|
||||||
|
.fifo_depth = 64,
|
||||||
|
.pixels_per_clock = 1,
|
||||||
|
+ .pixels_per_clock_int = 1,
|
||||||
|
.encoder_types = {
|
||||||
|
[PV_CONTROL_CLK_SELECT_VEC] = VC4_ENCODER_TYPE_VEC,
|
||||||
|
},
|
||||||
|
@@ -1326,6 +1337,7 @@ const struct vc4_pv_data bcm2711_pv4_dat
|
||||||
|
},
|
||||||
|
.fifo_depth = 64,
|
||||||
|
.pixels_per_clock = 2,
|
||||||
|
+ .pixels_per_clock_int = 2,
|
||||||
|
.encoder_types = {
|
||||||
|
[0] = VC4_ENCODER_TYPE_HDMI1,
|
||||||
|
},
|
||||||
|
@@ -1339,6 +1351,7 @@ const struct vc4_pv_data bcm2712_pv0_dat
|
||||||
|
},
|
||||||
|
.fifo_depth = 64,
|
||||||
|
.pixels_per_clock = 1,
|
||||||
|
+ .pixels_per_clock_int = 2,
|
||||||
|
.encoder_types = {
|
||||||
|
[0] = VC4_ENCODER_TYPE_HDMI0,
|
||||||
|
},
|
||||||
|
@@ -1352,6 +1365,7 @@ const struct vc4_pv_data bcm2712_pv1_dat
|
||||||
|
},
|
||||||
|
.fifo_depth = 64,
|
||||||
|
.pixels_per_clock = 1,
|
||||||
|
+ .pixels_per_clock_int = 2,
|
||||||
|
.encoder_types = {
|
||||||
|
[0] = VC4_ENCODER_TYPE_HDMI1,
|
||||||
|
},
|
||||||
|
--- a/drivers/gpu/drm/vc4/vc4_drv.h
|
||||||
|
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
|
||||||
|
@@ -569,6 +569,8 @@ struct vc4_pv_data {
|
||||||
|
|
||||||
|
/* Number of pixels output per clock period */
|
||||||
|
u8 pixels_per_clock;
|
||||||
|
+ /* Number of pixels output per clock period when in an interlaced mode */
|
||||||
|
+ u8 pixels_per_clock_int;
|
||||||
|
|
||||||
|
enum vc4_encoder_type encoder_types[4];
|
||||||
|
};
|
||||||
|
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
|
||||||
|
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
|
||||||
|
@@ -2263,7 +2263,9 @@ static int vc4_hdmi_encoder_atomic_check
|
||||||
|
unsigned long long tmds_bit_rate;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
- if (vc4_hdmi->variant->unsupported_odd_h_timings) {
|
||||||
|
+ if (vc4_hdmi->variant->unsupported_odd_h_timings ||
|
||||||
|
+ (vc4_hdmi->variant->unsupported_int_odd_h_timings &&
|
||||||
|
+ (mode->flags & DRM_MODE_FLAG_INTERLACE))) {
|
||||||
|
if (mode->flags & DRM_MODE_FLAG_DBLCLK) {
|
||||||
|
/* Only try to fixup DBLCLK modes to get 480i and 576i
|
||||||
|
* working.
|
||||||
|
@@ -3974,6 +3976,7 @@ static const struct vc4_hdmi_variant bcm
|
||||||
|
PHY_LANE_CK,
|
||||||
|
},
|
||||||
|
.unsupported_odd_h_timings = true,
|
||||||
|
+ .unsupported_int_odd_h_timings = true,
|
||||||
|
.external_irq_controller = true,
|
||||||
|
|
||||||
|
.init_resources = vc5_hdmi_init_resources,
|
||||||
|
@@ -4003,6 +4006,7 @@ static const struct vc4_hdmi_variant bcm
|
||||||
|
PHY_LANE_2,
|
||||||
|
},
|
||||||
|
.unsupported_odd_h_timings = true,
|
||||||
|
+ .unsupported_int_odd_h_timings = true,
|
||||||
|
.external_irq_controller = true,
|
||||||
|
|
||||||
|
.init_resources = vc5_hdmi_init_resources,
|
||||||
|
@@ -4032,6 +4036,7 @@ static const struct vc4_hdmi_variant bcm
|
||||||
|
PHY_LANE_CK,
|
||||||
|
},
|
||||||
|
.unsupported_odd_h_timings = false,
|
||||||
|
+ .unsupported_int_odd_h_timings = true,
|
||||||
|
.external_irq_controller = true,
|
||||||
|
|
||||||
|
.init_resources = vc5_hdmi_init_resources,
|
||||||
|
@@ -4059,6 +4064,7 @@ static const struct vc4_hdmi_variant bcm
|
||||||
|
PHY_LANE_CK,
|
||||||
|
},
|
||||||
|
.unsupported_odd_h_timings = false,
|
||||||
|
+ .unsupported_int_odd_h_timings = true,
|
||||||
|
.external_irq_controller = true,
|
||||||
|
|
||||||
|
.init_resources = vc5_hdmi_init_resources,
|
||||||
|
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
|
||||||
|
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
|
||||||
|
@@ -49,6 +49,10 @@ struct vc4_hdmi_variant {
|
||||||
|
|
||||||
|
/* The BCM2711 cannot deal with odd horizontal pixel timings */
|
||||||
|
bool unsupported_odd_h_timings;
|
||||||
|
+ /* The BCM2712 can handle odd horizontal pixel timings, but not in
|
||||||
|
+ * interlaced modes
|
||||||
|
+ */
|
||||||
|
+ bool unsupported_int_odd_h_timings;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The BCM2711 CEC/hotplug IRQ controller is shared between the
|
@ -0,0 +1,26 @@
|
|||||||
|
From 70636ad110715b5e1ec6b08e24f0ddaf5df7186d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Dom Cobley <popcornmix@gmail.com>
|
||||||
|
Date: Tue, 30 Jul 2024 19:00:03 +0100
|
||||||
|
Subject: [PATCH 1200/1215] ARM: dts: bcm2712: Fix invalid
|
||||||
|
polling-delay-passive setting
|
||||||
|
|
||||||
|
This produces a hard fail on later (6.11) kernels.
|
||||||
|
|
||||||
|
See: https://lore.kernel.org/all/5802156.DvuYhMxLoT@rjwysocki.net/
|
||||||
|
|
||||||
|
Signed-off-by: Dom Cobley <popcornmix@gmail.com>
|
||||||
|
---
|
||||||
|
arch/arm64/boot/dts/broadcom/bcm2712.dtsi | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
--- a/arch/arm64/boot/dts/broadcom/bcm2712.dtsi
|
||||||
|
+++ b/arch/arm64/boot/dts/broadcom/bcm2712.dtsi
|
||||||
|
@@ -40,7 +40,7 @@
|
||||||
|
|
||||||
|
thermal-zones {
|
||||||
|
cpu_thermal: cpu-thermal {
|
||||||
|
- polling-delay-passive = <2000>;
|
||||||
|
+ polling-delay-passive = <1000>;
|
||||||
|
polling-delay = <1000>;
|
||||||
|
coefficients = <(-550) 450000>;
|
||||||
|
thermal-sensors = <&thermal>;
|
@ -0,0 +1,143 @@
|
|||||||
|
From 199e611183de09ad91fe01fc79da78cc9d11ccb6 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Phil Elwell <phil@raspberrypi.com>
|
||||||
|
Date: Mon, 29 Jul 2024 11:12:38 +0100
|
||||||
|
Subject: [PATCH 1201/1215] spi: dw: Fix non-DMA transmit-only transfers
|
||||||
|
|
||||||
|
Ensure the transmit FIFO has emptied before ending the transfer by
|
||||||
|
dropping the TX threshold to 0 when the last byte has been pushed into
|
||||||
|
the FIFO. Include a similar fix for the non-IRQ paths.
|
||||||
|
|
||||||
|
See: https://github.com/raspberrypi/linux/issues/6285
|
||||||
|
Fixes: 6014649de765 ("spi: dw: Save bandwidth with the TMOD_TO feature")
|
||||||
|
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||||
|
---
|
||||||
|
drivers/spi/spi-dw-core.c | 62 +++++++++++++++++++++++++++++++++------
|
||||||
|
drivers/spi/spi-dw.h | 3 ++
|
||||||
|
2 files changed, 56 insertions(+), 9 deletions(-)
|
||||||
|
|
||||||
|
--- a/drivers/spi/spi-dw-core.c
|
||||||
|
+++ b/drivers/spi/spi-dw-core.c
|
||||||
|
@@ -220,6 +220,32 @@ int dw_spi_check_status(struct dw_spi *d
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_NS_GPL(dw_spi_check_status, SPI_DW_CORE);
|
||||||
|
|
||||||
|
+static inline bool dw_spi_ctlr_busy(struct dw_spi *dws)
|
||||||
|
+{
|
||||||
|
+ return dw_readl(dws, DW_SPI_SR) & DW_SPI_SR_BUSY;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static enum hrtimer_restart dw_spi_hrtimer_handler(struct hrtimer *hr)
|
||||||
|
+{
|
||||||
|
+ struct dw_spi *dws = container_of(hr, struct dw_spi, hrtimer);
|
||||||
|
+
|
||||||
|
+ if (!dw_spi_ctlr_busy(dws)) {
|
||||||
|
+ spi_finalize_current_transfer(dws->host);
|
||||||
|
+ return HRTIMER_NORESTART;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!dws->idle_wait_retries) {
|
||||||
|
+ dev_err(&dws->host->dev, "controller stuck at busy\n");
|
||||||
|
+ spi_finalize_current_transfer(dws->host);
|
||||||
|
+ return HRTIMER_NORESTART;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ dws->idle_wait_retries--;
|
||||||
|
+ hrtimer_forward_now(hr, dws->idle_wait_interval);
|
||||||
|
+
|
||||||
|
+ return HRTIMER_RESTART;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static irqreturn_t dw_spi_transfer_handler(struct dw_spi *dws)
|
||||||
|
{
|
||||||
|
u16 irq_status = dw_readl(dws, DW_SPI_ISR);
|
||||||
|
@@ -246,7 +272,22 @@ static irqreturn_t dw_spi_transfer_handl
|
||||||
|
}
|
||||||
|
} else if (!dws->tx_len) {
|
||||||
|
dw_spi_mask_intr(dws, DW_SPI_INT_TXEI);
|
||||||
|
- spi_finalize_current_transfer(dws->host);
|
||||||
|
+ if (dw_spi_ctlr_busy(dws)) {
|
||||||
|
+ ktime_t period = ns_to_ktime(DIV_ROUND_UP(NSEC_PER_SEC, dws->current_freq));
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Make the initial wait an underestimate of how long the transfer
|
||||||
|
+ * should take, then poll rapidly to reduce the delay
|
||||||
|
+ */
|
||||||
|
+ hrtimer_start(&dws->hrtimer,
|
||||||
|
+ period * (8 * dws->n_bytes - 1),
|
||||||
|
+ HRTIMER_MODE_REL);
|
||||||
|
+ dws->idle_wait_retries = 10;
|
||||||
|
+ dws->idle_wait_interval = period;
|
||||||
|
+ } else {
|
||||||
|
+ spi_finalize_current_transfer(dws->host);
|
||||||
|
+ }
|
||||||
|
+ return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -255,9 +296,13 @@ static irqreturn_t dw_spi_transfer_handl
|
||||||
|
* have the TXE IRQ flood at the final stage of the transfer.
|
||||||
|
*/
|
||||||
|
if (irq_status & DW_SPI_INT_TXEI) {
|
||||||
|
- if (!dws->tx_len)
|
||||||
|
- dw_spi_mask_intr(dws, DW_SPI_INT_TXEI);
|
||||||
|
dw_writer(dws);
|
||||||
|
+ if (!dws->tx_len) {
|
||||||
|
+ if (dws->rx_len)
|
||||||
|
+ dw_spi_mask_intr(dws, DW_SPI_INT_TXEI);
|
||||||
|
+ else
|
||||||
|
+ dw_writel(dws, DW_SPI_TXFTLR, 0);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
@@ -428,7 +473,7 @@ static int dw_spi_poll_transfer(struct d
|
||||||
|
ret = dw_spi_check_status(dws, true);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
- } while (dws->rx_len);
|
||||||
|
+ } while (dws->rx_len || dws->tx_len || dw_spi_ctlr_busy(dws));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@@ -652,11 +697,6 @@ static int dw_spi_write_then_read(struct
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static inline bool dw_spi_ctlr_busy(struct dw_spi *dws)
|
||||||
|
-{
|
||||||
|
- return dw_readl(dws, DW_SPI_SR) & DW_SPI_SR_BUSY;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
static int dw_spi_wait_mem_op_done(struct dw_spi *dws)
|
||||||
|
{
|
||||||
|
int retry = DW_SPI_WAIT_RETRIES;
|
||||||
|
@@ -993,6 +1033,9 @@ int dw_spi_add_host(struct device *dev,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ hrtimer_init(&dws->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
|
||||||
|
+ dws->hrtimer.function = dw_spi_hrtimer_handler;
|
||||||
|
+
|
||||||
|
ret = spi_register_controller(host);
|
||||||
|
if (ret) {
|
||||||
|
dev_err_probe(dev, ret, "problem registering spi host\n");
|
||||||
|
@@ -1018,6 +1061,7 @@ void dw_spi_remove_host(struct dw_spi *d
|
||||||
|
{
|
||||||
|
dw_spi_debugfs_remove(dws);
|
||||||
|
|
||||||
|
+ hrtimer_cancel(&dws->hrtimer);
|
||||||
|
spi_unregister_controller(dws->host);
|
||||||
|
|
||||||
|
if (dws->dma_ops && dws->dma_ops->dma_exit)
|
||||||
|
--- a/drivers/spi/spi-dw.h
|
||||||
|
+++ b/drivers/spi/spi-dw.h
|
||||||
|
@@ -180,6 +180,9 @@ struct dw_spi {
|
||||||
|
u32 current_freq; /* frequency in hz */
|
||||||
|
u32 cur_rx_sample_dly;
|
||||||
|
u32 def_rx_sample_dly_ns;
|
||||||
|
+ struct hrtimer hrtimer;
|
||||||
|
+ ktime_t idle_wait_interval;
|
||||||
|
+ int idle_wait_retries;
|
||||||
|
|
||||||
|
/* Custom memory operations */
|
||||||
|
struct spi_controller_mem_ops mem_ops;
|
@ -0,0 +1,26 @@
|
|||||||
|
From e9294823cf02068189a0e901223ed4991923c689 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Phil Elwell <phil@raspberrypi.com>
|
||||||
|
Date: Wed, 31 Jul 2024 10:55:19 +0100
|
||||||
|
Subject: [PATCH 1202/1215] spi: dw: Clamp the minimum clock speed
|
||||||
|
|
||||||
|
The DW SPI interface has a 16-bit clock divider, where the bottom bit
|
||||||
|
of the divisor must be 0. Limit how low the clock speed can go to
|
||||||
|
prevent the clock divider from being truncated, as that could lead to
|
||||||
|
a much higher clock rate than requested.
|
||||||
|
|
||||||
|
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||||
|
---
|
||||||
|
drivers/spi/spi-dw-core.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
--- a/drivers/spi/spi-dw-core.c
|
||||||
|
+++ b/drivers/spi/spi-dw-core.c
|
||||||
|
@@ -397,7 +397,7 @@ void dw_spi_update_config(struct dw_spi
|
||||||
|
dw_writel(dws, DW_SPI_CTRLR1, cfg->ndf ? cfg->ndf - 1 : 0);
|
||||||
|
|
||||||
|
/* Note DW APB SSI clock divider doesn't support odd numbers */
|
||||||
|
- clk_div = (DIV_ROUND_UP(dws->max_freq, cfg->freq) + 1) & 0xfffe;
|
||||||
|
+ clk_div = min(DIV_ROUND_UP(dws->max_freq, cfg->freq) + 1, 0xfffe) & 0xfffe;
|
||||||
|
speed_hz = dws->max_freq / clk_div;
|
||||||
|
|
||||||
|
if (dws->current_freq != speed_hz) {
|
@ -0,0 +1,26 @@
|
|||||||
|
From 05e3687c6c973c30bf35f3b7f4a7589b5030a830 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Phil Elwell <phil@raspberrypi.com>
|
||||||
|
Date: Wed, 31 Jul 2024 13:19:26 +0100
|
||||||
|
Subject: [PATCH 1203/1215] overlays: i2c-rtc: Correct bq32000 property name
|
||||||
|
|
||||||
|
The DT property for the BQ32000 controlled by trickle-resistor-ohms
|
||||||
|
parameter should be "trickle-resistor-ohms", not "abracon,tc-resistor".
|
||||||
|
|
||||||
|
See: https://github.com/raspberrypi/linux/issues/6291
|
||||||
|
|
||||||
|
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||||
|
---
|
||||||
|
arch/arm/boot/dts/overlays/i2c-rtc-common.dtsi | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
--- a/arch/arm/boot/dts/overlays/i2c-rtc-common.dtsi
|
||||||
|
+++ b/arch/arm/boot/dts/overlays/i2c-rtc-common.dtsi
|
||||||
|
@@ -354,7 +354,7 @@
|
||||||
|
<&rv3028>,"trickle-resistor-ohms:0",
|
||||||
|
<&rv3032>,"trickle-resistor-ohms:0",
|
||||||
|
<&rv1805>,"abracon,tc-resistor:0",
|
||||||
|
- <&bq32000>,"abracon,tc-resistor:0";
|
||||||
|
+ <&bq32000>,"trickle-resistor-ohms:0";
|
||||||
|
trickle-voltage-mv = <&rv3032>,"trickle-voltage-millivolts:0";
|
||||||
|
backup-switchover-mode = <&rv3028>,"backup-switchover-mode:0";
|
||||||
|
wakeup-source = <&ds1339>,"wakeup-source?",
|
@ -0,0 +1,31 @@
|
|||||||
|
From 16d0ee22d2c0b32cc67db73ce03263b740bba2a7 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Phil Elwell <phil@raspberrypi.com>
|
||||||
|
Date: Wed, 31 Jul 2024 15:02:47 +0100
|
||||||
|
Subject: [PATCH 1204/1215] hwmon: (adt7410) Add DT compatible strings
|
||||||
|
|
||||||
|
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||||
|
---
|
||||||
|
drivers/hwmon/adt7410.c | 8 ++++++++
|
||||||
|
1 file changed, 8 insertions(+)
|
||||||
|
|
||||||
|
--- a/drivers/hwmon/adt7410.c
|
||||||
|
+++ b/drivers/hwmon/adt7410.c
|
||||||
|
@@ -94,10 +94,18 @@ static const struct i2c_device_id adt741
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(i2c, adt7410_ids);
|
||||||
|
|
||||||
|
+static const struct of_device_id adt7410_of_ids[] = {
|
||||||
|
+ { .compatible = "adi,adt7410" },
|
||||||
|
+ { .compatible = "adi,adt7420" },
|
||||||
|
+ {}
|
||||||
|
+};
|
||||||
|
+MODULE_DEVICE_TABLE(of, adt7410_of_ids);
|
||||||
|
+
|
||||||
|
static struct i2c_driver adt7410_driver = {
|
||||||
|
.class = I2C_CLASS_HWMON,
|
||||||
|
.driver = {
|
||||||
|
.name = "adt7410",
|
||||||
|
+ .of_match_table = adt7410_of_ids,
|
||||||
|
.pm = pm_sleep_ptr(&adt7x10_dev_pm_ops),
|
||||||
|
},
|
||||||
|
.probe = adt7410_i2c_probe,
|
@ -0,0 +1,23 @@
|
|||||||
|
From a4bf61fad9fe102514243ed263c458b053c87681 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Phil Elwell <phil@raspberrypi.com>
|
||||||
|
Date: Fri, 2 Aug 2024 11:29:03 +0100
|
||||||
|
Subject: [PATCH 1205/1215] fixup! pinctrl: bcm2712 pinctrl/pinconf driver
|
||||||
|
|
||||||
|
Fix cut-and-paste error spotted during upstreaming process.
|
||||||
|
|
||||||
|
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||||
|
---
|
||||||
|
drivers/pinctrl/bcm/pinctrl-bcm2712.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
--- a/drivers/pinctrl/bcm/pinctrl-bcm2712.c
|
||||||
|
+++ b/drivers/pinctrl/bcm/pinctrl-bcm2712.c
|
||||||
|
@@ -1029,7 +1029,7 @@ static int bcm2712_pinconf_get(struct pi
|
||||||
|
|
||||||
|
*config = pinconf_to_config_packed(param, arg);
|
||||||
|
|
||||||
|
- return -ENOTSUPP;
|
||||||
|
+ return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bcm2712_pinconf_set(struct pinctrl_dev *pctldev,
|
@ -0,0 +1,125 @@
|
|||||||
|
From e94e761305fa2281718adcf625d78f3cf662e12d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
||||||
|
Date: Thu, 1 Aug 2024 18:12:50 +0100
|
||||||
|
Subject: [PATCH 1206/1215] dtoverlays: Add overlay for HD44780 via I2C PCF8574
|
||||||
|
backpack
|
||||||
|
|
||||||
|
Many HD44780 LCD displays are connected via very common I2C
|
||||||
|
GPIO expander.
|
||||||
|
We have an overlay for connecting the displays directly to GPIOs,
|
||||||
|
but not one for it connected via a backpack. Add such an overlay.
|
||||||
|
|
||||||
|
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
||||||
|
---
|
||||||
|
arch/arm/boot/dts/overlays/Makefile | 1 +
|
||||||
|
arch/arm/boot/dts/overlays/README | 27 +++++++++
|
||||||
|
.../dts/overlays/hd44780-i2c-lcd-overlay.dts | 57 +++++++++++++++++++
|
||||||
|
3 files changed, 85 insertions(+)
|
||||||
|
create mode 100644 arch/arm/boot/dts/overlays/hd44780-i2c-lcd-overlay.dts
|
||||||
|
|
||||||
|
--- a/arch/arm/boot/dts/overlays/Makefile
|
||||||
|
+++ b/arch/arm/boot/dts/overlays/Makefile
|
||||||
|
@@ -82,6 +82,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
|
||||||
|
gpio-no-irq.dtbo \
|
||||||
|
gpio-poweroff.dtbo \
|
||||||
|
gpio-shutdown.dtbo \
|
||||||
|
+ hd44780-i2c-lcd.dtbo \
|
||||||
|
hd44780-lcd.dtbo \
|
||||||
|
hdmi-backlight-hwhack-gpio.dtbo \
|
||||||
|
hifiberry-amp.dtbo \
|
||||||
|
--- a/arch/arm/boot/dts/overlays/README
|
||||||
|
+++ b/arch/arm/boot/dts/overlays/README
|
||||||
|
@@ -1705,6 +1705,33 @@ Params: gpio_pin GPIO pin
|
||||||
|
(default 100)
|
||||||
|
|
||||||
|
|
||||||
|
+Name: hd44780-i2c-lcd
|
||||||
|
+Info: Configures an HD44780 compatible LCD display connected via a PCF8574 as
|
||||||
|
+ is often found as a backpack interface for these displays.
|
||||||
|
+Load: dtoverlay=hd44780-i2c-lcd,<param>=<val>
|
||||||
|
+Params: addr I2C address of PCF8574
|
||||||
|
+ pin_d4 GPIO pin for data pin D4 (default 4)
|
||||||
|
+
|
||||||
|
+ pin_d5 GPIO pin for data pin D5 (default 5)
|
||||||
|
+
|
||||||
|
+ pin_d6 GPIO pin for data pin D6 (default 6)
|
||||||
|
+
|
||||||
|
+ pin_d7 GPIO pin for data pin D7 (default 7)
|
||||||
|
+
|
||||||
|
+ pin_en GPIO pin for "Enable" (default 2)
|
||||||
|
+
|
||||||
|
+ pin_rs GPIO pin for "Register Select" (default 0)
|
||||||
|
+
|
||||||
|
+ pin_rw GPIO pin for R/W select (default 1)
|
||||||
|
+
|
||||||
|
+ pin_bl GPIO pin for enabling/disabling the display
|
||||||
|
+ backlight. (default 3)
|
||||||
|
+
|
||||||
|
+ display_height Height of the display in characters (default 2)
|
||||||
|
+
|
||||||
|
+ display_width Width of the display in characters (default 16)
|
||||||
|
+
|
||||||
|
+
|
||||||
|
Name: hd44780-lcd
|
||||||
|
Info: Configures an HD44780 compatible LCD display. Uses 4 gpio pins for
|
||||||
|
data, 2 gpio pins for enable and register select and 1 optional pin
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/arch/arm/boot/dts/overlays/hd44780-i2c-lcd-overlay.dts
|
||||||
|
@@ -0,0 +1,57 @@
|
||||||
|
+/dts-v1/;
|
||||||
|
+/plugin/;
|
||||||
|
+
|
||||||
|
+/ {
|
||||||
|
+ compatible = "brcm,bcm2835";
|
||||||
|
+
|
||||||
|
+ fragment@0 {
|
||||||
|
+ target = <&i2c_arm>;
|
||||||
|
+ __overlay__ {
|
||||||
|
+ status = "okay";
|
||||||
|
+
|
||||||
|
+ pcf857x: pcf857x@27 {
|
||||||
|
+ compatible = "nxp,pcf8574";
|
||||||
|
+ reg = <0x27>;
|
||||||
|
+ gpio-controller;
|
||||||
|
+ #gpio-cells = <2>;
|
||||||
|
+ status = "okay";
|
||||||
|
+ };
|
||||||
|
+ };
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ fragment@1 {
|
||||||
|
+ target-path = "/";
|
||||||
|
+ __overlay__ {
|
||||||
|
+ lcd_screen: auxdisplay {
|
||||||
|
+ compatible = "hit,hd44780";
|
||||||
|
+
|
||||||
|
+ data-gpios = <&pcf857x 4 0>,
|
||||||
|
+ <&pcf857x 5 0>,
|
||||||
|
+ <&pcf857x 6 0>,
|
||||||
|
+ <&pcf857x 7 0>;
|
||||||
|
+ enable-gpios = <&pcf857x 2 0>;
|
||||||
|
+ rs-gpios = <&pcf857x 0 0>;
|
||||||
|
+ rw-gpios = <&pcf857x 1 0>;
|
||||||
|
+ backlight-gpios = <&pcf857x 3 0>;
|
||||||
|
+
|
||||||
|
+ display-width-chars = <16>;
|
||||||
|
+ display-height-chars = <2>;
|
||||||
|
+ };
|
||||||
|
+ };
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ __overrides__ {
|
||||||
|
+ pin_d4 = <&lcd_screen>,"data-gpios:4";
|
||||||
|
+ pin_d5 = <&lcd_screen>,"data-gpios:16";
|
||||||
|
+ pin_d6 = <&lcd_screen>,"data-gpios:28";
|
||||||
|
+ pin_d7 = <&lcd_screen>,"data-gpios:40";
|
||||||
|
+ pin_en = <&lcd_screen>,"enable-gpios:4";
|
||||||
|
+ pin_rs = <&lcd_screen>,"rs-gpios:4";
|
||||||
|
+ pin_rw = <&lcd_screen>,"rw-gpios:4";
|
||||||
|
+ pin_bl = <&lcd_screen>,"backlight-gpios:4";
|
||||||
|
+ display_height = <&lcd_screen>,"display-height-chars:0";
|
||||||
|
+ display_width = <&lcd_screen>,"display-width-chars:0";
|
||||||
|
+ addr = <&pcf857x>,"reg:0";
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+};
|
@ -0,0 +1,28 @@
|
|||||||
|
From 3c319a466a1c718f66c471a9d5ec60de6de44612 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
||||||
|
Date: Fri, 2 Aug 2024 10:41:28 +0100
|
||||||
|
Subject: [PATCH 1207/1215] dtoverlays: Document display_[width|height] on
|
||||||
|
hd44780-lcd overlay
|
||||||
|
|
||||||
|
The default values defining a 16x2 display weren't documented,
|
||||||
|
so add them.
|
||||||
|
|
||||||
|
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
||||||
|
---
|
||||||
|
arch/arm/boot/dts/overlays/README | 4 ++--
|
||||||
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
--- a/arch/arm/boot/dts/overlays/README
|
||||||
|
+++ b/arch/arm/boot/dts/overlays/README
|
||||||
|
@@ -1752,9 +1752,9 @@ Params: pin_d4 GPIO pin
|
||||||
|
pin_bl Optional pin for enabling/disabling the
|
||||||
|
display backlight. (default disabled)
|
||||||
|
|
||||||
|
- display_height Height of the display in characters
|
||||||
|
+ display_height Height of the display in characters (default 2)
|
||||||
|
|
||||||
|
- display_width Width of the display in characters
|
||||||
|
+ display_width Width of the display in characters (default 16)
|
||||||
|
|
||||||
|
|
||||||
|
Name: hdmi-backlight-hwhack-gpio
|
@ -0,0 +1,39 @@
|
|||||||
|
From 216df57950849f905c398904e7d6cbdf278b5717 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jonathan Bell <jonathan@raspberrypi.com>
|
||||||
|
Date: Mon, 5 Aug 2024 11:28:36 +0100
|
||||||
|
Subject: [PATCH 1208/1215] DTS: bcm2712: enable SD slot CQE by default on Pi 5
|
||||||
|
|
||||||
|
The corresponding driver implementation has seen sufficient testing,
|
||||||
|
so enable by default. Retain the dtparam so it can be turned off for test.
|
||||||
|
|
||||||
|
Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
|
||||||
|
---
|
||||||
|
arch/arm/boot/dts/overlays/README | 6 +++---
|
||||||
|
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts | 1 +
|
||||||
|
2 files changed, 4 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
--- a/arch/arm/boot/dts/overlays/README
|
||||||
|
+++ b/arch/arm/boot/dts/overlays/README
|
||||||
|
@@ -378,9 +378,9 @@ Params:
|
||||||
|
non-lite SKU of CM4).
|
||||||
|
(default "on")
|
||||||
|
|
||||||
|
- sd_cqe Use to enable Command Queueing on the SD
|
||||||
|
- interface for faster Class A2 card performance
|
||||||
|
- (Pi 5 only, default "off")
|
||||||
|
+ sd_cqe Set to "off" to disable Command Queueing if you
|
||||||
|
+ have an incompatible Class A2 SD card
|
||||||
|
+ (Pi 5 only, default "on")
|
||||||
|
|
||||||
|
sd_overclock Clock (in MHz) to use when the MMC framework
|
||||||
|
requests 50MHz
|
||||||
|
--- a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts
|
||||||
|
+++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts
|
||||||
|
@@ -363,6 +363,7 @@ dpi_16bit_gpio2: &rp1_dpi_16bit_g
|
||||||
|
sd-uhs-sdr50;
|
||||||
|
sd-uhs-ddr50;
|
||||||
|
sd-uhs-sdr104;
|
||||||
|
+ supports-cqe;
|
||||||
|
cd-gpios = <&gio_aon 5 GPIO_ACTIVE_LOW>;
|
||||||
|
//no-1-8-v;
|
||||||
|
status = "okay";
|
@ -0,0 +1,50 @@
|
|||||||
|
From 53b9d9bbb57e292c6b332a2fb9899003586e17ca Mon Sep 17 00:00:00 2001
|
||||||
|
From: Phil Elwell <phil@raspberrypi.com>
|
||||||
|
Date: Thu, 2 May 2024 16:17:02 +0100
|
||||||
|
Subject: [PATCH 1211/1215] gpiolib: Override gpiochip numbers with DT aliases
|
||||||
|
|
||||||
|
In the same way that other subsystems support the setting of device
|
||||||
|
id numbers from Device Tree aliases, allow gpiochip numbers to be
|
||||||
|
derived from "gpiochip<n>" aliases.
|
||||||
|
|
||||||
|
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||||
|
---
|
||||||
|
drivers/gpio/gpiolib.c | 13 ++++++++++++-
|
||||||
|
1 file changed, 12 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
--- a/drivers/gpio/gpiolib.c
|
||||||
|
+++ b/drivers/gpio/gpiolib.c
|
||||||
|
@@ -110,6 +110,7 @@ static int gpiochip_irqchip_init_valid_m
|
||||||
|
static void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gc);
|
||||||
|
|
||||||
|
static bool gpiolib_initialized;
|
||||||
|
+static int first_dynamic_gpiochip_num = -1;
|
||||||
|
|
||||||
|
static inline void desc_set_label(struct gpio_desc *d, const char *label)
|
||||||
|
{
|
||||||
|
@@ -745,6 +746,7 @@ int gpiochip_add_data_with_key(struct gp
|
||||||
|
unsigned int i;
|
||||||
|
int base = 0;
|
||||||
|
int ret = 0;
|
||||||
|
+ int id;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First: allocate and populate the internal stat container, and
|
||||||
|
@@ -769,7 +771,16 @@ int gpiochip_add_data_with_key(struct gp
|
||||||
|
else if (gc->parent)
|
||||||
|
device_set_node(&gdev->dev, dev_fwnode(gc->parent));
|
||||||
|
|
||||||
|
- gdev->id = ida_alloc(&gpio_ida, GFP_KERNEL);
|
||||||
|
+ if (first_dynamic_gpiochip_num < 0) {
|
||||||
|
+ id = of_alias_get_highest_id("gpiochip");
|
||||||
|
+ first_dynamic_gpiochip_num = (id >= 0) ? (id + 1) : 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ id = of_alias_get_id(gdev->dev.of_node, "gpiochip");
|
||||||
|
+ if (id < 0)
|
||||||
|
+ id = first_dynamic_gpiochip_num;
|
||||||
|
+
|
||||||
|
+ gdev->id = ida_alloc_range(&gpio_ida, id, ~0, GFP_KERNEL);
|
||||||
|
if (gdev->id < 0) {
|
||||||
|
ret = gdev->id;
|
||||||
|
goto err_free_gdev;
|
@ -0,0 +1,23 @@
|
|||||||
|
From 1162316fd26eeb4193b23fcc1bb332f42938aa70 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Phil Elwell <phil@raspberrypi.com>
|
||||||
|
Date: Thu, 2 May 2024 16:58:59 +0100
|
||||||
|
Subject: [PATCH 1212/1215] dts: bcm2712-rpi: Add gpiochip0 alias
|
||||||
|
|
||||||
|
Add a gpiochip0 aliase pointing to the rp1 GPIO node, making it appear
|
||||||
|
as gpiochip0.
|
||||||
|
|
||||||
|
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||||
|
---
|
||||||
|
arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi | 1 +
|
||||||
|
1 file changed, 1 insertion(+)
|
||||||
|
|
||||||
|
--- a/arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi
|
||||||
|
+++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi
|
||||||
|
@@ -112,6 +112,7 @@
|
||||||
|
gpio2 = &gio_aon;
|
||||||
|
gpio3 = &pinctrl;
|
||||||
|
gpio4 = &pinctrl_aon;
|
||||||
|
+ gpiochip0 = &gpio;
|
||||||
|
i2c = &i2c_arm;
|
||||||
|
i2c0 = &i2c0;
|
||||||
|
i2c1 = &i2c1;
|
@ -0,0 +1,24 @@
|
|||||||
|
From 70c640ce992234aacba5a717f3fb47319f451431 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Phil Elwell <phil@raspberrypi.com>
|
||||||
|
Date: Thu, 2 May 2024 17:40:25 +0100
|
||||||
|
Subject: [PATCH 1213/1215] dts: bcm2712-rpi: The SoC gpiochips start at 10
|
||||||
|
|
||||||
|
Make the BCM2712's onboard GPIOs start at gpiochip10, marking them out
|
||||||
|
as system resources and preventing accidental use by existing Pi 5
|
||||||
|
code.
|
||||||
|
|
||||||
|
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||||
|
---
|
||||||
|
arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi | 1 +
|
||||||
|
1 file changed, 1 insertion(+)
|
||||||
|
|
||||||
|
--- a/arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi
|
||||||
|
+++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi
|
||||||
|
@@ -113,6 +113,7 @@
|
||||||
|
gpio3 = &pinctrl;
|
||||||
|
gpio4 = &pinctrl_aon;
|
||||||
|
gpiochip0 = &gpio;
|
||||||
|
+ gpiochip10 = &gio;
|
||||||
|
i2c = &i2c_arm;
|
||||||
|
i2c0 = &i2c0;
|
||||||
|
i2c1 = &i2c1;
|
Loading…
Reference in New Issue
Block a user