aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2018-05-15 01:23:47 -0400
committerDave Airlie <airlied@redhat.com>2018-05-15 01:23:48 -0400
commit9037d4b98b255979c6636045794775f5a89cc623 (patch)
tree4eef5575a28ee4aaa3928c87d26fb89077add084 /drivers/gpu
parent2989b3ced370aa8e23e572c9ecaa7404d96e1c7a (diff)
parentb06078de418d6f77c81aa74516f787663f51a262 (diff)
Merge branch 'drm/du/next' of git://linuxtv.org/pinchartl/media into drm-next
Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/2792436.F0zlxykWp6@avalon
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_crtc.c26
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_crtc.h3
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_drv.c51
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_drv.h4
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_group.c16
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_group.h2
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_kms.c25
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_of.c1
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_regs.h16
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_vsp.c10
10 files changed, 104 insertions, 50 deletions
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index c4420538ec85..f2a0bd1e5119 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -767,7 +767,8 @@ static irqreturn_t rcar_du_crtc_irq(int irq, void *arg)
767 * Initialization 767 * Initialization
768 */ 768 */
769 769
770int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index) 770int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int swindex,
771 unsigned int hwindex)
771{ 772{
772 static const unsigned int mmio_offsets[] = { 773 static const unsigned int mmio_offsets[] = {
773 DU0_REG_OFFSET, DU1_REG_OFFSET, DU2_REG_OFFSET, DU3_REG_OFFSET 774 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 776
776 struct rcar_du_device *rcdu = rgrp->dev; 777 struct rcar_du_device *rcdu = rgrp->dev;
777 struct platform_device *pdev = to_platform_device(rcdu->dev); 778 struct platform_device *pdev = to_platform_device(rcdu->dev);
778 struct rcar_du_crtc *rcrtc = &rcdu->crtcs[index]; 779 struct rcar_du_crtc *rcrtc = &rcdu->crtcs[swindex];
779 struct drm_crtc *crtc = &rcrtc->crtc; 780 struct drm_crtc *crtc = &rcrtc->crtc;
780 struct drm_plane *primary; 781 struct drm_plane *primary;
781 unsigned int irqflags; 782 unsigned int irqflags;
@@ -787,7 +788,7 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
787 788
788 /* Get the CRTC clock and the optional external clock. */ 789 /* Get the CRTC clock and the optional external clock. */
789 if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CRTC_IRQ_CLOCK)) { 790 if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CRTC_IRQ_CLOCK)) {
790 sprintf(clk_name, "du.%u", index); 791 sprintf(clk_name, "du.%u", hwindex);
791 name = clk_name; 792 name = clk_name;
792 } else { 793 } else {
793 name = NULL; 794 name = NULL;
@@ -795,16 +796,16 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
795 796
796 rcrtc->clock = devm_clk_get(rcdu->dev, name); 797 rcrtc->clock = devm_clk_get(rcdu->dev, name);
797 if (IS_ERR(rcrtc->clock)) { 798 if (IS_ERR(rcrtc->clock)) {
798 dev_err(rcdu->dev, "no clock for CRTC %u\n", index); 799 dev_err(rcdu->dev, "no clock for DU channel %u\n", hwindex);
799 return PTR_ERR(rcrtc->clock); 800 return PTR_ERR(rcrtc->clock);
800 } 801 }
801 802
802 sprintf(clk_name, "dclkin.%u", index); 803 sprintf(clk_name, "dclkin.%u", hwindex);
803 clk = devm_clk_get(rcdu->dev, clk_name); 804 clk = devm_clk_get(rcdu->dev, clk_name);
804 if (!IS_ERR(clk)) { 805 if (!IS_ERR(clk)) {
805 rcrtc->extclock = clk; 806 rcrtc->extclock = clk;
806 } else if (PTR_ERR(rcrtc->clock) == -EPROBE_DEFER) { 807 } else if (PTR_ERR(rcrtc->clock) == -EPROBE_DEFER) {
807 dev_info(rcdu->dev, "can't get external clock %u\n", index); 808 dev_info(rcdu->dev, "can't get external clock %u\n", hwindex);
808 return -EPROBE_DEFER; 809 return -EPROBE_DEFER;
809 } 810 }
810 811
@@ -813,13 +814,13 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
813 spin_lock_init(&rcrtc->vblank_lock); 814 spin_lock_init(&rcrtc->vblank_lock);
814 815
815 rcrtc->group = rgrp; 816 rcrtc->group = rgrp;
816 rcrtc->mmio_offset = mmio_offsets[index]; 817 rcrtc->mmio_offset = mmio_offsets[hwindex];
817 rcrtc->index = index; 818 rcrtc->index = hwindex;
818 819
819 if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) 820 if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE))
820 primary = &rcrtc->vsp->planes[rcrtc->vsp_pipe].plane; 821 primary = &rcrtc->vsp->planes[rcrtc->vsp_pipe].plane;
821 else 822 else
822 primary = &rgrp->planes[index % 2].plane; 823 primary = &rgrp->planes[swindex % 2].plane;
823 824
824 ret = drm_crtc_init_with_planes(rcdu->ddev, crtc, primary, 825 ret = drm_crtc_init_with_planes(rcdu->ddev, crtc, primary,
825 NULL, &crtc_funcs, NULL); 826 NULL, &crtc_funcs, NULL);
@@ -833,7 +834,8 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
833 834
834 /* Register the interrupt handler. */ 835 /* Register the interrupt handler. */
835 if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CRTC_IRQ_CLOCK)) { 836 if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CRTC_IRQ_CLOCK)) {
836 irq = platform_get_irq(pdev, index); 837 /* The IRQ's are associated with the CRTC (sw)index. */
838 irq = platform_get_irq(pdev, swindex);
837 irqflags = 0; 839 irqflags = 0;
838 } else { 840 } else {
839 irq = platform_get_irq(pdev, 0); 841 irq = platform_get_irq(pdev, 0);
@@ -841,7 +843,7 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
841 } 843 }
842 844
843 if (irq < 0) { 845 if (irq < 0) {
844 dev_err(rcdu->dev, "no IRQ for CRTC %u\n", index); 846 dev_err(rcdu->dev, "no IRQ for CRTC %u\n", swindex);
845 return irq; 847 return irq;
846 } 848 }
847 849
@@ -849,7 +851,7 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
849 dev_name(rcdu->dev), rcrtc); 851 dev_name(rcdu->dev), rcrtc);
850 if (ret < 0) { 852 if (ret < 0) {
851 dev_err(rcdu->dev, 853 dev_err(rcdu->dev,
852 "failed to register IRQ for CRTC %u\n", index); 854 "failed to register IRQ for CRTC %u\n", swindex);
853 return ret; 855 return ret;
854 } 856 }
855 857
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
index fdc2bf99bda1..84b5e23a85b1 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
@@ -80,7 +80,8 @@ enum rcar_du_output {
80 RCAR_DU_OUTPUT_MAX, 80 RCAR_DU_OUTPUT_MAX,
81}; 81};
82 82
83int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index); 83int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int swindex,
84 unsigned int hwindex);
84void rcar_du_crtc_suspend(struct rcar_du_crtc *rcrtc); 85void rcar_du_crtc_suspend(struct rcar_du_crtc *rcrtc);
85void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc); 86void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc);
86 87
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
index 3917d839c04c..02aee6cb0e53 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
@@ -40,7 +40,7 @@ static const struct rcar_du_device_info rzg1_du_r8a7743_info = {
40 .gen = 2, 40 .gen = 2,
41 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK 41 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
42 | RCAR_DU_FEATURE_EXT_CTRL_REGS, 42 | RCAR_DU_FEATURE_EXT_CTRL_REGS,
43 .num_crtcs = 2, 43 .channels_mask = BIT(1) | BIT(0),
44 .routes = { 44 .routes = {
45 /* 45 /*
46 * R8A7743 has one RGB output and one LVDS output 46 * 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 .gen = 2, 61 .gen = 2,
62 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK 62 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
63 | RCAR_DU_FEATURE_EXT_CTRL_REGS, 63 | RCAR_DU_FEATURE_EXT_CTRL_REGS,
64 .num_crtcs = 2, 64 .channels_mask = BIT(1) | BIT(0),
65 .routes = { 65 .routes = {
66 /* 66 /*
67 * R8A7745 has two RGB outputs 67 * R8A7745 has two RGB outputs
@@ -80,7 +80,7 @@ static const struct rcar_du_device_info rzg1_du_r8a7745_info = {
80static const struct rcar_du_device_info rcar_du_r8a7779_info = { 80static const struct rcar_du_device_info rcar_du_r8a7779_info = {
81 .gen = 2, 81 .gen = 2,
82 .features = 0, 82 .features = 0,
83 .num_crtcs = 2, 83 .channels_mask = BIT(1) | BIT(0),
84 .routes = { 84 .routes = {
85 /* 85 /*
86 * R8A7779 has two RGB outputs and one (currently unsupported) 86 * 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 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK 102 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
103 | RCAR_DU_FEATURE_EXT_CTRL_REGS, 103 | RCAR_DU_FEATURE_EXT_CTRL_REGS,
104 .quirks = RCAR_DU_QUIRK_ALIGN_128B, 104 .quirks = RCAR_DU_QUIRK_ALIGN_128B,
105 .num_crtcs = 3, 105 .channels_mask = BIT(2) | BIT(1) | BIT(0),
106 .routes = { 106 .routes = {
107 /* 107 /*
108 * R8A7790 has one RGB output, two LVDS outputs and one 108 * 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 .gen = 2, 129 .gen = 2,
130 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK 130 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
131 | RCAR_DU_FEATURE_EXT_CTRL_REGS, 131 | RCAR_DU_FEATURE_EXT_CTRL_REGS,
132 .num_crtcs = 2, 132 .channels_mask = BIT(1) | BIT(0),
133 .routes = { 133 .routes = {
134 /* 134 /*
135 * R8A779[13] has one RGB output, one LVDS output and one 135 * 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 .gen = 2, 151 .gen = 2,
152 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK 152 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
153 | RCAR_DU_FEATURE_EXT_CTRL_REGS, 153 | RCAR_DU_FEATURE_EXT_CTRL_REGS,
154 .num_crtcs = 2, 154 .channels_mask = BIT(1) | BIT(0),
155 .routes = { 155 .routes = {
156 /* R8A7792 has two RGB outputs. */ 156 /* R8A7792 has two RGB outputs. */
157 [RCAR_DU_OUTPUT_DPAD0] = { 157 [RCAR_DU_OUTPUT_DPAD0] = {
@@ -169,7 +169,7 @@ static const struct rcar_du_device_info rcar_du_r8a7794_info = {
169 .gen = 2, 169 .gen = 2,
170 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK 170 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
171 | RCAR_DU_FEATURE_EXT_CTRL_REGS, 171 | RCAR_DU_FEATURE_EXT_CTRL_REGS,
172 .num_crtcs = 2, 172 .channels_mask = BIT(1) | BIT(0),
173 .routes = { 173 .routes = {
174 /* 174 /*
175 * R8A7794 has two RGB outputs and one (currently unsupported) 175 * 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 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK 191 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
192 | RCAR_DU_FEATURE_EXT_CTRL_REGS 192 | RCAR_DU_FEATURE_EXT_CTRL_REGS
193 | RCAR_DU_FEATURE_VSP1_SOURCE, 193 | RCAR_DU_FEATURE_VSP1_SOURCE,
194 .num_crtcs = 4, 194 .channels_mask = BIT(3) | BIT(2) | BIT(1) | BIT(0),
195 .routes = { 195 .routes = {
196 /* 196 /*
197 * R8A7795 has one RGB output, two HDMI outputs and one 197 * 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 }, 215 },
216 }, 216 },
217 .num_lvds = 1, 217 .num_lvds = 1,
218 .dpll_ch = BIT(1) | BIT(2), 218 .dpll_ch = BIT(2) | BIT(1),
219}; 219};
220 220
221static const struct rcar_du_device_info rcar_du_r8a7796_info = { 221static 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 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK 223 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
224 | RCAR_DU_FEATURE_EXT_CTRL_REGS 224 | RCAR_DU_FEATURE_EXT_CTRL_REGS
225 | RCAR_DU_FEATURE_VSP1_SOURCE, 225 | RCAR_DU_FEATURE_VSP1_SOURCE,
226 .num_crtcs = 3, 226 .channels_mask = BIT(2) | BIT(1) | BIT(0),
227 .routes = { 227 .routes = {
228 /* 228 /*
229 * R8A7796 has one RGB output, one LVDS output and one HDMI 229 * 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 .dpll_ch = BIT(1), 246 .dpll_ch = BIT(1),
247}; 247};
248 248
249static const struct rcar_du_device_info rcar_du_r8a77965_info = {
250 .gen = 3,
251 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
252 | RCAR_DU_FEATURE_EXT_CTRL_REGS
253 | RCAR_DU_FEATURE_VSP1_SOURCE,
254 .channels_mask = BIT(3) | BIT(1) | BIT(0),
255 .routes = {
256 /*
257 * R8A77965 has one RGB output, one LVDS output and one HDMI
258 * output.
259 */
260 [RCAR_DU_OUTPUT_DPAD0] = {
261 .possible_crtcs = BIT(2),
262 .port = 0,
263 },
264 [RCAR_DU_OUTPUT_HDMI0] = {
265 .possible_crtcs = BIT(1),
266 .port = 1,
267 },
268 [RCAR_DU_OUTPUT_LVDS0] = {
269 .possible_crtcs = BIT(0),
270 .port = 2,
271 },
272 },
273 .num_lvds = 1,
274 .dpll_ch = BIT(1),
275};
276
249static const struct rcar_du_device_info rcar_du_r8a77970_info = { 277static const struct rcar_du_device_info rcar_du_r8a77970_info = {
250 .gen = 3, 278 .gen = 3,
251 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK 279 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
252 | RCAR_DU_FEATURE_EXT_CTRL_REGS 280 | RCAR_DU_FEATURE_EXT_CTRL_REGS
253 | RCAR_DU_FEATURE_VSP1_SOURCE, 281 | RCAR_DU_FEATURE_VSP1_SOURCE,
254 .num_crtcs = 1, 282 .channels_mask = BIT(0),
255 .routes = { 283 .routes = {
256 /* R8A77970 has one RGB output and one LVDS output. */ 284 /* R8A77970 has one RGB output and one LVDS output. */
257 [RCAR_DU_OUTPUT_DPAD0] = { 285 [RCAR_DU_OUTPUT_DPAD0] = {
@@ -277,6 +305,7 @@ static const struct of_device_id rcar_du_of_table[] = {
277 { .compatible = "renesas,du-r8a7794", .data = &rcar_du_r8a7794_info }, 305 { .compatible = "renesas,du-r8a7794", .data = &rcar_du_r8a7794_info },
278 { .compatible = "renesas,du-r8a7795", .data = &rcar_du_r8a7795_info }, 306 { .compatible = "renesas,du-r8a7795", .data = &rcar_du_r8a7795_info },
279 { .compatible = "renesas,du-r8a7796", .data = &rcar_du_r8a7796_info }, 307 { .compatible = "renesas,du-r8a7796", .data = &rcar_du_r8a7796_info },
308 { .compatible = "renesas,du-r8a77965", .data = &rcar_du_r8a77965_info },
280 { .compatible = "renesas,du-r8a77970", .data = &rcar_du_r8a77970_info }, 309 { .compatible = "renesas,du-r8a77970", .data = &rcar_du_r8a77970_info },
281 { } 310 { }
282}; 311};
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
index 131d8e88b06c..b3a25e8e07d0 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
@@ -52,7 +52,7 @@ struct rcar_du_output_routing {
52 * @gen: device generation (2 or 3) 52 * @gen: device generation (2 or 3)
53 * @features: device features (RCAR_DU_FEATURE_*) 53 * @features: device features (RCAR_DU_FEATURE_*)
54 * @quirks: device quirks (RCAR_DU_QUIRK_*) 54 * @quirks: device quirks (RCAR_DU_QUIRK_*)
55 * @num_crtcs: total number of CRTCs 55 * @channels_mask: bit mask of available DU channels
56 * @routes: array of CRTC to output routes, indexed by output (RCAR_DU_OUTPUT_*) 56 * @routes: array of CRTC to output routes, indexed by output (RCAR_DU_OUTPUT_*)
57 * @num_lvds: number of internal LVDS encoders 57 * @num_lvds: number of internal LVDS encoders
58 */ 58 */
@@ -60,7 +60,7 @@ struct rcar_du_device_info {
60 unsigned int gen; 60 unsigned int gen;
61 unsigned int features; 61 unsigned int features;
62 unsigned int quirks; 62 unsigned int quirks;
63 unsigned int num_crtcs; 63 unsigned int channels_mask;
64 struct rcar_du_output_routing routes[RCAR_DU_OUTPUT_MAX]; 64 struct rcar_du_output_routing routes[RCAR_DU_OUTPUT_MAX];
65 unsigned int num_lvds; 65 unsigned int num_lvds;
66 unsigned int dpll_ch; 66 unsigned int dpll_ch;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
index 2f37ea901873..d539cb290a35 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
@@ -46,10 +46,13 @@ void rcar_du_group_write(struct rcar_du_group *rgrp, u32 reg, u32 data)
46 46
47static void rcar_du_group_setup_pins(struct rcar_du_group *rgrp) 47static void rcar_du_group_setup_pins(struct rcar_du_group *rgrp)
48{ 48{
49 u32 defr6 = DEFR6_CODE | DEFR6_ODPM12_DISP; 49 u32 defr6 = DEFR6_CODE;
50 50
51 if (rgrp->num_crtcs > 1) 51 if (rgrp->channels_mask & BIT(0))
52 defr6 |= DEFR6_ODPM22_DISP; 52 defr6 |= DEFR6_ODPM02_DISP;
53
54 if (rgrp->channels_mask & BIT(1))
55 defr6 |= DEFR6_ODPM12_DISP;
53 56
54 rcar_du_group_write(rgrp, DEFR6, defr6); 57 rcar_du_group_write(rgrp, DEFR6, defr6);
55} 58}
@@ -80,10 +83,11 @@ static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp)
80 * On Gen3 VSPD routing can't be configured, but DPAD routing 83 * On Gen3 VSPD routing can't be configured, but DPAD routing
81 * needs to be set despite having a single option available. 84 * needs to be set despite having a single option available.
82 */ 85 */
83 u32 crtc = ffs(possible_crtcs) - 1; 86 unsigned int rgb_crtc = ffs(possible_crtcs) - 1;
87 struct rcar_du_crtc *crtc = &rcdu->crtcs[rgb_crtc];
84 88
85 if (crtc / 2 == rgrp->index) 89 if (crtc->index / 2 == rgrp->index)
86 defr8 |= DEFR8_DRGBS_DU(crtc); 90 defr8 |= DEFR8_DRGBS_DU(crtc->index);
87 } 91 }
88 92
89 rcar_du_group_write(rgrp, DEFR8, defr8); 93 rcar_du_group_write(rgrp, DEFR8, defr8);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.h b/drivers/gpu/drm/rcar-du/rcar_du_group.h
index 5e3adc6b31b5..42105aedecc8 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.h
@@ -25,6 +25,7 @@ struct rcar_du_device;
25 * @dev: the DU device 25 * @dev: the DU device
26 * @mmio_offset: registers offset in the device memory map 26 * @mmio_offset: registers offset in the device memory map
27 * @index: group index 27 * @index: group index
28 * @channels_mask: bitmask of populated DU channels in this group
28 * @num_crtcs: number of CRTCs in this group (1 or 2) 29 * @num_crtcs: number of CRTCs in this group (1 or 2)
29 * @use_count: number of users of the group (rcar_du_group_(get|put)) 30 * @use_count: number of users of the group (rcar_du_group_(get|put))
30 * @used_crtcs: number of CRTCs currently in use 31 * @used_crtcs: number of CRTCs currently in use
@@ -39,6 +40,7 @@ struct rcar_du_group {
39 unsigned int mmio_offset; 40 unsigned int mmio_offset;
40 unsigned int index; 41 unsigned int index;
41 42
43 unsigned int channels_mask;
42 unsigned int num_crtcs; 44 unsigned int num_crtcs;
43 unsigned int use_count; 45 unsigned int use_count;
44 unsigned int used_crtcs; 46 unsigned int used_crtcs;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index f4ac0f884f00..f0bc7cc0e913 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -428,7 +428,7 @@ static int rcar_du_vsps_init(struct rcar_du_device *rcdu)
428 struct { 428 struct {
429 struct device_node *np; 429 struct device_node *np;
430 unsigned int crtcs_mask; 430 unsigned int crtcs_mask;
431 } vsps[RCAR_DU_MAX_VSPS] = { { 0, }, }; 431 } vsps[RCAR_DU_MAX_VSPS] = { { NULL, }, };
432 unsigned int vsps_count = 0; 432 unsigned int vsps_count = 0;
433 unsigned int cells; 433 unsigned int cells;
434 unsigned int i; 434 unsigned int i;
@@ -507,6 +507,8 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
507 struct drm_fbdev_cma *fbdev; 507 struct drm_fbdev_cma *fbdev;
508 unsigned int num_encoders; 508 unsigned int num_encoders;
509 unsigned int num_groups; 509 unsigned int num_groups;
510 unsigned int swindex;
511 unsigned int hwindex;
510 unsigned int i; 512 unsigned int i;
511 int ret; 513 int ret;
512 514
@@ -520,7 +522,7 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
520 dev->mode_config.funcs = &rcar_du_mode_config_funcs; 522 dev->mode_config.funcs = &rcar_du_mode_config_funcs;
521 dev->mode_config.helper_private = &rcar_du_mode_config_helper; 523 dev->mode_config.helper_private = &rcar_du_mode_config_helper;
522 524
523 rcdu->num_crtcs = rcdu->info->num_crtcs; 525 rcdu->num_crtcs = hweight8(rcdu->info->channels_mask);
524 526
525 ret = rcar_du_properties_init(rcdu); 527 ret = rcar_du_properties_init(rcdu);
526 if (ret < 0) 528 if (ret < 0)
@@ -530,7 +532,7 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
530 * Initialize vertical blanking interrupts handling. Start with vblank 532 * Initialize vertical blanking interrupts handling. Start with vblank
531 * disabled for all CRTCs. 533 * disabled for all CRTCs.
532 */ 534 */
533 ret = drm_vblank_init(dev, (1 << rcdu->info->num_crtcs) - 1); 535 ret = drm_vblank_init(dev, (1 << rcdu->num_crtcs) - 1);
534 if (ret < 0) 536 if (ret < 0)
535 return ret; 537 return ret;
536 538
@@ -545,7 +547,10 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
545 rgrp->dev = rcdu; 547 rgrp->dev = rcdu;
546 rgrp->mmio_offset = mmio_offsets[i]; 548 rgrp->mmio_offset = mmio_offsets[i];
547 rgrp->index = i; 549 rgrp->index = i;
548 rgrp->num_crtcs = min(rcdu->num_crtcs - 2 * i, 2U); 550 /* Extract the channel mask for this group only. */
551 rgrp->channels_mask = (rcdu->info->channels_mask >> (2 * i))
552 & GENMASK(1, 0);
553 rgrp->num_crtcs = hweight8(rgrp->channels_mask);
549 554
550 /* 555 /*
551 * If we have more than one CRTCs in this group pre-associate 556 * 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 } 577 }
573 578
574 /* Create the CRTCs. */ 579 /* Create the CRTCs. */
575 for (i = 0; i < rcdu->num_crtcs; ++i) { 580 for (swindex = 0, hwindex = 0; swindex < rcdu->num_crtcs; ++hwindex) {
576 struct rcar_du_group *rgrp = &rcdu->groups[i / 2]; 581 struct rcar_du_group *rgrp;
582
583 /* Skip unpopulated DU channels. */
584 if (!(rcdu->info->channels_mask & BIT(hwindex)))
585 continue;
586
587 rgrp = &rcdu->groups[hwindex / 2];
577 588
578 ret = rcar_du_crtc_create(rgrp, i); 589 ret = rcar_du_crtc_create(rgrp, swindex++, hwindex);
579 if (ret < 0) 590 if (ret < 0)
580 return ret; 591 return ret;
581 } 592 }
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_of.c b/drivers/gpu/drm/rcar-du/rcar_du_of.c
index 68a0b82cb17e..afef69669bb4 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_of.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_of.c
@@ -18,6 +18,7 @@
18 18
19#include "rcar_du_crtc.h" 19#include "rcar_du_crtc.h"
20#include "rcar_du_drv.h" 20#include "rcar_du_drv.h"
21#include "rcar_du_of.h"
21 22
22/* ----------------------------------------------------------------------------- 23/* -----------------------------------------------------------------------------
23 * Generic Overlay Handling 24 * Generic Overlay Handling
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_regs.h b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
index d5bae99d3cfe..9dfd220ceda1 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_regs.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
@@ -187,14 +187,14 @@
187 187
188#define DEFR6 0x000e8 188#define DEFR6 0x000e8
189#define DEFR6_CODE (0x7778 << 16) 189#define DEFR6_CODE (0x7778 << 16)
190#define DEFR6_ODPM22_DSMR (0 << 10) 190#define DEFR6_ODPM12_DSMR (0 << 10)
191#define DEFR6_ODPM22_DISP (2 << 10) 191#define DEFR6_ODPM12_DISP (2 << 10)
192#define DEFR6_ODPM22_CDE (3 << 10) 192#define DEFR6_ODPM12_CDE (3 << 10)
193#define DEFR6_ODPM22_MASK (3 << 10) 193#define DEFR6_ODPM12_MASK (3 << 10)
194#define DEFR6_ODPM12_DSMR (0 << 8) 194#define DEFR6_ODPM02_DSMR (0 << 8)
195#define DEFR6_ODPM12_DISP (2 << 8) 195#define DEFR6_ODPM02_DISP (2 << 8)
196#define DEFR6_ODPM12_CDE (3 << 8) 196#define DEFR6_ODPM02_CDE (3 << 8)
197#define DEFR6_ODPM12_MASK (3 << 8) 197#define DEFR6_ODPM02_MASK (3 << 8)
198#define DEFR6_TCNE1 (1 << 6) 198#define DEFR6_TCNE1 (1 << 6)
199#define DEFR6_TCNE0 (1 << 4) 199#define DEFR6_TCNE0 (1 << 4)
200#define DEFR6_MLOS1 (1 << 2) 200#define DEFR6_MLOS1 (1 << 2)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
index b3bec0125696..27a440886b17 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
@@ -17,6 +17,7 @@
17#include <drm/drm_crtc_helper.h> 17#include <drm/drm_crtc_helper.h>
18#include <drm/drm_fb_cma_helper.h> 18#include <drm/drm_fb_cma_helper.h>
19#include <drm/drm_gem_cma_helper.h> 19#include <drm/drm_gem_cma_helper.h>
20#include <drm/drm_gem_framebuffer_helper.h>
20#include <drm/drm_plane_helper.h> 21#include <drm/drm_plane_helper.h>
21 22
22#include <linux/bitops.h> 23#include <linux/bitops.h>
@@ -237,6 +238,10 @@ static int rcar_du_vsp_plane_prepare_fb(struct drm_plane *plane,
237 } 238 }
238 } 239 }
239 240
241 ret = drm_gem_fb_prepare_fb(plane, state);
242 if (ret)
243 goto fail;
244
240 return 0; 245 return 0;
241 246
242fail: 247fail:
@@ -299,18 +304,17 @@ static const struct drm_plane_helper_funcs rcar_du_vsp_plane_helper_funcs = {
299static struct drm_plane_state * 304static struct drm_plane_state *
300rcar_du_vsp_plane_atomic_duplicate_state(struct drm_plane *plane) 305rcar_du_vsp_plane_atomic_duplicate_state(struct drm_plane *plane)
301{ 306{
302 struct rcar_du_vsp_plane_state *state;
303 struct rcar_du_vsp_plane_state *copy; 307 struct rcar_du_vsp_plane_state *copy;
304 308
305 if (WARN_ON(!plane->state)) 309 if (WARN_ON(!plane->state))
306 return NULL; 310 return NULL;
307 311
308 state = to_rcar_vsp_plane_state(plane->state); 312 copy = kzalloc(sizeof(*copy), GFP_KERNEL);
309 copy = kmemdup(state, sizeof(*state), GFP_KERNEL);
310 if (copy == NULL) 313 if (copy == NULL)
311 return NULL; 314 return NULL;
312 315
313 __drm_atomic_helper_plane_duplicate_state(plane, &copy->state); 316 __drm_atomic_helper_plane_duplicate_state(plane, &copy->state);
317 copy->alpha = to_rcar_vsp_plane_state(plane->state)->alpha;
314 318
315 return &copy->state; 319 return &copy->state;
316} 320}