Merge "disp: msm: sde: parse property for max concurrent TUI displays"

This commit is contained in:
qctecmdr
2020-07-10 21:28:17 -07:00
committed by Gerrit - the friendly Code Review server
commit 0ea5003877
13 muutettua tiedostoa jossa 357 lisäystä ja 11 poistoa

Näytä tiedosto

@@ -85,7 +85,12 @@ struct dss_module_power {
int msm_dss_ioremap_byname(struct platform_device *pdev,
struct dss_io_data *io_data, const char *name);
void msm_dss_iounmap(struct dss_io_data *io_data);
int msm_dss_get_io_mem(struct platform_device *pdev,
struct list_head *mem_list);
void msm_dss_clean_io_mem(struct list_head *mem_list);
int msm_dss_get_io_irq(struct platform_device *pdev,
struct list_head *irq_list, u32 label);
void msm_dss_clean_io_irq(struct list_head *irq_list);
int msm_dss_enable_gpio(struct dss_gpio *in_gpio, int num_gpio, int enable);
int msm_dss_gpio_enable(struct dss_gpio *in_gpio, int num_gpio, int enable);

Näytä tiedosto

@@ -0,0 +1,97 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
*/
#ifndef __SDE_VM_EVENT_H__
#define __SDE_VM_EVENT_H__
#include <linux/list.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <drm/drm_device.h>
/**
* struct - msm_io_irq_entry - define irq item
* @label: hh_irq_label for the irq
* @irq_num: linux mapped irq num
* @list: list head pointer
*/
struct msm_io_irq_entry {
u32 label;
u32 irq_num;
struct list_head list;
};
/**
* struct - msm_io_mem_entry - define io memory item
* @base: reg base
* @size: size of the reg range
* @list: list head pointer
*/
struct msm_io_mem_entry {
phys_addr_t base;
phys_addr_t size;
struct list_head list;
};
/**
* struct - msm_io_res - represents the hw resources for vm sharing
* @irq: list of IRQ's of all the dislay sub-devices
* @mem: list of IO memory ranges of all the display sub-devices
*/
struct msm_io_res {
struct list_head irq;
struct list_head mem;
};
/**
* struct msm_vm_ops - hooks for communication with vm clients
* @vm_pre_hw_release: invoked before releasing the HW
* @vm_post_hw_acquire: invoked before pushing the first commit
* @vm_check: invoked to check the readiness of the vm_clients
* before releasing the HW
* @vm_get_io_resources: invoked to collect HW resources
*/
struct msm_vm_ops {
int (*vm_pre_hw_release)(void *priv_data);
int (*vm_post_hw_acquire)(void *priv_data);
int (*vm_check)(void *priv_data);
int (*vm_get_io_resources)(struct msm_io_res *io_res, void *priv_data);
};
/**
* msm_vm_client_entry - defines the vm client info
* @ops: client vm_ops
* @dev: clients device id. Used in unregister
* @data: client custom data
* @list: linked list entry
*/
struct msm_vm_client_entry {
struct msm_vm_ops ops;
struct device *dev;
void *data;
struct list_head list;
};
/**
* msm_register_vm_event - api for display dependent drivers(clients) to
* register for vm events
* @dev: msm device
* @client_dev: client device
* @ops: vm event hooks
* @priv_data: client custom data
*/
int msm_register_vm_event(struct device *dev, struct device *client_dev,
struct msm_vm_ops *ops, void *priv_data);
/**
* msm_unregister_vm_event - api for display dependent drivers(clients) to
* unregister from vm events
* @dev: msm device
* @client_dev: client device
*/
void msm_unregister_vm_event(struct device *dev, struct device *client_dev);
#endif //__SDE_VM_EVENT_H__

Näytä tiedosto

@@ -48,6 +48,7 @@ msm_drm-$(CONFIG_DRM_MSM_SDE) += sde/sde_crtc.o \
sde/sde_color_processing.o \
sde/sde_vbif.o \
sde_io_util.o \
sde_vm_event.o \
sde/sde_hw_reg_dma_v1_color_proc.o \
sde/sde_hw_color_proc_v4.o \
sde/sde_hw_ad4.o \

Näytä tiedosto

@@ -394,6 +394,7 @@ static int msm_drm_uninit(struct device *dev)
struct drm_device *ddev = platform_get_drvdata(pdev);
struct msm_drm_private *priv = ddev->dev_private;
struct msm_kms *kms = priv->kms;
struct msm_vm_client_entry *client_entry, *tmp;
int i;
/* We must cancel and cleanup any pending vblank enable/disable
@@ -455,6 +456,17 @@ static int msm_drm_uninit(struct device *dev)
sde_power_resource_deinit(pdev, &priv->phandle);
mutex_lock(&priv->vm_client_lock);
/* clean up any unregistered clients */
list_for_each_entry_safe(client_entry, tmp, &priv->vm_client_list,
list) {
list_del(&client_entry->list);
kfree(client_entry);
}
mutex_unlock(&priv->vm_client_lock);
msm_mdss_destroy(ddev);
ddev->dev_private = NULL;
@@ -831,6 +843,9 @@ static int msm_drm_component_init(struct device *dev)
INIT_LIST_HEAD(&priv->client_event_list);
INIT_LIST_HEAD(&priv->inactive_list);
INIT_LIST_HEAD(&priv->vm_client_list);
mutex_init(&priv->vm_client_lock);
/* Bind all our sub-components: */
ret = msm_component_bind_all(dev, ddev);

Näytä tiedosto

@@ -34,6 +34,7 @@
#include <linux/of_graph.h>
#include <linux/of_device.h>
#include <linux/sde_io_util.h>
#include <linux/sde_vm_event.h>
#include <linux/sizes.h>
#include <linux/kthread.h>
@@ -922,6 +923,9 @@ struct msm_drm_private {
/* update the flag when msm driver receives shutdown notification */
bool shutdown_in_progress;
struct mutex vm_client_lock;
struct list_head vm_client_list;
};
/* get struct msm_kms * from drm_device * */

Näytä tiedosto

@@ -1342,7 +1342,7 @@ static int _sde_encoder_update_rsc_client(
return ret;
}
static void _sde_encoder_irq_control(struct drm_encoder *drm_enc, bool enable)
void sde_encoder_irq_control(struct drm_encoder *drm_enc, bool enable)
{
struct sde_encoder_virt *sde_enc;
int i;
@@ -1452,7 +1452,7 @@ static int _sde_encoder_resource_control_helper(struct drm_encoder *drm_enc,
}
/* enable all the irq */
_sde_encoder_irq_control(drm_enc, true);
sde_encoder_irq_control(drm_enc, true);
_sde_encoder_pm_qos_add_request(drm_enc);
@@ -1460,7 +1460,7 @@ static int _sde_encoder_resource_control_helper(struct drm_encoder *drm_enc,
_sde_encoder_pm_qos_remove_request(drm_enc);
/* disable all the irq */
_sde_encoder_irq_control(drm_enc, false);
sde_encoder_irq_control(drm_enc, false);
/* disable DSI clks */
sde_connector_clk_ctrl(sde_enc->cur_master->connector, false);
@@ -1627,7 +1627,7 @@ static int _sde_encoder_rc_kickoff(struct drm_encoder *drm_enc,
}
if (is_vid_mode && sde_enc->rc_state == SDE_ENC_RC_STATE_IDLE) {
_sde_encoder_irq_control(drm_enc, true);
sde_encoder_irq_control(drm_enc, true);
} else {
/* enable all the clks and resources */
ret = _sde_encoder_resource_control_helper(drm_enc,
@@ -1664,7 +1664,7 @@ static int _sde_encoder_rc_pre_stop(struct drm_encoder *drm_enc,
if (is_vid_mode &&
sde_enc->rc_state == SDE_ENC_RC_STATE_IDLE) {
_sde_encoder_irq_control(drm_enc, true);
sde_encoder_irq_control(drm_enc, true);
}
/* skip if is already OFF or IDLE, resources are off already */
else if (sde_enc->rc_state == SDE_ENC_RC_STATE_OFF ||
@@ -1781,7 +1781,7 @@ static int _sde_encoder_rc_pre_modeset(struct drm_encoder *drm_enc,
goto end;
}
_sde_encoder_irq_control(drm_enc, false);
sde_encoder_irq_control(drm_enc, false);
_sde_encoder_modeset_helper_locked(drm_enc, sw_event);
SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state,
@@ -1819,7 +1819,7 @@ static int _sde_encoder_rc_post_modeset(struct drm_encoder *drm_enc,
}
_sde_encoder_modeset_helper_locked(drm_enc, sw_event);
_sde_encoder_irq_control(drm_enc, true);
sde_encoder_irq_control(drm_enc, true);
_sde_encoder_update_rsc_client(drm_enc, true);
@@ -1863,7 +1863,7 @@ static int _sde_encoder_rc_idle(struct drm_encoder *drm_enc,
}
if (is_vid_mode) {
_sde_encoder_irq_control(drm_enc, false);
sde_encoder_irq_control(drm_enc, false);
} else {
/* disable all the clks and resources */
_sde_encoder_update_rsc_client(drm_enc, false);

Näytä tiedosto

@@ -525,6 +525,13 @@ void sde_encoder_needs_hw_reset(struct drm_encoder *enc);
*/
void sde_encoder_uidle_enable(struct drm_encoder *drm_enc, bool enable);
/**
* sde_encoder_irq_control - control enable/disable of IRQ's
* @drm_enc: Pointer to drm encoder structure
* @enable: enable/disable flag
*/
void sde_encoder_irq_control(struct drm_encoder *drm_enc, bool enable);
/**
* sde_encoder_get_kms - retrieve the kms from encoder
* @drm_enc: Pointer to drm encoder structure

Näytä tiedosto

@@ -202,6 +202,7 @@ enum sde_prop {
SEC_SID_MASK,
BASE_LAYER,
TRUSTED_VM_ENV,
MAX_TRUSTED_VM_DISPLAYS,
SDE_PROP_MAX,
};
@@ -574,6 +575,8 @@ static struct sde_prop_type sde_prop[] = {
{SEC_SID_MASK, "qcom,sde-secure-sid-mask", false, PROP_TYPE_U32_ARRAY},
{BASE_LAYER, "qcom,sde-mixer-stage-base-layer", false, PROP_TYPE_BOOL},
{TRUSTED_VM_ENV, "qcom,sde-trusted-vm-env", false, PROP_TYPE_BOOL},
{MAX_TRUSTED_VM_DISPLAYS, "qcom,sde-max-trusted-vm-displays", false,
PROP_TYPE_U32},
};
static struct sde_prop_type sde_perf_prop[] = {
@@ -3752,6 +3755,8 @@ static void _sde_top_parse_dt_helper(struct sde_mdss_cfg *cfg,
QSEED_HW_VERSION, 0);
cfg->trusted_vm_env = PROP_VALUE_ACCESS(props->values, TRUSTED_VM_ENV,
0);
cfg->max_trusted_vm_displays = PROP_VALUE_ACCESS(props->values,
MAX_TRUSTED_VM_DISPLAYS, 0);
}
static int sde_top_parse_dt(struct device_node *np, struct sde_mdss_cfg *cfg)

Näytä tiedosto

@@ -1364,6 +1364,8 @@ struct sde_perf_cfg {
*
* @trusted_vm_env set to true, if the driver is executing in
* the trusted VM. false, otherwise.
* @max_trusted_vm_displays maximum number of concurrent trusted
* vm displays supported.
* @max_sspp_linewidth max source pipe line width support.
* @vig_sspp_linewidth max vig source pipe line width support.
* @scaling_linewidth max vig source pipe linewidth for scaling usecases
@@ -1438,6 +1440,7 @@ struct sde_perf_cfg {
struct sde_mdss_cfg {
u32 hwversion;
bool trusted_vm_env;
u32 max_trusted_vm_displays;
u32 max_sspp_linewidth;
u32 vig_sspp_linewidth;

Näytä tiedosto

@@ -52,6 +52,7 @@
#include <linux/qcom_scm.h>
#include "soc/qcom/secure_buffer.h"
#include <linux/qtee_shmbridge.h>
#include <linux/haven/hh_irq_lend.h>
#define CREATE_TRACE_POINTS
#include "sde_trace.h"
@@ -349,7 +350,7 @@ static int _sde_kms_scm_call(struct sde_kms *sde_kms, int vmid)
set_dma_ops(&dummy, NULL);
dma_handle = dma_map_single(&dummy, sec_sid,
num_sids *sizeof(uint32_t), DMA_TO_DEVICE);
num_sids * sizeof(uint32_t), DMA_TO_DEVICE);
if (dma_mapping_error(&dummy, dma_handle)) {
SDE_ERROR("dma_map_single for dummy dev failed vmid 0x%x\n",
vmid);
@@ -367,7 +368,7 @@ static int _sde_kms_scm_call(struct sde_kms *sde_kms, int vmid)
vmid, qtee_en, num_sids, ret);
dma_unmap_single(&dummy, dma_handle,
num_sids *sizeof(uint32_t), DMA_TO_DEVICE);
num_sids * sizeof(uint32_t), DMA_TO_DEVICE);
map_error:
if (qtee_en)
@@ -3601,6 +3602,26 @@ power_error:
return rc;
}
int sde_kms_get_io_resources(struct sde_kms *sde_kms, struct msm_io_res *io_res)
{
struct platform_device *pdev = to_platform_device(sde_kms->dev->dev);
int rc = 0;
rc = msm_dss_get_io_mem(pdev, &io_res->mem);
if (rc) {
SDE_ERROR("failed to get io mem for KMS, rc = %d\n", rc);
return rc;
}
rc = msm_dss_get_io_irq(pdev, &io_res->irq, HH_IRQ_LABEL_SDE);
if (rc) {
SDE_ERROR("failed to get io irq for KMS");
return rc;
}
return rc;
}
static int sde_kms_hw_init(struct msm_kms *kms)
{
struct sde_kms *sde_kms;

Näytä tiedosto

@@ -691,4 +691,12 @@ int sde_kms_handle_recovery(struct drm_encoder *encoder);
*/
void sde_kms_irq_enable_notify(struct sde_kms *sde_kms, bool enable);
/**
* sde_kms_get_io_resources() - reads associated register range
* @kms: pointer to sde_kms structure
* @io_res: pointer to msm_io_res struct to populate the ranges
* Return: error code.
*/
int sde_kms_get_io_resources(struct sde_kms *kms, struct msm_io_res *io_res);
#endif /* __sde_kms_H__ */

Näytä tiedosto

@@ -9,6 +9,7 @@
#include <linux/regulator/consumer.h>
#include <linux/delay.h>
#include <linux/sde_io_util.h>
#include <linux/sde_vm_event.h>
#define MAX_I2C_CMDS 16
void dss_reg_w(struct dss_io_data *io, u32 offset, u32 value, u32 debug)
@@ -129,6 +130,127 @@ void msm_dss_iounmap(struct dss_io_data *io_data)
} /* msm_dss_iounmap */
EXPORT_SYMBOL(msm_dss_iounmap);
int msm_dss_get_io_mem(struct platform_device *pdev, struct list_head *mem_list)
{
struct list_head temp_head;
struct msm_io_mem_entry *io_mem;
struct resource *res = NULL;
const char *reg_name, *exclude_reg_name;
int i, j, rc = 0;
int num_entry, num_exclude_entry;
INIT_LIST_HEAD(&temp_head);
num_entry = of_property_count_strings(pdev->dev.of_node,
"reg-names");
if (num_entry < 0)
num_entry = 0;
/*
* check the dt property to know whether the platform device wants
* to exclude any reg ranges from the IO list
*/
num_exclude_entry = of_property_count_strings(pdev->dev.of_node,
"qcom,sde-vm-exclude-reg-names");
if (num_exclude_entry < 0)
num_exclude_entry = 0;
for (i = 0; i < num_entry; i++) {
bool exclude = false;
of_property_read_string_index(pdev->dev.of_node,
"reg-names", i, &reg_name);
for (j = 0; j < num_exclude_entry; j++) {
of_property_read_string_index(pdev->dev.of_node,
"qcom,sde-vm-exclude-reg-names", j,
&exclude_reg_name);
if (!strcmp(reg_name, exclude_reg_name)) {
exclude = true;
break;
}
}
if (exclude)
continue;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
reg_name);
if (!res)
break;
io_mem = kzalloc(sizeof(*io_mem), GFP_KERNEL);
if (!io_mem) {
msm_dss_clean_io_mem(&temp_head);
rc = -ENOMEM;
goto parse_fail;
}
io_mem->base = res->start;
io_mem->size = resource_size(res);
list_add(&io_mem->list, &temp_head);
}
list_splice(&temp_head, mem_list);
return 0;
parse_fail:
msm_dss_clean_io_mem(&temp_head);
return rc;
}
EXPORT_SYMBOL(msm_dss_get_io_mem);
void msm_dss_clean_io_mem(struct list_head *mem_list)
{
struct msm_io_mem_entry *pos, *tmp;
list_for_each_entry_safe(pos, tmp, mem_list, list) {
list_del(&pos->list);
kzfree(pos);
}
}
EXPORT_SYMBOL(msm_dss_clean_io_mem);
int msm_dss_get_io_irq(struct platform_device *pdev, struct list_head *irq_list,
u32 label)
{
struct msm_io_irq_entry *io_irq;
int irq;
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
pr_err("invalid IRQ\n");
return irq;
}
io_irq = kzalloc(sizeof(*io_irq), GFP_KERNEL);
if (!io_irq)
return -ENOMEM;
io_irq->label = label;
io_irq->irq_num = irq;
list_add(&io_irq->list, irq_list);
return 0;
}
EXPORT_SYMBOL(msm_dss_get_io_irq);
void msm_dss_clean_io_irq(struct list_head *irq_list)
{
struct msm_io_irq_entry *pos, *tmp;
list_for_each_entry_safe(pos, tmp, irq_list, list) {
list_del(&pos->list);
kzfree(pos);
}
}
EXPORT_SYMBOL(msm_dss_clean_io_irq);
int msm_dss_get_vreg(struct device *dev, struct dss_vreg *in_vreg,
int num_vreg, int enable)
{

58
msm/sde_vm_event.c Normal file
Näytä tiedosto

@@ -0,0 +1,58 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
*/
#include <linux/sde_vm_event.h>
#include "msm_drv.h"
int msm_register_vm_event(struct device *dev, struct device *client_dev,
struct msm_vm_ops *ops, void *priv_data)
{
struct platform_device *pdev = to_platform_device(dev);
struct drm_device *ddev = platform_get_drvdata(pdev);
struct msm_drm_private *priv = ddev->dev_private;
struct msm_vm_client_entry *client_entry;
if (!client_dev || !ops)
return -EINVAL;
client_entry = kzalloc(sizeof(*client_entry), GFP_KERNEL);
if (!client_entry)
return -ENOMEM;
mutex_lock(&priv->vm_client_lock);
memcpy(&client_entry->ops, ops, sizeof(*ops));
client_entry->dev = client_dev;
client_entry->data = priv_data;
list_add(&client_entry->list, &priv->vm_client_list);
mutex_unlock(&priv->vm_client_lock);
return 0;
}
EXPORT_SYMBOL(msm_register_vm_event);
void msm_unregister_vm_event(struct device *dev, struct device *client_dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct drm_device *ddev = platform_get_drvdata(pdev);
struct msm_drm_private *priv = ddev->dev_private;
struct msm_vm_client_entry *client_entry, *tmp;
mutex_lock(&priv->vm_client_lock);
list_for_each_entry_safe(client_entry, tmp, &priv->vm_client_list,
list) {
if (client_entry->dev == client_dev) {
list_del(&client_entry->list);
kfree(client_entry);
break;
}
}
mutex_unlock(&priv->vm_client_lock);
}
EXPORT_SYMBOL(msm_unregister_vm_event);