sde_kms_info_add_keyint(info, "hw_version", catalog->hwversion);
sde_kms_info_add_keyint(info, "max_linewidth",
catalog->max_mixer_width);
- sde_kms_info_add_keyint(info, "max_blendstages",
- catalog->max_mixer_blendstages);
+
+ /* till now, we can't know which display early RVC will run on.
+ * Not to impact early RVC's layer, we decrease all lm's blend stage.
+ * This should be restored after handoff is done.
+ */
+ if (sde_kms->splash_info.handoff)
+ sde_kms_info_add_keyint(info, "max_blendstages",
+ catalog->max_mixer_blendstages - 1);
+ else
+ sde_kms_info_add_keyint(info, "max_blendstages",
+ catalog->max_mixer_blendstages);
+
if (catalog->qseed_type == SDE_SSPP_SCALER_QSEED2)
sde_kms_info_add_keystr(info, "qseed_type", "qseed2");
if (catalog->qseed_type == SDE_SSPP_SCALER_QSEED3)
struct msm_drm_private *priv;
struct sde_mdss_cfg *catalog;
+ struct sde_splash_info *sinfo;
int primary_planes_idx, i, ret;
int max_crtc_count, max_plane_count;
dev = sde_kms->dev;
priv = dev->dev_private;
catalog = sde_kms->catalog;
+ sinfo = &sde_kms->splash_info;
ret = sde_core_irq_domain_add(sde_kms);
if (ret)
primary = false;
plane = sde_plane_init(dev, catalog->vp[i].id,
- primary, 1UL << crtc_id, true);
+ primary, 1UL << crtc_id, true, false);
if (IS_ERR(plane)) {
SDE_ERROR("sde_plane_init failed\n");
ret = PTR_ERR(plane);
for (i = 0; i < max_plane_count; i++) {
bool primary = true;
+ bool resv_plane = false;
if (catalog->sspp[i].features & BIT(SDE_SSPP_CURSOR)
|| primary_planes_idx >= max_crtc_count)
primary = false;
+ if (sde_splash_query_plane_is_reserved(sinfo,
+ catalog->sspp[i].id)) {
+ resv_plane = true;
+ DRM_INFO("pipe%d is reserved\n",
+ catalog->sspp[i].id);
+ }
+
plane = sde_plane_init(dev, catalog->sspp[i].id,
primary, (1UL << max_crtc_count) - 1,
- false);
+ false, resv_plane);
if (IS_ERR(plane)) {
SDE_ERROR("sde_plane_init failed\n");
ret = PTR_ERR(plane);
*/
sinfo = &sde_kms->splash_info;
if (sinfo->handoff) {
- rc = sde_splash_parse_dt(dev);
+ rc = sde_splash_parse_memory_dt(dev);
if (rc) {
- SDE_ERROR("parse dt for splash info failed: %d\n", rc);
+ SDE_ERROR("parse memory dt failed: %d\n", rc);
goto power_error;
}
+ rc = sde_splash_parse_reserved_plane_dt(sinfo,
+ sde_kms->catalog);
+ if (rc)
+ SDE_ERROR("parse reserved plane dt failed: %d\n", rc);
+
sde_splash_init(&priv->phandle, kms);
}
/* helper to install properties which are common to planes and crtcs */
static void _sde_plane_install_properties(struct drm_plane *plane,
- struct sde_mdss_cfg *catalog)
+ struct sde_mdss_cfg *catalog, bool plane_reserved)
{
static const struct drm_prop_enum_list e_blend_op[] = {
{SDE_DRM_BLEND_OP_NOT_DEFINED, "not_defined"},
sde_kms_info_add_keyint(info, "max_downscale", maxdwnscale);
sde_kms_info_add_keyint(info, "max_horizontal_deci", maxhdeciexp);
sde_kms_info_add_keyint(info, "max_vertical_deci", maxvdeciexp);
+
+ /* When early RVC is enabled in bootloader and doesn't exit,
+ * user app should not touch the pipe which RVC is on.
+ * So mark the plane_unavailibility to the special pipe's property,
+ * user can parse this property of this pipe and stop this pipe's
+ * allocation after parsing.
+ * plane_reserved is 1, means the pipe is occupied in bootloader.
+ * plane_reserved is 0, means it's not used in bootloader.
+ */
+ sde_kms_info_add_keyint(info, "plane_unavailability", plane_reserved);
msm_property_set_blob(&psde->property_info, &psde->blob_info,
info->data, info->len, PLANE_PROP_INFO);
/* initialize plane */
struct drm_plane *sde_plane_init(struct drm_device *dev,
uint32_t pipe, bool primary_plane,
- unsigned long possible_crtcs, bool vp_enabled)
+ unsigned long possible_crtcs,
+ bool vp_enabled, bool plane_reserved)
{
struct drm_plane *plane = NULL;
struct sde_plane *psde;
PLANE_PROP_COUNT, PLANE_PROP_BLOBCOUNT,
sizeof(struct sde_plane_state));
- _sde_plane_install_properties(plane, kms->catalog);
+ _sde_plane_install_properties(plane, kms->catalog, plane_reserved);
/* save user friendly pipe name for later */
snprintf(psde->pipe_name, SDE_NAME_SIZE, "plane%u", plane->base.id);
/*
- * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
* Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com>
*
* @primary_plane: true if this pipe is primary plane for crtc
* @possible_crtcs: bitmask of crtc that can be attached to the given pipe
* @vp_enabled: Flag indicating if virtual planes enabled
+ * @plane_reserved: Flag indicating the plane is occupied in bootloader
*/
struct drm_plane *sde_plane_init(struct drm_device *dev,
uint32_t pipe, bool primary_plane,
- unsigned long possible_crtcs, bool vp_enabled);
+ unsigned long possible_crtcs,
+ bool vp_enabled, bool plane_reserved);
/**
* sde_plane_wait_input_fence - wait for input fence object
}
/*
- * sde_splash_parse_dt.
+ * sde_splash_parse_memory_dt.
* In the function, it will parse and reserve two kinds of memory node.
* First is to get the reserved memory for display buffers.
- * Second is to get the memory node LK's code stack is running on.
+ * Second is to get the memory node which LK's heap memory is running on.
*/
-int sde_splash_parse_dt(struct drm_device *dev)
+int sde_splash_parse_memory_dt(struct drm_device *dev)
{
struct msm_drm_private *priv = dev->dev_private;
struct sde_kms *sde_kms;
return 0;
}
+static inline u32 _sde_splash_parse_sspp_id(struct sde_mdss_cfg *cfg,
+ const char *name)
+{
+ int i;
+
+ for (i = 0; i < cfg->sspp_count; i++) {
+ if (!strcmp(cfg->sspp[i].name, name))
+ return cfg->sspp[i].id;
+ }
+
+ return 0;
+}
+
+int sde_splash_parse_reserved_plane_dt(struct sde_splash_info *splash_info,
+ struct sde_mdss_cfg *cfg)
+{
+ struct device_node *parent, *node;
+ struct property *prop;
+ const char *cname;
+ int ret = 0, i = 0;
+
+ if (!splash_info || !cfg)
+ return -EINVAL;
+
+ parent = of_find_node_by_path("/qcom,sde-reserved-plane");
+ if (!parent)
+ return -EINVAL;
+
+ for (i = 0; i < MAX_BLOCKS; i++)
+ splash_info->reserved_pipe_info[i] = 0xFFFFFFFF;
+
+ i = 0;
+ for_each_child_of_node(parent, node) {
+ if (i >= MAX_BLOCKS) {
+ SDE_ERROR("num of nodes(%d) is bigger than max(%d)\n",
+ i, MAX_BLOCKS);
+ ret = -EINVAL;
+ goto parent_node_err;
+ }
+
+ of_property_for_each_string(node, "qcom,plane-name",
+ prop, cname)
+ splash_info->reserved_pipe_info[i] =
+ _sde_splash_parse_sspp_id(cfg, cname);
+ i++;
+ }
+
+parent_node_err:
+ of_node_put(parent);
+
+ return ret;
+}
+
+bool sde_splash_query_plane_is_reserved(struct sde_splash_info *sinfo,
+ uint32_t pipe)
+{
+ int i = 0;
+
+ if (!sinfo)
+ return false;
+
+ /* early return if no splash is enabled */
+ if (!sinfo->handoff)
+ return false;
+
+ for (i = 0; i < MAX_BLOCKS; i++) {
+ if (sinfo->reserved_pipe_info[i] == pipe)
+ return true;
+ }
+
+ return false;
+}
+
int sde_splash_get_handoff_status(struct msm_kms *kms)
{
uint32_t intf_sel = 0;
/* registered dst connector count */
uint32_t dsi_connector_cnt;
+
+ /* reserved pipe info for early RVC */
+ uint32_t reserved_pipe_info[MAX_BLOCKS];
};
/* APIs for early splash handoff functions */
int connector_type, void *display);
/**
- * sde_splash_parse_dt.
+ * sde_splash_parse_memory_dt.
*
* Parse reserved memory block from DT for early splash.
*/
-int sde_splash_parse_dt(struct drm_device *dev);
+int sde_splash_parse_memory_dt(struct drm_device *dev);
+
+/**
+ * sde_splash_parse_reserved_plane_dt
+ *
+ * Parse reserved plane information from DT for early RVC case.
+ */
+int sde_splash_parse_reserved_plane_dt(struct sde_splash_info *splash_info,
+ struct sde_mdss_cfg *cfg);
+
+/*
+ * sde_splash_query_plane_is_reserved
+ *
+ * Query plane is reserved in dt.
+ */
+bool sde_splash_query_plane_is_reserved(struct sde_splash_info *sinfo,
+ uint32_t pipe);
/**
* sde_splash_smmu_map.