drm: msm: Import xiaomi drm modifications

Change-Id: I2e8dd1a2a47c4739b879459cf17a45a7a4956800
Signed-off-by: UtsavBalar1231 <utsavbalar1231@gmail.com>
This commit is contained in:
UtsavBalar1231 2021-05-31 05:37:54 +02:00 committed by spakkkk
parent b66e866c6c
commit 7205ae1ea1
10 changed files with 497 additions and 3 deletions

View File

@ -18,7 +18,8 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \
drm_encoder.o drm_mode_object.o drm_property.o \
drm_plane.o drm_color_mgmt.o drm_print.o \
drm_dumb_buffers.o drm_mode_config.o drm_vblank.o \
drm_syncobj.o drm_lease.o drm_writeback.o drm_client.o
drm_syncobj.o drm_lease.o drm_writeback.o drm_client.o \
drm_notifier_mi.o
drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o
drm-$(CONFIG_DRM_VM) += drm_vm.o

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 2014 Samsung Electronics Co., Ltd
* Copyright (C) 2021 XiaoMi, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@ -270,9 +271,15 @@ void drm_bridge_post_disable(struct drm_bridge *bridge)
if (!bridge)
return;
if (bridge->is_dsi_drm_bridge)
mutex_lock(&bridge->lock);
if (bridge->funcs->post_disable)
bridge->funcs->post_disable(bridge);
if (bridge->is_dsi_drm_bridge)
mutex_unlock(&bridge->lock);
drm_bridge_post_disable(bridge->next);
}
EXPORT_SYMBOL(drm_bridge_post_disable);
@ -321,8 +328,14 @@ void drm_bridge_pre_enable(struct drm_bridge *bridge)
drm_bridge_pre_enable(bridge->next);
if (bridge->is_dsi_drm_bridge)
mutex_lock(&bridge->lock);
if (bridge->funcs->pre_enable)
bridge->funcs->pre_enable(bridge);
if (bridge->is_dsi_drm_bridge)
mutex_unlock(&bridge->lock);
}
EXPORT_SYMBOL(drm_bridge_pre_enable);

View File

@ -0,0 +1,63 @@
/*
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
* Copyright (C) 2021 XiaoMi, Inc.
*
* 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
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef _DRM_INTERFACE_MI_H_
#define _DRM_INTERFACE_MI_H_
/* dsi_display_mi.c */
int dsi_display_set_disp_param(struct drm_connector *connector,
u32 param_type);
int dsi_display_get_disp_param(struct drm_connector *connector,
u32 *param_type);
ssize_t dsi_display_write_mipi_reg(struct drm_connector *connector,
char *buf);
ssize_t dsi_display_read_mipi_reg(struct drm_connector *connector,
char *buf);
ssize_t dsi_display_read_oled_pmic_id(struct drm_connector *connector,
char *buf);
ssize_t dsi_display_read_panel_info(struct drm_connector *connector,
char *buf);
ssize_t dsi_display_read_wp_info(struct drm_connector *connector,
char *buf);
ssize_t dsi_display_read_dynamic_fps(struct drm_connector *connector,
char *buf);
int dsi_display_set_doze_brightness(struct drm_connector *connector,
int doze_brightness);
ssize_t dsi_display_get_doze_brightness(struct drm_connector *connector,
char *buf);
int dsi_display_read_gamma_param(struct drm_connector *connector);
ssize_t dsi_display_print_gamma_param(struct drm_connector *connector,
char *buf);
ssize_t dsi_display_fod_get(struct drm_connector *connector, char *buf);
ssize_t complete_commit_time_get(struct drm_connector *connector, char *buf);
int dsi_display_set_thermal_hbm_disabled(struct drm_connector *connector,
bool thermal_hbm_disabled);
int dsi_display_get_thermal_hbm_disabled(struct drm_connector *connector,
bool *thermal_hbm_disabled);
ssize_t dsi_display_get_hw_vsync_info(struct drm_connector *connector,
char *buf);
#endif /*_DRM_INTERFACE_MI_H_*/

View File

@ -2,6 +2,7 @@
* Created: Fri Jan 8 09:01:26 1999 by faith@valinux.com
*
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
* Copyright (C) 2021 XiaoMi, Inc.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All Rights Reserved.
*
@ -514,6 +515,31 @@ int drm_version(struct drm_device *dev, void *data,
return err;
}
const char *support_list[] = {
"displayfeature",
"DisplayFeature",
"disp_pcc",
"displayeffect",
"factoryreset",
"recovery",
NULL
};
static bool drm_master_filter(char *task_name)
{
unsigned int i = 0;
bool ret = false;
for (i = 0; support_list[i] != NULL; i++) {
if (!strncmp(task_name, support_list[i], strlen(support_list[i]))) {
ret = true;
break;
}
}
return ret;
}
/**
* drm_ioctl_permit - Check ioctl permissions against caller
*
@ -528,6 +554,7 @@ int drm_version(struct drm_device *dev, void *data,
*/
int drm_ioctl_permit(u32 flags, struct drm_file *file_priv)
{
struct task_struct *task = get_current();
/* ROOT_ONLY is only for CAP_SYS_ADMIN */
if (unlikely((flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)))
return -EACCES;
@ -539,8 +566,11 @@ int drm_ioctl_permit(u32 flags, struct drm_file *file_priv)
/* MASTER is only for master or control clients */
if (unlikely((flags & DRM_MASTER) &&
!drm_is_current_master(file_priv)))
return -EACCES;
!drm_is_current_master(file_priv))) {
if (!drm_master_filter(task->comm)) {
return -EACCES;
}
}
/* Render clients must be explicitly allowed */
if (unlikely(!(flags & DRM_RENDER_ALLOW) &&

View File

@ -2,6 +2,7 @@
* MIPI DSI Bus
*
* Copyright (C) 2012-2013, Samsung Electronics, Co., Ltd.
* Copyright (C) 2021 XiaoMi, Inc.
* Andrzej Hajda <a.hajda@samsung.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
@ -1071,6 +1072,29 @@ int mipi_dsi_dcs_set_display_brightness(struct mipi_dsi_device *dsi,
}
EXPORT_SYMBOL(mipi_dsi_dcs_set_display_brightness);
/**
* mipi_dsi_dcs_set_display_brightness_bigendian() - sets the brightness value of the
* display with big endian, high byte to 1st parameter, low byte to 2nd parameter
* @dsi: DSI peripheral device
* @brightness: brightness value
*
* Return: 0 on success or a negative error code on failure.
*/
int mipi_dsi_dcs_set_display_brightness_big_endian(struct mipi_dsi_device *dsi,
u16 brightness)
{
u8 payload[2] = { brightness >> 8, brightness & 0xff};
ssize_t err;
err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_BRIGHTNESS,
payload, sizeof(payload));
if (err < 0)
return err;
return 0;
}
EXPORT_SYMBOL(mipi_dsi_dcs_set_display_brightness_big_endian);
/**
* mipi_dsi_dcs_get_display_brightness() - gets the current brightness value
* of the display

View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
* Copyright (C) 2021 XiaoMi, Inc.
*
* 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
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/notifier.h>
static BLOCKING_NOTIFIER_HEAD(mi_drm_notifier_list);
/**
* mi_drm_register_client - register a client notifier
* @nb: notifier block to callback on events
*
* This function registers a notifier callback function
* to msm_drm_notifier_list, which would be called when
* received unblank/power down event.
*/
int mi_drm_register_client(struct notifier_block *nb)
{
return blocking_notifier_chain_register(&mi_drm_notifier_list, nb);
}
EXPORT_SYMBOL(mi_drm_register_client);
/**
* mi_drm_unregister_client - unregister a client notifier
* @nb: notifier block to callback on events
*
* This function unregisters the callback function from
* msm_drm_notifier_list.
*/
int mi_drm_unregister_client(struct notifier_block *nb)
{
return blocking_notifier_chain_unregister(&mi_drm_notifier_list, nb);
}
EXPORT_SYMBOL(mi_drm_unregister_client);
/**
* mi_drm_notifier_call_chain - notify clients of drm_events
* @val: event MSM_DRM_EARLY_EVENT_BLANK or MSM_DRM_EVENT_BLANK
* @v: notifier data, inculde display id and display blank
* event(unblank or power down).
*/
int mi_drm_notifier_call_chain(unsigned long val, void *v)
{
return blocking_notifier_call_chain(&mi_drm_notifier_list, val, v);
}
EXPORT_SYMBOL(mi_drm_notifier_call_chain);

View File

@ -5,6 +5,7 @@
* does not allow adding attributes.
*
* Copyright (c) 2004 Jon Smirl <jonsmirl@gmail.com>
* Copyright (C) 2021 XiaoMi, Inc.
* Copyright (c) 2003-2004 Greg Kroah-Hartman <greg@kroah.com>
* Copyright (c) 2003-2004 IBM Corp.
*
@ -21,10 +22,13 @@
#include <drm/drm_sysfs.h>
#include <drm/drmP.h>
#include "drm_internal.h"
#include "drm_internal_mi.h"
#define to_drm_minor(d) dev_get_drvdata(d)
#define to_drm_connector(d) dev_get_drvdata(d)
/**
* DOC: overview
*
@ -44,6 +48,7 @@ static struct device_type drm_sysfs_device_minor = {
};
struct class *drm_class;
struct device *connector_kdev;
static char *drm_devnode(struct device *dev, umode_t *mode)
{
@ -229,16 +234,251 @@ static ssize_t modes_show(struct device *device,
return written;
}
static ssize_t disp_param_store(struct device *device,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct drm_connector *connector = to_drm_connector(device);
char *input_copy, *input_dup = NULL;
u32 param;
int ret;
input_copy = kstrdup(buf, GFP_KERNEL);
if (!input_copy) {
DRM_ERROR("can not allocate memory\n");
ret = -ENOMEM;
goto exit;
}
input_dup = input_copy;
/* removes leading and trailing whitespace from input_copy */
input_copy = strim(input_copy);
ret = kstrtouint(input_copy, 16, &param);
if (ret) {
DRM_ERROR("input buffer conversion failed\n");
ret = -EAGAIN;
goto exit_free;
}
ret = dsi_display_set_disp_param(connector, param);
exit_free:
kfree(input_dup);
exit:
return ret ? ret : count;
}
static ssize_t disp_param_show(struct device *device,
struct device_attribute *attr,
char *buf)
{
struct drm_connector *connector = to_drm_connector(device);
u32 param;
dsi_display_get_disp_param(connector, &param);
return snprintf(buf, PAGE_SIZE, "0x%08X\n", param);
}
static ssize_t mipi_reg_store(struct device *device,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct drm_connector *connector = to_drm_connector(device);
int ret;
ret = dsi_display_write_mipi_reg(connector, (char *)buf);
return ret ? ret : count;
}
static ssize_t mipi_reg_show(struct device *device,
struct device_attribute *attr,
char *buf)
{
struct drm_connector *connector = to_drm_connector(device);
return dsi_display_read_mipi_reg(connector, buf);
}
static ssize_t oled_pmic_id_show(struct device *device,
struct device_attribute *attr,
char *buf)
{
struct drm_connector *connector = to_drm_connector(device);
return dsi_display_read_oled_pmic_id(connector, buf);
}
static ssize_t panel_info_show(struct device *device,
struct device_attribute *attr,
char *buf)
{
struct drm_connector *connector = to_drm_connector(device);
return dsi_display_read_panel_info(connector, buf);
}
static ssize_t wp_info_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct drm_connector *connector = to_drm_connector(dev);
return dsi_display_read_wp_info(connector, buf);
}
static ssize_t dynamic_fps_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct drm_connector *connector = to_drm_connector(dev);
return dsi_display_read_dynamic_fps(connector, buf);
}
static ssize_t doze_brightness_store(struct device *device,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct drm_connector *connector = to_drm_connector(device);
int doze_brightness;
int ret;
ret = kstrtoint(buf, 0, &doze_brightness);;
if (ret)
return ret;
ret = dsi_display_set_doze_brightness(connector, doze_brightness);
return ret ? ret : count;
}
static ssize_t doze_brightness_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct drm_connector *connector = to_drm_connector(dev);
return dsi_display_get_doze_brightness(connector, buf);
}
static ssize_t gamma_test_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct drm_connector *connector = to_drm_connector(dev);
int ret = 0;
ret = dsi_display_read_gamma_param(connector);
if (ret) {
pr_err("Failed to update panel id and gamma para!\n");
}
ret = dsi_display_print_gamma_param(connector, buf);
return ret;
}
extern ssize_t smart_fps_value_show(struct device *device,
struct device_attribute *attr,
char *buf);
static ssize_t fod_ui_ready_show(struct device *device,
struct device_attribute *attr,
char *buf)
{
struct drm_connector *connector = to_drm_connector(device);
return dsi_display_fod_get(connector, buf);
}
static ssize_t complete_commit_time_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct drm_connector *connector = to_drm_connector(dev);
return complete_commit_time_get(connector, buf);
}
static ssize_t thermal_hbm_disabled_store(struct device *device,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct drm_connector *connector = to_drm_connector(device);
char *input_copy, *input_dup = NULL;
bool thermal_hbm_disabled;
int ret;
input_copy = kstrdup(buf, GFP_KERNEL);
if (!input_copy) {
DRM_ERROR("can not allocate memory\n");
ret = -ENOMEM;
goto exit;
}
input_dup = input_copy;
/* removes leading and trailing whitespace from input_copy */
input_copy = strim(input_copy);
ret = kstrtobool(input_copy, &thermal_hbm_disabled);
if (ret) {
DRM_ERROR("input buffer conversion failed\n");
ret = -EAGAIN;
goto exit_free;
}
DRM_INFO("set thermal_hbm_disabled %d\n", thermal_hbm_disabled);
ret = dsi_display_set_thermal_hbm_disabled(connector, thermal_hbm_disabled);
exit_free:
kfree(input_dup);
exit:
return ret ? ret : count;
}
static ssize_t thermal_hbm_disabled_show(struct device *device,
struct device_attribute *attr,
char *buf)
{
struct drm_connector *connector = to_drm_connector(device);
bool thermal_hbm_disabled;
dsi_display_get_thermal_hbm_disabled(connector, &thermal_hbm_disabled);
return snprintf(buf, PAGE_SIZE, "%d\n", thermal_hbm_disabled);
}
static ssize_t hw_vsync_info_show(struct device *device,
struct device_attribute *attr,
char *buf)
{
struct drm_connector *connector = to_drm_connector(device);
return dsi_display_get_hw_vsync_info(connector, buf);
}
static DEVICE_ATTR_RW(status);
static DEVICE_ATTR_RO(enabled);
static DEVICE_ATTR_RO(dpms);
static DEVICE_ATTR_RO(modes);
static DEVICE_ATTR_RW(disp_param);
static DEVICE_ATTR_RW(mipi_reg);
static DEVICE_ATTR_RO(oled_pmic_id);
static DEVICE_ATTR_RO(panel_info);
static DEVICE_ATTR_RO(wp_info);
static DEVICE_ATTR_RO(dynamic_fps);
static DEVICE_ATTR_RW(doze_brightness);
static DEVICE_ATTR_RO(gamma_test);
static DEVICE_ATTR_RO(fod_ui_ready);
static DEVICE_ATTR_RO(smart_fps_value);
static DEVICE_ATTR_RO(complete_commit_time);
static DEVICE_ATTR_RW(thermal_hbm_disabled);
static DEVICE_ATTR_RO(hw_vsync_info);
static struct attribute *connector_dev_attrs[] = {
&dev_attr_status.attr,
&dev_attr_enabled.attr,
&dev_attr_dpms.attr,
&dev_attr_modes.attr,
&dev_attr_disp_param.attr,
&dev_attr_mipi_reg.attr,
&dev_attr_oled_pmic_id.attr,
&dev_attr_panel_info.attr,
&dev_attr_wp_info.attr,
&dev_attr_dynamic_fps.attr,
&dev_attr_doze_brightness.attr,
&dev_attr_gamma_test.attr,
&dev_attr_fod_ui_ready.attr,
&dev_attr_smart_fps_value.attr,
&dev_attr_complete_commit_time.attr,
&dev_attr_thermal_hbm_disabled.attr,
&dev_attr_hw_vsync_info.attr,
NULL
};
@ -279,6 +519,9 @@ int drm_sysfs_connector_add(struct drm_connector *connector)
DRM_DEBUG("adding \"%s\" to sysfs\n",
connector->name);
if (!connector_kdev)
connector_kdev = connector->kdev;
if (IS_ERR(connector->kdev)) {
DRM_ERROR("failed to register connector device: %ld\n", PTR_ERR(connector->kdev));
return PTR_ERR(connector->kdev);

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 2016 Intel Corporation
* Copyright (C) 2021 XiaoMi, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
@ -294,6 +295,8 @@ struct drm_bridge {
const struct drm_bridge_funcs *funcs;
/** @driver_private: pointer to the bridge driver's internal context */
void *driver_private;
struct mutex lock;
bool is_dsi_drm_bridge;
};
void drm_bridge_add(struct drm_bridge *bridge);
@ -314,6 +317,7 @@ void drm_bridge_mode_set(struct drm_bridge *bridge,
struct drm_display_mode *adjusted_mode);
void drm_bridge_pre_enable(struct drm_bridge *bridge);
void drm_bridge_enable(struct drm_bridge *bridge);
int dsi_bridge_interface_enable(int timeout);
#ifdef CONFIG_DRM_PANEL_BRIDGE
struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel,

View File

@ -2,6 +2,7 @@
* MIPI DSI Bus
*
* Copyright (C) 2012-2013, Samsung Electronics, Co., Ltd.
* Copyright (C) 2021 XiaoMi, Inc.
* Andrzej Hajda <a.hajda@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
@ -284,6 +285,8 @@ int mipi_dsi_dcs_set_pixel_format(struct mipi_dsi_device *dsi, u8 format);
int mipi_dsi_dcs_set_tear_scanline(struct mipi_dsi_device *dsi, u16 scanline);
int mipi_dsi_dcs_set_display_brightness(struct mipi_dsi_device *dsi,
u16 brightness);
int mipi_dsi_dcs_set_display_brightness_big_endian(struct mipi_dsi_device *dsi,
u16 brightness);
int mipi_dsi_dcs_get_display_brightness(struct mipi_dsi_device *dsi,
u16 *brightness);

View File

@ -0,0 +1,56 @@
/*
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
* Copyright (C) 2021 XiaoMi, Inc.
*
* 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
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef _DRM_NOTIFIER_MI_H_
#define _DRM_NOTIFIER_MI_H_
#include <linux/notifier.h>
/* A hardware display blank change occurred */
#define MI_DRM_EVENT_BLANK 0x01
/* A hardware display blank early change occurred */
#define MI_DRM_EARLY_EVENT_BLANK 0x02
/* A hardware display blank more early change occured */
#define MI_DRM_PRE_EVENT_BLANK 0x03
enum msm_drm_display_id {
/* primary display */
MSM_DRM_PRIMARY_DISPLAY,
/* external display */
MSM_DRM_EXTERNAL_DISPLAY,
MSM_DRM_DISPLAY_MAX
};
enum {
/* panel: power on */
MI_DRM_BLANK_UNBLANK = 0,
MI_DRM_BLANK_LP1 = 1,
MI_DRM_BLANK_LP2 = 2,
MI_DRM_BLANK_STANDBY = 3,
MI_DRM_BLANK_SUSPEND = 4,
/* panel: power off */
MI_DRM_BLANK_POWERDOWN = 5,
};
struct mi_drm_notifier {
enum msm_drm_display_id id;
void *data;
};
int mi_drm_register_client(struct notifier_block *nb);
int mi_drm_unregister_client(struct notifier_block *nb);
int mi_drm_notifier_call_chain(unsigned long val, void *v);
#endif /*_DRM_NOTIFIER_MI_H*/