Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm: rcar-du: kms: Initialize CMM instances

Implement device tree parsing to collect the available CMM instances
described by the 'renesas,cmms' property. Associate CMMs with CRTCs and
store a mask of active CMMs in the DU group for later enablement.

Enforce the probe and suspend/resume ordering of DU and CMM by creating
a stateless device link between the two.

Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

authored by

Jacopo Mondi and committed by
Laurent Pinchart
8de707ae e08e934d

+88
+6
drivers/gpu/drm/rcar-du/rcar_du_crtc.c
··· 1194 1194 if (ret < 0) 1195 1195 return ret; 1196 1196 1197 + /* CMM might be disabled for this CRTC. */ 1198 + if (rcdu->cmms[swindex]) { 1199 + rcrtc->cmm = rcdu->cmms[swindex]; 1200 + rgrp->cmms_mask |= BIT(hwindex % 2); 1201 + } 1202 + 1197 1203 drm_crtc_helper_add(crtc, &crtc_helper_funcs); 1198 1204 1199 1205 /* Start with vertical blanking interrupt reporting disabled. */
+2
drivers/gpu/drm/rcar-du/rcar_du_crtc.h
··· 39 39 * @vblank_wait: wait queue used to signal vertical blanking 40 40 * @vblank_count: number of vertical blanking interrupts to wait for 41 41 * @group: CRTC group this CRTC belongs to 42 + * @cmm: CMM associated with this CRTC 42 43 * @vsp: VSP feeding video to this CRTC 43 44 * @vsp_pipe: index of the VSP pipeline feeding video to this CRTC 44 45 * @writeback: the writeback connector ··· 65 64 unsigned int vblank_count; 66 65 67 66 struct rcar_du_group *group; 67 + struct platform_device *cmm; 68 68 struct rcar_du_vsp *vsp; 69 69 unsigned int vsp_pipe; 70 70
+2
drivers/gpu/drm/rcar-du/rcar_du_drv.h
··· 13 13 #include <linux/kernel.h> 14 14 #include <linux/wait.h> 15 15 16 + #include "rcar_cmm.h" 16 17 #include "rcar_du_crtc.h" 17 18 #include "rcar_du_group.h" 18 19 #include "rcar_du_vsp.h" ··· 86 85 struct rcar_du_encoder *encoders[RCAR_DU_OUTPUT_MAX]; 87 86 88 87 struct rcar_du_group groups[RCAR_DU_MAX_GROUPS]; 88 + struct platform_device *cmms[RCAR_DU_MAX_CRTCS]; 89 89 struct rcar_du_vsp vsps[RCAR_DU_MAX_VSPS]; 90 90 91 91 struct {
+2
drivers/gpu/drm/rcar-du/rcar_du_group.h
··· 22 22 * @mmio_offset: registers offset in the device memory map 23 23 * @index: group index 24 24 * @channels_mask: bitmask of populated DU channels in this group 25 + * @cmms_mask: bitmask of available CMMs in this group 25 26 * @num_crtcs: number of CRTCs in this group (1 or 2) 26 27 * @use_count: number of users of the group (rcar_du_group_(get|put)) 27 28 * @used_crtcs: number of CRTCs currently in use ··· 38 37 unsigned int index; 39 38 40 39 unsigned int channels_mask; 40 + unsigned int cmms_mask; 41 41 unsigned int num_crtcs; 42 42 unsigned int use_count; 43 43 unsigned int used_crtcs;
+76
drivers/gpu/drm/rcar-du/rcar_du_kms.c
··· 17 17 #include <drm/drm_probe_helper.h> 18 18 #include <drm/drm_vblank.h> 19 19 20 + #include <linux/device.h> 20 21 #include <linux/of_graph.h> 22 + #include <linux/of_platform.h> 21 23 #include <linux/wait.h> 22 24 23 25 #include "rcar_du_crtc.h" ··· 620 618 return ret; 621 619 } 622 620 621 + static int rcar_du_cmm_init(struct rcar_du_device *rcdu) 622 + { 623 + const struct device_node *np = rcdu->dev->of_node; 624 + unsigned int i; 625 + int cells; 626 + 627 + cells = of_property_count_u32_elems(np, "renesas,cmms"); 628 + if (cells == -EINVAL) 629 + return 0; 630 + 631 + if (cells > rcdu->num_crtcs) { 632 + dev_err(rcdu->dev, 633 + "Invalid number of entries in 'renesas,cmms'\n"); 634 + return -EINVAL; 635 + } 636 + 637 + for (i = 0; i < cells; ++i) { 638 + struct platform_device *pdev; 639 + struct device_link *link; 640 + struct device_node *cmm; 641 + int ret; 642 + 643 + cmm = of_parse_phandle(np, "renesas,cmms", i); 644 + if (IS_ERR(cmm)) { 645 + dev_err(rcdu->dev, 646 + "Failed to parse 'renesas,cmms' property\n"); 647 + return PTR_ERR(cmm); 648 + } 649 + 650 + if (!of_device_is_available(cmm)) { 651 + /* It's fine to have a phandle to a non-enabled CMM. */ 652 + of_node_put(cmm); 653 + continue; 654 + } 655 + 656 + pdev = of_find_device_by_node(cmm); 657 + if (IS_ERR(pdev)) { 658 + dev_err(rcdu->dev, "No device found for CMM%u\n", i); 659 + of_node_put(cmm); 660 + return PTR_ERR(pdev); 661 + } 662 + 663 + of_node_put(cmm); 664 + 665 + /* 666 + * -ENODEV is used to report that the CMM config option is 667 + * disabled: return 0 and let the DU continue probing. 668 + */ 669 + ret = rcar_cmm_init(pdev); 670 + if (ret) 671 + return ret == -ENODEV ? 0 : ret; 672 + 673 + /* 674 + * Enforce suspend/resume ordering by making the CMM a provider 675 + * of the DU: CMM is suspended after and resumed before the DU. 676 + */ 677 + link = device_link_add(rcdu->dev, &pdev->dev, DL_FLAG_STATELESS); 678 + if (!link) { 679 + dev_err(rcdu->dev, 680 + "Failed to create device link to CMM%u\n", i); 681 + return -EINVAL; 682 + } 683 + 684 + rcdu->cmms[i] = pdev; 685 + } 686 + 687 + return 0; 688 + } 689 + 623 690 int rcar_du_modeset_init(struct rcar_du_device *rcdu) 624 691 { 625 692 static const unsigned int mmio_offsets[] = { ··· 778 707 if (ret < 0) 779 708 return ret; 780 709 } 710 + 711 + /* Initialize the Color Management Modules. */ 712 + ret = rcar_du_cmm_init(rcdu); 713 + if (ret) 714 + return ret; 781 715 782 716 /* Create the CRTCs. */ 783 717 for (swindex = 0, hwindex = 0; swindex < rcdu->num_crtcs; ++hwindex) {