Skip to content

Commit 4bc65d7

Browse files
drm/rp1/rp1_dpi: Move Composite Sync generation into the kernel
Move RP1 DPI's PIO-assisted Composite Sync generation code, previously released as a separate utility, into the kernel driver. There are 3 variants for progressive, generic interlaced and TV- style interlaced CSync, alongside the existing VSync fixup. Check that all of GPIOs 1-3 are mapped to DPI, so PIO won't try to snoop on a missing output, or override another device's pins. Add "force_csync" module parameter, for convenience of testing, as few tools can set DRM_MODE_FLAG_CSYNC. Signed-off-by: Nick Hollinghurst <[email protected]> Signed-off-by: Phil Elwell <[email protected]>
1 parent dd91a4b commit 4bc65d7

File tree

4 files changed

+408
-33
lines changed

4 files changed

+408
-33
lines changed

drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi.c

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,16 @@
6161
static unsigned int default_bus_fmt = MEDIA_BUS_FMT_RGB666_1X18;
6262
module_param(default_bus_fmt, uint, 0644);
6363

64+
/*
65+
* Override DRM mode flags to force the use of Composite Sync on GPIO1.
66+
* This is mostly for testing, as neither panel-timing nor command-line
67+
* arguments nor utilities such as "kmstest" can set DRM_MODE_FLAG_CSYNC.
68+
* Sampled on each enable/mode-switch. Default polarity will be -ve.
69+
* (Setting this may break Vertical Sync on GPIO2 for interlaced modes.)
70+
*/
71+
static bool force_csync;
72+
module_param(force_csync, bool, 0644);
73+
6474
/* -------------------------------------------------------------- */
6575

6676
static void rp1dpi_pipe_update(struct drm_simple_display_pipe *pipe,
@@ -89,7 +99,8 @@ static void rp1dpi_pipe_update(struct drm_simple_display_pipe *pipe,
8999
dpi->bus_fmt,
90100
dpi->de_inv,
91101
&pipe->crtc.state->mode);
92-
rp1dpi_pio_start(dpi, &pipe->crtc.state->mode);
102+
rp1dpi_pio_start(dpi, &pipe->crtc.state->mode,
103+
force_csync);
93104
dpi->dpi_running = true;
94105
}
95106
dpi->cur_fmt = fb->format->format;
@@ -294,6 +305,7 @@ static int rp1dpi_platform_probe(struct platform_device *pdev)
294305
struct drm_bridge *bridge = NULL;
295306
const char *rgb_order = NULL;
296307
struct drm_panel *panel;
308+
u32 missing_gpios;
297309
int i, j, ret;
298310

299311
dev_info(dev, __func__);
@@ -354,6 +366,7 @@ static int rp1dpi_platform_probe(struct platform_device *pdev)
354366
if (ret)
355367
goto done_err;
356368

369+
/* RGB order property - to match VC4 */
357370
dpi->rgb_order_override = RP1DPI_ORDER_UNCHANGED;
358371
if (!of_property_read_string(dev->of_node, "rgb_order", &rgb_order)) {
359372
if (!strcmp(rgb_order, "rgb"))
@@ -368,9 +381,9 @@ static int rp1dpi_platform_probe(struct platform_device *pdev)
368381
DRM_ERROR("Invalid dpi order %s - ignored\n", rgb_order);
369382
}
370383

371-
/* Check if PIO can snoop on or override DPI's GPIO1 */
372-
dpi->gpio1_used = false;
373-
for (i = 0; !dpi->gpio1_used; i++) {
384+
/* Check if all of GPIOs 1, 2 and 3 are assigned to DPI */
385+
missing_gpios = BIT(1) | BIT(2) | BIT(3);
386+
for (i = 0; missing_gpios; i++) {
374387
u32 p = 0;
375388
const char *str = NULL;
376389
struct device_node *np1 = of_parse_phandle(dev->of_node, "pinctrl-0", i);
@@ -379,21 +392,26 @@ static int rp1dpi_platform_probe(struct platform_device *pdev)
379392
break;
380393

381394
if (!of_property_read_string(np1, "function", &str) && !strcmp(str, "dpi")) {
382-
for (j = 0; !dpi->gpio1_used; j++) {
395+
for (j = 0; missing_gpios; j++) {
383396
if (of_property_read_string_index(np1, "pins", j, &str))
384397
break;
385398
if (!strcmp(str, "gpio1"))
386-
dpi->gpio1_used = true;
399+
missing_gpios &= ~BIT(1);
400+
else if (!strcmp(str, "gpio2"))
401+
missing_gpios &= ~BIT(2);
402+
else if (!strcmp(str, "gpio3"))
403+
missing_gpios &= ~BIT(3);
387404
}
388-
for (j = 0; !dpi->gpio1_used; j++) {
405+
for (j = 0; missing_gpios; j++) {
389406
if (of_property_read_u32_index(np1, "brcm,pins", j, &p))
390407
break;
391-
if (p == 1)
392-
dpi->gpio1_used = true;
408+
if (p < 32)
409+
missing_gpios &= ~(1 << p);
393410
}
394411
}
395412
of_node_put(np1);
396413
}
414+
dpi->sync_gpios_mapped = !missing_gpios;
397415

398416
/* Now we have all our resources, finish driver initialization */
399417
dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));

drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,9 @@ struct rp1_dpi {
5555
unsigned int rgb_order_override;
5656
struct completion finished;
5757

58-
/* Experimental stuff for interlace follows */
58+
/* The following are for Interlace and CSYNC support using PIO */
5959
struct rp1_pio_client *pio;
60-
bool gpio1_used;
61-
bool pio_stole_gpio2;
60+
bool sync_gpios_mapped;
6261

6362
spinlock_t hw_lock; /* the following are used in line-match ISR */
6463
dma_addr_t last_dma_addr;
@@ -91,5 +90,6 @@ void rp1dpi_vidout_poweroff(struct rp1_dpi *dpi);
9190
/* ---------------------------------------------------------------------- */
9291
/* PIO control -- we need PIO to generate VSync (from DE) when interlaced */
9392

94-
int rp1dpi_pio_start(struct rp1_dpi *dpi, const struct drm_display_mode *mode);
93+
int rp1dpi_pio_start(struct rp1_dpi *dpi, const struct drm_display_mode *mode,
94+
bool force_csync);
9595
void rp1dpi_pio_stop(struct rp1_dpi *dpi);

drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi_hw.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ void rp1dpi_hw_setup(struct rp1_dpi *dpi,
392392
int order, i;
393393

394394
drm_info(&dpi->drm,
395-
"in_fmt=\'%c%c%c%c\' bus_fmt=0x%x mode=%dx%d total=%dx%d%s %dkHz %cH%cV%cD%cC",
395+
"in_fmt=\'%c%c%c%c\' bus_fmt=0x%x mode=%dx%d total=%dx%d%s %dkHz %cH%cV%cDE%cCK",
396396
in_format, in_format >> 8, in_format >> 16, in_format >> 24, bus_format,
397397
mode->hdisplay, mode->vdisplay,
398398
mode->htotal, mode->vtotal,
@@ -497,7 +497,7 @@ void rp1dpi_hw_setup(struct rp1_dpi *dpi,
497497
* This driver includes a PIO program to do that, when DE is enabled.
498498
*
499499
* An alternative fixup is to synthesize CSYNC from HSYNC and modified-VSYNC.
500-
* We don't implement that here, but to facilitate it, DPI's VSYNC is replaced
500+
* We can't do this and make VSYNC at the same time; DPI's VSYNC is replaced
501501
* by a "helper signal" that pulses low for 1 or 2 scan-lines, starting 2.0 or
502502
* 2.5 scan-lines respectively before nominal VSYNC start.
503503
*/

0 commit comments

Comments
 (0)