Skip to content

Commit 6f132ab

Browse files
njhollinghurstpopcornmix
authored andcommitted
drm/rp1/rp1_dsi: 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]>
1 parent 2fc25e8 commit 6f132ab

File tree

4 files changed

+406
-32
lines changed

4 files changed

+406
-32
lines changed

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

+27-9
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,16 @@
6262
static unsigned int default_bus_fmt = MEDIA_BUS_FMT_RGB666_1X18;
6363
module_param(default_bus_fmt, uint, 0644);
6464

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

6777
static void rp1dpi_pipe_update(struct drm_simple_display_pipe *pipe,
@@ -90,7 +100,8 @@ static void rp1dpi_pipe_update(struct drm_simple_display_pipe *pipe,
90100
dpi->bus_fmt,
91101
dpi->de_inv,
92102
&pipe->crtc.state->mode);
93-
rp1dpi_pio_start(dpi, &pipe->crtc.state->mode);
103+
rp1dpi_pio_start(dpi, &pipe->crtc.state->mode,
104+
force_csync);
94105
dpi->dpi_running = true;
95106
}
96107
dpi->cur_fmt = fb->format->format;
@@ -295,6 +306,7 @@ static int rp1dpi_platform_probe(struct platform_device *pdev)
295306
struct drm_bridge *bridge = NULL;
296307
const char *rgb_order = NULL;
297308
struct drm_panel *panel;
309+
u32 missing_gpios;
298310
int i, j, ret;
299311

300312
dev_info(dev, __func__);
@@ -355,6 +367,7 @@ static int rp1dpi_platform_probe(struct platform_device *pdev)
355367
if (ret)
356368
goto done_err;
357369

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

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

382395
if (!of_property_read_string(np1, "function", &str) && !strcmp(str, "dpi")) {
383-
for (j = 0; !dpi->gpio1_used; j++) {
396+
for (j = 0; missing_gpios; j++) {
384397
if (of_property_read_string_index(np1, "pins", j, &str))
385398
break;
386399
if (!strcmp(str, "gpio1"))
387-
dpi->gpio1_used = true;
400+
missing_gpios &= ~BIT(1);
401+
else if (!strcmp(str, "gpio2"))
402+
missing_gpios &= ~BIT(2);
403+
else if (!strcmp(str, "gpio3"))
404+
missing_gpios &= ~BIT(3);
388405
}
389-
for (j = 0; !dpi->gpio1_used; j++) {
406+
for (j = 0; missing_gpios; j++) {
390407
if (of_property_read_u32_index(np1, "brcm,pins", j, &p))
391408
break;
392-
if (p == 1)
393-
dpi->gpio1_used = true;
409+
if (p < 32)
410+
missing_gpios &= ~(1 << p);
394411
}
395412
}
396413
of_node_put(np1);
397414
}
415+
dpi->sync_gpios_mapped = !missing_gpios;
398416

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

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

+4-4
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

+2-2
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)