diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c index 47ffcd7cc8f5..86d260e7ca5f 100644 --- a/drivers/gpu/drm/msm/sde/sde_crtc.c +++ b/drivers/gpu/drm/msm/sde/sde_crtc.c @@ -1995,6 +1995,26 @@ static void _sde_crtc_init_debugfs(struct sde_crtc *sde_crtc, } #endif +void sde_crtc_update_blob_property(struct drm_crtc *crtc, + const char *key, + int32_t value) +{ + struct sde_crtc *sde_crtc; + char *kms_info_str = NULL; + size_t len; + + sde_crtc = to_sde_crtc(crtc); + + kms_info_str = (char *)msm_property_get_blob(&sde_crtc->property_info, + &sde_crtc->blob_info, &len, CRTC_PROP_INFO); + if (!kms_info_str) { + SDE_ERROR("get crtc property_info failed"); + return; + } + + sde_kms_info_update_keystr(kms_info_str, key, value); +} + /* initialize crtc */ struct drm_crtc *sde_crtc_init(struct drm_device *dev, struct drm_plane *plane) diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.h b/drivers/gpu/drm/msm/sde/sde_crtc.h index 200073995d43..a1042390b1a9 100644 --- a/drivers/gpu/drm/msm/sde/sde_crtc.h +++ b/drivers/gpu/drm/msm/sde/sde_crtc.h @@ -292,4 +292,13 @@ static inline bool sde_crtc_is_enabled(struct drm_crtc *crtc) return crtc ? crtc->enabled : false; } +/** + * sde_crtc_update_blob_property - update blob property of a given crtc + * @crtc: Pointer to crtc + * @key: Pointer to key string + * @value: Signed 32 bit integer value + */ +void sde_crtc_update_blob_property(struct drm_crtc *crtc, + const char *key, + int32_t value); #endif /* _SDE_CRTC_H_ */ diff --git a/drivers/gpu/drm/msm/sde/sde_kms.h b/drivers/gpu/drm/msm/sde/sde_kms.h index dee16d119d47..c7355f5bd891 100644 --- a/drivers/gpu/drm/msm/sde/sde_kms.h +++ b/drivers/gpu/drm/msm/sde/sde_kms.h @@ -1,5 +1,5 @@ /* - * 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 * @@ -305,6 +305,16 @@ void sde_kms_info_add_keyint(struct sde_kms_info *info, const char *key, int32_t value); +/** + * sde_kms_info_update_keystr - update the special string's value. + * @info_str: Pointer to source blob str + * @key: Pointer to key string + * @value: Signed 32-bit integer value + */ +void sde_kms_info_update_keystr(char *info_str, + const char *key, + int32_t value); + /** * sde_kms_info_add_keystr - add string value to 'sde_kms_info' * @info: Pointer to sde_kms_info structure diff --git a/drivers/gpu/drm/msm/sde/sde_kms_utils.c b/drivers/gpu/drm/msm/sde/sde_kms_utils.c index 30e12c969538..90fd3912eb59 100644 --- a/drivers/gpu/drm/msm/sde/sde_kms_utils.c +++ b/drivers/gpu/drm/msm/sde/sde_kms_utils.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -41,6 +41,64 @@ void sde_kms_info_add_keyint(struct sde_kms_info *info, } } +void sde_kms_info_update_keystr(char *info_str, + const char *key, + int32_t value) +{ + char *str, *temp, *append_str; + uint32_t dst_len = 0, prefix_len = 0; + char c; + int32_t size = 0; + + if (info_str && key) { + str = strnstr(info_str, key, strlen(info_str)); + if (str) { + temp = str + strlen(key); + c = *temp; + while (c != '\n') { + dst_len++; + c = *(++temp); + } + /* + * If input key string to update is exactly the last + * string in source string, no need to allocate one + * memory to store the string after string key. Just + * replace the value of the last string. + * + * If it is not, allocate one new memory to save + * the string after string key+"\n". This new allocated + * string will be appended to the whole source string + * after key value is updated. + */ + size = strlen(str) - strlen(key) - dst_len - 1; + if (size > 0) { + append_str = kzalloc(size + 1, GFP_KERNEL); + if (!append_str) { + SDE_ERROR("failed to alloc memory\n"); + return; + } + memcpy(append_str, + str + strlen(key) + dst_len + 1, size); + } + + prefix_len = strlen(info_str) - strlen(str); + /* Update string with new value for the string key. */ + snprintf(info_str + prefix_len, + SDE_KMS_INFO_MAX_SIZE - prefix_len, + "%s%d\n", key, value); + + /* Append the string save aboved. */ + if (size > 0 && append_str) { + size = prefix_len + strlen(key) + dst_len + 1; + snprintf(info_str + size, + SDE_KMS_INFO_MAX_SIZE - size, + "%s", append_str); + kfree(append_str); + } + } + } +} + void sde_kms_info_add_keystr(struct sde_kms_info *info, const char *key, const char *value) diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c index e50577e3eb4b..a35428c93867 100644 --- a/drivers/gpu/drm/msm/sde/sde_plane.c +++ b/drivers/gpu/drm/msm/sde/sde_plane.c @@ -2732,6 +2732,24 @@ end: return rc; } +void sde_plane_update_blob_property(struct drm_plane *plane, + const char *key, + int32_t value) +{ + char *kms_info_str = NULL; + struct sde_plane *sde_plane = to_sde_plane(plane); + size_t len; + + kms_info_str = (char *)msm_property_get_blob(&sde_plane->property_info, + &sde_plane->blob_info, &len, 0); + if (!kms_info_str) { + SDE_ERROR("get plane property_info failed\n"); + return; + } + + sde_kms_info_update_keystr(kms_info_str, key, value); +} + /* initialize plane */ struct drm_plane *sde_plane_init(struct drm_device *dev, uint32_t pipe, bool primary_plane, diff --git a/drivers/gpu/drm/msm/sde/sde_plane.h b/drivers/gpu/drm/msm/sde/sde_plane.h index 8ac582643926..c1414e7db74e 100644 --- a/drivers/gpu/drm/msm/sde/sde_plane.h +++ b/drivers/gpu/drm/msm/sde/sde_plane.h @@ -102,4 +102,13 @@ int sde_plane_wait_input_fence(struct drm_plane *plane, uint32_t wait_ms); int sde_plane_color_fill(struct drm_plane *plane, uint32_t color, uint32_t alpha); +/** + * sde_plane_update_blob_property - update plane blob property + * @plane: Pointer to DRM plane object + * @key: Pointer to key string + * @value: Signed 32 bit integer value + */ +void sde_plane_update_blob_property(struct drm_plane *plane, + const char *key, + int32_t value); #endif /* _SDE_PLANE_H_ */ diff --git a/drivers/gpu/drm/msm/sde/sde_splash.c b/drivers/gpu/drm/msm/sde/sde_splash.c index 16f9248b7abe..3ea93b654ce8 100644 --- a/drivers/gpu/drm/msm/sde/sde_splash.c +++ b/drivers/gpu/drm/msm/sde/sde_splash.c @@ -26,6 +26,7 @@ #include "dsi_display.h" #include "sde_hdmi.h" #include "sde_crtc.h" +#include "sde_plane.h" #define MDP_SSPP_TOP0_OFF 0x1000 #define DISP_INTF_SEL 0x004 @@ -391,6 +392,28 @@ static bool _sde_splash_validate_commit(struct sde_kms *sde_kms, return false; } +static void _sde_splash_update_property(struct sde_kms *sde_kms) +{ + struct drm_device *dev = sde_kms->dev; + struct drm_crtc *crtc; + struct drm_plane *plane; + struct sde_mdss_cfg *catalog = sde_kms->catalog; + + /* + * Update plane availability property + * after splash handoff is done. + */ + drm_for_each_plane(plane, dev) { + sde_plane_update_blob_property(plane, + "plane_unavailability=", 0); + } + + /* update crtc blend stage property */ + drm_for_each_crtc(crtc, dev) + sde_crtc_update_blob_property(crtc, "max_blendstages=", + catalog->max_mixer_blendstages); +} + __ref int sde_splash_init(struct sde_power_handle *phandle, struct msm_kms *kms) { struct sde_kms *sde_kms; @@ -837,6 +860,9 @@ int sde_splash_free_resource(struct msm_kms *kms, /* send uevent to notify user to recycle resource */ _sde_splash_sent_pipe_update_uevent(sde_kms); + /* update impacted crtc and plane property by splash */ + _sde_splash_update_property(sde_kms); + /* set display's splash status to false after handoff is done */ _sde_splash_update_display_splash_status(sde_kms);