Commit 9037d4b9 authored by Dave Airlie's avatar Dave Airlie
parents 2989b3ce b06078de
...@@ -14,6 +14,7 @@ Required properties: ...@@ -14,6 +14,7 @@ Required properties:
- compatible : Shall contain one or more of - compatible : Shall contain one or more of
- "renesas,r8a7795-hdmi" for R8A7795 (R-Car H3) compatible HDMI TX - "renesas,r8a7795-hdmi" for R8A7795 (R-Car H3) compatible HDMI TX
- "renesas,r8a7796-hdmi" for R8A7796 (R-Car M3-W) compatible HDMI TX - "renesas,r8a7796-hdmi" for R8A7796 (R-Car M3-W) compatible HDMI TX
- "renesas,r8a77965-hdmi" for R8A77965 (R-Car M3-N) compatible HDMI TX
- "renesas,rcar-gen3-hdmi" for the generic R-Car Gen3 compatible HDMI TX - "renesas,rcar-gen3-hdmi" for the generic R-Car Gen3 compatible HDMI TX
When compatible with generic versions, nodes must list the SoC-specific When compatible with generic versions, nodes must list the SoC-specific
......
...@@ -13,6 +13,7 @@ Required Properties: ...@@ -13,6 +13,7 @@ Required Properties:
- "renesas,du-r8a7794" for R8A7794 (R-Car E2) compatible DU - "renesas,du-r8a7794" for R8A7794 (R-Car E2) compatible DU
- "renesas,du-r8a7795" for R8A7795 (R-Car H3) compatible DU - "renesas,du-r8a7795" for R8A7795 (R-Car H3) compatible DU
- "renesas,du-r8a7796" for R8A7796 (R-Car M3-W) compatible DU - "renesas,du-r8a7796" for R8A7796 (R-Car M3-W) compatible DU
- "renesas,du-r8a77965" for R8A77965 (R-Car M3-N) compatible DU
- "renesas,du-r8a77970" for R8A77970 (R-Car V3M) compatible DU - "renesas,du-r8a77970" for R8A77970 (R-Car V3M) compatible DU
- "renesas,du-r8a77995" for R8A77995 (R-Car D3) compatible DU - "renesas,du-r8a77995" for R8A77995 (R-Car D3) compatible DU
...@@ -47,20 +48,21 @@ bindings specified in Documentation/devicetree/bindings/graph.txt. ...@@ -47,20 +48,21 @@ bindings specified in Documentation/devicetree/bindings/graph.txt.
The following table lists for each supported model the port number The following table lists for each supported model the port number
corresponding to each DU output. corresponding to each DU output.
Port0 Port1 Port2 Port3 Port0 Port1 Port2 Port3
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
R8A7743 (RZ/G1M) DPAD 0 LVDS 0 - - R8A7743 (RZ/G1M) DPAD 0 LVDS 0 - -
R8A7745 (RZ/G1E) DPAD 0 DPAD 1 - - R8A7745 (RZ/G1E) DPAD 0 DPAD 1 - -
R8A7779 (R-Car H1) DPAD 0 DPAD 1 - - R8A7779 (R-Car H1) DPAD 0 DPAD 1 - -
R8A7790 (R-Car H2) DPAD 0 LVDS 0 LVDS 1 - R8A7790 (R-Car H2) DPAD 0 LVDS 0 LVDS 1 -
R8A7791 (R-Car M2-W) DPAD 0 LVDS 0 - - R8A7791 (R-Car M2-W) DPAD 0 LVDS 0 - -
R8A7792 (R-Car V2H) DPAD 0 DPAD 1 - - R8A7792 (R-Car V2H) DPAD 0 DPAD 1 - -
R8A7793 (R-Car M2-N) DPAD 0 LVDS 0 - - R8A7793 (R-Car M2-N) DPAD 0 LVDS 0 - -
R8A7794 (R-Car E2) DPAD 0 DPAD 1 - - R8A7794 (R-Car E2) DPAD 0 DPAD 1 - -
R8A7795 (R-Car H3) DPAD 0 HDMI 0 HDMI 1 LVDS 0 R8A7795 (R-Car H3) DPAD 0 HDMI 0 HDMI 1 LVDS 0
R8A7796 (R-Car M3-W) DPAD 0 HDMI 0 LVDS 0 - R8A7796 (R-Car M3-W) DPAD 0 HDMI 0 LVDS 0 -
R8A77970 (R-Car V3M) DPAD 0 LVDS 0 - - R8A77965 (R-Car M3-N) DPAD 0 HDMI 0 LVDS 0 -
R8A77995 (R-Car D3) DPAD 0 LVDS 0 LVDS 1 - R8A77970 (R-Car V3M) DPAD 0 LVDS 0 - -
R8A77995 (R-Car D3) DPAD 0 LVDS 0 LVDS 1 -
Example: R8A7795 (R-Car H3) ES2.0 DU Example: R8A7795 (R-Car H3) ES2.0 DU
......
...@@ -767,7 +767,8 @@ static irqreturn_t rcar_du_crtc_irq(int irq, void *arg) ...@@ -767,7 +767,8 @@ static irqreturn_t rcar_du_crtc_irq(int irq, void *arg)
* Initialization * Initialization
*/ */
int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index) int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int swindex,
unsigned int hwindex)
{ {
static const unsigned int mmio_offsets[] = { static const unsigned int mmio_offsets[] = {
DU0_REG_OFFSET, DU1_REG_OFFSET, DU2_REG_OFFSET, DU3_REG_OFFSET DU0_REG_OFFSET, DU1_REG_OFFSET, DU2_REG_OFFSET, DU3_REG_OFFSET
...@@ -775,7 +776,7 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index) ...@@ -775,7 +776,7 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
struct rcar_du_device *rcdu = rgrp->dev; struct rcar_du_device *rcdu = rgrp->dev;
struct platform_device *pdev = to_platform_device(rcdu->dev); struct platform_device *pdev = to_platform_device(rcdu->dev);
struct rcar_du_crtc *rcrtc = &rcdu->crtcs[index]; struct rcar_du_crtc *rcrtc = &rcdu->crtcs[swindex];
struct drm_crtc *crtc = &rcrtc->crtc; struct drm_crtc *crtc = &rcrtc->crtc;
struct drm_plane *primary; struct drm_plane *primary;
unsigned int irqflags; unsigned int irqflags;
...@@ -787,7 +788,7 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index) ...@@ -787,7 +788,7 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
/* Get the CRTC clock and the optional external clock. */ /* Get the CRTC clock and the optional external clock. */
if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CRTC_IRQ_CLOCK)) { if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CRTC_IRQ_CLOCK)) {
sprintf(clk_name, "du.%u", index); sprintf(clk_name, "du.%u", hwindex);
name = clk_name; name = clk_name;
} else { } else {
name = NULL; name = NULL;
...@@ -795,16 +796,16 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index) ...@@ -795,16 +796,16 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
rcrtc->clock = devm_clk_get(rcdu->dev, name); rcrtc->clock = devm_clk_get(rcdu->dev, name);
if (IS_ERR(rcrtc->clock)) { if (IS_ERR(rcrtc->clock)) {
dev_err(rcdu->dev, "no clock for CRTC %u\n", index); dev_err(rcdu->dev, "no clock for DU channel %u\n", hwindex);
return PTR_ERR(rcrtc->clock); return PTR_ERR(rcrtc->clock);
} }
sprintf(clk_name, "dclkin.%u", index); sprintf(clk_name, "dclkin.%u", hwindex);
clk = devm_clk_get(rcdu->dev, clk_name); clk = devm_clk_get(rcdu->dev, clk_name);
if (!IS_ERR(clk)) { if (!IS_ERR(clk)) {
rcrtc->extclock = clk; rcrtc->extclock = clk;
} else if (PTR_ERR(rcrtc->clock) == -EPROBE_DEFER) { } else if (PTR_ERR(rcrtc->clock) == -EPROBE_DEFER) {
dev_info(rcdu->dev, "can't get external clock %u\n", index); dev_info(rcdu->dev, "can't get external clock %u\n", hwindex);
return -EPROBE_DEFER; return -EPROBE_DEFER;
} }
...@@ -813,13 +814,13 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index) ...@@ -813,13 +814,13 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
spin_lock_init(&rcrtc->vblank_lock); spin_lock_init(&rcrtc->vblank_lock);
rcrtc->group = rgrp; rcrtc->group = rgrp;
rcrtc->mmio_offset = mmio_offsets[index]; rcrtc->mmio_offset = mmio_offsets[hwindex];
rcrtc->index = index; rcrtc->index = hwindex;
if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE))
primary = &rcrtc->vsp->planes[rcrtc->vsp_pipe].plane; primary = &rcrtc->vsp->planes[rcrtc->vsp_pipe].plane;
else else
primary = &rgrp->planes[index % 2].plane; primary = &rgrp->planes[swindex % 2].plane;
ret = drm_crtc_init_with_planes(rcdu->ddev, crtc, primary, ret = drm_crtc_init_with_planes(rcdu->ddev, crtc, primary,
NULL, &crtc_funcs, NULL); NULL, &crtc_funcs, NULL);
...@@ -833,7 +834,8 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index) ...@@ -833,7 +834,8 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
/* Register the interrupt handler. */ /* Register the interrupt handler. */
if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CRTC_IRQ_CLOCK)) { if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CRTC_IRQ_CLOCK)) {
irq = platform_get_irq(pdev, index); /* The IRQ's are associated with the CRTC (sw)index. */
irq = platform_get_irq(pdev, swindex);
irqflags = 0; irqflags = 0;
} else { } else {
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
...@@ -841,7 +843,7 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index) ...@@ -841,7 +843,7 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
} }
if (irq < 0) { if (irq < 0) {
dev_err(rcdu->dev, "no IRQ for CRTC %u\n", index); dev_err(rcdu->dev, "no IRQ for CRTC %u\n", swindex);
return irq; return irq;
} }
...@@ -849,7 +851,7 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index) ...@@ -849,7 +851,7 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
dev_name(rcdu->dev), rcrtc); dev_name(rcdu->dev), rcrtc);
if (ret < 0) { if (ret < 0) {
dev_err(rcdu->dev, dev_err(rcdu->dev,
"failed to register IRQ for CRTC %u\n", index); "failed to register IRQ for CRTC %u\n", swindex);
return ret; return ret;
} }
......
...@@ -80,7 +80,8 @@ enum rcar_du_output { ...@@ -80,7 +80,8 @@ enum rcar_du_output {
RCAR_DU_OUTPUT_MAX, RCAR_DU_OUTPUT_MAX,
}; };
int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index); int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int swindex,
unsigned int hwindex);
void rcar_du_crtc_suspend(struct rcar_du_crtc *rcrtc); void rcar_du_crtc_suspend(struct rcar_du_crtc *rcrtc);
void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc); void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc);
......
...@@ -40,7 +40,7 @@ static const struct rcar_du_device_info rzg1_du_r8a7743_info = { ...@@ -40,7 +40,7 @@ static const struct rcar_du_device_info rzg1_du_r8a7743_info = {
.gen = 2, .gen = 2,
.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
| RCAR_DU_FEATURE_EXT_CTRL_REGS, | RCAR_DU_FEATURE_EXT_CTRL_REGS,
.num_crtcs = 2, .channels_mask = BIT(1) | BIT(0),
.routes = { .routes = {
/* /*
* R8A7743 has one RGB output and one LVDS output * R8A7743 has one RGB output and one LVDS output
...@@ -61,7 +61,7 @@ static const struct rcar_du_device_info rzg1_du_r8a7745_info = { ...@@ -61,7 +61,7 @@ static const struct rcar_du_device_info rzg1_du_r8a7745_info = {
.gen = 2, .gen = 2,
.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
| RCAR_DU_FEATURE_EXT_CTRL_REGS, | RCAR_DU_FEATURE_EXT_CTRL_REGS,
.num_crtcs = 2, .channels_mask = BIT(1) | BIT(0),
.routes = { .routes = {
/* /*
* R8A7745 has two RGB outputs * R8A7745 has two RGB outputs
...@@ -80,7 +80,7 @@ static const struct rcar_du_device_info rzg1_du_r8a7745_info = { ...@@ -80,7 +80,7 @@ static const struct rcar_du_device_info rzg1_du_r8a7745_info = {
static const struct rcar_du_device_info rcar_du_r8a7779_info = { static const struct rcar_du_device_info rcar_du_r8a7779_info = {
.gen = 2, .gen = 2,
.features = 0, .features = 0,
.num_crtcs = 2, .channels_mask = BIT(1) | BIT(0),
.routes = { .routes = {
/* /*
* R8A7779 has two RGB outputs and one (currently unsupported) * R8A7779 has two RGB outputs and one (currently unsupported)
...@@ -102,7 +102,7 @@ static const struct rcar_du_device_info rcar_du_r8a7790_info = { ...@@ -102,7 +102,7 @@ static const struct rcar_du_device_info rcar_du_r8a7790_info = {
.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
| RCAR_DU_FEATURE_EXT_CTRL_REGS, | RCAR_DU_FEATURE_EXT_CTRL_REGS,
.quirks = RCAR_DU_QUIRK_ALIGN_128B, .quirks = RCAR_DU_QUIRK_ALIGN_128B,
.num_crtcs = 3, .channels_mask = BIT(2) | BIT(1) | BIT(0),
.routes = { .routes = {
/* /*
* R8A7790 has one RGB output, two LVDS outputs and one * R8A7790 has one RGB output, two LVDS outputs and one
...@@ -129,7 +129,7 @@ static const struct rcar_du_device_info rcar_du_r8a7791_info = { ...@@ -129,7 +129,7 @@ static const struct rcar_du_device_info rcar_du_r8a7791_info = {
.gen = 2, .gen = 2,
.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
| RCAR_DU_FEATURE_EXT_CTRL_REGS, | RCAR_DU_FEATURE_EXT_CTRL_REGS,
.num_crtcs = 2, .channels_mask = BIT(1) | BIT(0),
.routes = { .routes = {
/* /*
* R8A779[13] has one RGB output, one LVDS output and one * R8A779[13] has one RGB output, one LVDS output and one
...@@ -151,7 +151,7 @@ static const struct rcar_du_device_info rcar_du_r8a7792_info = { ...@@ -151,7 +151,7 @@ static const struct rcar_du_device_info rcar_du_r8a7792_info = {
.gen = 2, .gen = 2,
.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
| RCAR_DU_FEATURE_EXT_CTRL_REGS, | RCAR_DU_FEATURE_EXT_CTRL_REGS,
.num_crtcs = 2, .channels_mask = BIT(1) | BIT(0),
.routes = { .routes = {
/* R8A7792 has two RGB outputs. */ /* R8A7792 has two RGB outputs. */
[RCAR_DU_OUTPUT_DPAD0] = { [RCAR_DU_OUTPUT_DPAD0] = {
...@@ -169,7 +169,7 @@ static const struct rcar_du_device_info rcar_du_r8a7794_info = { ...@@ -169,7 +169,7 @@ static const struct rcar_du_device_info rcar_du_r8a7794_info = {
.gen = 2, .gen = 2,
.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
| RCAR_DU_FEATURE_EXT_CTRL_REGS, | RCAR_DU_FEATURE_EXT_CTRL_REGS,
.num_crtcs = 2, .channels_mask = BIT(1) | BIT(0),
.routes = { .routes = {
/* /*
* R8A7794 has two RGB outputs and one (currently unsupported) * R8A7794 has two RGB outputs and one (currently unsupported)
...@@ -191,7 +191,7 @@ static const struct rcar_du_device_info rcar_du_r8a7795_info = { ...@@ -191,7 +191,7 @@ static const struct rcar_du_device_info rcar_du_r8a7795_info = {
.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
| RCAR_DU_FEATURE_EXT_CTRL_REGS | RCAR_DU_FEATURE_EXT_CTRL_REGS
| RCAR_DU_FEATURE_VSP1_SOURCE, | RCAR_DU_FEATURE_VSP1_SOURCE,
.num_crtcs = 4, .channels_mask = BIT(3) | BIT(2) | BIT(1) | BIT(0),
.routes = { .routes = {
/* /*
* R8A7795 has one RGB output, two HDMI outputs and one * R8A7795 has one RGB output, two HDMI outputs and one
...@@ -215,7 +215,7 @@ static const struct rcar_du_device_info rcar_du_r8a7795_info = { ...@@ -215,7 +215,7 @@ static const struct rcar_du_device_info rcar_du_r8a7795_info = {
}, },
}, },
.num_lvds = 1, .num_lvds = 1,
.dpll_ch = BIT(1) | BIT(2), .dpll_ch = BIT(2) | BIT(1),
}; };
static const struct rcar_du_device_info rcar_du_r8a7796_info = { static const struct rcar_du_device_info rcar_du_r8a7796_info = {
...@@ -223,7 +223,7 @@ static const struct rcar_du_device_info rcar_du_r8a7796_info = { ...@@ -223,7 +223,7 @@ static const struct rcar_du_device_info rcar_du_r8a7796_info = {
.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
| RCAR_DU_FEATURE_EXT_CTRL_REGS | RCAR_DU_FEATURE_EXT_CTRL_REGS
| RCAR_DU_FEATURE_VSP1_SOURCE, | RCAR_DU_FEATURE_VSP1_SOURCE,
.num_crtcs = 3, .channels_mask = BIT(2) | BIT(1) | BIT(0),
.routes = { .routes = {
/* /*
* R8A7796 has one RGB output, one LVDS output and one HDMI * R8A7796 has one RGB output, one LVDS output and one HDMI
...@@ -246,12 +246,40 @@ static const struct rcar_du_device_info rcar_du_r8a7796_info = { ...@@ -246,12 +246,40 @@ static const struct rcar_du_device_info rcar_du_r8a7796_info = {
.dpll_ch = BIT(1), .dpll_ch = BIT(1),
}; };
static const struct rcar_du_device_info rcar_du_r8a77965_info = {
.gen = 3,
.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
| RCAR_DU_FEATURE_EXT_CTRL_REGS
| RCAR_DU_FEATURE_VSP1_SOURCE,
.channels_mask = BIT(3) | BIT(1) | BIT(0),
.routes = {
/*
* R8A77965 has one RGB output, one LVDS output and one HDMI
* output.
*/
[RCAR_DU_OUTPUT_DPAD0] = {
.possible_crtcs = BIT(2),
.port = 0,
},
[RCAR_DU_OUTPUT_HDMI0] = {
.possible_crtcs = BIT(1),
.port = 1,
},
[RCAR_DU_OUTPUT_LVDS0] = {
.possible_crtcs = BIT(0),
.port = 2,
},
},
.num_lvds = 1,
.dpll_ch = BIT(1),
};
static const struct rcar_du_device_info rcar_du_r8a77970_info = { static const struct rcar_du_device_info rcar_du_r8a77970_info = {
.gen = 3, .gen = 3,
.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
| RCAR_DU_FEATURE_EXT_CTRL_REGS | RCAR_DU_FEATURE_EXT_CTRL_REGS
| RCAR_DU_FEATURE_VSP1_SOURCE, | RCAR_DU_FEATURE_VSP1_SOURCE,
.num_crtcs = 1, .channels_mask = BIT(0),
.routes = { .routes = {
/* R8A77970 has one RGB output and one LVDS output. */ /* R8A77970 has one RGB output and one LVDS output. */
[RCAR_DU_OUTPUT_DPAD0] = { [RCAR_DU_OUTPUT_DPAD0] = {
...@@ -277,6 +305,7 @@ static const struct of_device_id rcar_du_of_table[] = { ...@@ -277,6 +305,7 @@ static const struct of_device_id rcar_du_of_table[] = {
{ .compatible = "renesas,du-r8a7794", .data = &rcar_du_r8a7794_info }, { .compatible = "renesas,du-r8a7794", .data = &rcar_du_r8a7794_info },
{ .compatible = "renesas,du-r8a7795", .data = &rcar_du_r8a7795_info }, { .compatible = "renesas,du-r8a7795", .data = &rcar_du_r8a7795_info },
{ .compatible = "renesas,du-r8a7796", .data = &rcar_du_r8a7796_info }, { .compatible = "renesas,du-r8a7796", .data = &rcar_du_r8a7796_info },
{ .compatible = "renesas,du-r8a77965", .data = &rcar_du_r8a77965_info },
{ .compatible = "renesas,du-r8a77970", .data = &rcar_du_r8a77970_info }, { .compatible = "renesas,du-r8a77970", .data = &rcar_du_r8a77970_info },
{ } { }
}; };
......
...@@ -52,7 +52,7 @@ struct rcar_du_output_routing { ...@@ -52,7 +52,7 @@ struct rcar_du_output_routing {
* @gen: device generation (2 or 3) * @gen: device generation (2 or 3)
* @features: device features (RCAR_DU_FEATURE_*) * @features: device features (RCAR_DU_FEATURE_*)
* @quirks: device quirks (RCAR_DU_QUIRK_*) * @quirks: device quirks (RCAR_DU_QUIRK_*)
* @num_crtcs: total number of CRTCs * @channels_mask: bit mask of available DU channels
* @routes: array of CRTC to output routes, indexed by output (RCAR_DU_OUTPUT_*) * @routes: array of CRTC to output routes, indexed by output (RCAR_DU_OUTPUT_*)
* @num_lvds: number of internal LVDS encoders * @num_lvds: number of internal LVDS encoders
*/ */
...@@ -60,7 +60,7 @@ struct rcar_du_device_info { ...@@ -60,7 +60,7 @@ struct rcar_du_device_info {
unsigned int gen; unsigned int gen;
unsigned int features; unsigned int features;
unsigned int quirks; unsigned int quirks;
unsigned int num_crtcs; unsigned int channels_mask;
struct rcar_du_output_routing routes[RCAR_DU_OUTPUT_MAX]; struct rcar_du_output_routing routes[RCAR_DU_OUTPUT_MAX];
unsigned int num_lvds; unsigned int num_lvds;
unsigned int dpll_ch; unsigned int dpll_ch;
......
...@@ -46,10 +46,13 @@ void rcar_du_group_write(struct rcar_du_group *rgrp, u32 reg, u32 data) ...@@ -46,10 +46,13 @@ void rcar_du_group_write(struct rcar_du_group *rgrp, u32 reg, u32 data)
static void rcar_du_group_setup_pins(struct rcar_du_group *rgrp) static void rcar_du_group_setup_pins(struct rcar_du_group *rgrp)
{ {
u32 defr6 = DEFR6_CODE | DEFR6_ODPM12_DISP; u32 defr6 = DEFR6_CODE;
if (rgrp->num_crtcs > 1) if (rgrp->channels_mask & BIT(0))
defr6 |= DEFR6_ODPM22_DISP; defr6 |= DEFR6_ODPM02_DISP;
if (rgrp->channels_mask & BIT(1))
defr6 |= DEFR6_ODPM12_DISP;
rcar_du_group_write(rgrp, DEFR6, defr6); rcar_du_group_write(rgrp, DEFR6, defr6);
} }
...@@ -80,10 +83,11 @@ static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp) ...@@ -80,10 +83,11 @@ static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp)
* On Gen3 VSPD routing can't be configured, but DPAD routing * On Gen3 VSPD routing can't be configured, but DPAD routing
* needs to be set despite having a single option available. * needs to be set despite having a single option available.
*/ */
u32 crtc = ffs(possible_crtcs) - 1; unsigned int rgb_crtc = ffs(possible_crtcs) - 1;
struct rcar_du_crtc *crtc = &rcdu->crtcs[rgb_crtc];
if (crtc / 2 == rgrp->index) if (crtc->index / 2 == rgrp->index)
defr8 |= DEFR8_DRGBS_DU(crtc); defr8 |= DEFR8_DRGBS_DU(crtc->index);
} }
rcar_du_group_write(rgrp, DEFR8, defr8); rcar_du_group_write(rgrp, DEFR8, defr8);
......
...@@ -25,6 +25,7 @@ struct rcar_du_device; ...@@ -25,6 +25,7 @@ struct rcar_du_device;
* @dev: the DU device * @dev: the DU device
* @mmio_offset: registers offset in the device memory map * @mmio_offset: registers offset in the device memory map
* @index: group index * @index: group index
* @channels_mask: bitmask of populated DU channels in this group
* @num_crtcs: number of CRTCs in this group (1 or 2) * @num_crtcs: number of CRTCs in this group (1 or 2)
* @use_count: number of users of the group (rcar_du_group_(get|put)) * @use_count: number of users of the group (rcar_du_group_(get|put))
* @used_crtcs: number of CRTCs currently in use * @used_crtcs: number of CRTCs currently in use
...@@ -39,6 +40,7 @@ struct rcar_du_group { ...@@ -39,6 +40,7 @@ struct rcar_du_group {
unsigned int mmio_offset; unsigned int mmio_offset;
unsigned int index; unsigned int index;
unsigned int channels_mask;
unsigned int num_crtcs; unsigned int num_crtcs;
unsigned int use_count; unsigned int use_count;
unsigned int used_crtcs; unsigned int used_crtcs;
......
...@@ -428,7 +428,7 @@ static int rcar_du_vsps_init(struct rcar_du_device *rcdu) ...@@ -428,7 +428,7 @@ static int rcar_du_vsps_init(struct rcar_du_device *rcdu)
struct { struct {
struct device_node *np; struct device_node *np;
unsigned int crtcs_mask; unsigned int crtcs_mask;
} vsps[RCAR_DU_MAX_VSPS] = { { 0, }, }; } vsps[RCAR_DU_MAX_VSPS] = { { NULL, }, };
unsigned int vsps_count = 0; unsigned int vsps_count = 0;
unsigned int cells; unsigned int cells;
unsigned int i; unsigned int i;
...@@ -507,6 +507,8 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu) ...@@ -507,6 +507,8 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
struct drm_fbdev_cma *fbdev; struct drm_fbdev_cma *fbdev;
unsigned int num_encoders; unsigned int num_encoders;
unsigned int num_groups; unsigned int num_groups;
unsigned int swindex;
unsigned int hwindex;
unsigned int i; unsigned int i;
int ret; int ret;
...@@ -520,7 +522,7 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu) ...@@ -520,7 +522,7 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
dev->mode_config.funcs = &rcar_du_mode_config_funcs; dev->mode_config.funcs = &rcar_du_mode_config_funcs;
dev->mode_config.helper_private = &rcar_du_mode_config_helper; dev->mode_config.helper_private = &rcar_du_mode_config_helper;
rcdu->num_crtcs = rcdu->info->num_crtcs; rcdu->num_crtcs = hweight8(rcdu->info->channels_mask);
ret = rcar_du_properties_init(rcdu); ret = rcar_du_properties_init(rcdu);
if (ret < 0) if (ret < 0)
...@@ -530,7 +532,7 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu) ...@@ -530,7 +532,7 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
* Initialize vertical blanking interrupts handling. Start with vblank * Initialize vertical blanking interrupts handling. Start with vblank
* disabled for all CRTCs. * disabled for all CRTCs.
*/ */
ret = drm_vblank_init(dev, (1 << rcdu->info->num_crtcs) - 1); ret = drm_vblank_init(dev, (1 << rcdu->num_crtcs) - 1);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -545,7 +547,10 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu) ...@@ -545,7 +547,10 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
rgrp->dev = rcdu; rgrp->dev = rcdu;
rgrp->mmio_offset = mmio_offsets[i]; rgrp->mmio_offset = mmio_offsets[i];
rgrp->index = i; rgrp->index = i;
rgrp->num_crtcs = min(rcdu->num_crtcs - 2 * i, 2U); /* Extract the channel mask for this group only. */
rgrp->channels_mask = (rcdu->info->channels_mask >> (2 * i))
& GENMASK(1, 0);
rgrp->num_crtcs = hweight8(rgrp->channels_mask);
/* /*
* If we have more than one CRTCs in this group pre-associate * If we have more than one CRTCs in this group pre-associate
...@@ -572,10 +577,16 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu) ...@@ -572,10 +577,16 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
} }
/* Create the CRTCs. */ /* Create the CRTCs. */
for (i = 0; i < rcdu->num_crtcs; ++i) { for (swindex = 0, hwindex = 0; swindex < rcdu->num_crtcs; ++hwindex) {
struct rcar_du_group *rgrp = &rcdu->groups[i / 2]; struct rcar_du_group *rgrp;
/* Skip unpopulated DU channels. */
if (!(rcdu->info->channels_mask & BIT(hwindex)))
continue;
rgrp = &rcdu->groups[hwindex / 2];
ret = rcar_du_crtc_create(rgrp, i); ret = rcar_du_crtc_create(rgrp, swindex++, hwindex);
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "rcar_du_crtc.h" #include "rcar_du_crtc.h"
#include "rcar_du_drv.h" #include "rcar_du_drv.h"
#include "rcar_du_of.h"
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* Generic Overlay Handling * Generic Overlay Handling
......
...@@ -187,14 +187,14 @@ ...@@ -187,14 +187,14 @@
#define DEFR6 0x000e8 #define DEFR6 0x000e8
#define DEFR6_CODE (0x7778 << 16) #define DEFR6_CODE (0x7778 << 16)
#define DEFR6_ODPM22_DSMR (0 << 10) #define DEFR6_ODPM12_DSMR (0 << 10)
#define DEFR6_ODPM22_DISP (2 << 10) #define DEFR6_ODPM12_DISP (2 << 10)
#define DEFR6_ODPM22_CDE (3 << 10) #define DEFR6_ODPM12_CDE (3 << 10)
#define DEFR6_ODPM22_MASK (3 << 10) #define DEFR6_ODPM12_MASK (3 << 10)
#define DEFR6_ODPM12_DSMR (0 << 8) #define DEFR6_ODPM02_DSMR (0 << 8)
#define DEFR6_ODPM12_DISP (2 << 8) #define DEFR6_ODPM02_DISP (2 << 8)
#define DEFR6_ODPM12_CDE (3 << 8) #define DEFR6_ODPM02_CDE (3 << 8)
#define DEFR6_ODPM12_MASK (3 << 8) #define DEFR6_ODPM02_MASK (3 << 8)
#define DEFR6_TCNE1 (1 << 6) #define DEFR6_TCNE1 (1 << 6)
#define DEFR6_TCNE0 (1 << 4) #define DEFR6_TCNE0 (1 << 4)
#define DEFR6_MLOS1 (1 << 2) #define DEFR6_MLOS1 (1 << 2)
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <drm/drm_crtc_helper.h> #include <drm/drm_crtc_helper.h>
#include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_cma_helper.h>
#include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_cma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_plane_helper.h> #include <drm/drm_plane_helper.h>
#include <linux/bitops.h> #include <linux/bitops.h>
...@@ -237,6 +238,10 @@ static int rcar_du_vsp_plane_prepare_fb(struct drm_plane *plane, ...@@ -237,6 +238,10 @@ static int rcar_du_vsp_plane_prepare_fb(struct drm_plane *plane,
} }
} }
ret = drm_gem_fb_prepare_fb(plane, state);
if (ret)
goto fail;
return 0; return 0;
fail: fail:
...@@ -299,18 +304,17 @@ static const struct drm_plane_helper_funcs rcar_du_vsp_plane_helper_funcs = { ...@@ -299,18 +304,17 @@ static const struct drm_plane_helper_funcs rcar_du_vsp_plane_helper_funcs = {
static struct drm_plane_state * static struct drm_plane_state *
rcar_du_vsp_plane_atomic_duplicate_state(struct drm_plane *plane) rcar_du_vsp_plane_atomic_duplicate_state(struct drm_plane *plane)
{ {
struct rcar_du_vsp_plane_state *state;
struct rcar_du_vsp_plane_state *copy; struct rcar_du_vsp_plane_state *copy;
if (WARN_ON(!plane->state)) if (WARN_ON(!plane->state))
return NULL; return NULL;
state = to_rcar_vsp_plane_state(plane->state); copy = kzalloc(sizeof(*copy), GFP_KERNEL);
copy = kmemdup(state, sizeof(*state), GFP_KERNEL);
if (copy == NULL) if (copy == NULL)
return NULL; return NULL;
__drm_atomic_helper_plane_duplicate_state(plane, &copy->state); __drm_atomic_helper_plane_duplicate_state(plane, &copy->state);
copy->alpha = to_rcar_vsp_plane_state(plane->state)->alpha;
return &copy->state; return &copy->state;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment