static struct drm_encoder *construct_encoder(struct mdp5_kms *mdp5_kms, enum mdp5_intf_type intf_type, int intf_num, enum mdp5_intf_mode intf_mode) { struct drm_device *dev = mdp5_kms->dev; struct msm_drm_private *priv = dev->dev_private; struct drm_encoder *encoder; struct mdp5_interface intf = { .num = intf_num, .type = intf_type, .mode = intf_mode, }; if ((intf_type == INTF_DSI) && (intf_mode == MDP5_INTF_DSI_MODE_COMMAND)) encoder = mdp5_cmd_encoder_init(dev, &intf); else encoder = mdp5_encoder_init(dev, &intf); if (IS_ERR(encoder)) { dev_err(dev->dev, "failed to construct encoder\n"); return encoder; } encoder->possible_crtcs = (1 << priv->num_crtcs) - 1; priv->encoders[priv->num_encoders++] = encoder; return encoder; }
static struct drm_encoder *construct_encoder(struct mdp5_kms *mdp5_kms, struct mdp5_interface *intf, struct mdp5_ctl *ctl) { struct drm_device *dev = mdp5_kms->dev; struct msm_drm_private *priv = dev->dev_private; struct drm_encoder *encoder; encoder = mdp5_encoder_init(dev, intf, ctl); if (IS_ERR(encoder)) { dev_err(dev->dev, "failed to construct encoder\n"); return encoder; } priv->encoders[priv->num_encoders++] = encoder; return encoder; }
static int modeset_init(struct mdp5_kms *mdp5_kms) { static const enum mdp5_pipe crtcs[] = { SSPP_RGB0, SSPP_RGB1, SSPP_RGB2, }; struct drm_device *dev = mdp5_kms->dev; struct msm_drm_private *priv = dev->dev_private; struct drm_encoder *encoder; int i, ret; /* construct CRTCs: */ for (i = 0; i < ARRAY_SIZE(crtcs); i++) { struct drm_plane *plane; struct drm_crtc *crtc; plane = mdp5_plane_init(dev, crtcs[i], true); if (IS_ERR(plane)) { ret = PTR_ERR(plane); dev_err(dev->dev, "failed to construct plane for %s (%d)\n", pipe2name(crtcs[i]), ret); goto fail; } crtc = mdp5_crtc_init(dev, plane, i); if (IS_ERR(crtc)) { ret = PTR_ERR(crtc); dev_err(dev->dev, "failed to construct crtc for %s (%d)\n", pipe2name(crtcs[i]), ret); goto fail; } priv->crtcs[priv->num_crtcs++] = crtc; } /* Construct encoder for HDMI: */ encoder = mdp5_encoder_init(dev, 3, INTF_HDMI); if (IS_ERR(encoder)) { dev_err(dev->dev, "failed to construct encoder\n"); ret = PTR_ERR(encoder); goto fail; } /* NOTE: the vsync and error irq's are actually associated with * the INTF/encoder.. the easiest way to deal with this (ie. what * we do now) is assume a fixed relationship between crtc's and * encoders. I'm not sure if there is ever a need to more freely * assign crtcs to encoders, but if there is then we need to take * care of error and vblank irq's that the crtc has registered, * and also update user-requested vblank_mask. */ encoder->possible_crtcs = BIT(0); mdp5_crtc_set_intf(priv->crtcs[0], 3, INTF_HDMI); priv->encoders[priv->num_encoders++] = encoder; /* Construct bridge/connector for HDMI: */ mdp5_kms->hdmi = hdmi_init(dev, encoder); if (IS_ERR(mdp5_kms->hdmi)) { ret = PTR_ERR(mdp5_kms->hdmi); dev_err(dev->dev, "failed to initialize HDMI: %d\n", ret); goto fail; } return 0; fail: return ret; }