Merge tag 'MMI-U1UGS34.23-110-23-2' of https://github.com/MotorolaMobilityLLC/kernel-msm-5.4-techpack-display into lineage-22.2

Fogos push for Android 14

* tag 'MMI-U1UGS34.23-110-23-2' of https://github.com/MotorolaMobilityLLC/kernel-msm-5.4-techpack-display: (116 commits)
  dsi_panel: panel_feature: corret the code mistake
  dsi_panel: fix the bug of local HBM
  gpu/msm: check fps value before enable lhbm
  msm/display-drivers: release lhbm resource
  dsi/dfps: update the dfps code to support "OLED+vid mode"
  dsi/dfps: set the right fps when panel resume
  Support 120Hz command sending
  dts/display: [bangkok] update the dsc configure for tianma panel
  display-drivers: local hbm: add suport for dc_hybird_threshold
  optimze lcd log
  kernel:pnangn:update 2nd panel brightness settings to 11bits
  kernel/panel:power on/off reset sequence
  display/backlight: support hbm dcs only with 51 cmd
  display/dsi:add new lcd backlight align type for bit11_4
  display: The lcd backlight shift mode update
  drm_ioctl: add return value for set_param
  drm/dsi_panel: resend hbm off commands
  msm/drm:compatible with different hbm table in panel
  drm/msm:add delay between mipi0 to reset0 when power off
  drm/panel: check panel status before send custom commands
  ...

 Conflicts:
	techpack/display/msm/sde/sde_connector.c
	techpack/display/msm/sde/sde_kms.c

Change-Id: I13ede04c21415717cd009ae73871894f1be74927
This commit is contained in:
Michael Bestas 2025-03-21 18:36:59 +02:00
commit 654ea8a9cd
No known key found for this signature in database
30 changed files with 3949 additions and 113 deletions

View file

@ -12,3 +12,4 @@ export CONFIG_MSM_SDE_ROTATOR=y
export CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
export CONFIG_DRM_SDE_RSC=y
export CONFIG_DISPLAY_BUILD=y
export CONFIG_DRM_DYNAMIC_REFRESH_RATE=y

View file

@ -17,4 +17,5 @@
#define CONFIG_MSM_SDE_ROTATOR 1
#define CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG 1
#define CONFIG_DRM_SDE_RSC 1
#define CONFIG_DRM_DYNAMIC_REFRESH_RATE 1

View file

@ -11,3 +11,4 @@ export CONFIG_QCOM_MDSS_PLL=y
export CONFIG_MSM_SDE_ROTATOR=y
export CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
export CONFIG_DRM_SDE_RSC=y
export CONFIG_DRM_DYNAMIC_REFRESH_RATE=y

View file

@ -17,3 +17,4 @@
#define CONFIG_MSM_SDE_ROTATOR 1
#define CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG 1
#define CONFIG_DRM_SDE_RSC 1
#define CONFIG_DRM_DYNAMIC_REFRESH_RATE 1

View file

@ -690,6 +690,27 @@ struct drm_msm_display_hint {
#define DRM_IOCTL_MSM_DISPLAY_HINT DRM_IOW((DRM_COMMAND_BASE + \
DRM_MSM_DISPLAY_HINT), struct drm_msm_display_hint)
/* panel feature */
typedef enum {
PARAM_HBM = 0,
PARAM_CABC,
PARAM_ACL,
PARAM_DC,
POWER_MODE_MAX_NUM,
PARAM_COLOR = POWER_MODE_MAX_NUM,
PARAM_MAX_NUM
} paramId_t;
struct panel_param_info {
paramId_t param_idx;
__u32 value;
};
#define DRM_SET_PANEL_FEATURE (DRM_COMMAND_END -1)
#define DRM_IOCTL_SET_PANEL_FEATURE DRM_IOWR(DRM_SET_PANEL_FEATURE, struct panel_param_info)
#define DRM_GET_PANEL_FEATURE (DRM_COMMAND_END-2)
#define DRM_IOCTL_GET_PANEL_FEATURE DRM_IOWR(DRM_GET_PANEL_FEATURE, struct panel_param_info)
#if defined(__cplusplus)
}
#endif

View file

@ -44,6 +44,7 @@ msm_drm-$(CONFIG_DRM_MSM_SDE) += sde/sde_crtc.o \
sde/sde_core_perf.o \
sde/sde_rm.o \
sde/sde_kms_utils.o \
sde/sde_motUtil.o \
sde/sde_kms.o \
sde/sde_plane.o \
sde/sde_connector.o \

View file

@ -332,7 +332,7 @@ void dsi_ctrl_hw_cmn_set_video_timing(struct dsi_ctrl_hw *ctrl,
u32 reg = 0;
u32 hs_start = 0;
u32 hs_end, active_h_start, active_h_end, h_total, width = 0;
u32 bytes_per_pkt, pkt_per_line, eol_byte_num;
u32 bytes_per_pkt, pkt_per_line, eol_byte_num, datatype;
u32 vs_start = 0, vs_end = 0;
u32 vpos_start = 0, vpos_end, active_v_start, active_v_end, v_total;
@ -342,7 +342,9 @@ void dsi_ctrl_hw_cmn_set_video_timing(struct dsi_ctrl_hw *ctrl,
&pkt_per_line, &eol_byte_num);
reg = bytes_per_pkt << 16;
/* data type of compressed image */
reg |= (0x0b << 8);
datatype = mode->dsc->datatype;
if(!datatype) datatype = 0x0b;
reg |= (datatype << 8);
/*
* pkt_per_line:
* 0 == 1 pkt

View file

@ -263,6 +263,27 @@ enum dsi_dyn_clk_feature_type {
* @DSI_CMD_SET_POST_TIMING_SWITCH: Post timing switch
* @DSI_CMD_SET_QSYNC_ON Enable qsync mode
* @DSI_CMD_SET_QSYNC_OFF Disable qsync mode
* @DSI_CMD_SET_HBM_FOD_ON: Turning HBM_FOD on
* @DSI_CMD_SET_HBM_ON: Turning HBM on
* @DSI_CMD_SET_HBM_OFF: Turning HBM off
* @DSI_CMD_SET_ACL_ON: Turning ACL on
* @DSI_CMD_SET_ACL_OFF: Turning ACL off
* @DSI_CMD_SET_HBM_DIM_OFF: Turning HBM DIM off
* @DSI_CMD_SET_CABC_UI: CABC UI mode
* @DSI_CMD_SET_CABC_MV: CABC MV mode
* @DSI_CMD_SET_CABC_DIS: CABC DIS mode
* @DSI_CMD_SET_DFPS_CMD_120: DFPS switch to 120
* @DSI_CMD_SET_DFPS_CMD_90: DFPS switch to 90
* @DSI_CMD_SET_DFPS_CMD_60: DFPS switch to 60
* @DSI_CMD_SET_DC_ON: DC mode on
* @DSI_CMD_SET_DC_OFF: DC mode off
* @DSI_CMD_SET_BRIGHTNESS_1E: Send demura codes when brightness changes to 0-1E
* @DSI_CMD_SET_BRIGHTNESS_1FD: Send demura codes when brightness changes to 1F-1FD
* @DSI_CMD_SET_BRIGHTNESS_2FF: Send demura codes when brightness changes to 1FE-2FF
* @DSI_CMD_SET_BRIGHTNESS_3FF: Send demura codes when brightness changes to 300-3FF
* @DSI_CMD_SET_BRIGHTNESS_4FF: Send demura codes when brightness changes to 400-4FF
* @DSI_CMD_SET_BRIGHTNESS_5FF: Send demura codes when brightness changes to 500-5FF
* @DSI_CMD_SET_BRIGHTNESS_FFF: Send demura codes when brightness changes to 600-FFF
* @DSI_CMD_SET_MAX
*/
enum dsi_cmd_set_type {
@ -289,6 +310,27 @@ enum dsi_cmd_set_type {
DSI_CMD_SET_POST_TIMING_SWITCH,
DSI_CMD_SET_QSYNC_ON,
DSI_CMD_SET_QSYNC_OFF,
DSI_CMD_SET_HBM_FOD_ON,
DSI_CMD_SET_HBM_ON,
DSI_CMD_SET_HBM_OFF,
DSI_CMD_SET_ACL_ON,
DSI_CMD_SET_ACL_OFF,
DSI_CMD_SET_HBM_DIM_OFF,
DSI_CMD_SET_CABC_UI,
DSI_CMD_SET_CABC_MV,
DSI_CMD_SET_CABC_DIS,
DSI_CMD_SET_DFPS_CMD_120,
DSI_CMD_SET_DFPS_CMD_90,
DSI_CMD_SET_DFPS_CMD_60,
DSI_CMD_SET_DC_ON,
DSI_CMD_SET_DC_OFF,
DSI_CMD_SET_BRIGHTNESS_1E,
DSI_CMD_SET_BRIGHTNESS_1FD,
DSI_CMD_SET_BRIGHTNESS_2FF,
DSI_CMD_SET_BRIGHTNESS_3FF,
DSI_CMD_SET_BRIGHTNESS_4FF,
DSI_CMD_SET_BRIGHTNESS_5FF,
DSI_CMD_SET_BRIGHTNESS_FFF,
DSI_CMD_SET_MAX
};
@ -622,11 +664,13 @@ struct dsi_display_mode_priv_info {
u32 dsi_transfer_time_us;
u64 clk_rate_hz;
u64 min_dsi_clk_hz;
u32 phy_drive_strength;
struct msm_display_topology topology;
struct msm_display_dsc_info dsc;
struct msm_display_vdc_info vdc;
bool dsc_enabled;
bool panel_dsc_update_pps_disable;
bool vdc_enabled;
struct msm_ratio pclk_scale;
struct msm_roi_caps roi_caps;

File diff suppressed because it is too large Load diff

View file

@ -20,6 +20,8 @@
#include "dsi_ctrl.h"
#include "dsi_phy.h"
#include "dsi_panel.h"
#include "sde_connector.h"
#include "sde_motUtil.h"
#define MAX_DSI_CTRLS_PER_DISPLAY 2
#define DSI_CLIENT_NAME_SIZE 20
@ -270,6 +272,7 @@ struct dsi_display {
bool misr_enable;
u32 misr_frame_count;
u32 esd_trigger;
bool disp_esd_chk_underway;
/* multiple dsi error handlers */
struct workqueue_struct *err_workq;
struct work_struct fifo_underflow_work;
@ -299,12 +302,13 @@ struct dsi_display {
int tx_cmd_buf_ndx;
struct dsi_panel_cmd_set cmd_set;
bool enabled;
u32 panel_idx;
};
int dsi_display_dev_probe(struct platform_device *pdev);
int dsi_display_dev_remove(struct platform_device *pdev);
void dsi_display_dev_shutdown(struct platform_device *pdev);
/**
* dsi_display_get_num_of_displays() - returns number of display devices
@ -596,6 +600,8 @@ int dsi_post_clkoff_cb(void *priv, enum dsi_clk_type clk_type,
enum dsi_lclk_type l_type,
enum dsi_clk_state curr_state);
int dsi_display_set_param(void *display, struct msm_param_info *param_info);
/**
* dsi_post_clkon_cb() - Callback after clock is turned on
* @priv: private data pointer.
@ -701,6 +707,29 @@ int dsi_display_cmd_transfer(struct drm_connector *connector,
*/
int dsi_display_cmd_receive(void *display, const char *cmd_buf,
u32 cmd_buf_len, u8 *recv_buf, u32 recv_buf_len);
/**
* dsi_display_motUtil_transfer() - Convert motUtil data and transfer command
* to the panel
* @display: Handle to display.
* @cmd_buf: Command buffer
* @cmd_buf_len: Command buffer length in bytes
* @motUtil_data: motUtil data information
*/
int dsi_display_motUtil_transfer(void *display, const char *cmd_buf,
u32 cmd_buf_len, struct motUtil *motUtil_data);
/**
* dsi_display_trigger_panel_dead_event() - Trigger ESD recovery
*
* @display: Handle to display.
*/
int dsi_display_trigger_panel_dead_event(struct dsi_display *display);
/**
* dsi_display_force_esd_disable() - check if ESD UTAG is forced to disable ESD
* @display: Handle to display.
*/
bool dsi_display_force_esd_disable(void *display);
/**
* dsi_display_soft_reset() - perform a soft reset on DSI controller
@ -764,6 +793,20 @@ enum dsi_pixel_format dsi_display_get_dst_format(
struct drm_connector *connector,
void *display);
/*
* dsi_display_cmd_mipi_transfer() - Sending the MIPI DSI command
* @display: Handle to display
* @msg: MIPI DSI command information
* @flags: Modifier flags
* Return: if this is a MIPI DSI read then it will return number read byte
* in success case. Otherwise will be "<=0"
* if this is a MIPI DSI write then it will return "0" for success
*
*/
int dsi_display_cmd_mipi_transfer(struct dsi_display *display,
struct mipi_dsi_msg *msg,
u32 flags);
/**
* dsi_display_cont_splash_config() - initialize splash resources
* @display: Handle to display

File diff suppressed because it is too large Load diff

View file

@ -37,6 +37,38 @@
#define MIPI_DSI_MSG_ASYNC_OVERRIDE BIT(4)
#define MIPI_DSI_MSG_CMD_DMA_SCHED BIT(5)
#define DSI_PANEL_MAX_PANEL_LEN 128
#define MAX_PARAM_NAME 10
#define BRIGHTNESS_HBM_ON 0xFFFFFFFE
#define BRIGHTNESS_HBM_OFF (BRIGHTNESS_HBM_ON - 1)
#define HBM_BRIGHTNESS(value) ((value) == HBM_OFF_STATE ?\
BRIGHTNESS_HBM_OFF : BRIGHTNESS_HBM_ON)
/* HBM implementation is different, depending on display and backlight hardware
* design, which is classified into the following types:
* HBM_TYPE_OLED: OLED panel, HBM is controlled by DSI register only, which
* is independent on brightness.
* HBM_TYPE_LCD_DCS_WLED: LCD panel, HBM is controlled by DSI register, and
* brightness is decided by WLED IC on I2C/SPI bus.
* HBM_TYPE_LCD_DCS_ONLY: LCD panel, brightness/HBM is controlled by DSI
* register only.
* HBM_TYPE_LCD_WLED_ONLY: LCD panel, brightness/HBM is controlled by WLED
* IC only.
* HBM_TYPE_LCD_DCS_GPIO: LCD panel, HBM is controlled by GPIO, and brightness
* is controlled by DSI register.
*
* Note: brightness must be at maximum while enabling HBM for all LCD panels
*/
enum panel_hbm_type {
HBM_TYPE_OLED = 0,
HBM_TYPE_LCD_DCS_WLED,
HBM_TYPE_LCD_DCS_ONLY,
HBM_TYPE_LCD_WLED_ONLY,
HBM_TYPE_LCD_DCS_GPIO
};
enum dsi_panel_rotation {
DSI_PANEL_ROTATE_NONE = 0,
DSI_PANEL_ROTATE_HV_FLIP,
@ -48,7 +80,9 @@ enum dsi_backlight_type {
DSI_BACKLIGHT_PWM = 0,
DSI_BACKLIGHT_WLED,
DSI_BACKLIGHT_DCS,
DSI_BACKLIGHT_DUMMY,
DSI_BACKLIGHT_EXTERNAL,
DSI_BACKLIGHT_I2C,
DSI_BACKLIGHT_UNKNOWN,
DSI_BACKLIGHT_MAX,
};
@ -58,6 +92,12 @@ enum bl_update_flag {
BL_UPDATE_NONE,
};
enum dsi_backlight_level_align_type {
DSI_BACKLIGHT_LEVEL_ALIGN_NORMAL = 0,
DSI_BACKLIGHT_LEVEL_ALIGN_BIT15_8_BIT3_0 = 1,
DSI_BACKLIGHT_LEVEL_ALIGN_BIT11_4_BYTE0 = 2,
};
enum {
MODE_GPIO_NOT_VALID = 0,
MODE_SEL_DUAL_PORT,
@ -84,6 +124,10 @@ struct dsi_dfps_capabilities {
u32 *dfps_list;
u32 dfps_list_len;
bool dfps_support;
bool dfps_send_cmd_support;
bool dfps_send_cmd_with_te_async;
u32 panel_on_fps;
u32 current_fps;
};
struct dsi_qsync_capabilities {
@ -118,13 +162,19 @@ struct dsi_backlight_config {
enum dsi_backlight_type type;
enum bl_update_flag bl_update;
bool bl_2bytes_enable;
bool bl_shift_left_1bit;
u32 bl_min_level;
u32 bl_max_level;
u32 brightness_max_level;
u32 brightness_default_level;
u32 bl_level;
u32 bl_scale;
u32 bl_scale_sv;
u32 bl_level_align;
bool bl_inverted_dbv;
bool bl_demura_cmd;
u32 demura_type;
int en_gpio;
/* PWM params */
@ -135,7 +185,8 @@ struct dsi_backlight_config {
/* WLED params */
struct led_trigger *wled;
struct backlight_device *raw_bd;
struct backlight_device *i2c_bd;
/* DCS params */
bool lp_mode;
};
@ -153,10 +204,12 @@ struct dsi_panel_reset_config {
int disp_en_gpio;
int lcd_mode_sel_gpio;
u32 mode_sel_state;
bool panel_on_rst_pull_down;
};
enum esd_check_status_mode {
ESD_MODE_REG_READ,
ESD_MODE_TE_CHK_REG_RD,
ESD_MODE_SW_BTA,
ESD_MODE_PANEL_TE,
ESD_MODE_SW_SIM_SUCCESS,
@ -182,6 +235,68 @@ struct dsi_panel_spr_info {
enum msm_display_spr_pack_type pack_type;
};
struct dsi_panel_lhbm_config {
bool enable;
u32 dc_hybird_threshold;
bool resend_lbhm_off;
u32 dbv_level;
u32 alpha_reg;
u32 alpha_size;
u32 *alpha;
bool lhbm_wait_for_fps_valid;
u32 lhbm_wait_for_fps_count;
u32 lhbm_wait_for_fps_interval;
u32 *lhbm_not_allowed_fps_list;
u32 lhbm_not_allowed_fps_list_len;
};
enum panel_idx {
MAIN_IDX = 0,
SEC_INX,
PANEL_IDX_MAX,
};
enum acl_state {
ACL_OFF_STATE = 0,
ACL_ON_STATE,
ACL_STATE_NUM,
};
enum hbm_state {
HBM_OFF_STATE = 0,
HBM_ON_STATE,
HBM_FOD_ON_STATE,
HBM_STATE_NUM
};
enum cabc_state {
CABC_UI_STATE,
CABC_MV_STATE,
CABC_DIS_STATE,
CABC_STATE_NUM,
};
enum dc_state {
DC_OFF_STATE = 0,
DC_ON_STATE,
DC_STATE_NUM,
};
struct panel_param_val_map {
int state;
enum dsi_cmd_set_type type;
struct dsi_panel_cmd_set *cmds;
};
struct panel_param {
const char *param_name;
struct panel_param_val_map *val_map;
u16 val_max;
const u16 default_value;
u16 value;
bool is_supported;
};
struct dsi_tlmm_gpio {
u32 num;
u32 addr;
@ -201,6 +316,10 @@ struct dsi_panel_ops {
int (*parse_gpios)(struct dsi_panel *panel);
int (*parse_power_cfg)(struct dsi_panel *panel);
};
enum touch_state {
TOUCH_DEEP_SLEEP_STATE = 0,
TOUCH_LOW_POWER_STATE,
};
struct dsi_panel {
const char *name;
@ -235,6 +354,8 @@ struct dsi_panel {
struct drm_panel_hdr_properties hdr_props;
struct drm_panel_esd_config esd_config;
struct dsi_panel_lhbm_config lhbm_config;
struct dsi_parser_utils utils;
bool lp11_init;
@ -242,8 +363,11 @@ struct dsi_panel {
bool ulps_suspend_enabled;
bool allow_phy_power_off;
bool reset_gpio_always_on;
bool need_execute_shutdown;
atomic_t esd_recovery_pending;
u32 delayms_before_resetlow;
bool is_twm_en;
bool skip_panel_off;
bool panel_initialized;
@ -261,14 +385,43 @@ struct dsi_panel {
int panel_test_gpio;
int power_mode;
bool keep_regulators_on;
enum dsi_panel_physical_type panel_type;
struct dsi_tlmm_gpio *tlmm_gpio;
u32 tlmm_gpio_count;
struct dsi_panel_ops panel_ops;
bool esd_utag_enable;
u64 panel_id;
u64 panel_ver;
u32 panel_regDA;
char panel_name[DSI_PANEL_MAX_PANEL_LEN];
char panel_supplier[DSI_PANEL_MAX_PANEL_LEN];
u32 disp_on_chk_val;
bool no_panel_on_read_support;
bool panel_hbm_fod;
bool panel_hbm_dim_off;
enum panel_hbm_type hbm_type;
u32 bl_lvl_during_hbm;
struct panel_param *param_cmds;
enum touch_state tp_state;
bool tp_state_check_enable;
int panel_recovery_retry;
bool is_panel_dead;
bool is_hbm_using_51_cmd;
int hbm_en_gpio;
};
bool dsi_display_all_displays_dead(void);
static inline bool dsi_panel_ulps_feature_enabled(struct dsi_panel *panel)
{
return panel->ulps_feature_enabled;
@ -299,7 +452,8 @@ struct dsi_panel *dsi_panel_get(struct device *parent,
struct device_node *parser_node,
const char *type,
int topology_override,
bool trusted_vm_env);
bool trusted_vm_env,
u32 panel_idx);
int dsi_panel_trigger_esd_attack(struct dsi_panel *panel, bool trusted_vm_env);
@ -340,6 +494,8 @@ int dsi_panel_set_nolp(struct dsi_panel *panel);
int dsi_panel_prepare(struct dsi_panel *panel);
int dsi_panel_reset(struct dsi_panel *panel);
int dsi_panel_enable(struct dsi_panel *panel);
int dsi_panel_post_enable(struct dsi_panel *panel);
@ -383,6 +539,8 @@ struct dsi_panel *dsi_panel_ext_bridge_get(struct device *parent,
int dsi_panel_parse_esd_reg_read_configs(struct dsi_panel *panel);
int dsi_panel_parse_panel_cfg(struct dsi_panel *panel, bool is_primary);
void dsi_panel_ext_bridge_put(struct dsi_panel *panel);
int dsi_panel_get_io_resources(struct dsi_panel *panel,
@ -402,4 +560,16 @@ int dsi_panel_create_cmd_packets(const char *data, u32 length, u32 count,
void dsi_panel_destroy_cmd_packets(struct dsi_panel_cmd_set *set);
void dsi_panel_dealloc_cmd_packets(struct dsi_panel_cmd_set *set);
int dsi_panel_set_param(struct dsi_panel *panel,
struct msm_param_info *param_info);
void dsi_panel_reset_param(struct dsi_panel *panel);
int dsi_panel_get_elvss_data(struct dsi_panel *panel);
int dsi_panel_get_elvss_data_1(struct dsi_panel *panel);
int dsi_panel_set_elvss_dim_off(struct dsi_panel *panel, u8 val);
int dsi_panel_parse_elvss_config(struct dsi_panel *panel, u8 elv_vl);
int dsi_panel_dfps_send_cmd(struct dsi_panel *panel);
#endif /* _DSI_PANEL_H_ */

View file

@ -63,7 +63,7 @@ static const struct dsi_ver_spec_info dsi_phy_v2_0 = {
static const struct dsi_ver_spec_info dsi_phy_v3_0 = {
.version = DSI_PHY_VERSION_3_0,
.lane_cfg_count = 4,
.strength_cfg_count = 2,
.strength_cfg_count = 4,
.regulator_cfg_count = 0,
.timing_cfg_count = 12,
};
@ -1114,6 +1114,32 @@ int dsi_phy_set_clk_freq(struct msm_dsi_phy *phy,
return 0;
}
/**
* dsi_phy_set_drive_strength_params - drive strength parameters for the panel
* @phy: DSI PHY handle
* @drive strength: array holding timing params.
*
* Return: error code.
*/
int dsi_phy_set_drive_strength_params(struct msm_dsi_phy *phy,
u32 drive_strength)
{
int rc = 0;
if (!phy || !drive_strength) {
DSI_PHY_ERR(phy, "Invalid params\n");
return -EINVAL;
}
mutex_lock(&phy->phy_lock);
phy->cfg.phy_drive_strength = drive_strength;
mutex_unlock(&phy->phy_lock);
return rc;
}
/**
* dsi_phy_set_timing_params() - timing parameters for the panel
* @phy: DSI PHY handle
@ -1147,7 +1173,6 @@ int dsi_phy_set_timing_params(struct msm_dsi_phy *phy,
if (phy->hw.ops.commit_phy_timing && commit)
phy->hw.ops.commit_phy_timing(&phy->hw, &phy->cfg.timing);
mutex_unlock(&phy->phy_lock);
return rc;
}

View file

@ -256,6 +256,16 @@ int dsi_phy_set_clamp_state(struct msm_dsi_phy *phy, bool enable);
int dsi_phy_set_clk_freq(struct msm_dsi_phy *phy,
struct link_clk_freq *clk_freq);
/**
* dsi_phy_set_drive_strength_params() - drive strength parameters for the panel
* @phy: DSI PHY handle
* @drive_strength: DSI PHY Drive Strength
*
* Return: error code.
*/
int dsi_phy_set_drive_strength_params(struct msm_dsi_phy *phy,
u32 drive_strength);
/**
* dsi_phy_set_timing_params() - timing parameters for the panel
* @phy: DSI PHY handle

View file

@ -103,6 +103,7 @@ struct dsi_phy_per_lane_cfgs {
* @force_clk_lane_hs:Boolean whether to force clock lane in HS mode.
* @phy_type: Phy-type (Dphy/Cphy).
* @bit_clk_rate_hz: DSI bit clk rate in HZ.
* @drive_strength: DSI PHY drive strength.
*/
struct dsi_phy_cfg {
struct dsi_phy_per_lane_cfgs lanecfg;
@ -115,6 +116,7 @@ struct dsi_phy_cfg {
bool force_clk_lane_hs;
enum dsi_phy_type phy_type;
unsigned long bit_clk_rate_hz;
u32 phy_drive_strength;
};
struct dsi_phy_hw;

View file

@ -185,6 +185,12 @@ static void dsi_phy_hw_v3_0_lane_settings(struct dsi_phy_hw *phy,
DSI_W32(phy, DSIPHY_LNX_LPRX_CTRL(i), 0);
DSI_W32(phy, DSIPHY_LNX_PIN_SWAP(i), 0x0);
DSI_W32(phy, DSIPHY_LNX_HSTX_STR_CTRL(i), 0x88);
if(cfg->phy_drive_strength) {
DSI_W32(phy, DSIPHY_LNX_HSTX_STR_CTRL(i), cfg->phy_drive_strength);
DSI_PHY_WARN(phy, "DSIPHY_LNX_HSTX_STR_CTRL of lane%d is rewrite to 0x%x from 0x88\n",
i, cfg->phy_drive_strength);
}
}
dsi_phy_hw_v3_0_config_lpcdrx(phy, cfg, true);
@ -194,8 +200,8 @@ static void dsi_phy_hw_v3_0_lane_settings(struct dsi_phy_hw *phy,
DSI_W32(phy, DSIPHY_LNX_CFG1(i), cfg->lanecfg.lane[i][1]);
DSI_W32(phy, DSIPHY_LNX_CFG2(i), cfg->lanecfg.lane[i][2]);
DSI_W32(phy, DSIPHY_LNX_CFG3(i), cfg->lanecfg.lane[i][3]);
DSI_W32(phy, DSIPHY_LNX_OFFSET_TOP_CTRL(i), 0x0);
DSI_W32(phy, DSIPHY_LNX_OFFSET_BOT_CTRL(i), 0x0);
DSI_W32(phy, DSIPHY_LNX_OFFSET_TOP_CTRL(i), cfg->strength.lane[i][2]);
DSI_W32(phy, DSIPHY_LNX_OFFSET_BOT_CTRL(i), cfg->strength.lane[i][3]);
DSI_W32(phy, DSIPHY_LNX_TX_DCTRL(i), tx_dctrl[i]);
}
}

View file

@ -349,6 +349,11 @@ static void dsi_phy_hw_dphy_enable(struct dsi_phy_hw *phy,
glbl_rescode_bot_ctrl = less_than_1500_mhz ? 0x39 : 0x3c;
glbl_str_swi_cal_sel_ctrl = 0x00;
glbl_hstx_str_ctrl_0 = 0x88;
if (cfg->phy_drive_strength != glbl_hstx_str_ctrl_0) {
glbl_str_swi_cal_sel_ctrl = 0x03;
glbl_hstx_str_ctrl_0 = cfg->phy_drive_strength;
}
} else {
vreg_ctrl_0 = less_than_1500_mhz ? 0x5B : 0x59;
glbl_str_swi_cal_sel_ctrl = less_than_1500_mhz ? 0x03 : 0x00;

View file

@ -22,6 +22,7 @@ static int dsi_pwr_parse_supply_node(struct dsi_parser_utils *utils,
int i = 0;
u32 tmp = 0;
struct device_node *node = NULL;
bool is_always_on = FALSE;
dsi_for_each_child_node(root, node) {
const char *st = NULL;
@ -112,6 +113,14 @@ static int dsi_pwr_parse_supply_node(struct dsi_parser_utils *utils,
regs->vregs[i].post_off_sleep = tmp;
}
is_always_on = utils->read_bool(node, "qcom,supply-always-on");
if (!is_always_on) {
DSI_DEBUG("qcom,supply-always-on not specified\n");
} else {
regs->vregs[i].is_always_on = is_always_on;
DSI_INFO("%s: always-on is specified\n", regs->vregs[i].vreg_name);
}
DSI_DEBUG("[%s] minv=%d maxv=%d, en_load=%d, dis_load=%d\n",
regs->vregs[i].vreg_name,
regs->vregs[i].min_voltage,
@ -206,6 +215,12 @@ static int dsi_pwr_enable_vregs(struct dsi_regulator_info *regs, bool enable)
pre_off_ms = vreg->pre_off_sleep;
post_off_ms = vreg->post_off_sleep;
if (vreg->is_always_on)
{
DSI_INFO("%s is always on\n", vreg->vreg_name);
continue;
}
if (pre_off_ms)
usleep_range((pre_off_ms * 1000),
(pre_off_ms * 1000) + 10);

View file

@ -41,6 +41,7 @@ struct dsi_vreg {
u32 post_on_sleep;
u32 pre_off_sleep;
u32 post_off_sleep;
bool is_always_on;
};
/**

View file

@ -43,6 +43,7 @@
#include <drm/drm_of.h>
#include <drm/drm_auth.h>
#include <drm/drm_probe_helper.h>
#include <linux/reboot.h>
#include "msm_drv.h"
#include "msm_gem.h"
@ -428,6 +429,11 @@ static int msm_drm_uninit(struct device *dev)
priv->registered = false;
}
if (priv->msm_drv_notifier.notifier_call) {
unregister_reboot_notifier(&priv->msm_drv_notifier);
priv->msm_drv_notifier.notifier_call = NULL;
}
#ifdef CONFIG_DRM_FBDEV_EMULATION
if (fbdev && priv->fbdev)
msm_fbdev_free(ddev);
@ -755,6 +761,23 @@ static struct msm_kms *_msm_drm_component_init_helper(
return kms;
}
static void msm_pdev_shutdown(struct platform_device *pdev);
static int msm_drv_shutdown_notifier_cb(struct notifier_block *nb,
unsigned long event, void *unused)
{
struct device *dev;
struct platform_device *pdev;
struct msm_drm_private *priv = container_of(nb, struct msm_drm_private,
msm_drv_notifier);
dev = priv->dev->dev;
pdev = to_platform_device(dev);
dev_warn(dev, "prepare to shutdown\n");
msm_pdev_shutdown(pdev);
return NOTIFY_DONE;
}
static int msm_drm_device_init(struct platform_device *pdev,
struct drm_driver *drv)
{
@ -938,6 +961,16 @@ static int msm_drm_component_init(struct device *dev)
drm_kms_helper_poll_init(ddev);
priv->msm_drv_notifier.notifier_call = msm_drv_shutdown_notifier_cb;
priv->msm_drv_notifier.next = NULL;
priv->msm_drv_notifier.priority = 1;
ret = register_reboot_notifier(&priv->msm_drv_notifier);
if (ret) {
dev_err(dev, "Failed to register for reboot_notifier. ret = %d\n",
ret);
goto fail;
}
return 0;
fail:
@ -1750,6 +1783,38 @@ int msm_ioctl_display_hint_ops(struct drm_device *dev, void *data,
return 0;
}
static int msm_ioctl_set_panel_feature(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct msm_drm_private *priv;
struct msm_kms *kms;
struct panel_param_info *param_info = data;
int ret;
priv = dev->dev_private;
kms = priv->kms;
if (unlikely(!param_info)) {
DRM_ERROR("ioctl_set_panel_feature invalid data\n");
return -EINVAL;
}
DRM_INFO("ioctl_set_panel_feature idx=%d, value=%d\n",
param_info->param_idx, param_info->value);
if (kms && kms->funcs && kms->funcs->set_panel_feature) {
ret = kms->funcs->set_panel_feature(kms, *param_info);
if (ret) {
DRM_ERROR("kms set_panel_feature failed.\n");
goto fail;
}
}
return 0;
fail:
return ret;
}
static const struct drm_ioctl_desc msm_ioctls[] = {
DRM_IOCTL_DEF_DRV(MSM_GEM_NEW, msm_ioctl_gem_new, DRM_AUTH|DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(MSM_GEM_CPU_PREP, msm_ioctl_gem_cpu_prep, DRM_AUTH|DRM_RENDER_ALLOW),
@ -1765,6 +1830,8 @@ static const struct drm_ioctl_desc msm_ioctls[] = {
DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(MSM_DISPLAY_HINT, msm_ioctl_display_hint_ops,
DRM_UNLOCKED),
DRM_IOCTL_DEF_DRV(SET_PANEL_FEATURE, msm_ioctl_set_panel_feature,
DRM_UNLOCKED),
};
static const struct vm_operations_struct vm_ops = {

View file

@ -38,6 +38,7 @@
#include <linux/sde_vm_event.h>
#include <linux/sizes.h>
#include <linux/kthread.h>
#include <linux/notifier.h>
#include <drm/drmP.h>
#include <drm/drm_atomic.h>
@ -215,12 +216,18 @@ enum msm_mdp_conn_property {
CONNECTOR_PROP_QSYNC_MODE,
CONNECTOR_PROP_CMD_FRAME_TRIGGER_MODE,
/* MOT feature panel*/
CONNECTOR_PROP_HBM,
CONNECTOR_PROP_CABC,
CONNECTOR_PROP_ACL,
CONNECTOR_PROP_DC,
/* total # of properties */
CONNECTOR_PROP_COUNT
};
#define MSM_GPU_MAX_RINGS 4
#define MAX_H_TILES_PER_DISPLAY 2
#define MSM_DISP_NAME_LEN_MAX 128
/**
* enum msm_display_compression_type - compression method used for pixel stream
@ -351,6 +358,27 @@ struct msm_roi_caps {
struct msm_roi_alignment align;
};
enum msm_param_state {
PARAM_STATE_OFF = 0,
PARAM_STATE_ON,
PARAM_STATE_NUM,
PARAM_STATE_DISABLE = 0xFFFF,
};
enum msm_param_id {
PARAM_HBM_ID = 0,
PARAM_CABC_ID,
PARAM_ACL_ID,
PARAM_DC_ID,
PARAM_ID_NUM
};
struct msm_param_info {
enum msm_param_id param_idx;
enum msm_mdp_conn_property param_conn_idx;
int value;
};
/**
* struct msm_display_dsc_info - defines dsc configuration
* @config DSC encoder configuration
@ -374,6 +402,7 @@ struct msm_roi_caps {
* @half_panel_pu True for single and dual dsc encoders if partial
* update sets the roi width to half of mode width
* False in all other cases
* @datatype: data type of compressed image
*/
struct msm_display_dsc_info {
struct drm_dsc_config config;
@ -396,6 +425,8 @@ struct msm_display_dsc_info {
u32 dsc_4hsmerge_padding;
u32 dsc_4hsmerge_alignment;
bool half_panel_pu;
int datatype;
bool dsc_novatek_ic;
};
@ -727,6 +758,10 @@ struct msm_resource_caps_info {
* @h_tile_instance: Controller instance used per tile. Number of elements is
* based on num_of_h_tiles
* @is_connected: Set to true if display is connected
* @panel_id
* @panel_ver
* @panel_regDA
* @panel_name[MSM_DISP_NAME_LEN_MAX];
* @width_mm: Physical width
* @height_mm: Physical height
* @max_width: Max width of display. In case of hot pluggable display
@ -756,6 +791,12 @@ struct msm_display_info {
bool is_connected;
uint64_t panel_id;
uint64_t panel_ver;
uint32_t panel_regDA;
char panel_name[MSM_DISP_NAME_LEN_MAX];
char panel_supplier[MSM_DISP_NAME_LEN_MAX];
unsigned int width_mm;
unsigned int height_mm;
@ -939,6 +980,7 @@ struct msm_drm_private {
struct mutex vm_client_lock;
struct list_head vm_client_list;
struct notifier_block msm_drv_notifier;
};
/* get struct msm_kms * from drm_device * */

View file

@ -135,6 +135,9 @@ struct msm_kms_funcs {
/* topology dsc information */
int (*get_dsc_count)(const struct msm_kms *kms,
u32 hdisplay, u32 *num_dsc);
/* set panel feature */
int (*set_panel_feature)(const struct msm_kms *kms,
struct panel_param_info param_info);
};
struct msm_kms {

View file

@ -138,6 +138,9 @@ static int sde_backlight_device_update_status(struct backlight_device *bd)
if (brightness > c_conn->thermal_max_brightness)
brightness = c_conn->thermal_max_brightness;
if(brightness && brightness < display->panel->bl_config.bl_min_level)
brightness = display->panel->bl_config.bl_min_level;
/* map UI brightness into driver backlight level with rounding */
bl_lvl = mult_frac(brightness, bl_max_level, brightness_max_level);
@ -244,7 +247,7 @@ static int sde_backlight_setup(struct sde_connector *c_conn,
props.type = BACKLIGHT_RAW;
props.power = FB_BLANK_UNBLANK;
props.max_brightness = brightness_max_level;
props.brightness = brightness_max_level;
props.brightness = bl_config->brightness_default_level;
snprintf(bl_node_name, BL_NODE_NAME_SIZE, "panel%u-backlight",
display_count);
c_conn->bl_device = backlight_device_register(bl_node_name, dev->dev,
@ -589,8 +592,10 @@ void sde_connector_schedule_status_work(struct drm_connector *connector,
return;
sde_connector_get_info(connector, &info);
if (c_conn->ops.check_status &&
(info.capabilities & MSM_DISPLAY_ESD_ENABLED)) {
if ((c_conn->ops.force_esd_disable &&
(c_conn->ops.force_esd_disable(c_conn->display) == false)) &&
(c_conn->ops.check_status &&
(info.capabilities & MSM_DISPLAY_ESD_ENABLED))) {
if (en) {
u32 interval;
@ -811,6 +816,24 @@ static int _sde_connector_update_hdr_metadata(struct sde_connector *c_conn,
return rc;
}
static int _sde_connector_update_param(struct sde_connector *c_conn,
struct msm_param_info *param_info)
{
struct dsi_display *dsi_display;
int rc = 0;
if (!c_conn) {
SDE_ERROR("Invalid params sde_connector null\n");
return -EINVAL;
}
dsi_display = c_conn->display;
if (dsi_display && c_conn->ops.set_param)
rc = c_conn->ops.set_param(dsi_display, param_info);
return rc;
}
static int _sde_connector_update_dirty_properties(
struct drm_connector *connector)
{
@ -1492,6 +1515,7 @@ static int sde_connector_atomic_set_property(struct drm_connector *connector,
int idx, rc;
uint64_t fence_user_fd;
uint64_t __user prev_user_fd;
struct msm_param_info param_info;
if (!connector || !state || !property) {
SDE_ERROR("invalid argument(s), conn %pK, state %pK, prp %pK\n",
@ -1598,6 +1622,38 @@ static int sde_connector_atomic_set_property(struct drm_connector *connector,
msm_property_set_dirty(&c_conn->property_info,
&c_state->property_state, idx);
break;
case CONNECTOR_PROP_HBM:
param_info.value = val;
param_info.param_idx = PARAM_HBM_ID;
param_info.param_conn_idx = CONNECTOR_PROP_HBM;
rc = _sde_connector_update_param(c_conn, &param_info);
if (rc)
goto end;
break;
case CONNECTOR_PROP_ACL:
param_info.value = val;
param_info.param_idx = PARAM_ACL_ID;
param_info.param_conn_idx = CONNECTOR_PROP_ACL;
rc = _sde_connector_update_param(c_conn, &param_info);
if (rc)
goto end;
break;
case CONNECTOR_PROP_CABC:
param_info.value = val;
param_info.param_idx = PARAM_CABC_ID;
param_info.param_conn_idx = CONNECTOR_PROP_CABC;
rc = _sde_connector_update_param(c_conn, &param_info);
if (rc)
goto end;
break;
case CONNECTOR_PROP_DC:
param_info.value = val;
param_info.param_idx = PARAM_DC_ID;
param_info.param_conn_idx = CONNECTOR_PROP_DC;
rc = _sde_connector_update_param(c_conn, &param_info);
if (rc)
goto end;
break;
default:
break;
}
@ -2674,6 +2730,59 @@ static int sde_connector_populate_mode_info(struct drm_connector *conn,
return rc;
}
static int sde_connector_install_panel_params(struct sde_connector *c_conn)
{
struct panel_param *param_cmds;
uint32_t prop_idx;
int i;
struct dsi_display *dsi_display;
u16 prop_max, prop_min, prop_init;
if (c_conn->connector_type != DRM_MODE_CONNECTOR_DSI)
return 0;
dsi_display = (struct dsi_display *) (c_conn->display);
param_cmds = dsi_display->panel->param_cmds;
for (i = 0; i < PARAM_ID_NUM; i++) {
SDE_DEBUG("%s:i = %d param_name = %s is_support=%d\n",
__func__, i,
param_cmds->param_name, param_cmds->is_supported);
if (!strncmp(param_cmds->param_name, "HBM", 3))
prop_idx = CONNECTOR_PROP_HBM;
else if (!strncmp(param_cmds->param_name, "CABC", 4))
prop_idx = CONNECTOR_PROP_CABC;
else if (!strncmp(param_cmds->param_name, "ACL", 3))
prop_idx = CONNECTOR_PROP_ACL;
else if (!strncmp(param_cmds->param_name, "DC", 2))
prop_idx = CONNECTOR_PROP_DC;
else {
SDE_ERROR("Invalid param_name =%s\n",
param_cmds->param_name);
return -EINVAL;
}
if (param_cmds->is_supported) {
prop_max = param_cmds->val_max;
prop_min = PARAM_STATE_OFF;
prop_init = param_cmds->default_value;
} else {
prop_max = PARAM_STATE_OFF;
prop_min = PARAM_STATE_OFF;
prop_init = PARAM_STATE_DISABLE;
}
msm_property_install_volatile_range( &c_conn->property_info,
param_cmds->param_name, 0x0,
prop_min, prop_max,
prop_init, prop_idx);
param_cmds++;
}
return 0;
}
int sde_connector_set_blob_data(struct drm_connector *conn,
struct drm_connector_state *state,
enum msm_mdp_conn_property prop_id)
@ -3119,6 +3228,14 @@ struct drm_connector *sde_connector_init(struct drm_device *dev,
}
}
rc = sde_connector_install_panel_params(c_conn);
if (rc) {
SDE_ERROR_CONN(c_conn,
"failed to install property for panel params. rc =%d\n",
rc);
goto error_cleanup_fence;
}
rc = sde_connector_get_info(&c_conn->base, &display_info);
if (!rc && (connector_type == DRM_MODE_CONNECTOR_DSI) &&
(display_info.capabilities & MSM_DISPLAY_CAP_VID_MODE))

View file

@ -15,6 +15,7 @@
#include "msm_prop.h"
#include "sde_kms.h"
#include "sde_fence.h"
#include "sde_motUtil.h"
#define SDE_CONNECTOR_NAME_SIZE 16
#define SDE_CONNECTOR_DHDR_MEMPOOL_MAX_SIZE SZ_32
@ -277,6 +278,32 @@ struct sde_connector_ops {
int (*cmd_receive)(void *display, const char *cmd_buf,
u32 cmd_buf_len, u8 *recv_buf, u32 recv_buf_len);
/**
* motUtil_transfer - Convert motUtil data and Transfer command
* to the connected display panel
* @display: Pointer to private display handle
* @cmd_buf: Command buffer
* @cmd_buf_len: Command buffer length in bytes
* @motUtil_data: motUtil data information
* Returns: Zero for success, negetive for failure
*/
int (*motUtil_transfer)(void *display, const char *cmd_buf,
u32 cmd_buf_len, struct motUtil *motUtil_data);
/**
* force_esd_disable - force to disable check_status
* @display: Pointer to private display handle
* Returns: true for forcing ESD disable
*/
bool (*force_esd_disable)(void *display);
/**
* set_param - set display's feature param setting
* @display: Pointer to private display handle
* Returns: Zero for success, negative for failure
*/
int (*set_param)(void *display, struct msm_param_info *param_info);
/**
* config_hdr - configure HDR
* @connector: Pointer to drm connector structure

View file

@ -30,6 +30,9 @@
#include <linux/suspend.h>
#include <drm/drm_atomic_uapi.h>
#include <drm/drm_probe_helper.h>
#include <linux/memblock.h>
#include <linux/string.h>
#include <linux/slab.h>
#include "msm_drv.h"
#include "msm_mmu.h"
@ -60,6 +63,8 @@
#include <linux/qtee_shmbridge.h>
#include <linux/haven/hh_irq_lend.h>
#include "sde_motUtil.h"
#define CREATE_TRACE_POINTS
#include "sde_trace.h"
@ -152,6 +157,7 @@ static int _sde_debugfs_init(struct sde_kms *sde_kms)
(void) sde_debugfs_vbif_init(sde_kms, debugfs_root);
(void) sde_debugfs_core_irq_init(sde_kms, debugfs_root);
(void) sde_debugfs_mot_util_init(sde_kms, debugfs_root);
rc = sde_core_perf_debugfs_init(&sde_kms->perf, debugfs_root);
if (rc) {
@ -1755,7 +1761,10 @@ static int _sde_kms_setup_displays(struct drm_device *dev,
.post_kickoff = dsi_conn_post_kickoff,
.check_status = dsi_display_check_status,
.enable_event = dsi_conn_enable_event,
.motUtil_transfer = dsi_display_motUtil_transfer,
.cmd_transfer = dsi_display_cmd_transfer,
.force_esd_disable = dsi_display_force_esd_disable,
.set_param = dsi_display_set_param,
.cont_splash_config = dsi_display_cont_splash_config,
.cont_splash_res_disable = dsi_display_cont_splash_res_disable,
.get_panel_vfp = dsi_display_get_panel_vfp,
@ -1779,6 +1788,8 @@ static int _sde_kms_setup_displays(struct drm_device *dev,
.get_dst_format = NULL,
.check_status = NULL,
.cmd_transfer = NULL,
.force_esd_disable = NULL,
.set_param = NULL,
.cont_splash_config = NULL,
.cont_splash_res_disable = NULL,
.get_panel_vfp = NULL,
@ -1801,6 +1812,8 @@ static int _sde_kms_setup_displays(struct drm_device *dev,
.set_colorspace = dp_connector_set_colorspace,
.config_hdr = dp_connector_config_hdr,
.cmd_transfer = NULL,
.force_esd_disable = NULL,
.set_param = NULL,
.cont_splash_config = dp_display_cont_splash_config,
.cont_splash_res_disable = NULL,
.get_panel_vfp = NULL,
@ -3723,6 +3736,31 @@ static int sde_kms_get_dsc_count(const struct msm_kms *kms,
return 0;
}
static int sde_kms_set_panel_feature(const struct msm_kms *kms,
struct panel_param_info param_info)
{
struct sde_kms *sde_kms;
struct dsi_display *display;
struct msm_param_info param_info_msm;
int rc = 0;
if (!kms) {
SDE_ERROR("invalid input args\n");
return -EINVAL;
}
sde_kms = to_sde_kms(kms);
param_info_msm.param_idx = (enum msm_param_id)param_info.param_idx;
param_info_msm.value = param_info.value;
display = (struct dsi_display *)sde_kms->dsi_displays[0];
rc = dsi_display_set_param(display, &param_info_msm);
if (rc)
SDE_ERROR("set param %d value %d failed\n",
param_info_msm.param_idx, param_info_msm.value);
return rc;
}
static int _sde_kms_null_commit(struct drm_device *dev,
struct drm_encoder *enc)
{
@ -4191,6 +4229,7 @@ static const struct msm_kms_funcs kms_funcs = {
.trigger_null_flush = sde_kms_trigger_null_flush,
.get_mixer_count = sde_kms_get_mixer_count,
.get_dsc_count = sde_kms_get_dsc_count,
.set_panel_feature = sde_kms_set_panel_feature,
};
static int _sde_kms_mmu_destroy(struct sde_kms *sde_kms)

View file

@ -126,7 +126,7 @@
#define SDE_KMS_OPS_PREPARE_PLANE_FB BIT(3)
/* ESD status check interval in miliseconds */
#define STATUS_CHECK_INTERVAL_MS 5000
#define STATUS_CHECK_INTERVAL_MS 8000
/**
* enum sde_kms_smmu_state: smmu state

View file

@ -0,0 +1,420 @@
/*
* Copyright (c) 2018-2019, 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
* 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.
*
*/
#define pr_fmt(fmt) "motUtil:[%s]" fmt, __func__
#include <linux/debugfs.h>
#include <linux/string.h>
#include <linux/slab.h>
#include "sde_connector.h"
#include "sde_encoder.h"
#include "sde_motUtil.h"
#include "dsi_display.h"
#define MAIN_DSI_CONN_NAME "DSI-1"
#define CLI_DSI_CONN_NAME "DSI-2"
struct motUtil motUtil_data;
static ssize_t _sde_debugfs_motUtil_string2num(const char __user *buf,
size_t count, char buffer[])
{
char *input, *input_copy, *token, *input_dup = NULL;
const char *delim =" ";
u32 buf_size = 0;
int rc=0, strtoint;
/*copy the data from user space*/
input = kmalloc(count + 1, GFP_KERNEL);
if (!input)
return -ENOMEM;
if (copy_from_user(input, buf, count)) {
SDE_ERROR("copy from user failed\n");
rc = -EFAULT;
goto end;
}
input[count]='\0';
SDE_INFO("input_cmd = %s\n", input);
input_copy = kstrdup(input, GFP_KERNEL);
if (!input_copy) {
rc = -ENOMEM;
goto end;
}
input_dup = input_copy,
token = strsep(&input_copy, delim);
while (token) {
rc = kstrtoint(token, 0, &strtoint);
if (rc) {
rc = -EIO;
SDE_ERROR("input buffer conversion failed\n");
goto end;
}
if (buf_size >= MAX_CMD_PAYLOAD_SIZE) {
SDE_ERROR("buffer size exceeding the limit %d\n",
MAX_CMD_PAYLOAD_SIZE);
goto end;
}
buffer[buf_size++] = (strtoint & 0xff);
token = strsep(&input_copy, delim);
}
SDE_DEBUG("command packet size in bytes: %u\n", buf_size);
rc = buf_size;
end:
kfree(input_dup);
kfree(input);
return rc;
}
static struct drm_connector *_sde_debugfs_motUtil_get_drm_conn(
struct sde_kms *kms,
size_t count, char input[])
{
struct drm_device *dev = kms->dev;
struct drm_connector *conn = NULL;
int found_conn = 0;
enum sde_motUtil_disp_cmd panel_type = input[DISPUTIL_PANEL_TYPE];
struct drm_connector_list_iter conn_iter;
mutex_lock(&dev->mode_config.mutex);
drm_connector_list_iter_begin(dev, &conn_iter);
drm_for_each_connector_iter(conn, &conn_iter) {
if (panel_type == MOTUTIL_MAIN_DISP) {
if (!strncmp(conn->name, MAIN_DSI_CONN_NAME, 5)) {
SDE_DEBUG("found MAIN disp conn\n");
found_conn = 1;
break;
}
} else if (panel_type == MOTUTIL_CLI_DISP) {
if (!strncmp(conn->name, CLI_DSI_CONN_NAME, 5)) {
SDE_DEBUG("found CLI disp conn\n");
found_conn = 1;
break;
}
}
}
drm_connector_list_iter_end(&conn_iter);
mutex_unlock(&dev->mode_config.mutex);
if (found_conn)
return conn;
else
return NULL;
}
static struct sde_connector *_sde_debugfs_motUtil_get_sde_conn(
struct sde_kms *kms,
size_t count, char input[])
{
struct drm_connector *conn = NULL;
struct sde_connector *sde_conn = NULL;
conn = _sde_debugfs_motUtil_get_drm_conn(kms, count, input);
if (conn)
sde_conn = to_sde_connector(conn);
else
DRM_ERROR("Can not find SDE Connector for %s\n",
(input[DISPUTIL_PANEL_TYPE] == MOTUTIL_MAIN_DISP) ?
"Main Display" : "CLI Display");
return sde_conn;
}
static int _sde_debugfs_motUtil_transfer(struct sde_kms *kms,
size_t count, char input[])
{
struct sde_connector *sde_conn = NULL;
int ret = 0;
enum sde_motUtil_disp_cmd panel_type = input[DISPUTIL_PANEL_TYPE];
if (panel_type > MOTUTIL_CLI_DISP) {
SDE_ERROR("Invalid panel number = %d\n", panel_type);
return -EINVAL;
}
sde_conn = _sde_debugfs_motUtil_get_sde_conn(kms, count, input);
if (!sde_conn) {
ret = -EINVAL;
goto end;
}
if (sde_conn && !sde_conn->ops.motUtil_transfer) {
SDE_ERROR("no motUtil_transfer support for connector name %s\n",
sde_conn->name);
ret = -ENOENT;
goto end;
}
if (motUtil_data.rd_buf) {
mutex_lock(&sde_conn->lock);
ret = sde_conn->ops.motUtil_transfer(sde_conn->display,
input, count, &motUtil_data);
motUtil_data.cmd_status = ret;
motUtil_data.read_len = ret;
mutex_unlock(&sde_conn->lock);
ret = count;
} else
ret = -ENOMEM;
end:
return ret;
}
static int _sde_debugfs_motUtil_kms_prop_test(struct sde_kms *kms,
size_t count, char input[])
{
struct drm_connector *conn = NULL;
struct sde_connector *sde_conn = NULL;
struct drm_property *property;
int ret = 0;
enum msm_mdp_conn_property conn_prop_idx;
uint64_t prop_val;
conn = _sde_debugfs_motUtil_get_drm_conn(kms, count, input);
if (!conn) {
ret = -EINVAL;
goto end;
}
sde_conn = to_sde_connector(conn);
if (!sde_conn) {
ret = -EINVAL;
goto end;
}
if (count < KMSPROPTEST_NEW_VAL) {
DRM_ERROR(" Number of Input data is invalid (%zu).\n", count);
ret = -EINVAL;
goto end;
}
switch (input[KMSPROPTEST_PROP_INDEX]) {
case KMSPROPTEST_TYPE_HBM:
conn_prop_idx = CONNECTOR_PROP_HBM;
break;
case KMSPROPTEST_TYPE_ACL:
conn_prop_idx = CONNECTOR_PROP_ACL;
break;
case KMSPROPTEST_TYPE_CABC:
conn_prop_idx = CONNECTOR_PROP_CABC;
break;
case KMSPROPTEST_TYPE_DC:
conn_prop_idx = CONNECTOR_PROP_DC;
break;
default:
DRM_ERROR(" Invalid KMSPROPTEST_PROP_INDEX = %d\n",
input[KMSPROPTEST_PROP_INDEX]);
ret = -EINVAL;
break;
}
if (ret)
goto end;
property = msm_property_index_to_drm_property(&sde_conn->property_info,
conn_prop_idx);
if (!property) {
SDE_ERROR("invalid property index %d for sde_conn_name=%s\n",
conn_prop_idx, sde_conn->name);
ret = -EINVAL;
goto end;
}
prop_val = sde_connector_get_property(conn->state, conn_prop_idx);
if (prop_val == PARAM_STATE_DISABLE) {
DRM_ERROR("This KMS Property=%d is disabled\n", conn_prop_idx);
ret = -EPERM;
goto end;
}
switch(input[KMSPROPTEST_PROP_TYPE]) {
case KMSPROPTEST_GETPROP:
motUtil_data.read_cmd = true;
motUtil_data.val = (int)prop_val;
break;
case KMSPROPTEST_SETPROP:
motUtil_data.read_cmd = false;
if (conn->funcs && conn->funcs->atomic_set_property) {
ret = conn->funcs->atomic_set_property(conn,
conn->state, property,
input[KMSPROPTEST_NEW_VAL]);
} else {
ret = -EINVAL;
DRM_ERROR("Unsupport KMS set property\n");
}
break;
default:
DRM_ERROR("Invalid KMSPROPTEST_PROP_TYPE = %d\n",
input[KMSPROPTEST_PROP_TYPE]);
ret = -EINVAL;
break;
}
end:
motUtil_data.cmd_status = ret;
return ret;
}
static ssize_t _sde_debugfs_motUtil_exe_command(struct sde_kms *kms,
size_t count, char input[])
{
int ret = 0;
enum sde_motUtil_type motUtil_type = input[0];
motUtil_data.motUtil_type = motUtil_type;
switch (motUtil_type) {
case MOTUTIL_DISP_UTIL:
ret = _sde_debugfs_motUtil_transfer(kms, count, input);
break;
case MOTUTIL_KMS_PROP_TEST:
ret = _sde_debugfs_motUtil_kms_prop_test(kms, count, input);
break;
default:
SDE_ERROR("Un-support motUtil type = %d\n", motUtil_type);
ret = -EINVAL;
}
return ret;
}
static int _sde_debugfs_motUtil_open(struct inode *inode,
struct file *file)
{
if (!inode || !file)
return -EINVAL;
/* non-seekable */
file->private_data = inode->i_private;
return nonseekable_open(inode, file);
}
static ssize_t _sde_debugfs_motUtil_write(struct file *file,
const char __user *buf, size_t count, loff_t *ppos)
{
u32 buf_size = 0;
char buffer[MAX_CMD_PAYLOAD_SIZE];
struct sde_kms *kms = (struct sde_kms *)file->private_data;
int ret = 0;
if (*ppos || !kms) {
SDE_ERROR("invalid argument(s)\n");
ret = -EINVAL;
goto end;
}
buf_size = _sde_debugfs_motUtil_string2num(buf, count, buffer);
if (buf_size <= 0){
SDE_ERROR("invalid input\n");
ret = -EINVAL;
goto end;
}
mutex_lock(&motUtil_data.lock);
ret = _sde_debugfs_motUtil_exe_command(kms, count, buffer);
mutex_unlock(&motUtil_data.lock);
end:
motUtil_data.cmd_status = ret;
return count;
}
static ssize_t _sde_debugfs_motUtil_dispUtil_read(char *buffer)
{
int blen = 0, i;
if (motUtil_data.read_len) {
blen = snprintf(buffer, 16, "motUtil_read: ");
for (i = 0; i < motUtil_data.read_len; i ++)
blen += snprintf((buffer + blen) , 6, "0x%02x ",
*motUtil_data.rd_buf++);
blen += snprintf((buffer + blen), 2, "\n");
} else
SDE_ERROR("motUtil failed to read from panel\n");
return blen;
}
static ssize_t _sde_debugfs_motUtil_read(struct file *file,
char __user *buf, size_t count, loff_t *ppos)
{
int blen = 0;
char buffer[MAX_CMD_PAYLOAD_SIZE];
if (*ppos)
return 0;
mutex_lock(&motUtil_data.lock);
if (motUtil_data.cmd_status < 0 || !motUtil_data.read_cmd) {
blen = snprintf(buffer, MAX_CMD_PAYLOAD_SIZE,
"motUtil_status: %d\n",
motUtil_data.cmd_status);
} else if (motUtil_data.motUtil_type == MOTUTIL_DISP_UTIL) {
blen = _sde_debugfs_motUtil_dispUtil_read(buffer);
} else if (motUtil_data.motUtil_type == MOTUTIL_KMS_PROP_TEST) {
blen = snprintf(buffer, 16, "motUtil_read: ");
blen += snprintf((buffer + blen), 12, "0x%08x ",
motUtil_data.val);
blen += snprintf((buffer + blen), 2, "\n");
}
SDE_INFO("%s\n", buffer);
if (blen <= 0) {
SDE_ERROR("snprintf failed, blen %d\n", blen);
return 0;
}
if (copy_to_user(buf, buffer, min(count, (size_t)blen+1))) {
SDE_ERROR("copy to user buffer failed\n");
return -EFAULT;
}
*ppos += blen;
mutex_unlock(&motUtil_data.lock);
return blen;
}
static const struct file_operations sde_debugfs_motUtil_fops = {
.open = _sde_debugfs_motUtil_open,
.read = _sde_debugfs_motUtil_read,
.write = _sde_debugfs_motUtil_write,
};
int sde_debugfs_mot_util_init(struct sde_kms *sde_kms,
struct dentry *parent)
{
debugfs_create_file("motUtil", 0606, parent,
sde_kms, &sde_debugfs_motUtil_fops);
motUtil_data.rd_buf = kzalloc(SZ_4K, GFP_KERNEL);
if (!motUtil_data.rd_buf)
return -ENOMEM;
motUtil_data.te_enable = true;
mutex_init(&motUtil_data.lock);
return 0;
}

View file

@ -0,0 +1,151 @@
/*
* Copyright (c) 2018-2019, 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
* 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 __MOTUTIL_H__
#define __MOTUTIL_H__
#include <linux/debugfs.h>
#include <linux/types.h>
/*****************************************************************************
* /d/dri/0/debug/motUtil sysfs *
* - This is Mot debug sysfs to provide some tools to test panel and panel *
* features. This tool only exist with the userdebug and Engineering build *
* - Currently, this motUtil will provide 3 kind of tests and it can enhance *
* to test more if needed *
* - Test#1: DispUtil: This test is able to send any MIPI DSI command and *
* it can read any data back from the panel *
* - Test#2: TeTest: This test will be used to test the TE trace between *
* the panels and MDSS to make sure it works *
* - Test#3: kmsPropTest: This test will test the panel features such as *
* HBM, ACL, CABC, etc. It can read these features configurations*
* in the KMS property and it can change these setting from KMS *
* property. *
* - Usage: *
* - 1st byte will indicate which motUtil test will be run. *
* 0x00 = dispUtil, 0x01 = TeTest, 0x02 = kmsPropTest *
* --------------------------------------------------------------------------*
* - dispUtil: *
* 1st byte: 0x00: dispUtil *
* 2nd byte: 0x00: primary panel and 0x01: Secondary panel *
* 3rd byte: 0x00: MIPI write cmd to panel and 0x01: MIPI read *
* 4th byte: 0x00: MIPI HS mode and 0x01: MIPI LP mode *
* 5th byte: 0x00: MIPI DCS cmd and 0x01: MIPI generaic cmd *
* 6th byte: Indicate number of bytes to read from panel *
* 7th and 8th: Indicate number of bytes for the payload cmd *
* 9th and .. :the payload cmd *
* - Example: *
* echo "0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x28" > motUtil *
* - This will send a mipi DSC command "0x28" to panel and *
* which will request the panel to turn off the panel *
* cat motUtil *
* - This will report a sending previous cmd status *
* 0: send success or errno if it fails *
* echo "0x00 0x01 0x01 0x00 0x00 0x01 0x00 0x01 0x0a" > motUtil *
* - This will send MIPI read cmd "0xa" to the panel. *
* cat motUtil *
* - number of reading bytes from previous command or errno if it fails*
*---------------------------------------------------------------------------*
* - TeTest: This test has been removed *
*---------------------------------------------------------------------------*
* - kmsPropTest *
* 1st byte: kmsPropTest *
* 2nd byte: 0x00: primary panel and 0x01: Secondary panel *
* 3rd byte: 0x00: get KMS property and 0x01: set KMS property *
* 4th byte: 0x00: HBM 0x01: ACL for the KMS property/panel feature *
* 5th byte: new data for a "set KMS property" operation *
* - Example *
* echo "0x02 0x00 0x010 0x00 0x00" > motUtil *
* - This will read the HBM setting of the primary panel in the KMS *
* property. *
* cat motUtil *
* - This will return the status of previous cmd. *
* 0 if success or errno if it fails *
* echo "0x02 0x00 0x01 0x00 0x01" > motUtil *
* - This will turn on the HBM feature of the primary panel in the KMS *
* property. The panel's backlight will be brighter when HBM is on *
* cat motUtil *
* - This will return the status of previous cmd. *
* 0 if success or errno if it fails *
* echo "0x02 0x00 0x010 0x00 0x00" > motUtil *
* - This will read back the HBM setting in KMS property *
* echo "0x02 0x00 0x01 0x00 0x00" > motUtil *
* - This will turn off the HBM feature of the primary panel in the KMS *
* property. The panel's backlight will be dimmer when HBM is off *
* *
****************************************************************************/
enum sde_motUtil_type {
MOTUTIL_DISP_UTIL = 0,
MOTUTIL_TE_TEST,
MOTUTIL_KMS_PROP_TEST,
};
enum sde_motUtil_disp_cmd {
DISPUTIL_TYPE = 0,
DISPUTIL_PANEL_TYPE,
DISPUTIL_CMD_TYPE,
DISPUTIL_CMD_XFER_MODE,
DISPUTIL_MIPI_CMD_TYPE,
DISPUTIL_NUM_BYTE_RD,
DISPUTIL_PAYLOAD_LEN_U,
DISPUTIL_PAYLOAD_LEN_L,
DISPUTIL_PAYLOAD,
};
enum sde_motUtil_kmsPropTest_cmd {
KMSPROPTEST_TYPE,
KMSPROPTEST_PANEL_TYPE,
KMSPROPTEST_PROP_TYPE,
KMSPROPTEST_PROP_INDEX,
KMSPROPTEST_NEW_VAL,
};
enum sde_motUtil_kmsPropTest_ConnPropType {
KMSPROPTEST_TYPE_HBM,
KMSPROPTEST_TYPE_ACL,
KMSPROPTEST_TYPE_CABC,
KMSPROPTEST_TYPE_DC,
};
struct motUtil {
struct mutex lock;
enum sde_motUtil_type motUtil_type;
bool read_cmd;
int cmd_status;
u16 read_len;
u8 *rd_buf;
int val;
bool te_enable;
};
#define DISPUTIL_DSI_WRITE 0
#define DISPUTIL_DSI_READ 1
#define DISPUTIL_DSI_DCS 0
#define DISPUTIL_DSI_GENERIC 1
#define DISPUTIL_DSI_HS_MODE 0
#define DISPUTIL_DSI_LP_MODE 1
#define KMSPROPTEST_GETPROP 0
#define KMSPROPTEST_SETPROP 1
#define MOTUTIL_MAIN_DISP 0
#define MOTUTIL_CLI_DISP 1
int sde_debugfs_mot_util_init(struct sde_kms *sde_kms,
struct dentry *parent);
#endif /* __MOTUTIL_H__ */

View file

@ -63,7 +63,7 @@ static char sde_dsc_rc_range_min_qp[DSC_RATIO_TYPE_MAX][DSC_NUM_BUF_RANGES] = {
static char sde_dsc_rc_range_max_qp[DSC_RATIO_TYPE_MAX][DSC_NUM_BUF_RANGES] = {
/* DSC v1.1 */
{4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 11, 12, 13, 13, 15},
{4, 8, 9, 10, 11, 11, 11, 12, 13, 14, 15, 16, 17, 17, 19},
{8, 8, 9, 10, 11, 11, 11, 12, 13, 14, 15, 16, 17, 17, 19},
{7, 8, 9, 10, 11, 11, 11, 12, 13, 13, 14, 14, 15, 15, 16},
/* DSC v1.1 SCR and DSC v1.2 RGB 444 */
{4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 10, 11, 11, 12, 13},
@ -103,6 +103,71 @@ static char sde_dsc_rc_range_bpg[DSC_RATIO_TYPE_MAX][DSC_NUM_BUF_RANGES] = {
{10, 8, 6, 4, 2, 0, -2, -4, -6, -8, -10, -10, -12, -12, -12},
};
static char sde_dsc_rc_range_min_qp_nt[DSC_RATIO_TYPE_MAX][DSC_NUM_BUF_RANGES] = {
/* DSC v1.1 */
{0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 13},
{0, 4, 5, 5, 7, 7, 7, 7, 7, 8, 9, 9, 9, 12, 16},
{0, 4, 5, 6, 7, 7, 7, 7, 7, 7, 9, 9, 9, 11, 15},
/* DSC v1.1 SCR and DSC v1.2 RGB 444 */
{0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 9, 12},
{0, 4, 5, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 13, 16},
{0, 4, 5, 6, 7, 7, 7, 7, 7, 7, 9, 9, 9, 11, 15},
/* DSC v1.2 YUV422 */
{0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 10},
{0, 4, 5, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 13, 16},
{0, 4, 9, 9, 11, 11, 11, 11, 11, 11, 13, 13, 13, 17, 20},
{0, 2, 3, 4, 5, 5, 5, 6, 6, 7, 8, 8, 9, 11, 12},
/* DSC v1.2 YUV420 */
{0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 10},
{0, 2, 3, 4, 6, 7, 7, 7, 7, 7, 9, 9, 9, 11, 14},
{0, 2, 3, 4, 5, 5, 5, 6, 6, 7, 8, 8, 9, 11, 12},
};
/*
* Rate control - Max QP values for each ratio type in sde_dsc_ratio_type
*/
static char sde_dsc_rc_range_max_qp_nt[DSC_RATIO_TYPE_MAX][DSC_NUM_BUF_RANGES] = {
/* DSC v1.1 */
{4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 11, 12, 13, 13, 15},
{8, 8, 9, 10, 11, 11, 11, 12, 13, 14, 14, 15, 15, 16, 17},
{7, 8, 9, 10, 11, 11, 11, 12, 13, 13, 14, 14, 15, 15, 16},
/* DSC v1.1 SCR and DSC v1.2 RGB 444 */
{4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 10, 11, 11, 12, 13},
{8, 8, 9, 10, 11, 11, 11, 12, 13, 14, 14, 15, 15, 16, 17},
{7, 8, 9, 10, 11, 11, 11, 12, 13, 13, 14, 14, 15, 15, 16},
/* DSC v1.2 YUV422 */
{3, 4, 5, 6, 7, 7, 7, 8, 9, 9, 10, 10, 11, 11, 12},
{2, 4, 5, 6, 7, 7, 7, 8, 8, 9, 9, 9, 9, 10, 11},
{7, 8, 9, 10, 11, 11, 11, 12, 13, 13, 14, 14, 15, 15, 16},
{2, 5, 5, 6, 6, 7, 7, 8, 9, 9, 10, 11, 11, 12, 13},
/* DSC v1.2 YUV420 */
{2, 4, 5, 6, 7, 7, 7, 8, 8, 9, 9, 9, 9, 10, 12},
{2, 5, 7, 8, 9, 10, 11, 12, 12, 13, 13, 13, 13, 14, 15},
{2, 5, 5, 6, 6, 7, 7, 8, 9, 9, 10, 11, 11, 12, 13},
};
/*
* Rate control - bpg offset values for each ratio type in sde_dsc_ratio_type
*/
static char sde_dsc_rc_range_bpg_nt[DSC_RATIO_TYPE_MAX][DSC_NUM_BUF_RANGES] = {
/* DSC v1.1 */
{2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12},
{2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12},
{2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12},
/* DSC v1.1 SCR and DSC V1.2 RGB 444 */
{2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12},
{2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12},
{2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12},
/* DSC v1.2 YUV422 */
{2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12},
{2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12},
{2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12},
{10, 8, 6, 4, 2, 0, -2, -4, -6, -8, -10, -10, -12, -12, -12},
/* DSC v1.2 YUV420 */
{2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12},
{2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12},
{10, 8, 6, 4, 2, 0, -2, -4, -6, -8, -10, -10, -12, -12, -12},
};
/**
* Maps to lookup the sde_dsc_ratio_type index used in rate control tables
*/
@ -352,6 +417,148 @@ int sde_dsc_populate_dsc_config(struct drm_dsc_config *dsc, int scr_ver) {
return 0;
}
int sde_dsc_populate_dsc_config_nt(struct drm_dsc_config *dsc, int scr_ver) {
int bpp, bpc;
int groups_per_line, groups_total;
int min_rate_buffer_size;
int hrd_delay;
int pre_num_extra_mux_bits, num_extra_mux_bits;
int slice_bits;
int data;
int final_value, final_scale;
int i, ratio_idx;
dsc->rc_model_size = 8192;
if ((dsc->dsc_version_major == 0x1) &&
(dsc->dsc_version_minor == 0x1)) {
if (scr_ver == 0x1)
dsc->first_line_bpg_offset = 15;
else
dsc->first_line_bpg_offset = 13;
} else if (dsc->dsc_version_minor == 0x2) {
dsc->first_line_bpg_offset = _get_dsc_v1_2_bpg_offset(dsc);
}
dsc->rc_edge_factor = 6;
dsc->rc_tgt_offset_high = 3;
dsc->rc_tgt_offset_low = 3;
dsc->simple_422 = 0;
dsc->convert_rgb = 1;
dsc->vbr_enable = 0;
bpp = DSC_BPP(*dsc);
bpc = dsc->bits_per_component;
ratio_idx = _get_rc_table_index(dsc, scr_ver);
if (ratio_idx == -EINVAL)
return ratio_idx;
for (i = 0; i < DSC_NUM_BUF_RANGES - 1; i++)
dsc->rc_buf_thresh[i] = sde_dsc_rc_buf_thresh[i];
for (i = 0; i < DSC_NUM_BUF_RANGES; i++) {
dsc->rc_range_params[i].range_min_qp =
sde_dsc_rc_range_min_qp_nt[ratio_idx][i];
dsc->rc_range_params[i].range_max_qp =
sde_dsc_rc_range_max_qp_nt[ratio_idx][i];
dsc->rc_range_params[i].range_bpg_offset =
sde_dsc_rc_range_bpg_nt[ratio_idx][i];
}
if (bpp == 8) {
dsc->initial_offset = 6144;
dsc->initial_xmit_delay = 512;
} else if (bpp == 10) {
dsc->initial_offset = 5632;
dsc->initial_xmit_delay = 410;
} else {
dsc->initial_offset = 2048;
dsc->initial_xmit_delay = 341;
}
dsc->line_buf_depth = bpc + 1;
if (bpc == 8) {
dsc->flatness_min_qp = 3;
dsc->flatness_max_qp = 12;
dsc->rc_quant_incr_limit0 = 11;
dsc->rc_quant_incr_limit1 = 11;
dsc->mux_word_size = DSC_MUX_WORD_SIZE_8_10_BPC;
} else if (bpc == 10) { /* 10bpc */
dsc->flatness_min_qp = 7;
dsc->flatness_max_qp = 16;
dsc->rc_quant_incr_limit0 = 15;
dsc->rc_quant_incr_limit1 = 15;
dsc->mux_word_size = DSC_MUX_WORD_SIZE_8_10_BPC;
} else { /* 12 bpc */
dsc->flatness_min_qp = 11;
dsc->flatness_max_qp = 20;
dsc->rc_quant_incr_limit0 = 19;
dsc->rc_quant_incr_limit1 = 19;
dsc->mux_word_size = DSC_MUX_WORD_SIZE_12_BPC;
}
if ((dsc->dsc_version_minor == 0x2) && (dsc->native_420)) {
dsc->second_line_bpg_offset = 12;
dsc->second_line_offset_adj = 512;
dsc->nsl_bpg_offset = 2048 *
(DIV_ROUND_UP(dsc->second_line_bpg_offset,
(dsc->slice_height - 1)));
}
groups_per_line = DIV_ROUND_UP(dsc->slice_width, 3);
dsc->slice_chunk_size = dsc->slice_width * bpp / 8;
if ((dsc->slice_width * bpp) % 8)
dsc->slice_chunk_size++;
/* rbs-min */
min_rate_buffer_size = dsc->rc_model_size - dsc->initial_offset +
dsc->initial_xmit_delay * bpp +
groups_per_line * dsc->first_line_bpg_offset;
hrd_delay = DIV_ROUND_UP(min_rate_buffer_size, bpp);
dsc->initial_dec_delay = hrd_delay - dsc->initial_xmit_delay;
dsc->initial_scale_value = 8 * dsc->rc_model_size /
(dsc->rc_model_size - dsc->initial_offset);
slice_bits = 8 * dsc->slice_chunk_size * dsc->slice_height;
groups_total = groups_per_line * dsc->slice_height;
data = dsc->first_line_bpg_offset * 2048;
dsc->nfl_bpg_offset = DIV_ROUND_UP(data, (dsc->slice_height - 1));
pre_num_extra_mux_bits = 3 * (dsc->mux_word_size + (4 * bpc + 4) - 2);
num_extra_mux_bits = pre_num_extra_mux_bits - (dsc->mux_word_size -
((slice_bits - pre_num_extra_mux_bits) % dsc->mux_word_size));
data = 2048 * (dsc->rc_model_size - dsc->initial_offset
+ num_extra_mux_bits);
dsc->slice_bpg_offset = DIV_ROUND_UP(data, groups_total);
data = dsc->initial_xmit_delay * bpp;
final_value = dsc->rc_model_size - data + num_extra_mux_bits;
final_scale = 8 * dsc->rc_model_size /
(dsc->rc_model_size - final_value);
dsc->final_offset = final_value;
data = (final_scale - 9) * (dsc->nfl_bpg_offset +
dsc->slice_bpg_offset);
dsc->scale_increment_interval = (2048 * dsc->final_offset) / data;
dsc->scale_decrement_interval = groups_per_line /
(dsc->initial_scale_value - 8);
return 0;
}
int sde_dsc_populate_dsc_private_params(struct msm_display_dsc_info *dsc_info,
int intf_width)
{

View file

@ -18,5 +18,7 @@ int sde_dsc_populate_dsc_private_params(struct msm_display_dsc_info *dsc_info,
int sde_dsc_create_pps_buf_cmd(struct msm_display_dsc_info *dsc_info,
char *buf, int pps_id, u32 len);
int sde_dsc_populate_dsc_config_nt(struct drm_dsc_config *dsc, int scr_ver);
#endif /* __SDE_DSC_HELPER_H__ */