Skip to content

Commit

Permalink
Merge pull request #6529 from njhollinghurst/dpi-interlace2
Browse files Browse the repository at this point in the history
  • Loading branch information
pelwell authored Dec 11, 2024
2 parents 574ea34 + 7735dd0 commit 0da5bec
Show file tree
Hide file tree
Showing 8 changed files with 465 additions and 71 deletions.
1 change: 1 addition & 0 deletions arch/arm/boot/dts/overlays/README
Original file line number Diff line number Diff line change
Expand Up @@ -5099,6 +5099,7 @@ Params: clock-frequency Display clock frequency (Hz)
vsync-invert Vertical sync active low
de-invert Data Enable active low
pixclk-invert Negative edge pixel clock
interlaced Use an interlaced mode (where supported)
width-mm Define the screen width in mm
height-mm Define the screen height in mm
rgb565 Change to RGB565 output on GPIOs 0-19
Expand Down
1 change: 1 addition & 0 deletions arch/arm/boot/dts/overlays/vc4-kms-dpi-generic-overlay.dts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
vsync-invert = <&timing>, "vsync-active:0=0";
de-invert = <&timing>, "de-active:0=0";
pixclk-invert = <&timing>, "pixelclk-active:0=0";
interlaced = <&timing>, "interlaced?";

width-mm = <&panel_generic>, "width-mm:0";
height-mm = <&panel_generic>, "height-mm:0";
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/bridge/panel.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ static int panel_bridge_attach(struct drm_bridge *bridge,
return ret;
}

connector->interlace_allowed = true;

drm_panel_bridge_set_orientation(connector, bridge);

drm_connector_attach_encoder(&panel_bridge->connector,
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/rp1/rp1-dpi/Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-only

drm-rp1-dpi-y := rp1_dpi.o rp1_dpi_hw.o rp1_dpi_cfg.o
drm-rp1-dpi-y := rp1_dpi.o rp1_dpi_hw.o rp1_dpi_cfg.o rp1_dpi_pio.o

obj-$(CONFIG_DRM_RP1_DPI) += drm-rp1-dpi.o
34 changes: 33 additions & 1 deletion drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ static void rp1dpi_pipe_update(struct drm_simple_display_pipe *pipe,
if (dpi->dpi_running &&
fb->format->format != dpi->cur_fmt) {
rp1dpi_hw_stop(dpi);
rp1dpi_pio_stop(dpi);
dpi->dpi_running = false;
}
if (!dpi->dpi_running) {
Expand All @@ -88,6 +89,7 @@ static void rp1dpi_pipe_update(struct drm_simple_display_pipe *pipe,
dpi->bus_fmt,
dpi->de_inv,
&pipe->crtc.state->mode);
rp1dpi_pio_start(dpi, &pipe->crtc.state->mode);
dpi->dpi_running = true;
}
dpi->cur_fmt = fb->format->format;
Expand Down Expand Up @@ -187,6 +189,7 @@ static void rp1dpi_pipe_disable(struct drm_simple_display_pipe *pipe)
drm_crtc_vblank_off(&pipe->crtc);
if (dpi->dpi_running) {
rp1dpi_hw_stop(dpi);
rp1dpi_pio_stop(dpi);
dpi->dpi_running = false;
}
clk_disable_unprepare(dpi->clocks[RP1DPI_CLK_DPI]);
Expand Down Expand Up @@ -236,6 +239,7 @@ static void rp1dpi_stopall(struct drm_device *drm)
if (dpi->dpi_running || rp1dpi_hw_busy(dpi)) {
rp1dpi_hw_stop(dpi);
clk_disable_unprepare(dpi->clocks[RP1DPI_CLK_DPI]);
rp1dpi_pio_stop(dpi);
dpi->dpi_running = false;
}
rp1dpi_vidout_poweroff(dpi);
Expand Down Expand Up @@ -273,7 +277,7 @@ static int rp1dpi_platform_probe(struct platform_device *pdev)
struct rp1_dpi *dpi;
struct drm_bridge *bridge = NULL;
struct drm_panel *panel;
int i, ret;
int i, j, ret;

dev_info(dev, __func__);
ret = drm_of_find_panel_or_bridge(pdev->dev.of_node, 0, 0,
Expand All @@ -295,6 +299,7 @@ static int rp1dpi_platform_probe(struct platform_device *pdev)
return ret;
}
dpi->pdev = pdev;
spin_lock_init(&dpi->hw_lock);

dpi->bus_fmt = default_bus_fmt;
ret = of_property_read_u32(dev->of_node, "default_bus_fmt", &dpi->bus_fmt);
Expand Down Expand Up @@ -332,6 +337,33 @@ static int rp1dpi_platform_probe(struct platform_device *pdev)
if (ret)
goto done_err;

/* Check if PIO can snoop on or override DPI's GPIO1 */
dpi->gpio1_used = false;
for (i = 0; !dpi->gpio1_used; i++) {
u32 p = 0;
const char *str = NULL;
struct device_node *np1 = of_parse_phandle(dev->of_node, "pinctrl-0", i);

if (!np1)
break;

if (!of_property_read_string(np1, "function", &str) && !strcmp(str, "dpi")) {
for (j = 0; !dpi->gpio1_used; j++) {
if (of_property_read_string_index(np1, "pins", j, &str))
break;
if (!strcmp(str, "gpio1"))
dpi->gpio1_used = true;
}
for (j = 0; !dpi->gpio1_used; j++) {
if (of_property_read_u32_index(np1, "brcm,pins", j, &p))
break;
if (p == 1)
dpi->gpio1_used = true;
}
}
of_node_put(np1);
}

/* Now we have all our resources, finish driver initialization */
dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
init_completion(&dpi->finished);
Expand Down
18 changes: 18 additions & 0 deletions drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,18 @@ struct rp1_dpi {
bool de_inv, clk_inv;
bool dpi_running, pipe_enabled;
struct completion finished;

/* Experimental stuff for interlace follows */
struct rp1_pio_client *pio;
bool gpio1_used;
bool pio_stole_gpio2;

spinlock_t hw_lock; /* the following are used in line-match ISR */
dma_addr_t last_dma_addr;
u32 last_stride;
u32 shorter_front_porch;
bool interlaced;
bool lower_field_flag;
};

/* ---------------------------------------------------------------------- */
Expand All @@ -67,3 +79,9 @@ void rp1dpi_hw_vblank_ctrl(struct rp1_dpi *dpi, int enable);

void rp1dpi_vidout_setup(struct rp1_dpi *dpi, bool drive_negedge);
void rp1dpi_vidout_poweroff(struct rp1_dpi *dpi);

/* ---------------------------------------------------------------------- */
/* PIO control -- we need PIO to generate VSync (from DE) when interlaced */

int rp1dpi_pio_start(struct rp1_dpi *dpi, const struct drm_display_mode *mode);
void rp1dpi_pio_stop(struct rp1_dpi *dpi);
Loading

0 comments on commit 0da5bec

Please sign in to comment.