SDM845 has switched from dsi-staging to dsi driver. Removing stale code. Signed-off-by: Jeykumar Sankaran <jsanka@xxxxxxxxxxxxxx> --- .../config/arm64/chromiumos-arm64.flavour.config | 1 - .../arm64/chromiumos-qualcomm.flavour.config | 1 - drivers/gpu/drm/msm/Kconfig | 12 - drivers/gpu/drm/msm/Makefile | 21 - drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c | 241 -- drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h | 201 - drivers/gpu/drm/msm/dsi-staging/dsi_clk.h | 276 -- drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c | 1235 ------ drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c | 2846 ------------- drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h | 623 --- drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h | 752 ---- drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_1_4.c | 480 --- drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_2_0.c | 234 -- drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_2_2.c | 42 - drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c | 1312 ------ drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_reg.h | 196 - drivers/gpu/drm/msm/dsi-staging/dsi_defs.h | 579 --- drivers/gpu/drm/msm/dsi-staging/dsi_display.c | 4221 -------------------- drivers/gpu/drm/msm/dsi-staging/dsi_display.h | 556 --- drivers/gpu/drm/msm/dsi-staging/dsi_display_test.c | 114 - drivers/gpu/drm/msm/dsi-staging/dsi_display_test.h | 31 - drivers/gpu/drm/msm/dsi-staging/dsi_drm.c | 688 ---- drivers/gpu/drm/msm/dsi-staging/dsi_drm.h | 127 - drivers/gpu/drm/msm/dsi-staging/dsi_hw.h | 48 - drivers/gpu/drm/msm/dsi-staging/dsi_panel.c | 3321 --------------- drivers/gpu/drm/msm/dsi-staging/dsi_panel.h | 257 -- drivers/gpu/drm/msm/dsi-staging/dsi_phy.c | 937 ----- drivers/gpu/drm/msm/dsi-staging/dsi_phy.h | 235 -- drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h | 260 -- drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v2_0.c | 252 -- drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v3_0.c | 447 --- .../gpu/drm/msm/dsi-staging/dsi_phy_timing_calc.c | 676 ---- .../gpu/drm/msm/dsi-staging/dsi_phy_timing_calc.h | 144 - .../gpu/drm/msm/dsi-staging/dsi_phy_timing_v2_0.c | 126 - .../gpu/drm/msm/dsi-staging/dsi_phy_timing_v3_0.c | 107 - drivers/gpu/drm/msm/dsi-staging/dsi_pwr.c | 365 -- drivers/gpu/drm/msm/dsi-staging/dsi_pwr.h | 93 - 37 files changed, 22057 deletions(-) delete mode 100644 drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c delete mode 100644 drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h delete mode 100644 drivers/gpu/drm/msm/dsi-staging/dsi_clk.h delete mode 100644 drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c delete mode 100644 drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c delete mode 100644 drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h delete mode 100644 drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h delete mode 100644 drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_1_4.c delete mode 100644 drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_2_0.c delete mode 100644 drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_2_2.c delete mode 100644 drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c delete mode 100644 drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_reg.h delete mode 100644 drivers/gpu/drm/msm/dsi-staging/dsi_defs.h delete mode 100644 drivers/gpu/drm/msm/dsi-staging/dsi_display.c delete mode 100644 drivers/gpu/drm/msm/dsi-staging/dsi_display.h delete mode 100644 drivers/gpu/drm/msm/dsi-staging/dsi_display_test.c delete mode 100644 drivers/gpu/drm/msm/dsi-staging/dsi_display_test.h delete mode 100644 drivers/gpu/drm/msm/dsi-staging/dsi_drm.c delete mode 100644 drivers/gpu/drm/msm/dsi-staging/dsi_drm.h delete mode 100644 drivers/gpu/drm/msm/dsi-staging/dsi_hw.h delete mode 100644 drivers/gpu/drm/msm/dsi-staging/dsi_panel.c delete mode 100644 drivers/gpu/drm/msm/dsi-staging/dsi_panel.h delete mode 100644 drivers/gpu/drm/msm/dsi-staging/dsi_phy.c delete mode 100644 drivers/gpu/drm/msm/dsi-staging/dsi_phy.h delete mode 100644 drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h delete mode 100644 drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v2_0.c delete mode 100644 drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v3_0.c delete mode 100644 drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_calc.c delete mode 100644 drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_calc.h delete mode 100644 drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_v2_0.c delete mode 100644 drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_v3_0.c delete mode 100644 drivers/gpu/drm/msm/dsi-staging/dsi_pwr.c delete mode 100644 drivers/gpu/drm/msm/dsi-staging/dsi_pwr.h diff --git a/chromeos/config/arm64/chromiumos-arm64.flavour.config b/chromeos/config/arm64/chromiumos-arm64.flavour.config index 7b20c8b..dd6767e 100644 --- a/chromeos/config/arm64/chromiumos-arm64.flavour.config +++ b/chromeos/config/arm64/chromiumos-arm64.flavour.config @@ -117,7 +117,6 @@ CONFIG_DRM_MIPI_DSI=y CONFIG_DRM_MSM=y CONFIG_DRM_MSM_DPU=y CONFIG_DRM_MSM_DSI=y -# CONFIG_DRM_MSM_DSI_STAGING is not set # CONFIG_DRM_MSM_HDCP is not set # CONFIG_DRM_MSM_HDMI is not set # CONFIG_DRM_MSM_HDMI_HDCP is not set diff --git a/chromeos/config/arm64/chromiumos-qualcomm.flavour.config b/chromeos/config/arm64/chromiumos-qualcomm.flavour.config index aad22a7..3b38646 100644 --- a/chromeos/config/arm64/chromiumos-qualcomm.flavour.config +++ b/chromeos/config/arm64/chromiumos-qualcomm.flavour.config @@ -30,7 +30,6 @@ CONFIG_DRM_MIPI_DSI=y CONFIG_DRM_MSM=y CONFIG_DRM_MSM_DPU=y CONFIG_DRM_MSM_DSI=y -# CONFIG_DRM_MSM_DSI_STAGING is not set # CONFIG_DRM_MSM_HDCP is not set # CONFIG_DRM_MSM_HDMI is not set # CONFIG_DRM_MSM_HDMI_HDCP is not set diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig index 5f3bdf0..89e1b82 100644 --- a/drivers/gpu/drm/msm/Kconfig +++ b/drivers/gpu/drm/msm/Kconfig @@ -58,18 +58,6 @@ config DRM_MSM_DSI Choose this option if you have a need for MIPI DSI connector support. -config DRM_MSM_DSI_STAGING - bool "Enable new DSI driver support in MSM DRM driver" - depends on DRM_MSM - select DRM_PANEL - select DRM_MIPI_DSI - default y - help - Choose this option if you need MIPI DSI connector support on MSM - which conforms to DRM. MIPI stands for Mobile Industry Processor - Interface and DSI stands for Display Serial Interface which powers - the primary display of your mobile device. - config DRM_MSM_DSI_PLL bool "Enable DSI PLL driver in MSM DRM" depends on DRM_MSM_DSI && COMMON_CLK diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index a8d8ad9..fee2857 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -1,7 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 ccflags-y := -Idrivers/gpu/drm/msm ccflags-y += -Idrivers/gpu/drm/msm/disp/dpu1 -ccflags-y += -Idrivers/gpu/drm/msm/dsi-staging ccflags-$(CONFIG_DRM_MSM_DSI) += -Idrivers/gpu/drm/msm/dsi msm-y := \ @@ -144,26 +143,6 @@ msm-$(CONFIG_DRM_MSM_DSI_28NM_8960_PHY) += dsi/phy/dsi_phy_28nm_8960.o msm-$(CONFIG_DRM_MSM_DSI_14NM_PHY) += dsi/phy/dsi_phy_14nm.o msm-$(CONFIG_DRM_MSM_DSI_10NM_PHY) += dsi/phy/dsi_phy_10nm.o -msm-$(CONFIG_DRM_MSM_DSI_STAGING) += dsi-staging/dsi_phy.o \ - dsi-staging/dsi_pwr.o \ - dsi-staging/dsi_phy.o \ - dsi-staging/dsi_phy_hw_v2_0.o \ - dsi-staging/dsi_phy_hw_v3_0.o \ - dsi-staging/dsi_phy_timing_calc.o \ - dsi-staging/dsi_phy_timing_v2_0.o \ - dsi-staging/dsi_phy_timing_v3_0.o \ - dsi-staging/dsi_ctrl_hw_cmn.o \ - dsi-staging/dsi_ctrl_hw_1_4.o \ - dsi-staging/dsi_ctrl_hw_2_0.o \ - dsi-staging/dsi_ctrl_hw_2_2.o \ - dsi-staging/dsi_ctrl.o \ - dsi-staging/dsi_catalog.o \ - dsi-staging/dsi_drm.o \ - dsi-staging/dsi_display.o \ - dsi-staging/dsi_panel.o \ - dsi-staging/dsi_clk_manager.o \ - dsi-staging/dsi_display_test.o - msm-$(CONFIG_DRM_MSM_DSI_28NM_PHY) += dsi/phy/dsi_phy_28nm.o msm-$(CONFIG_DRM_MSM_DSI_20NM_PHY) += dsi/phy/dsi_phy_20nm.o msm-$(CONFIG_DRM_MSM_DSI_28NM_8960_PHY) += dsi/phy/dsi_phy_28nm_8960.o diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c deleted file mode 100644 index 3cb659a..0000000 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * 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) "msm-dsi-catalog:[%s] " fmt, __func__ -#include <linux/errno.h> - -#include "dsi_catalog.h" - -/** - * dsi_catalog_cmn_init() - catalog init for dsi controller v1.4 - */ -static void dsi_catalog_cmn_init(struct dsi_ctrl_hw *ctrl, - enum dsi_ctrl_version version) -{ - /* common functions */ - ctrl->ops.host_setup = dsi_ctrl_hw_cmn_host_setup; - ctrl->ops.video_engine_en = dsi_ctrl_hw_cmn_video_engine_en; - ctrl->ops.video_engine_setup = dsi_ctrl_hw_cmn_video_engine_setup; - ctrl->ops.set_video_timing = dsi_ctrl_hw_cmn_set_video_timing; - ctrl->ops.set_timing_db = dsi_ctrl_hw_cmn_set_timing_db; - ctrl->ops.cmd_engine_setup = dsi_ctrl_hw_cmn_cmd_engine_setup; - ctrl->ops.setup_cmd_stream = dsi_ctrl_hw_cmn_setup_cmd_stream; - ctrl->ops.ctrl_en = dsi_ctrl_hw_cmn_ctrl_en; - ctrl->ops.cmd_engine_en = dsi_ctrl_hw_cmn_cmd_engine_en; - ctrl->ops.phy_sw_reset = dsi_ctrl_hw_cmn_phy_sw_reset; - ctrl->ops.soft_reset = dsi_ctrl_hw_cmn_soft_reset; - ctrl->ops.kickoff_command = dsi_ctrl_hw_cmn_kickoff_command; - ctrl->ops.kickoff_fifo_command = dsi_ctrl_hw_cmn_kickoff_fifo_command; - ctrl->ops.reset_cmd_fifo = dsi_ctrl_hw_cmn_reset_cmd_fifo; - ctrl->ops.trigger_command_dma = dsi_ctrl_hw_cmn_trigger_command_dma; - ctrl->ops.get_interrupt_status = dsi_ctrl_hw_cmn_get_interrupt_status; - ctrl->ops.get_error_status = dsi_ctrl_hw_cmn_get_error_status; - ctrl->ops.clear_error_status = dsi_ctrl_hw_cmn_clear_error_status; - ctrl->ops.clear_interrupt_status = - dsi_ctrl_hw_cmn_clear_interrupt_status; - ctrl->ops.enable_status_interrupts = - dsi_ctrl_hw_cmn_enable_status_interrupts; - ctrl->ops.enable_error_interrupts = - dsi_ctrl_hw_cmn_enable_error_interrupts; - ctrl->ops.video_test_pattern_setup = - dsi_ctrl_hw_cmn_video_test_pattern_setup; - ctrl->ops.cmd_test_pattern_setup = - dsi_ctrl_hw_cmn_cmd_test_pattern_setup; - ctrl->ops.test_pattern_enable = dsi_ctrl_hw_cmn_test_pattern_enable; - ctrl->ops.trigger_cmd_test_pattern = - dsi_ctrl_hw_cmn_trigger_cmd_test_pattern; - ctrl->ops.clear_phy0_ln_err = dsi_ctrl_hw_dln0_phy_err; - ctrl->ops.phy_reset_config = dsi_ctrl_hw_cmn_phy_reset_config; - ctrl->ops.setup_misr = dsi_ctrl_hw_cmn_setup_misr; - ctrl->ops.collect_misr = dsi_ctrl_hw_cmn_collect_misr; - ctrl->ops.debug_bus = dsi_ctrl_hw_cmn_debug_bus; - - switch (version) { - case DSI_CTRL_VERSION_1_4: - ctrl->ops.setup_lane_map = dsi_ctrl_hw_14_setup_lane_map; - ctrl->ops.ulps_ops.ulps_request = dsi_ctrl_hw_14_ulps_request; - ctrl->ops.ulps_ops.ulps_exit = dsi_ctrl_hw_14_ulps_exit; - ctrl->ops.wait_for_lane_idle = - dsi_ctrl_hw_14_wait_for_lane_idle; - ctrl->ops.ulps_ops.get_lanes_in_ulps = - dsi_ctrl_hw_14_get_lanes_in_ulps; - ctrl->ops.clamp_enable = dsi_ctrl_hw_14_clamp_enable; - ctrl->ops.clamp_disable = dsi_ctrl_hw_14_clamp_disable; - ctrl->ops.reg_dump_to_buffer = - dsi_ctrl_hw_14_reg_dump_to_buffer; - break; - case DSI_CTRL_VERSION_2_0: - ctrl->ops.setup_lane_map = dsi_ctrl_hw_20_setup_lane_map; - ctrl->ops.wait_for_lane_idle = - dsi_ctrl_hw_20_wait_for_lane_idle; - ctrl->ops.reg_dump_to_buffer = - dsi_ctrl_hw_20_reg_dump_to_buffer; - ctrl->ops.ulps_ops.ulps_request = NULL; - ctrl->ops.ulps_ops.ulps_exit = NULL; - ctrl->ops.ulps_ops.get_lanes_in_ulps = NULL; - ctrl->ops.clamp_enable = NULL; - ctrl->ops.clamp_disable = NULL; - break; - case DSI_CTRL_VERSION_2_2: - ctrl->ops.phy_reset_config = dsi_ctrl_hw_22_phy_reset_config; - ctrl->ops.setup_lane_map = dsi_ctrl_hw_20_setup_lane_map; - ctrl->ops.wait_for_lane_idle = - dsi_ctrl_hw_20_wait_for_lane_idle; - ctrl->ops.reg_dump_to_buffer = - dsi_ctrl_hw_20_reg_dump_to_buffer; - ctrl->ops.ulps_ops.ulps_request = NULL; - ctrl->ops.ulps_ops.ulps_exit = NULL; - ctrl->ops.ulps_ops.get_lanes_in_ulps = NULL; - ctrl->ops.clamp_enable = NULL; - ctrl->ops.clamp_disable = NULL; - break; - default: - break; - } -} - -/** - * dsi_catalog_ctrl_setup() - return catalog info for dsi controller - * @ctrl: Pointer to DSI controller hw object. - * @version: DSI controller version. - * @index: DSI controller instance ID. - * @phy_isolation_enabled: DSI controller works isolated from phy. - * - * This function setups the catalog information in the dsi_ctrl_hw object. - * - * return: error code for failure and 0 for success. - */ -int dsi_catalog_ctrl_setup(struct dsi_ctrl_hw *ctrl, - enum dsi_ctrl_version version, u32 index, - bool phy_isolation_enabled) -{ - int rc = 0; - - if (version == DSI_CTRL_VERSION_UNKNOWN || - version >= DSI_CTRL_VERSION_MAX) { - pr_err("Unsupported version: %d\n", version); - return -ENOTSUPP; - } - - ctrl->index = index; - set_bit(DSI_CTRL_VIDEO_TPG, ctrl->feature_map); - set_bit(DSI_CTRL_CMD_TPG, ctrl->feature_map); - set_bit(DSI_CTRL_VARIABLE_REFRESH_RATE, ctrl->feature_map); - set_bit(DSI_CTRL_DYNAMIC_REFRESH, ctrl->feature_map); - set_bit(DSI_CTRL_DESKEW_CALIB, ctrl->feature_map); - set_bit(DSI_CTRL_DPHY, ctrl->feature_map); - - switch (version) { - case DSI_CTRL_VERSION_1_4: - dsi_catalog_cmn_init(ctrl, version); - break; - case DSI_CTRL_VERSION_2_0: - case DSI_CTRL_VERSION_2_2: - ctrl->phy_isolation_enabled = phy_isolation_enabled; - dsi_catalog_cmn_init(ctrl, version); - break; - default: - return -ENOTSUPP; - } - - return rc; -} - -/** - * dsi_catalog_phy_2_0_init() - catalog init for DSI PHY 14nm - */ -static void dsi_catalog_phy_2_0_init(struct dsi_phy_hw *phy) -{ - phy->ops.regulator_enable = dsi_phy_hw_v2_0_regulator_enable; - phy->ops.regulator_disable = dsi_phy_hw_v2_0_regulator_disable; - phy->ops.enable = dsi_phy_hw_v2_0_enable; - phy->ops.disable = dsi_phy_hw_v2_0_disable; - phy->ops.calculate_timing_params = - dsi_phy_hw_calculate_timing_params; - phy->ops.phy_idle_on = dsi_phy_hw_v2_0_idle_on; - phy->ops.phy_idle_off = dsi_phy_hw_v2_0_idle_off; - phy->ops.calculate_timing_params = - dsi_phy_hw_calculate_timing_params; - phy->ops.phy_timing_val = dsi_phy_hw_timing_val_v2_0; -} - -/** - * dsi_catalog_phy_3_0_init() - catalog init for DSI PHY 10nm - */ -static void dsi_catalog_phy_3_0_init(struct dsi_phy_hw *phy) -{ - phy->ops.regulator_enable = dsi_phy_hw_v3_0_regulator_enable; - phy->ops.regulator_disable = dsi_phy_hw_v3_0_regulator_disable; - phy->ops.enable = dsi_phy_hw_v3_0_enable; - phy->ops.disable = dsi_phy_hw_v3_0_disable; - phy->ops.calculate_timing_params = - dsi_phy_hw_calculate_timing_params; - phy->ops.ulps_ops.wait_for_lane_idle = - dsi_phy_hw_v3_0_wait_for_lane_idle; - phy->ops.ulps_ops.ulps_request = - dsi_phy_hw_v3_0_ulps_request; - phy->ops.ulps_ops.ulps_exit = - dsi_phy_hw_v3_0_ulps_exit; - phy->ops.ulps_ops.get_lanes_in_ulps = - dsi_phy_hw_v3_0_get_lanes_in_ulps; - phy->ops.ulps_ops.is_lanes_in_ulps = - dsi_phy_hw_v3_0_is_lanes_in_ulps; - phy->ops.phy_timing_val = dsi_phy_hw_timing_val_v3_0; -} - -/** - * dsi_catalog_phy_setup() - return catalog info for dsi phy hardware - * @ctrl: Pointer to DSI PHY hw object. - * @version: DSI PHY version. - * @index: DSI PHY instance ID. - * - * This function setups the catalog information in the dsi_phy_hw object. - * - * return: error code for failure and 0 for success. - */ -int dsi_catalog_phy_setup(struct dsi_phy_hw *phy, - enum dsi_phy_version version, - u32 index) -{ - int rc = 0; - - if (version == DSI_PHY_VERSION_UNKNOWN || - version >= DSI_PHY_VERSION_MAX) { - pr_err("Unsupported version: %d\n", version); - return -ENOTSUPP; - } - - phy->index = index; - set_bit(DSI_PHY_DPHY, phy->feature_map); - - dsi_phy_timing_calc_init(phy, version); - - switch (version) { - case DSI_PHY_VERSION_2_0: - dsi_catalog_phy_2_0_init(phy); - break; - case DSI_PHY_VERSION_3_0: - dsi_catalog_phy_3_0_init(phy); - break; - case DSI_PHY_VERSION_0_0_HPM: - case DSI_PHY_VERSION_0_0_LPM: - case DSI_PHY_VERSION_1_0: - default: - return -ENOTSUPP; - } - - return rc; -} - - diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h deleted file mode 100644 index 0a46ae0..0000000 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * 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 _DSI_CATALOG_H_ -#define _DSI_CATALOG_H_ - -#include "dsi_ctrl_hw.h" -#include "dsi_phy_hw.h" - -/** - * dsi_catalog_ctrl_setup() - return catalog info for dsi controller - * @ctrl: Pointer to DSI controller hw object. - * @version: DSI controller version. - * @index: DSI controller instance ID. - * @phy_isolation_enabled: DSI controller works isolated from phy. - * - * This function setups the catalog information in the dsi_ctrl_hw object. - * - * return: error code for failure and 0 for success. - */ -int dsi_catalog_ctrl_setup(struct dsi_ctrl_hw *ctrl, - enum dsi_ctrl_version version, u32 index, - bool phy_isolation_enabled); - -/** - * dsi_catalog_phy_setup() - return catalog info for dsi phy hardware - * @phy: Pointer to DSI PHY hw object. - * @version: DSI PHY version. - * @index: DSI PHY instance ID. - * - * This function setups the catalog information in the dsi_phy_hw object. - * - * return: error code for failure and 0 for success. - */ -int dsi_catalog_phy_setup(struct dsi_phy_hw *phy, - enum dsi_phy_version version, - u32 index); - -/** - * dsi_phy_timing_calc_init() - initialize info for DSI PHY timing calculations - * @phy: Pointer to DSI PHY hw object. - * @version: DSI PHY version. - * - * This function setups the catalog information in the dsi_phy_hw object. - * - * return: error code for failure and 0 for success. - */ -int dsi_phy_timing_calc_init(struct dsi_phy_hw *phy, - enum dsi_phy_version version); - -/** - * dsi_phy_hw_calculate_timing_params() - DSI PHY timing parameter calculations - * @phy: Pointer to DSI PHY hw object. - * @mode: DSI mode information. - * @host: DSI host configuration. - * @timing: DSI phy lane configurations. - * - * This function setups the catalog information in the dsi_phy_hw object. - * - * return: error code for failure and 0 for success. - */ -int dsi_phy_hw_calculate_timing_params(struct dsi_phy_hw *phy, - struct dsi_mode_info *mode, - struct dsi_host_common_cfg *host, - struct dsi_phy_per_lane_cfgs *timing); - -/* Definitions for 14nm PHY hardware driver */ -void dsi_phy_hw_v2_0_regulator_enable(struct dsi_phy_hw *phy, - struct dsi_phy_per_lane_cfgs *cfg); -void dsi_phy_hw_v2_0_regulator_disable(struct dsi_phy_hw *phy); -void dsi_phy_hw_v2_0_enable(struct dsi_phy_hw *phy, struct dsi_phy_cfg *cfg); -void dsi_phy_hw_v2_0_disable(struct dsi_phy_hw *phy, struct dsi_phy_cfg *cfg); -void dsi_phy_hw_v2_0_idle_on(struct dsi_phy_hw *phy, struct dsi_phy_cfg *cfg); -void dsi_phy_hw_v2_0_idle_off(struct dsi_phy_hw *phy); -int dsi_phy_hw_timing_val_v2_0(struct dsi_phy_per_lane_cfgs *timing_cfg, - u32 *timing_val, u32 size); - -/* Definitions for 10nm PHY hardware driver */ -void dsi_phy_hw_v3_0_regulator_enable(struct dsi_phy_hw *phy, - struct dsi_phy_per_lane_cfgs *cfg); -void dsi_phy_hw_v3_0_regulator_disable(struct dsi_phy_hw *phy); -void dsi_phy_hw_v3_0_enable(struct dsi_phy_hw *phy, struct dsi_phy_cfg *cfg); -void dsi_phy_hw_v3_0_disable(struct dsi_phy_hw *phy, struct dsi_phy_cfg *cfg); -int dsi_phy_hw_v3_0_wait_for_lane_idle(struct dsi_phy_hw *phy, u32 lanes); -void dsi_phy_hw_v3_0_ulps_request(struct dsi_phy_hw *phy, - struct dsi_phy_cfg *cfg, u32 lanes); -void dsi_phy_hw_v3_0_ulps_exit(struct dsi_phy_hw *phy, - struct dsi_phy_cfg *cfg, u32 lanes); -u32 dsi_phy_hw_v3_0_get_lanes_in_ulps(struct dsi_phy_hw *phy); -bool dsi_phy_hw_v3_0_is_lanes_in_ulps(u32 lanes, u32 ulps_lanes); -int dsi_phy_hw_timing_val_v3_0(struct dsi_phy_per_lane_cfgs *timing_cfg, - u32 *timing_val, u32 size); - -/* DSI controller common ops */ -u32 dsi_ctrl_hw_cmn_get_interrupt_status(struct dsi_ctrl_hw *ctrl); -void dsi_ctrl_hw_cmn_debug_bus(struct dsi_ctrl_hw *ctrl); -void dsi_ctrl_hw_cmn_clear_interrupt_status(struct dsi_ctrl_hw *ctrl, u32 ints); -void dsi_ctrl_hw_cmn_enable_status_interrupts(struct dsi_ctrl_hw *ctrl, - u32 ints); - -u64 dsi_ctrl_hw_cmn_get_error_status(struct dsi_ctrl_hw *ctrl); -void dsi_ctrl_hw_cmn_clear_error_status(struct dsi_ctrl_hw *ctrl, u64 errors); -void dsi_ctrl_hw_cmn_enable_error_interrupts(struct dsi_ctrl_hw *ctrl, - u64 errors); - -void dsi_ctrl_hw_cmn_video_test_pattern_setup(struct dsi_ctrl_hw *ctrl, - enum dsi_test_pattern type, - u32 init_val); -void dsi_ctrl_hw_cmn_cmd_test_pattern_setup(struct dsi_ctrl_hw *ctrl, - enum dsi_test_pattern type, - u32 init_val, - u32 stream_id); -void dsi_ctrl_hw_cmn_test_pattern_enable(struct dsi_ctrl_hw *ctrl, bool enable); -void dsi_ctrl_hw_cmn_trigger_cmd_test_pattern(struct dsi_ctrl_hw *ctrl, - u32 stream_id); - -void dsi_ctrl_hw_cmn_host_setup(struct dsi_ctrl_hw *ctrl, - struct dsi_host_common_cfg *config); -void dsi_ctrl_hw_cmn_video_engine_en(struct dsi_ctrl_hw *ctrl, bool on); -void dsi_ctrl_hw_cmn_video_engine_setup(struct dsi_ctrl_hw *ctrl, - struct dsi_host_common_cfg *common_cfg, - struct dsi_video_engine_cfg *cfg); -void dsi_ctrl_hw_cmn_set_video_timing(struct dsi_ctrl_hw *ctrl, - struct dsi_mode_info *mode); -void dsi_ctrl_hw_cmn_set_timing_db(struct dsi_ctrl_hw *ctrl, - bool enable); -void dsi_ctrl_hw_cmn_cmd_engine_setup(struct dsi_ctrl_hw *ctrl, - struct dsi_host_common_cfg *common_cfg, - struct dsi_cmd_engine_cfg *cfg); - -void dsi_ctrl_hw_cmn_ctrl_en(struct dsi_ctrl_hw *ctrl, bool on); -void dsi_ctrl_hw_cmn_cmd_engine_en(struct dsi_ctrl_hw *ctrl, bool on); - -void dsi_ctrl_hw_cmn_setup_cmd_stream(struct dsi_ctrl_hw *ctrl, - struct dsi_mode_info *mode, - u32 h_stride, - u32 vc_id, - struct dsi_rect *roi); -void dsi_ctrl_hw_cmn_phy_sw_reset(struct dsi_ctrl_hw *ctrl); -void dsi_ctrl_hw_cmn_soft_reset(struct dsi_ctrl_hw *ctrl); - -void dsi_ctrl_hw_cmn_setup_misr(struct dsi_ctrl_hw *ctrl, - enum dsi_op_mode panel_mode, - bool enable, u32 frame_count); -u32 dsi_ctrl_hw_cmn_collect_misr(struct dsi_ctrl_hw *ctrl, - enum dsi_op_mode panel_mode); - -void dsi_ctrl_hw_cmn_kickoff_command(struct dsi_ctrl_hw *ctrl, - struct dsi_ctrl_cmd_dma_info *cmd, - u32 flags); - -void dsi_ctrl_hw_cmn_kickoff_fifo_command(struct dsi_ctrl_hw *ctrl, - struct dsi_ctrl_cmd_dma_fifo_info *cmd, - u32 flags); -void dsi_ctrl_hw_cmn_reset_cmd_fifo(struct dsi_ctrl_hw *ctrl); -void dsi_ctrl_hw_cmn_trigger_command_dma(struct dsi_ctrl_hw *ctrl); -void dsi_ctrl_hw_dln0_phy_err(struct dsi_ctrl_hw *ctrl); -void dsi_ctrl_hw_cmn_phy_reset_config(struct dsi_ctrl_hw *ctrl, - bool enable); -void dsi_ctrl_hw_22_phy_reset_config(struct dsi_ctrl_hw *ctrl, - bool enable); - -/* Definitions specific to 1.4 DSI controller hardware */ -int dsi_ctrl_hw_14_wait_for_lane_idle(struct dsi_ctrl_hw *ctrl, u32 lanes); -void dsi_ctrl_hw_14_setup_lane_map(struct dsi_ctrl_hw *ctrl, - struct dsi_lane_map *lane_map); -void dsi_ctrl_hw_14_ulps_request(struct dsi_ctrl_hw *ctrl, u32 lanes); -void dsi_ctrl_hw_14_ulps_exit(struct dsi_ctrl_hw *ctrl, u32 lanes); -u32 dsi_ctrl_hw_14_get_lanes_in_ulps(struct dsi_ctrl_hw *ctrl); - -void dsi_ctrl_hw_14_clamp_enable(struct dsi_ctrl_hw *ctrl, - u32 lanes, - bool enable_ulps); - -void dsi_ctrl_hw_14_clamp_disable(struct dsi_ctrl_hw *ctrl, - u32 lanes, - bool disable_ulps); -ssize_t dsi_ctrl_hw_14_reg_dump_to_buffer(struct dsi_ctrl_hw *ctrl, - char *buf, - u32 size); - -/* Definitions specific to 2.0 DSI controller hardware */ -void dsi_ctrl_hw_20_setup_lane_map(struct dsi_ctrl_hw *ctrl, - struct dsi_lane_map *lane_map); -int dsi_ctrl_hw_20_wait_for_lane_idle(struct dsi_ctrl_hw *ctrl, u32 lanes); -ssize_t dsi_ctrl_hw_20_reg_dump_to_buffer(struct dsi_ctrl_hw *ctrl, - char *buf, - u32 size); - -#endif /* _DSI_CATALOG_H_ */ diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_clk.h b/drivers/gpu/drm/msm/dsi-staging/dsi_clk.h deleted file mode 100644 index 38fca04..0000000 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_clk.h +++ /dev/null @@ -1,276 +0,0 @@ -/* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * 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 _DSI_CLK_H_ -#define _DSI_CLK_H_ - -#include <linux/device.h> -#include <linux/platform_device.h> -#include <linux/types.h> -#include <linux/clk.h> -#include "dpu_power_handle.h" - -#define MAX_STRING_LEN 32 -#define MAX_DSI_CTRL 2 - -enum dsi_clk_state { - DSI_CLK_OFF, - DSI_CLK_ON, - DSI_CLK_EARLY_GATE, -}; - -enum clk_req_client { - DSI_CLK_REQ_MDP_CLIENT = 0, - DSI_CLK_REQ_DSI_CLIENT, -}; - -enum dsi_link_clk_type { - DSI_LINK_ESC_CLK, - DSI_LINK_BYTE_CLK, - DSI_LINK_PIX_CLK, - DSI_LINK_BYTE_INTF_CLK, - DSI_LINK_CLK_MAX, -}; - -enum dsi_clk_type { - DSI_CORE_CLK = BIT(0), - DSI_LINK_CLK = BIT(1), - DSI_ALL_CLKS = (BIT(0) | BIT(1)), - DSI_CLKS_MAX = BIT(2), -}; - -struct dsi_clk_ctrl_info { - enum dsi_clk_type clk_type; - enum dsi_clk_state clk_state; - enum clk_req_client client; -}; - -struct clk_ctrl_cb { - void *priv; - int (*dsi_clk_cb)(void *priv, struct dsi_clk_ctrl_info clk_ctrl_info); -}; - -/** - * struct dsi_core_clk_info - Core clock information for DSI hardware - * @mdp_core_clk: Handle to MDP core clock. - * @iface_clk: Handle to MDP interface clock. - * @core_mmss_clk: Handle to MMSS core clock. - * @bus_clk: Handle to bus clock. - * @mnoc_clk: Handle to MMSS NOC clock. - * @dsi_core_client: Pointer to DPU power client - * @phandle: Pointer to DPU power handle - */ -struct dsi_core_clk_info { - struct clk *mdp_core_clk; - struct clk *iface_clk; - struct clk *core_mmss_clk; - struct clk *bus_clk; - struct clk *mnoc_clk; - struct dpu_power_client *dsi_core_client; - struct dpu_power_handle *phandle; -}; - -/** - * struct dsi_link_clk_info - Link clock information for DSI hardware. - * @byte_clk: Handle to DSI byte clock. - * @pixel_clk: Handle to DSI pixel clock. - * @esc_clk: Handle to DSI escape clock. - * @byte_intf_clk: Handle to DSI byte intf. clock. - */ -struct dsi_link_clk_info { - struct clk *byte_clk; - struct clk *pixel_clk; - struct clk *esc_clk; - struct clk *byte_intf_clk; -}; - -/** - * struct link_clk_freq - Clock frequency information for Link clocks - * @byte_clk_rate: Frequency of DSI byte clock in KHz. - * @pixel_clk_rate: Frequency of DSI pixel clock in KHz. - * @esc_clk_rate: Frequency of DSI escape clock in KHz. - */ -struct link_clk_freq { - u32 byte_clk_rate; - u32 pix_clk_rate; - u32 esc_clk_rate; -}; - -/** - * typedef *pre_clockoff_cb() - Callback before clock is turned off - * @priv: private data pointer. - * @clk_type: clock which is being turned off. - * @new_state: next state for the clock. - * - * @return: error code. - */ -typedef int (*pre_clockoff_cb)(void *priv, - enum dsi_clk_type clk_type, - enum dsi_clk_state new_state); - -/** - * typedef *post_clockoff_cb() - Callback after clock is turned off - * @priv: private data pointer. - * @clk_type: clock which was turned off. - * @curr_state: current state for the clock. - * - * @return: error code. - */ -typedef int (*post_clockoff_cb)(void *priv, - enum dsi_clk_type clk_type, - enum dsi_clk_state curr_state); - -/** - * typedef *post_clockon_cb() - Callback after clock is turned on - * @priv: private data pointer. - * @clk_type: clock which was turned on. - * @curr_state: current state for the clock. - * - * @return: error code. - */ -typedef int (*post_clockon_cb)(void *priv, - enum dsi_clk_type clk_type, - enum dsi_clk_state curr_state); - -/** - * typedef *pre_clockon_cb() - Callback before clock is turned on - * @priv: private data pointer. - * @clk_type: clock which is being turned on. - * @new_state: next state for the clock. - * - * @return: error code. - */ -typedef int (*pre_clockon_cb)(void *priv, - enum dsi_clk_type clk_type, - enum dsi_clk_state new_state); - - -/** - * struct dsi_clk_info - clock information for DSI hardware. - * @name: client name. - * @c_clks[MAX_DSI_CTRL] array of core clock configurations - * @l_clks[MAX_DSI_CTRL] array of link clock configurations - * @bus_handle[MAX_DSI_CTRL] array of bus handles - * @ctrl_index[MAX_DSI_CTRL] array of DSI controller indexes mapped - * to core and link clock configurations - * @pre_clkoff_cb callback before clock is turned off - * @post_clkoff_cb callback after clock is turned off - * @post_clkon_cb callback after clock is turned on - * @pre_clkon_cb callback before clock is turned on - * @priv_data pointer to private data - * @master_ndx master DSI controller index - * @dsi_ctrl_count number of DSI controllers - */ -struct dsi_clk_info { - char name[MAX_STRING_LEN]; - struct dsi_core_clk_info c_clks[MAX_DSI_CTRL]; - struct dsi_link_clk_info l_clks[MAX_DSI_CTRL]; - u32 bus_handle[MAX_DSI_CTRL]; - u32 ctrl_index[MAX_DSI_CTRL]; - pre_clockoff_cb pre_clkoff_cb; - post_clockoff_cb post_clkoff_cb; - post_clockon_cb post_clkon_cb; - pre_clockon_cb pre_clkon_cb; - void *priv_data; - u32 master_ndx; - u32 dsi_ctrl_count; -}; - -/** - * struct dsi_clk_link_set - Pair of clock handles to describe link clocks - * @byte_clk: Handle to DSi byte clock. - * @pixel_clk: Handle to DSI pixel clock. - */ -struct dsi_clk_link_set { - struct clk *byte_clk; - struct clk *pixel_clk; -}; - -/** - * dsi_display_clk_mgr_register() - Register DSI clock manager - * @info: Structure containing DSI clock information - */ -void *dsi_display_clk_mngr_register(struct dsi_clk_info *info); - -/** - * dsi_display_clk_mngr_deregister() - Deregister DSI clock manager - * @clk_mngr: DSI clock manager pointer - */ -int dsi_display_clk_mngr_deregister(void *clk_mngr); - -/** - * dsi_register_clk_handle() - Register clock handle with DSI clock manager - * @clk_mngr: DSI clock manager pointer - * @client: DSI clock client pointer. - */ -void *dsi_register_clk_handle(void *clk_mngr, char *client); - -/** - * dsi_deregister_clk_handle() - Deregister clock handle from DSI clock manager - * @client: DSI clock client pointer. - * - * return: error code in case of failure or 0 for success. - */ -int dsi_deregister_clk_handle(void *client); - -/** - * dsi_display_clk_ctrl() - set frequencies for link clks - * @handle: Handle of desired DSI clock client. - * @clk_type: Clock which is being controlled. - * @clk_state: Desired state of clock - * - * return: error code in case of failure or 0 for success. - */ -int dsi_display_clk_ctrl(void *handle, - enum dsi_clk_type clk_type, enum dsi_clk_state clk_state); - -/** - * dsi_clk_set_link_frequencies() - set frequencies for link clks - * @client: DSI clock client pointer. - * @freq: Structure containing link clock frequencies. - * @index: Index of the DSI controller. - * - * return: error code in case of failure or 0 for success. - */ -int dsi_clk_set_link_frequencies(void *client, struct link_clk_freq freq, - u32 index); - - -/** - * dsi_clk_set_pixel_clk_rate() - set frequency for pixel clock - * @client: DSI clock client pointer. - * @pixel_clk: Pixel clock rate in Hz. - * @index: Index of the DSI controller. - * return: error code in case of failure or 0 for success. - */ -int dsi_clk_set_pixel_clk_rate(void *client, u64 pixel_clk, u32 index); - - -/** - * dsi_clk_set_byte_clk_rate() - set frequency for byte clock - * @client: DSI clock client pointer. - * @byte_clk: Pixel clock rate in Hz. - * @index: Index of the DSI controller. - * return: error code in case of failure or 0 for success. - */ -int dsi_clk_set_byte_clk_rate(void *client, u64 byte_clk, u32 index); - -/** - * dsi_clk_update_parent() - update parent clocks for specified clock - * @parent: link clock pair which are set as parent. - * @child: link clock pair whose parent has to be set. - */ -int dsi_clk_update_parent(struct dsi_clk_link_set *parent, - struct dsi_clk_link_set *child); -#endif /* _DSI_CLK_H_ */ diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c b/drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c deleted file mode 100644 index 047f759..0000000 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c +++ /dev/null @@ -1,1235 +0,0 @@ -/* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * 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/of.h> -#include <linux/delay.h> -#include <linux/slab.h> -#include "dsi_clk.h" - -#ifdef CONFIG_QCOM_BUS_SCALING -#include <linux/msm-bus.h> -#endif - -struct dsi_core_clks { - struct dsi_core_clk_info clks; - u32 bus_handle; -}; - -struct dsi_link_clks { - struct dsi_link_clk_info clks; - struct link_clk_freq freq; -}; - -struct dsi_clk_mngr { - char name[MAX_STRING_LEN]; - struct mutex clk_mutex; - struct list_head client_list; - - u32 dsi_ctrl_count; - u32 master_ndx; - struct dsi_core_clks core_clks[MAX_DSI_CTRL]; - struct dsi_link_clks link_clks[MAX_DSI_CTRL]; - u32 ctrl_index[MAX_DSI_CTRL]; - u32 core_clk_state; - u32 link_clk_state; - - pre_clockoff_cb pre_clkoff_cb; - post_clockoff_cb post_clkoff_cb; - post_clockon_cb post_clkon_cb; - pre_clockon_cb pre_clkon_cb; - - void *priv_data; -}; - -struct dsi_clk_client_info { - char name[MAX_STRING_LEN]; - u32 core_refcount; - u32 link_refcount; - u32 core_clk_state; - u32 link_clk_state; - struct list_head list; - struct dsi_clk_mngr *mngr; -}; - -static int _get_clk_mngr_index(struct dsi_clk_mngr *mngr, - u32 dsi_ctrl_index, - u32 *clk_mngr_index) -{ - int i; - - for (i = 0; i < mngr->dsi_ctrl_count; i++) { - if (mngr->ctrl_index[i] == dsi_ctrl_index) { - *clk_mngr_index = i; - return 0; - } - } - - return -EINVAL; -} - -/** - * dsi_clk_set_link_frequencies() - set frequencies for link clks - * @clks: Link clock information - * @pixel_clk: pixel clock frequency in KHz. - * @byte_clk: Byte clock frequency in KHz. - * @esc_clk: Escape clock frequency in KHz. - * - * return: error code in case of failure or 0 for success. - */ -int dsi_clk_set_link_frequencies(void *client, struct link_clk_freq freq, - u32 index) -{ - int rc = 0, clk_mngr_index = 0; - struct dsi_clk_client_info *c = client; - struct dsi_clk_mngr *mngr; - - if (!client) { - pr_err("invalid params\n"); - return -EINVAL; - } - - mngr = c->mngr; - rc = _get_clk_mngr_index(mngr, index, &clk_mngr_index); - if (rc) { - pr_err("failed to map control index %d\n", index); - return -EINVAL; - } - - memcpy(&mngr->link_clks[clk_mngr_index].freq, &freq, - sizeof(struct link_clk_freq)); - - return rc; -} - -/** - * dsi_clk_set_pixel_clk_rate() - set frequency for pixel clock - * @clks: DSI link clock information. - * @pixel_clk: Pixel clock rate in KHz. - * - * return: error code in case of failure or 0 for success. - */ -int dsi_clk_set_pixel_clk_rate(void *client, u64 pixel_clk, u32 index) -{ - int rc = 0; - struct dsi_clk_client_info *c = client; - struct dsi_clk_mngr *mngr; - - mngr = c->mngr; - rc = clk_set_rate(mngr->link_clks[index].clks.pixel_clk, pixel_clk); - if (rc) - pr_err("failed to set clk rate for pixel clk, rc=%d\n", rc); - else - mngr->link_clks[index].freq.pix_clk_rate = pixel_clk; - - return rc; -} - -/** - * dsi_clk_set_byte_clk_rate() - set frequency for byte clock - * @client: DSI clock client pointer. - * @byte_clk: Pixel clock rate in Hz. - * @index: Index of the DSI controller. - * return: error code in case of failure or 0 for success. - */ -int dsi_clk_set_byte_clk_rate(void *client, u64 byte_clk, u32 index) -{ - int rc = 0; - struct dsi_clk_client_info *c = client; - struct dsi_clk_mngr *mngr; - - mngr = c->mngr; - rc = clk_set_rate(mngr->link_clks[index].clks.byte_clk, byte_clk); - if (rc) - pr_err("failed to set clk rate for byte clk, rc=%d\n", rc); - else - mngr->link_clks[index].freq.byte_clk_rate = byte_clk; - - return rc; - -} - -/** - * dsi_clk_update_parent() - update parent clocks for specified clock - * @parent: link clock pair which are set as parent. - * @child: link clock pair whose parent has to be set. - */ -int dsi_clk_update_parent(struct dsi_clk_link_set *parent, - struct dsi_clk_link_set *child) -{ - int rc = 0; - - rc = clk_set_parent(child->byte_clk, parent->byte_clk); - if (rc) { - pr_err("failed to set byte clk parent\n"); - goto error; - } - - rc = clk_set_parent(child->pixel_clk, parent->pixel_clk); - if (rc) { - pr_err("failed to set pixel clk parent\n"); - goto error; - } -error: - return rc; -} - -int dsi_core_clk_start(struct dsi_core_clks *c_clks) -{ - int rc = 0; - - if (c_clks->clks.mdp_core_clk) { - rc = clk_prepare_enable(c_clks->clks.mdp_core_clk); - if (rc) { - pr_err("failed to enable mdp_core_clk, rc=%d\n", rc); - goto error; - } - } - - if (c_clks->clks.mnoc_clk) { - rc = clk_prepare_enable(c_clks->clks.mnoc_clk); - if (rc) { - pr_err("failed to enable mnoc_clk, rc=%d\n", rc); - goto error_disable_core_clk; - } - } - - if (c_clks->clks.iface_clk) { - rc = clk_prepare_enable(c_clks->clks.iface_clk); - if (rc) { - pr_err("failed to enable iface_clk, rc=%d\n", rc); - goto error_disable_mnoc_clk; - } - } - - if (c_clks->clks.bus_clk) { - rc = clk_prepare_enable(c_clks->clks.bus_clk); - if (rc) { - pr_err("failed to enable bus_clk, rc=%d\n", rc); - goto error_disable_iface_clk; - } - } - - if (c_clks->clks.core_mmss_clk) { - rc = clk_prepare_enable(c_clks->clks.core_mmss_clk); - if (rc) { - pr_err("failed to enable core_mmss_clk, rc=%d\n", rc); - goto error_disable_bus_clk; - } - } - -#ifdef CONFIG_QCOM_BUS_SCALING - if (c_clks->bus_handle) { - rc = msm_bus_scale_client_update_request(c_clks->bus_handle, 1); - if (rc) { - pr_err("bus scale client enable failed, rc=%d\n", rc); - goto error_disable_mmss_clk; - } - } -#endif - return rc; - -#ifdef CONFIG_QCOM_BUS_SCALING -error_disable_mmss_clk: - if (c_clks->clks.core_mmss_clk) - clk_disable_unprepare(c_clks->clks.core_mmss_clk); -#endif - -error_disable_bus_clk: - if (c_clks->clks.bus_clk) - clk_disable_unprepare(c_clks->clks.bus_clk); -error_disable_iface_clk: - if (c_clks->clks.iface_clk) - clk_disable_unprepare(c_clks->clks.iface_clk); -error_disable_mnoc_clk: - if (c_clks->clks.mnoc_clk) - clk_disable_unprepare(c_clks->clks.mnoc_clk); -error_disable_core_clk: - if (c_clks->clks.mdp_core_clk) - clk_disable_unprepare(c_clks->clks.mdp_core_clk); -error: - return rc; -} - -int dsi_core_clk_stop(struct dsi_core_clks *c_clks) -{ - int rc = 0; - -#ifdef CONFIG_QCOM_BUS_SCALING - if (c_clks->bus_handle) { - rc = msm_bus_scale_client_update_request(c_clks->bus_handle, 0); - if (rc) { - pr_err("bus scale client disable failed, rc=%d\n", rc); - return rc; - } - } -#endif - - if (c_clks->clks.core_mmss_clk) - clk_disable_unprepare(c_clks->clks.core_mmss_clk); - - if (c_clks->clks.bus_clk) - clk_disable_unprepare(c_clks->clks.bus_clk); - - if (c_clks->clks.iface_clk) - clk_disable_unprepare(c_clks->clks.iface_clk); - - if (c_clks->clks.mnoc_clk) - clk_disable_unprepare(c_clks->clks.mnoc_clk); - - if (c_clks->clks.mdp_core_clk) - clk_disable_unprepare(c_clks->clks.mdp_core_clk); - - return rc; -} - -static int dsi_link_clk_set_rate(struct dsi_link_clks *l_clks) -{ - int rc = 0; - - rc = clk_set_rate(l_clks->clks.esc_clk, l_clks->freq.esc_clk_rate); - if (rc) { - pr_err("clk_set_rate failed for esc_clk rc = %d\n", rc); - goto error; - } - - rc = clk_set_rate(l_clks->clks.byte_clk, l_clks->freq.byte_clk_rate); - if (rc) { - pr_err("clk_set_rate failed for byte_clk rc = %d\n", rc); - goto error; - } - - rc = clk_set_rate(l_clks->clks.pixel_clk, l_clks->freq.pix_clk_rate); - if (rc) { - pr_err("clk_set_rate failed for pixel_clk rc = %d\n", rc); - goto error; - } - - /* - * If byte_intf_clk is present, set rate for that too. - * For DPHY: byte_intf_clk_rate = byte_clk_rate / 2 - * todo: this needs to be revisited when support for CPHY is added - */ - if (l_clks->clks.byte_intf_clk) { - rc = clk_set_rate(l_clks->clks.byte_intf_clk, - (l_clks->freq.byte_clk_rate / 2)); - if (rc) { - pr_err("set_rate failed for byte_intf_clk rc = %d\n", - rc); - goto error; - } - } -error: - return rc; -} - -static int dsi_link_clk_prepare(struct dsi_link_clks *l_clks) -{ - int rc = 0; - - rc = clk_prepare(l_clks->clks.esc_clk); - if (rc) { - pr_err("Failed to prepare dsi esc clk, rc=%d\n", rc); - goto esc_clk_err; - } - - rc = clk_prepare(l_clks->clks.byte_clk); - if (rc) { - pr_err("Failed to prepare dsi byte clk, rc=%d\n", rc); - goto byte_clk_err; - } - - rc = clk_prepare(l_clks->clks.pixel_clk); - if (rc) { - pr_err("Failed to prepare dsi pixel clk, rc=%d\n", rc); - goto pixel_clk_err; - } - - if (l_clks->clks.byte_intf_clk) { - rc = clk_prepare(l_clks->clks.byte_intf_clk); - if (rc) { - pr_err("Failed to prepare dsi byte intf clk, rc=%d\n", - rc); - goto byte_intf_clk_err; - } - } - - return rc; - -byte_intf_clk_err: - clk_unprepare(l_clks->clks.pixel_clk); -pixel_clk_err: - clk_unprepare(l_clks->clks.byte_clk); -byte_clk_err: - clk_unprepare(l_clks->clks.esc_clk); -esc_clk_err: - return rc; -} - -static void dsi_link_clk_unprepare(struct dsi_link_clks *l_clks) -{ - if (l_clks->clks.byte_intf_clk) - clk_unprepare(l_clks->clks.byte_intf_clk); - clk_unprepare(l_clks->clks.pixel_clk); - clk_unprepare(l_clks->clks.byte_clk); - clk_unprepare(l_clks->clks.esc_clk); -} - -static int dsi_link_clk_enable(struct dsi_link_clks *l_clks) -{ - int rc = 0; - - rc = clk_enable(l_clks->clks.esc_clk); - if (rc) { - pr_err("Failed to enable dsi esc clk, rc=%d\n", rc); - goto esc_clk_err; - } - - rc = clk_enable(l_clks->clks.byte_clk); - if (rc) { - pr_err("Failed to enable dsi byte clk, rc=%d\n", rc); - goto byte_clk_err; - } - - rc = clk_enable(l_clks->clks.pixel_clk); - if (rc) { - pr_err("Failed to enable dsi pixel clk, rc=%d\n", rc); - goto pixel_clk_err; - } - - if (l_clks->clks.byte_intf_clk) { - rc = clk_enable(l_clks->clks.byte_intf_clk); - if (rc) { - pr_err("Failed to enable dsi byte intf clk, rc=%d\n", - rc); - goto byte_intf_clk_err; - } - } - - return rc; - -byte_intf_clk_err: - clk_disable(l_clks->clks.pixel_clk); -pixel_clk_err: - clk_disable(l_clks->clks.byte_clk); -byte_clk_err: - clk_disable(l_clks->clks.esc_clk); -esc_clk_err: - return rc; -} - -static void dsi_link_clk_disable(struct dsi_link_clks *l_clks) -{ - if (l_clks->clks.byte_intf_clk) - clk_disable(l_clks->clks.byte_intf_clk); - clk_disable(l_clks->clks.esc_clk); - clk_disable(l_clks->clks.pixel_clk); - clk_disable(l_clks->clks.byte_clk); -} - -/** - * dsi_link_clk_start() - enable dsi link clocks - */ -int dsi_link_clk_start(struct dsi_link_clks *clks) -{ - int rc = 0; - - rc = dsi_link_clk_set_rate(clks); - if (rc) { - pr_err("failed to set clk rates, rc = %d\n", rc); - goto error; - } - - rc = dsi_link_clk_prepare(clks); - if (rc) { - pr_err("failed to prepare link clks, rc = %d\n", rc); - goto error; - } - - rc = dsi_link_clk_enable(clks); - if (rc) { - pr_err("failed to enable link clks, rc = %d\n", rc); - goto error_unprepare; - } - - pr_debug("Link clocks are enabled\n"); - return rc; -error_unprepare: - dsi_link_clk_unprepare(clks); -error: - return rc; -} - -/** - * dsi_link_clk_stop() - Stop DSI link clocks. - */ -int dsi_link_clk_stop(struct dsi_link_clks *clks) -{ - dsi_link_clk_disable(clks); - dsi_link_clk_unprepare(clks); - - pr_debug("Link clocks disabled\n"); - - return 0; -} - -static int dsi_display_core_clk_enable(struct dsi_core_clks *clks, - u32 ctrl_count, u32 master_ndx) -{ - int rc = 0; - int i; - struct dsi_core_clks *clk, *m_clks; - - /* - * In case of split DSI usecases, the clock for master controller should - * be enabled before the other controller. Master controller in the - * clock context refers to the controller that sources the clock. - */ - - m_clks = &clks[master_ndx]; - rc = dpu_power_resource_enable(m_clks->clks.phandle, - m_clks->clks.dsi_core_client, true); - - if (rc) { - pr_err("Power resource enable failed, rc=%d\n", rc); - goto error; - } - - rc = dsi_core_clk_start(m_clks); - if (rc) { - pr_err("failed to turn on master clocks, rc=%d\n", rc); - goto error_disable_master_resource; - } - - /* Turn on rest of the core clocks */ - for (i = 0; i < ctrl_count; i++) { - clk = &clks[i]; - if (!clk || (clk == m_clks)) - continue; - - rc = dpu_power_resource_enable(clk->clks.phandle, - clk->clks.dsi_core_client, true); - if (rc) { - pr_err("Power resource enable failed, rc=%d\n", rc); - goto error_disable_master; - } - - rc = dsi_core_clk_start(clk); - if (rc) { - pr_err("failed to turn on clocks, rc=%d\n", rc); - (void)dpu_power_resource_enable(clk->clks.phandle, - clk->clks.dsi_core_client, false); - goto error_disable_master; - } - } - return rc; -error_disable_master: - (void)dsi_core_clk_stop(m_clks); - -error_disable_master_resource: - (void)dpu_power_resource_enable(m_clks->clks.phandle, - m_clks->clks.dsi_core_client, false); -error: - return rc; -} - -static int dsi_display_link_clk_enable(struct dsi_link_clks *clks, - u32 ctrl_count, u32 master_ndx) -{ - int rc = 0; - int i; - struct dsi_link_clks *clk, *m_clks; - - /* - * In case of split DSI usecases, the clock for master controller should - * be enabled before the other controller. Master controller in the - * clock context refers to the controller that sources the clock. - */ - - m_clks = &clks[master_ndx]; - - rc = dsi_link_clk_start(m_clks); - if (rc) { - pr_err("failed to turn on master clocks, rc=%d\n", rc); - goto error; - } - - /* Turn on rest of the core clocks */ - for (i = 0; i < ctrl_count; i++) { - clk = &clks[i]; - if (!clk || (clk == m_clks)) - continue; - - rc = dsi_link_clk_start(clk); - if (rc) { - pr_err("failed to turn on clocks, rc=%d\n", rc); - goto error_disable_master; - } - } - return rc; -error_disable_master: - (void)dsi_link_clk_stop(m_clks); -error: - return rc; -} - -static int dsi_display_core_clk_disable(struct dsi_core_clks *clks, - u32 ctrl_count, u32 master_ndx) -{ - int rc = 0; - int i; - struct dsi_core_clks *clk, *m_clks; - - /* - * In case of split DSI usecases, clock for slave DSI controllers should - * be disabled first before disabling clock for master controller. Slave - * controllers in the clock context refer to controller which source - * clock from another controller. - */ - - m_clks = &clks[master_ndx]; - - /* Turn off non-master core clocks */ - for (i = 0; i < ctrl_count; i++) { - clk = &clks[i]; - if (!clk || (clk == m_clks)) - continue; - - rc = dsi_core_clk_stop(clk); - if (rc) { - pr_debug("failed to turn off clocks, rc=%d\n", rc); - goto error; - } - - rc = dpu_power_resource_enable(clk->clks.phandle, - clk->clks.dsi_core_client, false); - if (rc) { - pr_err("Power resource disable failed: %d\n", rc); - goto error; - } - } - - rc = dsi_core_clk_stop(m_clks); - if (rc) { - pr_err("failed to turn off master clocks, rc=%d\n", rc); - goto error; - } - - rc = dpu_power_resource_enable(m_clks->clks.phandle, - m_clks->clks.dsi_core_client, false); - if (rc) - pr_err("Power resource disable failed: %d\n", rc); -error: - return rc; -} - -static int dsi_display_link_clk_disable(struct dsi_link_clks *clks, - u32 ctrl_count, u32 master_ndx) -{ - int rc = 0; - int i; - struct dsi_link_clks *clk, *m_clks; - - /* - * In case of split DSI usecases, clock for slave DSI controllers should - * be disabled first before disabling clock for master controller. Slave - * controllers in the clock context refer to controller which source - * clock from another controller. - */ - - m_clks = &clks[master_ndx]; - - /* Turn off non-master link clocks */ - for (i = 0; i < ctrl_count; i++) { - clk = &clks[i]; - if (!clk || (clk == m_clks)) - continue; - - rc = dsi_link_clk_stop(clk); - if (rc) - pr_err("failed to turn off clocks, rc=%d\n", rc); - } - - rc = dsi_link_clk_stop(m_clks); - if (rc) - pr_err("failed to turn off master clocks, rc=%d\n", rc); - - return rc; -} - -static int dsi_update_clk_state(struct dsi_core_clks *c_clks, u32 c_state, - struct dsi_link_clks *l_clks, u32 l_state) -{ - int rc = 0; - struct dsi_clk_mngr *mngr; - bool l_c_on = false; - - if (c_clks) { - mngr = - container_of(c_clks, struct dsi_clk_mngr, core_clks[0]); - } else if (l_clks) { - mngr = - container_of(l_clks, struct dsi_clk_mngr, link_clks[0]); - } else { - mngr = NULL; - } - - if (!mngr) - return -EINVAL; - - pr_debug("c_state = %d, l_state = %d\n", - c_clks ? c_state : -1, l_clks ? l_state : -1); - /* - * Below is the sequence to toggle DSI clocks: - * 1. For ON sequence, Core clocks before link clocks - * 2. For OFF sequence, Link clocks before core clocks. - */ - if (c_clks && (c_state == DSI_CLK_ON)) { - if (mngr->core_clk_state == DSI_CLK_OFF) { - rc = mngr->pre_clkon_cb(mngr->priv_data, - DSI_CORE_CLK, - DSI_CLK_ON); - if (rc) { - pr_err("failed to turn on MDP FS rc= %d\n", rc); - goto error; - } - } - rc = dsi_display_core_clk_enable(c_clks, mngr->dsi_ctrl_count, - mngr->master_ndx); - if (rc) { - pr_err("failed to turn on core clks rc = %d\n", rc); - goto error; - } - - if (mngr->post_clkon_cb) { - rc = mngr->post_clkon_cb(mngr->priv_data, - DSI_CORE_CLK, - DSI_CLK_ON); - if (rc) - pr_err("post clk on cb failed, rc = %d\n", rc); - } - mngr->core_clk_state = DSI_CLK_ON; - } - - if (l_clks) { - if (l_state == DSI_CLK_ON) { - if (mngr->pre_clkon_cb) { - rc = mngr->pre_clkon_cb(mngr->priv_data, - DSI_LINK_CLK, l_state); - if (rc) - pr_err("pre link clk on cb failed\n"); - } - rc = dsi_display_link_clk_enable(l_clks, - mngr->dsi_ctrl_count, mngr->master_ndx); - if (rc) { - pr_err("failed to start link clk rc= %d\n", rc); - goto error; - } - if (mngr->post_clkon_cb) { - rc = mngr->post_clkon_cb(mngr->priv_data, - DSI_LINK_CLK, - l_state); - if (rc) - pr_err("post link clk on cb failed\n"); - } - } else { - /* - * Two conditions that need to be checked for Link - * clocks: - * 1. Link clocks need core clocks to be on when - * transitioning from EARLY_GATE to OFF state. - * 2. ULPS mode might have to be enabled in case of OFF - * state. For ULPS, Link clocks should be turned ON - * first before they are turned off again. - * - * If Link is going from EARLY_GATE to OFF state AND - * Core clock is already in EARLY_GATE or OFF state, - * turn on Core clocks and link clocks. - * - * ULPS state is managed as part of the pre_clkoff_cb. - */ - if ((l_state == DSI_CLK_OFF) && - (mngr->link_clk_state == - DSI_CLK_EARLY_GATE) && - (mngr->core_clk_state != - DSI_CLK_ON)) { - rc = dsi_display_core_clk_enable( - mngr->core_clks, mngr->dsi_ctrl_count, - mngr->master_ndx); - if (rc) { - pr_err("core clks did not start\n"); - goto error; - } - - rc = dsi_display_link_clk_enable(l_clks, - mngr->dsi_ctrl_count, mngr->master_ndx); - if (rc) { - pr_err("Link clks did not start\n"); - goto error; - } - l_c_on = true; - pr_debug("ECG: core and Link_on\n"); - } - - if (mngr->pre_clkoff_cb) { - rc = mngr->pre_clkoff_cb(mngr->priv_data, - DSI_LINK_CLK, l_state); - if (rc) - pr_err("pre link clk off cb failed\n"); - } - - rc = dsi_display_link_clk_disable(l_clks, - mngr->dsi_ctrl_count, mngr->master_ndx); - if (rc) { - pr_err("failed to stop link clk, rc = %d\n", - rc); - goto error; - } - - if (mngr->post_clkoff_cb) { - rc = mngr->post_clkoff_cb(mngr->priv_data, - DSI_LINK_CLK, l_state); - if (rc) - pr_err("post link clk off cb failed\n"); - } - /* - * This check is to save unnecessary clock state - * change when going from EARLY_GATE to OFF. In the - * case where the request happens for both Core and Link - * clocks in the same call, core clocks need to be - * turned on first before OFF state can be entered. - * - * Core clocks are turned on here for Link clocks to go - * to OFF state. If core clock request is also present, - * then core clocks can be turned off Core clocks are - * transitioned to OFF state. - */ - if (l_c_on && (!(c_clks && (c_state == DSI_CLK_OFF) - && (mngr->core_clk_state == - DSI_CLK_EARLY_GATE)))) { - rc = dsi_display_core_clk_disable( - mngr->core_clks, mngr->dsi_ctrl_count, - mngr->master_ndx); - if (rc) { - pr_err("core clks did not stop\n"); - goto error; - } - - l_c_on = false; - pr_debug("ECG: core off\n"); - } else - pr_debug("ECG: core off skip\n"); - } - - mngr->link_clk_state = l_state; - } - - if (c_clks && (c_state != DSI_CLK_ON)) { - /* - * When going to OFF state from EARLY GATE state, Core clocks - * should be turned on first so that the IOs can be clamped. - * l_c_on flag is set, then the core clocks were turned before - * to the Link clocks go to OFF state. So Core clocks are - * already ON and this step can be skipped. - * - * IOs are clamped in pre_clkoff_cb callback. - */ - if ((c_state == DSI_CLK_OFF) && - (mngr->core_clk_state == - DSI_CLK_EARLY_GATE) && !l_c_on) { - rc = dsi_display_core_clk_enable(mngr->core_clks, - mngr->dsi_ctrl_count, mngr->master_ndx); - if (rc) { - pr_err("core clks did not start\n"); - goto error; - } - pr_debug("ECG: core on\n"); - } else - pr_debug("ECG: core on skip\n"); - - if (mngr->pre_clkoff_cb) { - rc = mngr->pre_clkoff_cb(mngr->priv_data, - DSI_CORE_CLK, - c_state); - if (rc) - pr_err("pre core clk off cb failed\n"); - } - - rc = dsi_display_core_clk_disable(c_clks, mngr->dsi_ctrl_count, - mngr->master_ndx); - if (rc) { - pr_err("failed to turn off core clks rc = %d\n", rc); - goto error; - } - - if (c_state == DSI_CLK_OFF) { - if (mngr->post_clkoff_cb) { - rc = mngr->post_clkoff_cb(mngr->priv_data, - DSI_CORE_CLK, - DSI_CLK_OFF); - if (rc) - pr_err("post clkoff cb fail, rc = %d\n", - rc); - } - } - mngr->core_clk_state = c_state; - } - -error: - return rc; -} - -static int dsi_recheck_clk_state(struct dsi_clk_mngr *mngr) -{ - int rc = 0; - struct list_head *pos = NULL; - struct dsi_clk_client_info *c; - u32 new_core_clk_state = DSI_CLK_OFF; - u32 new_link_clk_state = DSI_CLK_OFF; - u32 old_c_clk_state = DSI_CLK_OFF; - u32 old_l_clk_state = DSI_CLK_OFF; - struct dsi_core_clks *c_clks = NULL; - struct dsi_link_clks *l_clks = NULL; - - /* - * Conditions to maintain DSI manager clock state based on - * clock states of various clients: - * 1. If any client has clock in ON state, DSI manager clock state - * should be ON. - * 2. If any client is in ECG state with rest of them turned OFF, - * go to Early gate state. - * 3. If all clients have clocks as OFF, then go to OFF state. - */ - list_for_each(pos, &mngr->client_list) { - c = list_entry(pos, struct dsi_clk_client_info, list); - if (c->core_clk_state == DSI_CLK_ON) { - new_core_clk_state = DSI_CLK_ON; - break; - } else if (c->core_clk_state == DSI_CLK_EARLY_GATE) { - new_core_clk_state = DSI_CLK_EARLY_GATE; - } - } - - list_for_each(pos, &mngr->client_list) { - c = list_entry(pos, struct dsi_clk_client_info, list); - if (c->link_clk_state == DSI_CLK_ON) { - new_link_clk_state = DSI_CLK_ON; - break; - } else if (c->link_clk_state == DSI_CLK_EARLY_GATE) { - new_link_clk_state = DSI_CLK_EARLY_GATE; - } - } - - if (new_core_clk_state != mngr->core_clk_state) - c_clks = mngr->core_clks; - - if (new_link_clk_state != mngr->link_clk_state) - l_clks = mngr->link_clks; - - old_c_clk_state = mngr->core_clk_state; - old_l_clk_state = mngr->link_clk_state; - - pr_debug("c_clk_state (%d -> %d)\n", - old_c_clk_state, new_core_clk_state); - pr_debug("l_clk_state (%d -> %d)\n", - old_l_clk_state, new_link_clk_state); - - if (c_clks || l_clks) { - rc = dsi_update_clk_state(c_clks, new_core_clk_state, - l_clks, new_link_clk_state); - if (rc) { - pr_err("failed to update clock state, rc = %d\n", rc); - goto error; - } - } - -error: - return rc; -} - -int dsi_clk_req_state(void *client, enum dsi_clk_type clk, - enum dsi_clk_state state) -{ - int rc = 0; - struct dsi_clk_client_info *c = client; - struct dsi_clk_mngr *mngr; - bool changed = false; - - if (!client || !clk || clk > (DSI_CORE_CLK | DSI_LINK_CLK) || - state > DSI_CLK_EARLY_GATE) { - pr_err("Invalid params, client = %pK, clk = 0x%x, state = %d\n", - client, clk, state); - return -EINVAL; - } - - mngr = c->mngr; - mutex_lock(&mngr->clk_mutex); - - pr_debug("[%s]%s: CLK=%d, new_state=%d, core=%d, linkl=%d\n", - mngr->name, c->name, clk, state, c->core_clk_state, - c->link_clk_state); - - /* - * Clock refcount handling as below: - * i. Increment refcount whenever ON is called. - * ii. Decrement refcount when transitioning from ON state to - * either OFF or EARLY_GATE. - * iii. Do not decrement refcount when changing from - * EARLY_GATE to OFF. - */ - if (state == DSI_CLK_ON) { - if (clk & DSI_CORE_CLK) { - c->core_refcount++; - if (c->core_clk_state != DSI_CLK_ON) { - c->core_clk_state = DSI_CLK_ON; - changed = true; - } - } - if (clk & DSI_LINK_CLK) { - c->link_refcount++; - if (c->link_clk_state != DSI_CLK_ON) { - c->link_clk_state = DSI_CLK_ON; - changed = true; - } - } - } else if ((state == DSI_CLK_EARLY_GATE) || - (state == DSI_CLK_OFF)) { - if (clk & DSI_CORE_CLK) { - if (c->core_refcount == 0) { - if ((c->core_clk_state == - DSI_CLK_EARLY_GATE) && - (state == DSI_CLK_OFF)) { - changed = true; - c->core_clk_state = DSI_CLK_OFF; - } else { - pr_warn("Core refcount is zero for %s", - c->name); - } - } else { - c->core_refcount--; - if (c->core_refcount == 0) { - c->core_clk_state = state; - changed = true; - } - } - } - if (clk & DSI_LINK_CLK) { - if (c->link_refcount == 0) { - if ((c->link_clk_state == - DSI_CLK_EARLY_GATE) && - (state == DSI_CLK_OFF)) { - changed = true; - c->link_clk_state = DSI_CLK_OFF; - } else { - pr_warn("Link refcount is zero for %s", - c->name); - } - } else { - c->link_refcount--; - if (c->link_refcount == 0) { - c->link_clk_state = state; - changed = true; - } - } - } - } - pr_debug("[%s]%s: change=%d, Core (ref=%d, state=%d), Link (ref=%d, state=%d)\n", - mngr->name, c->name, changed, c->core_refcount, - c->core_clk_state, c->link_refcount, c->link_clk_state); - - if (changed) { - rc = dsi_recheck_clk_state(mngr); - if (rc) - pr_err("Failed to adjust clock state rc = %d\n", rc); - } - - mutex_unlock(&mngr->clk_mutex); - return rc; -} - -DEFINE_MUTEX(dsi_mngr_clk_mutex); - -int dsi_display_clk_ctrl(void *handle, - enum dsi_clk_type clk_type, enum dsi_clk_state clk_state) -{ - int rc = 0; - - if (!handle) { - pr_err("%s: Invalid arg\n", __func__); - return -EINVAL; - } - - mutex_lock(&dsi_mngr_clk_mutex); - rc = dsi_clk_req_state(handle, clk_type, clk_state); - if (rc) - pr_err("%s: failed set clk state, rc = %d\n", __func__, rc); - mutex_unlock(&dsi_mngr_clk_mutex); - - return rc; -} - -void *dsi_register_clk_handle(void *clk_mngr, char *client) -{ - void *handle = NULL; - struct dsi_clk_mngr *mngr = clk_mngr; - struct dsi_clk_client_info *c; - - if (!mngr) { - pr_err("bad params\n"); - return ERR_PTR(-EINVAL); - } - - mutex_lock(&mngr->clk_mutex); - - c = kzalloc(sizeof(*c), GFP_KERNEL); - if (!c) { - handle = ERR_PTR(-ENOMEM); - goto error; - } - - strlcpy(c->name, client, MAX_STRING_LEN); - c->mngr = mngr; - - list_add(&c->list, &mngr->client_list); - - pr_debug("[%s]: Added new client (%s)\n", mngr->name, c->name); - handle = c; -error: - mutex_unlock(&mngr->clk_mutex); - return handle; -} - -int dsi_deregister_clk_handle(void *client) -{ - int rc = 0; - struct dsi_clk_client_info *c = client; - struct dsi_clk_mngr *mngr; - struct list_head *pos = NULL; - struct list_head *tmp = NULL; - struct dsi_clk_client_info *node = NULL; - - if (!client) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - mngr = c->mngr; - pr_debug("%s: ENTER\n", mngr->name); - mutex_lock(&mngr->clk_mutex); - c->core_clk_state = DSI_CLK_OFF; - c->link_clk_state = DSI_CLK_OFF; - - rc = dsi_recheck_clk_state(mngr); - if (rc) { - pr_err("clock state recheck failed rc = %d\n", rc); - goto error; - } - - list_for_each_safe(pos, tmp, &mngr->client_list) { - node = list_entry(pos, struct dsi_clk_client_info, - list); - if (node == c) { - list_del(&node->list); - pr_debug("Removed device (%s)\n", node->name); - kfree(node); - break; - } - } - -error: - mutex_unlock(&mngr->clk_mutex); - pr_debug("%s: EXIT, rc = %d\n", mngr->name, rc); - return rc; -} - -void *dsi_display_clk_mngr_register(struct dsi_clk_info *info) -{ - struct dsi_clk_mngr *mngr; - int i = 0; - - if (!info) { - pr_err("Invalid params\n"); - return ERR_PTR(-EINVAL); - } - - mngr = kzalloc(sizeof(*mngr), GFP_KERNEL); - if (!mngr) { - mngr = ERR_PTR(-ENOMEM); - goto error; - } - - mutex_init(&mngr->clk_mutex); - mngr->dsi_ctrl_count = info->dsi_ctrl_count; - mngr->master_ndx = info->master_ndx; - - if (mngr->dsi_ctrl_count > MAX_DSI_CTRL) { - kfree(mngr); - return ERR_PTR(-EINVAL); - } - - for (i = 0; i < mngr->dsi_ctrl_count; i++) { - memcpy(&mngr->core_clks[i].clks, &info->c_clks[i], - sizeof(struct dsi_core_clk_info)); - memcpy(&mngr->link_clks[i].clks, &info->l_clks[i], - sizeof(struct dsi_link_clk_info)); - mngr->core_clks[i].bus_handle = info->bus_handle[i]; - mngr->ctrl_index[i] = info->ctrl_index[i]; - } - - INIT_LIST_HEAD(&mngr->client_list); - mngr->pre_clkon_cb = info->pre_clkon_cb; - mngr->post_clkon_cb = info->post_clkon_cb; - mngr->pre_clkoff_cb = info->pre_clkoff_cb; - mngr->post_clkoff_cb = info->post_clkoff_cb; - mngr->priv_data = info->priv_data; - memcpy(mngr->name, info->name, MAX_STRING_LEN); - -error: - pr_debug("EXIT, rc = %ld\n", PTR_ERR(mngr)); - return mngr; -} - -int dsi_display_clk_mngr_deregister(void *clk_mngr) -{ - int rc = 0; - struct dsi_clk_mngr *mngr = clk_mngr; - struct list_head *position = NULL; - struct list_head *tmp = NULL; - struct dsi_clk_client_info *node = NULL; - - if (!mngr) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - pr_debug("%s: ENTER\n", mngr->name); - mutex_lock(&mngr->clk_mutex); - - list_for_each_safe(position, tmp, &mngr->client_list) { - node = list_entry(position, struct dsi_clk_client_info, - list); - list_del(&node->list); - pr_debug("Removed device (%s)\n", node->name); - kfree(node); - } - - rc = dsi_recheck_clk_state(mngr); - if (rc) - pr_err("failed to disable all clocks\n"); - - mutex_unlock(&mngr->clk_mutex); - pr_debug("%s: EXIT, rc = %d\n", mngr->name, rc); - kfree(mngr); - return rc; -} - diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c deleted file mode 100644 index c0cf9ca..0000000 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c +++ /dev/null @@ -1,2846 +0,0 @@ -/* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * 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) "dsi-ctrl:[%s] " fmt, __func__ - -#include <linux/of_device.h> -#include <linux/err.h> -#include <linux/regulator/consumer.h> -#include <linux/clk.h> -#ifdef CONFIG_QCOM_BUS_SCALING -#include <linux/msm-bus.h> -#endif -#include <linux/of_irq.h> -#include <video/mipi_display.h> - -#include "msm_drv.h" -#include "msm_kms.h" -#include "msm_gpu.h" -#include "msm_mmu.h" -#include "dsi_ctrl.h" -#include "dsi_ctrl_hw.h" -#include "dsi_clk.h" -#include "dsi_pwr.h" -#include "dsi_catalog.h" - -#include "dpu_dbg.h" - -#define DSI_CTRL_DEFAULT_LABEL "MDSS DSI CTRL" - -#define DSI_CTRL_TX_TO_MS 200 - -#define TO_ON_OFF(x) ((x) ? "ON" : "OFF") - -#define CEIL(x, y) (((x) + ((y)-1)) / (y)) -/** - * enum dsi_ctrl_driver_ops - controller driver ops - */ -enum dsi_ctrl_driver_ops { - DSI_CTRL_OP_POWER_STATE_CHANGE, - DSI_CTRL_OP_CMD_ENGINE, - DSI_CTRL_OP_VID_ENGINE, - DSI_CTRL_OP_HOST_ENGINE, - DSI_CTRL_OP_CMD_TX, - DSI_CTRL_OP_HOST_INIT, - DSI_CTRL_OP_TPG, - DSI_CTRL_OP_PHY_SW_RESET, - DSI_CTRL_OP_ASYNC_TIMING, - DSI_CTRL_OP_MAX -}; - -struct dsi_ctrl_list_item { - struct dsi_ctrl *ctrl; - struct list_head list; -}; - -static LIST_HEAD(dsi_ctrl_list); -static DEFINE_MUTEX(dsi_ctrl_list_lock); - -static const enum dsi_ctrl_version dsi_ctrl_v1_4 = DSI_CTRL_VERSION_1_4; -static const enum dsi_ctrl_version dsi_ctrl_v2_0 = DSI_CTRL_VERSION_2_0; -static const enum dsi_ctrl_version dsi_ctrl_v2_2 = DSI_CTRL_VERSION_2_2; - -static const struct of_device_id msm_dsi_of_match[] = { - { - .compatible = "qcom,dsi-ctrl-hw-v1.4", - .data = &dsi_ctrl_v1_4, - }, - { - .compatible = "qcom,dsi-ctrl-hw-v2.0", - .data = &dsi_ctrl_v2_0, - }, - { - .compatible = "qcom,dsi-ctrl-hw-v2.2", - .data = &dsi_ctrl_v2_2, - }, - {} -}; - -static ssize_t debugfs_state_info_read(struct file *file, - char __user *buff, - size_t count, - loff_t *ppos) -{ - struct dsi_ctrl *dsi_ctrl = file->private_data; - char *buf; - u32 len = 0; - - if (!dsi_ctrl) - return -ENODEV; - - if (*ppos) - return 0; - - buf = kzalloc(SZ_4K, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - /* Dump current state */ - len += snprintf((buf + len), (SZ_4K - len), "Current State:\n"); - len += snprintf((buf + len), (SZ_4K - len), - "\tCTRL_ENGINE = %s\n", - TO_ON_OFF(dsi_ctrl->current_state.controller_state)); - len += snprintf((buf + len), (SZ_4K - len), - "\tVIDEO_ENGINE = %s\n\tCOMMAND_ENGINE = %s\n", - TO_ON_OFF(dsi_ctrl->current_state.vid_engine_state), - TO_ON_OFF(dsi_ctrl->current_state.cmd_engine_state)); - - /* Dump clock information */ - len += snprintf((buf + len), (SZ_4K - len), "\nClock Info:\n"); - len += snprintf((buf + len), (SZ_4K - len), - "\tBYTE_CLK = %u, PIXEL_CLK = %u, ESC_CLK = %u\n", - dsi_ctrl->clk_freq.byte_clk_rate, - dsi_ctrl->clk_freq.pix_clk_rate, - dsi_ctrl->clk_freq.esc_clk_rate); - - /* TODO: make sure that this does not exceed 4K */ - if (copy_to_user(buff, buf, len)) { - kfree(buf); - return -EFAULT; - } - - *ppos += len; - kfree(buf); - return len; -} - -static ssize_t debugfs_reg_dump_read(struct file *file, - char __user *buff, - size_t count, - loff_t *ppos) -{ - struct dsi_ctrl *dsi_ctrl = file->private_data; - char *buf; - u32 len = 0; - struct dsi_clk_ctrl_info clk_info; - int rc = 0; - - if (!dsi_ctrl) - return -ENODEV; - - if (*ppos) - return 0; - - buf = kzalloc(SZ_4K, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - clk_info.client = DSI_CLK_REQ_DSI_CLIENT; - clk_info.clk_type = DSI_CORE_CLK; - clk_info.clk_state = DSI_CLK_ON; - - rc = dsi_ctrl->clk_cb.dsi_clk_cb(dsi_ctrl->clk_cb.priv, clk_info); - if (rc) { - pr_err("failed to enable DSI core clocks\n"); - kfree(buf); - return rc; - } - - if (dsi_ctrl->hw.ops.reg_dump_to_buffer) - len = dsi_ctrl->hw.ops.reg_dump_to_buffer(&dsi_ctrl->hw, - buf, SZ_4K); - - clk_info.clk_state = DSI_CLK_OFF; - rc = dsi_ctrl->clk_cb.dsi_clk_cb(dsi_ctrl->clk_cb.priv, clk_info); - if (rc) { - pr_err("failed to disable DSI core clocks\n"); - kfree(buf); - return rc; - } - - - /* TODO: make sure that this does not exceed 4K */ - if (copy_to_user(buff, buf, len)) { - kfree(buf); - return -EFAULT; - } - - *ppos += len; - kfree(buf); - return len; -} - -static const struct file_operations state_info_fops = { - .open = simple_open, - .read = debugfs_state_info_read, -}; - -static const struct file_operations reg_dump_fops = { - .open = simple_open, - .read = debugfs_reg_dump_read, -}; - -static int dsi_ctrl_debugfs_init(struct dsi_ctrl *dsi_ctrl, - struct dentry *parent) -{ - int rc = 0; - struct dentry *dir, *state_file, *reg_dump; - char dbg_name[DSI_DEBUG_NAME_LEN]; - - dir = debugfs_create_dir(dsi_ctrl->name, parent); - if (IS_ERR_OR_NULL(dir)) { - rc = PTR_ERR(dir); - pr_err("[DSI_%d] debugfs create dir failed, rc=%d\n", - dsi_ctrl->cell_index, rc); - goto error; - } - - state_file = debugfs_create_file("state_info", - 0444, - dir, - dsi_ctrl, - &state_info_fops); - if (IS_ERR_OR_NULL(state_file)) { - rc = PTR_ERR(state_file); - pr_err("[DSI_%d] state file failed, rc=%d\n", - dsi_ctrl->cell_index, rc); - goto error_remove_dir; - } - - reg_dump = debugfs_create_file("reg_dump", - 0444, - dir, - dsi_ctrl, - ®_dump_fops); - if (IS_ERR_OR_NULL(reg_dump)) { - rc = PTR_ERR(reg_dump); - pr_err("[DSI_%d] reg dump file failed, rc=%d\n", - dsi_ctrl->cell_index, rc); - goto error_remove_dir; - } - - dsi_ctrl->debugfs_root = dir; - - snprintf(dbg_name, DSI_DEBUG_NAME_LEN, "dsi%d_ctrl", - dsi_ctrl->cell_index); - dpu_dbg_reg_register_base(dbg_name, dsi_ctrl->hw.base, - msm_iomap_size(dsi_ctrl->pdev, "dsi_ctrl")); -error_remove_dir: - debugfs_remove(dir); -error: - return rc; -} - -static int dsi_ctrl_debugfs_deinit(struct dsi_ctrl *dsi_ctrl) -{ - debugfs_remove(dsi_ctrl->debugfs_root); - return 0; -} - -static inline struct msm_gem_address_space* -dsi_ctrl_get_aspace(struct dsi_ctrl *dsi_ctrl, - int domain) -{ - if (!dsi_ctrl || !dsi_ctrl->drm_dev) - return NULL; - - return msm_gem_smmu_address_space_get(dsi_ctrl->drm_dev, domain); -} - -static int dsi_ctrl_check_state(struct dsi_ctrl *dsi_ctrl, - enum dsi_ctrl_driver_ops op, - u32 op_state) -{ - int rc = 0; - struct dsi_ctrl_state_info *state = &dsi_ctrl->current_state; - - switch (op) { - case DSI_CTRL_OP_POWER_STATE_CHANGE: - if (state->power_state == op_state) { - pr_debug("[%d] No change in state, pwr_state=%d\n", - dsi_ctrl->cell_index, op_state); - rc = -EINVAL; - } else if (state->power_state == DSI_CTRL_POWER_VREG_ON) { - if (state->vid_engine_state == DSI_CTRL_ENGINE_ON) { - pr_debug("[%d]State error: op=%d: %d\n", - dsi_ctrl->cell_index, - op_state, - state->vid_engine_state); - rc = -EINVAL; - } - } - break; - case DSI_CTRL_OP_CMD_ENGINE: - if (state->cmd_engine_state == op_state) { - pr_debug("[%d] No change in state, cmd_state=%d\n", - dsi_ctrl->cell_index, op_state); - rc = -EINVAL; - } else if ((state->power_state != DSI_CTRL_POWER_VREG_ON) || - (state->controller_state != DSI_CTRL_ENGINE_ON)) { - pr_debug("[%d]State error: op=%d: %d, %d\n", - dsi_ctrl->cell_index, - op, - state->power_state, - state->controller_state); - rc = -EINVAL; - } - break; - case DSI_CTRL_OP_VID_ENGINE: - if (state->vid_engine_state == op_state) { - pr_debug("[%d] No change in state, cmd_state=%d\n", - dsi_ctrl->cell_index, op_state); - rc = -EINVAL; - } else if ((state->power_state != DSI_CTRL_POWER_VREG_ON) || - (state->controller_state != DSI_CTRL_ENGINE_ON)) { - pr_debug("[%d]State error: op=%d: %d, %d\n", - dsi_ctrl->cell_index, - op, - state->power_state, - state->controller_state); - rc = -EINVAL; - } - break; - case DSI_CTRL_OP_HOST_ENGINE: - if (state->controller_state == op_state) { - pr_debug("[%d] No change in state, ctrl_state=%d\n", - dsi_ctrl->cell_index, op_state); - rc = -EINVAL; - } else if (state->power_state != DSI_CTRL_POWER_VREG_ON) { - pr_debug("[%d]State error (link is off): op=%d:, %d\n", - dsi_ctrl->cell_index, - op_state, - state->power_state); - rc = -EINVAL; - } else if ((op_state == DSI_CTRL_ENGINE_OFF) && - ((state->cmd_engine_state != DSI_CTRL_ENGINE_OFF) || - (state->vid_engine_state != DSI_CTRL_ENGINE_OFF))) { - pr_debug("[%d]State error (eng on): op=%d: %d, %d\n", - dsi_ctrl->cell_index, - op_state, - state->cmd_engine_state, - state->vid_engine_state); - rc = -EINVAL; - } - break; - case DSI_CTRL_OP_CMD_TX: - if ((state->power_state != DSI_CTRL_POWER_VREG_ON) || - (state->host_initialized != true) || - (state->cmd_engine_state != DSI_CTRL_ENGINE_ON)) { - pr_debug("[%d]State error: op=%d: %d, %d, %d\n", - dsi_ctrl->cell_index, - op, - state->power_state, - state->host_initialized, - state->cmd_engine_state); - rc = -EINVAL; - } - break; - case DSI_CTRL_OP_HOST_INIT: - if (state->host_initialized == op_state) { - pr_debug("[%d] No change in state, host_init=%d\n", - dsi_ctrl->cell_index, op_state); - rc = -EINVAL; - } else if (state->power_state != DSI_CTRL_POWER_VREG_ON) { - pr_debug("[%d]State error: op=%d: %d\n", - dsi_ctrl->cell_index, op, state->power_state); - rc = -EINVAL; - } - break; - case DSI_CTRL_OP_TPG: - if (state->tpg_enabled == op_state) { - pr_debug("[%d] No change in state, tpg_enabled=%d\n", - dsi_ctrl->cell_index, op_state); - rc = -EINVAL; - } else if ((state->power_state != DSI_CTRL_POWER_VREG_ON) || - (state->controller_state != DSI_CTRL_ENGINE_ON)) { - pr_debug("[%d]State error: op=%d: %d, %d\n", - dsi_ctrl->cell_index, - op, - state->power_state, - state->controller_state); - rc = -EINVAL; - } - break; - case DSI_CTRL_OP_PHY_SW_RESET: - if (state->power_state != DSI_CTRL_POWER_VREG_ON) { - pr_debug("[%d]State error: op=%d: %d\n", - dsi_ctrl->cell_index, op, state->power_state); - rc = -EINVAL; - } - break; - case DSI_CTRL_OP_ASYNC_TIMING: - if (state->vid_engine_state != op_state) { - pr_err("[%d] Unexpected engine state vid_state=%d\n", - dsi_ctrl->cell_index, op_state); - rc = -EINVAL; - } - break; - default: - rc = -ENOTSUPP; - break; - } - - return rc; -} - -static void dsi_ctrl_update_state(struct dsi_ctrl *dsi_ctrl, - enum dsi_ctrl_driver_ops op, - u32 op_state) -{ - struct dsi_ctrl_state_info *state = &dsi_ctrl->current_state; - - switch (op) { - case DSI_CTRL_OP_POWER_STATE_CHANGE: - state->power_state = op_state; - break; - case DSI_CTRL_OP_CMD_ENGINE: - state->cmd_engine_state = op_state; - break; - case DSI_CTRL_OP_VID_ENGINE: - state->vid_engine_state = op_state; - break; - case DSI_CTRL_OP_HOST_ENGINE: - state->controller_state = op_state; - break; - case DSI_CTRL_OP_HOST_INIT: - state->host_initialized = (op_state == 1) ? true : false; - break; - case DSI_CTRL_OP_TPG: - state->tpg_enabled = (op_state == 1) ? true : false; - break; - case DSI_CTRL_OP_CMD_TX: - case DSI_CTRL_OP_PHY_SW_RESET: - default: - break; - } -} - -static int dsi_ctrl_init_regmap(struct platform_device *pdev, - struct dsi_ctrl *ctrl) -{ - int rc = 0; - void __iomem *ptr; - - ptr = msm_ioremap(pdev, "dsi_ctrl", ctrl->name); - if (IS_ERR(ptr)) { - rc = PTR_ERR(ptr); - return rc; - } - - ctrl->hw.base = ptr; - pr_debug("[%s] map dsi_ctrl registers to %p\n", ctrl->name, - ctrl->hw.base); - - switch (ctrl->version) { - case DSI_CTRL_VERSION_1_4: - case DSI_CTRL_VERSION_2_0: - ptr = msm_ioremap(pdev, "mmss_misc", ctrl->name); - if (IS_ERR(ptr)) { - pr_err("mmss_misc base address not found for [%s]\n", - ctrl->name); - rc = PTR_ERR(ptr); - return rc; - } - ctrl->hw.mmss_misc_base = ptr; - ctrl->hw.disp_cc_base = NULL; - break; - case DSI_CTRL_VERSION_2_2: - ptr = msm_ioremap(pdev, "disp_cc_base", ctrl->name); - if (IS_ERR(ptr)) { - pr_err("disp_cc base address not found for [%s]\n", - ctrl->name); - rc = PTR_ERR(ptr); - return rc; - } - ctrl->hw.disp_cc_base = ptr; - ctrl->hw.mmss_misc_base = NULL; - break; - default: - break; - } - - return rc; -} - -static int dsi_ctrl_clocks_deinit(struct dsi_ctrl *ctrl) -{ - struct dsi_core_clk_info *core = &ctrl->clk_info.core_clks; - struct dsi_link_clk_info *link = &ctrl->clk_info.link_clks; - struct dsi_clk_link_set *rcg = &ctrl->clk_info.rcg_clks; - - if (core->mdp_core_clk) - devm_clk_put(&ctrl->pdev->dev, core->mdp_core_clk); - if (core->iface_clk) - devm_clk_put(&ctrl->pdev->dev, core->iface_clk); - if (core->core_mmss_clk) - devm_clk_put(&ctrl->pdev->dev, core->core_mmss_clk); - if (core->bus_clk) - devm_clk_put(&ctrl->pdev->dev, core->bus_clk); - if (core->mnoc_clk) - devm_clk_put(&ctrl->pdev->dev, core->mnoc_clk); - - memset(core, 0x0, sizeof(*core)); - - if (link->byte_clk) - devm_clk_put(&ctrl->pdev->dev, link->byte_clk); - if (link->pixel_clk) - devm_clk_put(&ctrl->pdev->dev, link->pixel_clk); - if (link->esc_clk) - devm_clk_put(&ctrl->pdev->dev, link->esc_clk); - if (link->byte_intf_clk) - devm_clk_put(&ctrl->pdev->dev, link->byte_intf_clk); - - memset(link, 0x0, sizeof(*link)); - - if (rcg->byte_clk) - devm_clk_put(&ctrl->pdev->dev, rcg->byte_clk); - if (rcg->pixel_clk) - devm_clk_put(&ctrl->pdev->dev, rcg->pixel_clk); - - memset(rcg, 0x0, sizeof(*rcg)); - - return 0; -} - -static int dsi_ctrl_clocks_init(struct platform_device *pdev, - struct dsi_ctrl *ctrl) -{ - int rc = 0; - struct dsi_core_clk_info *core = &ctrl->clk_info.core_clks; - struct dsi_link_clk_info *link = &ctrl->clk_info.link_clks; - struct dsi_clk_link_set *rcg = &ctrl->clk_info.rcg_clks; - - core->mdp_core_clk = devm_clk_get(&pdev->dev, "mdp_core_clk"); - if (IS_ERR(core->mdp_core_clk)) { - core->mdp_core_clk = NULL; - pr_debug("failed to get mdp_core_clk, rc=%d\n", rc); - } - - core->iface_clk = devm_clk_get(&pdev->dev, "iface_clk"); - if (IS_ERR(core->iface_clk)) { - core->iface_clk = NULL; - pr_debug("failed to get iface_clk, rc=%d\n", rc); - } - - core->core_mmss_clk = devm_clk_get(&pdev->dev, "core_mmss_clk"); - if (IS_ERR(core->core_mmss_clk)) { - core->core_mmss_clk = NULL; - pr_debug("failed to get core_mmss_clk, rc=%d\n", rc); - } - - core->bus_clk = devm_clk_get(&pdev->dev, "bus_clk"); - if (IS_ERR(core->bus_clk)) { - core->bus_clk = NULL; - pr_debug("failed to get bus_clk, rc=%d\n", rc); - } - - core->mnoc_clk = devm_clk_get(&pdev->dev, "mnoc_clk"); - if (IS_ERR(core->mnoc_clk)) { - core->mnoc_clk = NULL; - pr_debug("can't get mnoc clock, rc=%d\n", rc); - } - - link->byte_clk = devm_clk_get(&pdev->dev, "byte_clk"); - if (IS_ERR(link->byte_clk)) { - rc = PTR_ERR(link->byte_clk); - pr_err("failed to get byte_clk, rc=%d\n", rc); - goto fail; - } - - link->pixel_clk = devm_clk_get(&pdev->dev, "pixel_clk"); - if (IS_ERR(link->pixel_clk)) { - rc = PTR_ERR(link->pixel_clk); - pr_err("failed to get pixel_clk, rc=%d\n", rc); - goto fail; - } - - link->esc_clk = devm_clk_get(&pdev->dev, "esc_clk"); - if (IS_ERR(link->esc_clk)) { - rc = PTR_ERR(link->esc_clk); - pr_err("failed to get esc_clk, rc=%d\n", rc); - goto fail; - } - - link->byte_intf_clk = devm_clk_get(&pdev->dev, "byte_intf_clk"); - if (IS_ERR(link->byte_intf_clk)) { - link->byte_intf_clk = NULL; - pr_debug("can't find byte intf clk, rc=%d\n", rc); - } - - rcg->byte_clk = devm_clk_get(&pdev->dev, "byte_clk_rcg"); - if (IS_ERR(rcg->byte_clk)) { - rc = PTR_ERR(rcg->byte_clk); - pr_err("failed to get byte_clk_rcg, rc=%d\n", rc); - goto fail; - } - - rcg->pixel_clk = devm_clk_get(&pdev->dev, "pixel_clk_rcg"); - if (IS_ERR(rcg->pixel_clk)) { - rc = PTR_ERR(rcg->pixel_clk); - pr_err("failed to get pixel_clk_rcg, rc=%d\n", rc); - goto fail; - } - - return 0; -fail: - dsi_ctrl_clocks_deinit(ctrl); - return rc; -} - -static int dsi_ctrl_supplies_deinit(struct dsi_ctrl *ctrl) -{ - int i = 0; - int rc = 0; - struct dsi_regulator_info *regs; - - regs = &ctrl->pwr_info.digital; - for (i = 0; i < regs->count; i++) { - if (!regs->vregs[i].vreg) - pr_err("vreg is NULL, should not reach here\n"); - else - devm_regulator_put(regs->vregs[i].vreg); - } - - regs = &ctrl->pwr_info.host_pwr; - for (i = 0; i < regs->count; i++) { - if (!regs->vregs[i].vreg) - pr_err("vreg is NULL, should not reach here\n"); - else - devm_regulator_put(regs->vregs[i].vreg); - } - - if (!ctrl->pwr_info.host_pwr.vregs) { - devm_kfree(&ctrl->pdev->dev, ctrl->pwr_info.host_pwr.vregs); - ctrl->pwr_info.host_pwr.vregs = NULL; - ctrl->pwr_info.host_pwr.count = 0; - } - - if (!ctrl->pwr_info.digital.vregs) { - devm_kfree(&ctrl->pdev->dev, ctrl->pwr_info.digital.vregs); - ctrl->pwr_info.digital.vregs = NULL; - ctrl->pwr_info.digital.count = 0; - } - - return rc; -} - -static int dsi_ctrl_supplies_init(struct platform_device *pdev, - struct dsi_ctrl *ctrl) -{ - int rc = 0; - int i = 0; - struct dsi_regulator_info *regs; - struct regulator *vreg = NULL; - - rc = dsi_pwr_get_dt_vreg_data(&pdev->dev, - &ctrl->pwr_info.digital, - "qcom,core-supply-entries"); - if (rc) - pr_debug("failed to get digital supply, rc = %d\n", rc); - - rc = dsi_pwr_get_dt_vreg_data(&pdev->dev, - &ctrl->pwr_info.host_pwr, - "qcom,ctrl-supply-entries"); - if (rc) { - pr_err("failed to get host power supplies, rc = %d\n", rc); - goto error_digital; - } - - regs = &ctrl->pwr_info.digital; - for (i = 0; i < regs->count; i++) { - vreg = devm_regulator_get(&pdev->dev, regs->vregs[i].vreg_name); - if (IS_ERR(vreg)) { - pr_err("failed to get %s regulator\n", - regs->vregs[i].vreg_name); - rc = PTR_ERR(vreg); - goto error_host_pwr; - } - regs->vregs[i].vreg = vreg; - } - - regs = &ctrl->pwr_info.host_pwr; - for (i = 0; i < regs->count; i++) { - vreg = devm_regulator_get(&pdev->dev, regs->vregs[i].vreg_name); - if (IS_ERR(vreg)) { - pr_err("failed to get %s regulator\n", - regs->vregs[i].vreg_name); - for (--i; i >= 0; i--) - devm_regulator_put(regs->vregs[i].vreg); - rc = PTR_ERR(vreg); - goto error_digital_put; - } - regs->vregs[i].vreg = vreg; - } - - return rc; - -error_digital_put: - regs = &ctrl->pwr_info.digital; - for (i = 0; i < regs->count; i++) - devm_regulator_put(regs->vregs[i].vreg); -error_host_pwr: - devm_kfree(&pdev->dev, ctrl->pwr_info.host_pwr.vregs); - ctrl->pwr_info.host_pwr.vregs = NULL; - ctrl->pwr_info.host_pwr.count = 0; -error_digital: - if (ctrl->pwr_info.digital.vregs) - devm_kfree(&pdev->dev, ctrl->pwr_info.digital.vregs); - ctrl->pwr_info.digital.vregs = NULL; - ctrl->pwr_info.digital.count = 0; - return rc; -} - -static int dsi_ctrl_axi_bus_client_init(struct platform_device *pdev, - struct dsi_ctrl *ctrl) -{ - int rc = 0; -#ifdef CONFIG_QCOM_BUS_SCALING - struct dsi_ctrl_bus_scale_info *bus = &ctrl->axi_bus_info; - - bus->bus_scale_table = msm_bus_cl_get_pdata(pdev); - if (IS_ERR_OR_NULL(bus->bus_scale_table)) { - rc = PTR_ERR(bus->bus_scale_table); - pr_debug("msm_bus_cl_get_pdata() failed, rc = %d\n", rc); - bus->bus_scale_table = NULL; - return rc; - } - - bus->bus_handle = msm_bus_scale_register_client(bus->bus_scale_table); - if (!bus->bus_handle) { - rc = -EINVAL; - pr_err("failed to register axi bus client\n"); - } -#endif - return rc; -} - -static int dsi_ctrl_axi_bus_client_deinit(struct dsi_ctrl *ctrl) -{ -#ifdef CONFIG_QCOM_BUS_SCALING - struct dsi_ctrl_bus_scale_info *bus = &ctrl->axi_bus_info; - - if (bus->bus_handle) { - msm_bus_scale_unregister_client(bus->bus_handle); - - bus->bus_handle = 0; - } -#endif - return 0; -} - -static int dsi_ctrl_validate_panel_info(struct dsi_ctrl *dsi_ctrl, - struct dsi_host_config *config) -{ - int rc = 0; - struct dsi_host_common_cfg *host_cfg = &config->common_config; - - if (config->panel_mode >= DSI_OP_MODE_MAX) { - pr_err("Invalid dsi operation mode (%d)\n", config->panel_mode); - rc = -EINVAL; - goto err; - } - - if ((host_cfg->data_lanes & (DSI_CLOCK_LANE - 1)) == 0) { - pr_err("No data lanes are enabled\n"); - rc = -EINVAL; - goto err; - } -err: - return rc; -} - -static int dsi_ctrl_update_link_freqs(struct dsi_ctrl *dsi_ctrl, - struct dsi_host_config *config, void *clk_handle) -{ - int rc = 0; - u32 num_of_lanes = 0; - u32 bpp = 3; - u64 h_period, v_period, bit_rate, pclk_rate, bit_rate_per_lane, - byte_clk_rate; - struct dsi_host_common_cfg *host_cfg = &config->common_config; - struct dsi_mode_info *timing = &config->video_timing; - - if (host_cfg->data_lanes & DSI_DATA_LANE_0) - num_of_lanes++; - if (host_cfg->data_lanes & DSI_DATA_LANE_1) - num_of_lanes++; - if (host_cfg->data_lanes & DSI_DATA_LANE_2) - num_of_lanes++; - if (host_cfg->data_lanes & DSI_DATA_LANE_3) - num_of_lanes++; - - h_period = DSI_H_TOTAL_DSC(timing); - v_period = DSI_V_TOTAL(timing); - - bit_rate = h_period * v_period * timing->refresh_rate * bpp * 8; - bit_rate_per_lane = bit_rate; - do_div(bit_rate_per_lane, num_of_lanes); - pclk_rate = bit_rate; - do_div(pclk_rate, (8 * bpp)); - byte_clk_rate = bit_rate_per_lane; - do_div(byte_clk_rate, 8); - pr_debug("bit_clk_rate = %llu, bit_clk_rate_per_lane = %llu\n", - bit_rate, bit_rate_per_lane); - pr_debug("byte_clk_rate = %llu, pclk_rate = %llu\n", - byte_clk_rate, pclk_rate); - - dsi_ctrl->clk_freq.byte_clk_rate = byte_clk_rate; - dsi_ctrl->clk_freq.pix_clk_rate = pclk_rate; - dsi_ctrl->clk_freq.esc_clk_rate = config->esc_clk_rate_hz; - - rc = dsi_clk_set_link_frequencies(clk_handle, dsi_ctrl->clk_freq, - dsi_ctrl->cell_index); - if (rc) - pr_err("Failed to update link frequencies\n"); - - return rc; -} - -static int dsi_ctrl_enable_supplies(struct dsi_ctrl *dsi_ctrl, bool enable) -{ - int rc = 0; - - if (enable) { - if (!dsi_ctrl->current_state.host_initialized) { - rc = dsi_pwr_enable_regulator( - &dsi_ctrl->pwr_info.host_pwr, true); - if (rc) { - pr_err("failed to enable host power regs\n"); - goto error; - } - } - - rc = dsi_pwr_enable_regulator(&dsi_ctrl->pwr_info.digital, - true); - if (rc) { - pr_err("failed to enable gdsc, rc=%d\n", rc); - (void)dsi_pwr_enable_regulator( - &dsi_ctrl->pwr_info.host_pwr, - false - ); - goto error; - } - } else { - rc = dsi_pwr_enable_regulator(&dsi_ctrl->pwr_info.digital, - false); - if (rc) { - pr_err("failed to disable gdsc, rc=%d\n", rc); - goto error; - } - - if (!dsi_ctrl->current_state.host_initialized) { - rc = dsi_pwr_enable_regulator( - &dsi_ctrl->pwr_info.host_pwr, false); - if (rc) { - pr_err("failed to disable host power regs\n"); - goto error; - } - } - } -error: - return rc; -} - -static int dsi_ctrl_copy_and_pad_cmd(struct dsi_ctrl *dsi_ctrl, - const struct mipi_dsi_packet *packet, - u8 **buffer, - u32 *size) -{ - int rc = 0; - u8 *buf = NULL; - u32 len; - - len = packet->size; - len += 0x3; len &= ~0x03; /* Align to 32 bits */ - - buf = devm_kzalloc(&dsi_ctrl->pdev->dev, len * sizeof(u8), GFP_KERNEL); - if (!buf) - return -ENOMEM; - - /* MSM specific command format in memory */ - buf[0] = packet->header[1]; - buf[1] = packet->header[2]; - buf[2] = packet->header[0]; - buf[3] = BIT(7); - if (packet->payload_length > 0) - buf[3] |= BIT(6); - - /* Long packet */ - if (packet->payload && packet->payload_length) - memcpy(buf + 4, packet->payload, packet->payload_length); - - /* Append 0xff to the end */ - if (packet->size < len) - memset(buf + packet->size, 0xff, len - packet->size); - - *buffer = buf; - *size = len; - - return rc; -} - -static void dsi_ctrl_wait_for_video_done(struct dsi_ctrl *dsi_ctrl) -{ - u32 v_total = 0, v_blank = 0, sleep_ms = 0, fps = 0, ret; - struct dsi_mode_info *timing; - - if (dsi_ctrl->host_config.panel_mode != DSI_OP_VIDEO_MODE) - return; - - dsi_ctrl->hw.ops.clear_interrupt_status(&dsi_ctrl->hw, - DSI_VIDEO_MODE_FRAME_DONE); - - dsi_ctrl_enable_status_interrupt(dsi_ctrl, - DSI_SINT_VIDEO_MODE_FRAME_DONE, NULL); - reinit_completion(&dsi_ctrl->irq_info.vid_frame_done); - ret = wait_for_completion_timeout( - &dsi_ctrl->irq_info.vid_frame_done, - msecs_to_jiffies(DSI_CTRL_TX_TO_MS)); - if (ret <= 0) - pr_debug("wait for video done failed\n"); - dsi_ctrl_disable_status_interrupt(dsi_ctrl, - DSI_SINT_VIDEO_MODE_FRAME_DONE); - - timing = &(dsi_ctrl->host_config.video_timing); - v_total = timing->v_sync_width + timing->v_back_porch + - timing->v_front_porch + timing->v_active; - v_blank = timing->v_sync_width + timing->v_back_porch; - fps = timing->refresh_rate; - - sleep_ms = CEIL((v_blank * 1000), (v_total * fps)) + 1; - udelay(sleep_ms * 1000); -} - -static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl, - const struct mipi_dsi_msg *msg, - u32 flags) -{ - int rc = 0, ret = 0; - struct mipi_dsi_packet packet; - struct dsi_ctrl_cmd_dma_fifo_info cmd; - struct dsi_ctrl_cmd_dma_info cmd_mem; - u32 hw_flags = 0; - u32 length = 0; - u8 *buffer = NULL; - u32 cnt = 0; - u8 *cmdbuf; - - rc = mipi_dsi_create_packet(&packet, msg); - if (rc) { - pr_err("Failed to create message packet, rc=%d\n", rc); - goto error; - } - - if (flags & DSI_CTRL_CMD_FETCH_MEMORY) { - rc = dsi_ctrl_copy_and_pad_cmd(dsi_ctrl, - &packet, - &buffer, - &length); - - if (rc) { - pr_err("[%s] failed to copy message, rc=%d\n", - dsi_ctrl->name, rc); - goto error; - } - - cmd_mem.offset = dsi_ctrl->cmd_buffer_iova; - cmd_mem.length = length; - cmd_mem.en_broadcast = (flags & DSI_CTRL_CMD_BROADCAST) ? - true : false; - cmd_mem.is_master = (flags & DSI_CTRL_CMD_BROADCAST_MASTER) ? - true : false; - cmd_mem.use_lpm = (msg->flags & MIPI_DSI_MSG_USE_LPM) ? - true : false; - - cmdbuf = (u8 *)(dsi_ctrl->vaddr); - for (cnt = 0; cnt < length; cnt++) - cmdbuf[cnt] = buffer[cnt]; - - } else if (flags & DSI_CTRL_CMD_FIFO_STORE) { - rc = dsi_ctrl_copy_and_pad_cmd(dsi_ctrl, - &packet, - &buffer, - &length); - if (rc) { - pr_err("[%s] failed to copy message, rc=%d\n", - dsi_ctrl->name, rc); - goto error; - } - cmd.command = (u32 *)buffer; - cmd.size = length; - cmd.en_broadcast = (flags & DSI_CTRL_CMD_BROADCAST) ? - true : false; - cmd.is_master = (flags & DSI_CTRL_CMD_BROADCAST_MASTER) ? - true : false; - cmd.use_lpm = (msg->flags & MIPI_DSI_MSG_USE_LPM) ? - true : false; - } - - hw_flags |= (flags & DSI_CTRL_CMD_DEFER_TRIGGER) ? - DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER : 0; - - if (flags & DSI_CTRL_CMD_DEFER_TRIGGER) { - if (flags & DSI_CTRL_CMD_FETCH_MEMORY) { - dsi_ctrl->hw.ops.kickoff_command(&dsi_ctrl->hw, - &cmd_mem, - hw_flags); - } else if (flags & DSI_CTRL_CMD_FIFO_STORE) { - dsi_ctrl->hw.ops.kickoff_fifo_command(&dsi_ctrl->hw, - &cmd, - hw_flags); - } - } - - if (!(flags & DSI_CTRL_CMD_DEFER_TRIGGER)) { - dsi_ctrl_wait_for_video_done(dsi_ctrl); - dsi_ctrl_enable_status_interrupt(dsi_ctrl, - DSI_SINT_CMD_MODE_DMA_DONE, NULL); - reinit_completion(&dsi_ctrl->irq_info.cmd_dma_done); - - if (flags & DSI_CTRL_CMD_FETCH_MEMORY) { - dsi_ctrl->hw.ops.kickoff_command(&dsi_ctrl->hw, - &cmd_mem, - hw_flags); - } else if (flags & DSI_CTRL_CMD_FIFO_STORE) { - dsi_ctrl->hw.ops.kickoff_fifo_command(&dsi_ctrl->hw, - &cmd, - hw_flags); - } - - ret = wait_for_completion_timeout( - &dsi_ctrl->irq_info.cmd_dma_done, - msecs_to_jiffies(DSI_CTRL_TX_TO_MS)); - - if (ret == 0) { - u32 status = 0; - u32 mask = DSI_CMD_MODE_DMA_DONE; - - if (status & mask) { - status |= (DSI_CMD_MODE_DMA_DONE | - DSI_BTA_DONE); - dsi_ctrl->hw.ops.clear_interrupt_status( - &dsi_ctrl->hw, - status); - dsi_ctrl_disable_status_interrupt(dsi_ctrl, - DSI_SINT_CMD_MODE_DMA_DONE); - complete_all(&dsi_ctrl->irq_info.cmd_dma_done); - pr_warn("dma_tx done but irq not triggered\n"); - } else { - rc = -ETIMEDOUT; - dsi_ctrl_disable_status_interrupt(dsi_ctrl, - DSI_SINT_CMD_MODE_DMA_DONE); - pr_err("[DSI_%d]Command transfer failed\n", - dsi_ctrl->cell_index); - } - } - - dsi_ctrl->hw.ops.reset_cmd_fifo(&dsi_ctrl->hw); - } -error: - if (buffer) - devm_kfree(&dsi_ctrl->pdev->dev, buffer); - return rc; -} - -static int dsi_set_max_return_size(struct dsi_ctrl *dsi_ctrl, - const struct mipi_dsi_msg *rx_msg, - u32 size) -{ - int rc = 0; - u8 tx[2] = { (u8)(size & 0xFF), (u8)(size >> 8) }; - struct mipi_dsi_msg msg = { - .channel = rx_msg->channel, - .type = MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, - .tx_len = 2, - .tx_buf = tx, - }; - - rc = dsi_message_tx(dsi_ctrl, &msg, 0x0); - if (rc) - pr_err("failed to send max return size packet, rc=%d\n", rc); - - return rc; -} - -static int dsi_message_rx(struct dsi_ctrl *dsi_ctrl, - const struct mipi_dsi_msg *msg, - u32 flags) -{ - int rc = 0; - u32 rd_pkt_size; - u32 total_read_len; - u32 bytes_read = 0, tot_bytes_read = 0; - u32 current_read_len; - bool short_resp = false; - bool read_done = false; - - if (msg->rx_len <= 2) { - short_resp = true; - rd_pkt_size = msg->rx_len; - total_read_len = 4; - } else { - short_resp = false; - current_read_len = 10; - if (msg->rx_len < current_read_len) - rd_pkt_size = msg->rx_len; - else - rd_pkt_size = current_read_len; - - total_read_len = current_read_len + 6; - } - - while (!read_done) { - rc = dsi_set_max_return_size(dsi_ctrl, msg, rd_pkt_size); - if (rc) { - pr_err("Failed to set max return packet size, rc=%d\n", - rc); - goto error; - } - - rc = dsi_message_tx(dsi_ctrl, msg, flags); - if (rc) { - pr_err("Message transmission failed, rc=%d\n", rc); - goto error; - } - - - tot_bytes_read += bytes_read; - if (short_resp) - read_done = true; - else if (msg->rx_len <= tot_bytes_read) - read_done = true; - } -error: - return rc; -} - - -static int dsi_enable_ulps(struct dsi_ctrl *dsi_ctrl) -{ - int rc = 0; - u32 lanes = 0; - u32 ulps_lanes; - - if (dsi_ctrl->host_config.panel_mode == DSI_OP_CMD_MODE) - lanes = dsi_ctrl->host_config.common_config.data_lanes; - - rc = dsi_ctrl->hw.ops.wait_for_lane_idle(&dsi_ctrl->hw, lanes); - if (rc) { - pr_err("lanes not entering idle, skip ULPS\n"); - return rc; - } - - if (!dsi_ctrl->hw.ops.ulps_ops.ulps_request || - !dsi_ctrl->hw.ops.ulps_ops.ulps_exit) { - pr_debug("DSI controller ULPS ops not present\n"); - return 0; - } - - lanes |= DSI_CLOCK_LANE; - dsi_ctrl->hw.ops.ulps_ops.ulps_request(&dsi_ctrl->hw, lanes); - - ulps_lanes = dsi_ctrl->hw.ops.ulps_ops.get_lanes_in_ulps(&dsi_ctrl->hw); - - if ((lanes & ulps_lanes) != lanes) { - pr_err("Failed to enter ULPS, request=0x%x, actual=0x%x\n", - lanes, ulps_lanes); - rc = -EIO; - } - - return rc; -} - -static int dsi_disable_ulps(struct dsi_ctrl *dsi_ctrl) -{ - int rc = 0; - u32 ulps_lanes, lanes = 0; - - dsi_ctrl->hw.ops.clear_phy0_ln_err(&dsi_ctrl->hw); - - if (!dsi_ctrl->hw.ops.ulps_ops.ulps_request || - !dsi_ctrl->hw.ops.ulps_ops.ulps_exit) { - pr_debug("DSI controller ULPS ops not present\n"); - return 0; - } - - if (dsi_ctrl->host_config.panel_mode == DSI_OP_CMD_MODE) - lanes = dsi_ctrl->host_config.common_config.data_lanes; - - lanes |= DSI_CLOCK_LANE; - - ulps_lanes = dsi_ctrl->hw.ops.ulps_ops.get_lanes_in_ulps(&dsi_ctrl->hw); - - if ((lanes & ulps_lanes) != lanes) - pr_err("Mismatch between lanes in ULPS\n"); - - lanes &= ulps_lanes; - - dsi_ctrl->hw.ops.ulps_ops.ulps_exit(&dsi_ctrl->hw, lanes); - - ulps_lanes = dsi_ctrl->hw.ops.ulps_ops.get_lanes_in_ulps(&dsi_ctrl->hw); - if (ulps_lanes & lanes) { - pr_err("Lanes (0x%x) stuck in ULPS\n", ulps_lanes); - rc = -EIO; - } - - return rc; -} - -static int dsi_ctrl_drv_state_init(struct dsi_ctrl *dsi_ctrl) -{ - int rc = 0; - bool splash_enabled = false; - struct dsi_ctrl_state_info *state = &dsi_ctrl->current_state; - - if (!splash_enabled) { - state->power_state = DSI_CTRL_POWER_VREG_OFF; - state->cmd_engine_state = DSI_CTRL_ENGINE_OFF; - state->vid_engine_state = DSI_CTRL_ENGINE_OFF; - } - - return rc; -} - -static int dsi_ctrl_buffer_deinit(struct dsi_ctrl *dsi_ctrl) -{ - struct msm_gem_address_space *aspace = NULL; - - if (dsi_ctrl->tx_cmd_buf) { - aspace = dsi_ctrl_get_aspace(dsi_ctrl, - MSM_SMMU_DOMAIN_UNSECURE); - if (!aspace) { - pr_err("failed to get address space\n"); - return -ENOMEM; - } - - msm_gem_put_iova(dsi_ctrl->tx_cmd_buf, aspace); - - mutex_lock(&dsi_ctrl->drm_dev->struct_mutex); - msm_gem_free_object(dsi_ctrl->tx_cmd_buf); - mutex_unlock(&dsi_ctrl->drm_dev->struct_mutex); - dsi_ctrl->tx_cmd_buf = NULL; - } - - return 0; -} - -int dsi_ctrl_buffer_init(struct dsi_ctrl *dsi_ctrl) -{ - int rc = 0; - u64 iova = 0; - struct msm_gem_address_space *aspace = NULL; - - aspace = dsi_ctrl_get_aspace(dsi_ctrl, MSM_SMMU_DOMAIN_UNSECURE); - if (!aspace) { - pr_err("failed to get address space\n"); - return -ENOMEM; - } - - dsi_ctrl->tx_cmd_buf = msm_gem_new(dsi_ctrl->drm_dev, - SZ_4K, - MSM_BO_UNCACHED); - - if (IS_ERR(dsi_ctrl->tx_cmd_buf)) { - rc = PTR_ERR(dsi_ctrl->tx_cmd_buf); - pr_err("failed to allocate gem, rc=%d\n", rc); - dsi_ctrl->tx_cmd_buf = NULL; - goto error; - } - - dsi_ctrl->cmd_buffer_size = SZ_4K; - - rc = msm_gem_get_iova(dsi_ctrl->tx_cmd_buf, aspace, &iova); - if (rc) { - pr_err("failed to get iova, rc=%d\n", rc); - (void)dsi_ctrl_buffer_deinit(dsi_ctrl); - goto error; - } - - if (iova & 0x07) { - pr_err("Tx command buffer is not 8 byte aligned\n"); - rc = -ENOTSUPP; - (void)dsi_ctrl_buffer_deinit(dsi_ctrl); - goto error; - } -error: - return rc; -} - -static int dsi_enable_io_clamp(struct dsi_ctrl *dsi_ctrl, - bool enable, bool ulps_enabled) -{ - u32 lanes = 0; - - if (dsi_ctrl->host_config.panel_mode == DSI_OP_CMD_MODE) - lanes = dsi_ctrl->host_config.common_config.data_lanes; - - lanes |= DSI_CLOCK_LANE; - - if (enable) - dsi_ctrl->hw.ops.clamp_enable(&dsi_ctrl->hw, - lanes, ulps_enabled); - else - dsi_ctrl->hw.ops.clamp_disable(&dsi_ctrl->hw, - lanes, ulps_enabled); - - return 0; -} - -static int dsi_ctrl_dts_parse(struct dsi_ctrl *dsi_ctrl, - struct device_node *of_node) -{ - u32 index = 0; - int rc = 0; - - if (!dsi_ctrl || !of_node) { - pr_err("invalid dsi_ctrl:%d or of_node:%d\n", - dsi_ctrl != NULL, of_node != NULL); - return -EINVAL; - } - - rc = of_property_read_u32(of_node, "cell-index", &index); - if (rc) { - pr_debug("cell index not set, default to 0\n"); - index = 0; - } - - dsi_ctrl->cell_index = index; - dsi_ctrl->name = of_get_property(of_node, "label", NULL); - if (!dsi_ctrl->name) - dsi_ctrl->name = DSI_CTRL_DEFAULT_LABEL; - - dsi_ctrl->phy_isolation_enabled = of_property_read_bool(of_node, - "qcom,dsi-phy-isolation-enabled"); - - return 0; -} - -static int dsi_ctrl_dev_probe(struct platform_device *pdev) -{ - struct dsi_ctrl *dsi_ctrl; - struct dsi_ctrl_list_item *item; - const struct of_device_id *id; - enum dsi_ctrl_version version; - int rc = 0; - - id = of_match_node(msm_dsi_of_match, pdev->dev.of_node); - if (!id) - return -ENODEV; - - version = *(enum dsi_ctrl_version *)id->data; - - item = devm_kzalloc(&pdev->dev, sizeof(*item), GFP_KERNEL); - if (!item) - return -ENOMEM; - - dsi_ctrl = devm_kzalloc(&pdev->dev, sizeof(*dsi_ctrl), GFP_KERNEL); - if (!dsi_ctrl) - return -ENOMEM; - - dsi_ctrl->version = version; - dsi_ctrl->irq_info.irq_num = -1; - dsi_ctrl->irq_info.irq_stat_mask = 0x0; - - spin_lock_init(&dsi_ctrl->irq_info.irq_lock); - - rc = dsi_ctrl_dts_parse(dsi_ctrl, pdev->dev.of_node); - if (rc) { - pr_err("ctrl:%d dts parse failed, rc = %d\n", - dsi_ctrl->cell_index, rc); - goto fail; - } - - rc = dsi_ctrl_init_regmap(pdev, dsi_ctrl); - if (rc) { - pr_err("Failed to parse register information, rc = %d\n", rc); - goto fail; - } - - rc = dsi_ctrl_clocks_init(pdev, dsi_ctrl); - if (rc) { - pr_err("Failed to parse clock information, rc = %d\n", rc); - goto fail; - } - - rc = dsi_ctrl_supplies_init(pdev, dsi_ctrl); - if (rc) { - pr_err("Failed to parse voltage supplies, rc = %d\n", rc); - goto fail_clks; - } - - rc = dsi_catalog_ctrl_setup(&dsi_ctrl->hw, dsi_ctrl->version, - dsi_ctrl->cell_index, dsi_ctrl->phy_isolation_enabled); - if (rc) { - pr_err("Catalog does not support version (%d)\n", - dsi_ctrl->version); - goto fail_supplies; - } - - rc = dsi_ctrl_axi_bus_client_init(pdev, dsi_ctrl); - if (rc) - pr_debug("failed to init axi bus client, rc = %d\n", rc); - - item->ctrl = dsi_ctrl; - - mutex_lock(&dsi_ctrl_list_lock); - list_add(&item->list, &dsi_ctrl_list); - mutex_unlock(&dsi_ctrl_list_lock); - - mutex_init(&dsi_ctrl->ctrl_lock); - - dsi_ctrl->pdev = pdev; - platform_set_drvdata(pdev, dsi_ctrl); - pr_info("Probe successful for %s\n", dsi_ctrl->name); - - return 0; - -fail_supplies: - (void)dsi_ctrl_supplies_deinit(dsi_ctrl); -fail_clks: - (void)dsi_ctrl_clocks_deinit(dsi_ctrl); -fail: - return rc; -} - -static int dsi_ctrl_dev_remove(struct platform_device *pdev) -{ - int rc = 0; - struct dsi_ctrl *dsi_ctrl; - struct list_head *pos, *tmp; - - dsi_ctrl = platform_get_drvdata(pdev); - - mutex_lock(&dsi_ctrl_list_lock); - list_for_each_safe(pos, tmp, &dsi_ctrl_list) { - struct dsi_ctrl_list_item *n = list_entry(pos, - struct dsi_ctrl_list_item, - list); - if (n->ctrl == dsi_ctrl) { - list_del(&n->list); - break; - } - } - mutex_unlock(&dsi_ctrl_list_lock); - - mutex_lock(&dsi_ctrl->ctrl_lock); - rc = dsi_ctrl_axi_bus_client_deinit(dsi_ctrl); - if (rc) - pr_err("failed to deinitialize axi bus client, rc = %d\n", rc); - - rc = dsi_ctrl_supplies_deinit(dsi_ctrl); - if (rc) - pr_err("failed to deinitialize voltage supplies, rc=%d\n", rc); - - rc = dsi_ctrl_clocks_deinit(dsi_ctrl); - if (rc) - pr_err("failed to deinitialize clocks, rc=%d\n", rc); - - mutex_unlock(&dsi_ctrl->ctrl_lock); - - mutex_destroy(&dsi_ctrl->ctrl_lock); - devm_kfree(&pdev->dev, dsi_ctrl); - - platform_set_drvdata(pdev, NULL); - return 0; -} - -static struct platform_driver dsi_ctrl_driver = { - .probe = dsi_ctrl_dev_probe, - .remove = dsi_ctrl_dev_remove, - .driver = { - .name = "drm_dsi_ctrl", - .of_match_table = msm_dsi_of_match, - }, -}; - -#if defined(CONFIG_DEBUG_FS) - -void dsi_ctrl_debug_dump(void) -{ - struct list_head *pos, *tmp; - struct dsi_ctrl *ctrl = NULL; - - mutex_lock(&dsi_ctrl_list_lock); - list_for_each_safe(pos, tmp, &dsi_ctrl_list) { - struct dsi_ctrl_list_item *n; - - n = list_entry(pos, struct dsi_ctrl_list_item, list); - ctrl = n->ctrl; - pr_err("dsi ctrl:%d\n", ctrl->cell_index); - ctrl->hw.ops.debug_bus(&ctrl->hw); - } - mutex_unlock(&dsi_ctrl_list_lock); -} - -#endif -/** - * dsi_ctrl_get() - get a dsi_ctrl handle from an of_node - * @of_node: of_node of the DSI controller. - * - * Gets the DSI controller handle for the corresponding of_node. The ref count - * is incremented to one and all subsequent gets will fail until the original - * clients calls a put. - * - * Return: DSI Controller handle. - */ -struct dsi_ctrl *dsi_ctrl_get(struct device_node *of_node) -{ - struct list_head *pos, *tmp; - struct dsi_ctrl *ctrl = NULL; - - mutex_lock(&dsi_ctrl_list_lock); - list_for_each_safe(pos, tmp, &dsi_ctrl_list) { - struct dsi_ctrl_list_item *n; - - n = list_entry(pos, struct dsi_ctrl_list_item, list); - if (n->ctrl->pdev->dev.of_node == of_node) { - ctrl = n->ctrl; - break; - } - } - mutex_unlock(&dsi_ctrl_list_lock); - - if (!ctrl) { - pr_err("Device with of node not found\n"); - ctrl = ERR_PTR(-EPROBE_DEFER); - return ctrl; - } - - mutex_lock(&ctrl->ctrl_lock); - if (ctrl->refcount == 1) { - pr_err("[%s] Device in use\n", ctrl->name); - ctrl = ERR_PTR(-EBUSY); - } else { - ctrl->refcount++; - } - mutex_unlock(&ctrl->ctrl_lock); - return ctrl; -} - -/** - * dsi_ctrl_put() - releases a dsi controller handle. - * @dsi_ctrl: DSI controller handle. - * - * Releases the DSI controller. Driver will clean up all resources and puts back - * the DSI controller into reset state. - */ -void dsi_ctrl_put(struct dsi_ctrl *dsi_ctrl) -{ - mutex_lock(&dsi_ctrl->ctrl_lock); - - if (dsi_ctrl->refcount == 0) - pr_err("Unbalanced %s call\n", __func__); - else - dsi_ctrl->refcount--; - - mutex_unlock(&dsi_ctrl->ctrl_lock); -} - -/** - * dsi_ctrl_drv_init() - initialize dsi controller driver. - * @dsi_ctrl: DSI controller handle. - * @parent: Parent directory for debug fs. - * - * Initializes DSI controller driver. Driver should be initialized after - * dsi_ctrl_get() succeeds. - * - * Return: error code. - */ -int dsi_ctrl_drv_init(struct dsi_ctrl *dsi_ctrl, struct dentry *parent) -{ - int rc = 0; - - if (!dsi_ctrl || !parent) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - mutex_lock(&dsi_ctrl->ctrl_lock); - rc = dsi_ctrl_drv_state_init(dsi_ctrl); - if (rc) { - pr_err("Failed to initialize driver state, rc=%d\n", rc); - goto error; - } - - rc = dsi_ctrl_debugfs_init(dsi_ctrl, parent); - if (rc) { - pr_err("[DSI_%d] failed to init debug fs, rc=%d\n", - dsi_ctrl->cell_index, rc); - goto error; - } - -error: - mutex_unlock(&dsi_ctrl->ctrl_lock); - return rc; -} - -/** - * dsi_ctrl_drv_deinit() - de-initializes dsi controller driver - * @dsi_ctrl: DSI controller handle. - * - * Releases all resources acquired by dsi_ctrl_drv_init(). - * - * Return: error code. - */ -int dsi_ctrl_drv_deinit(struct dsi_ctrl *dsi_ctrl) -{ - int rc = 0; - - if (!dsi_ctrl) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - mutex_lock(&dsi_ctrl->ctrl_lock); - - rc = dsi_ctrl_debugfs_deinit(dsi_ctrl); - if (rc) - pr_err("failed to release debugfs root, rc=%d\n", rc); - - rc = dsi_ctrl_buffer_deinit(dsi_ctrl); - if (rc) - pr_err("Failed to free cmd buffers, rc=%d\n", rc); - - mutex_unlock(&dsi_ctrl->ctrl_lock); - return rc; -} - -int dsi_ctrl_clk_cb_register(struct dsi_ctrl *dsi_ctrl, - struct clk_ctrl_cb *clk_cb) -{ - if (!dsi_ctrl || !clk_cb) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - dsi_ctrl->clk_cb.priv = clk_cb->priv; - dsi_ctrl->clk_cb.dsi_clk_cb = clk_cb->dsi_clk_cb; - return 0; -} - -/** - * dsi_ctrl_phy_sw_reset() - perform a PHY software reset - * @dsi_ctrl: DSI controller handle. - * - * Performs a PHY software reset on the DSI controller. Reset should be done - * when the controller power state is DSI_CTRL_POWER_CORE_CLK_ON and the PHY is - * not enabled. - * - * This function will fail if driver is in any other state. - * - * Return: error code. - */ -int dsi_ctrl_phy_sw_reset(struct dsi_ctrl *dsi_ctrl) -{ - int rc = 0; - - if (!dsi_ctrl) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - mutex_lock(&dsi_ctrl->ctrl_lock); - rc = dsi_ctrl_check_state(dsi_ctrl, DSI_CTRL_OP_PHY_SW_RESET, 0x0); - if (rc) { - pr_err("[DSI_%d] Controller state check failed, rc=%d\n", - dsi_ctrl->cell_index, rc); - goto error; - } - - dsi_ctrl->hw.ops.phy_sw_reset(&dsi_ctrl->hw); - - pr_debug("[DSI_%d] PHY soft reset done\n", dsi_ctrl->cell_index); - dsi_ctrl_update_state(dsi_ctrl, DSI_CTRL_OP_PHY_SW_RESET, 0x0); -error: - mutex_unlock(&dsi_ctrl->ctrl_lock); - return rc; -} - -/** - * dsi_ctrl_seamless_timing_update() - update only controller timing - * @dsi_ctrl: DSI controller handle. - * @timing: New DSI timing info - * - * Updates host timing values to conduct a seamless transition to new timing - * For example, to update the porch values in a dynamic fps switch. - * - * Return: error code. - */ -int dsi_ctrl_async_timing_update(struct dsi_ctrl *dsi_ctrl, - struct dsi_mode_info *timing) -{ - struct dsi_mode_info *host_mode; - int rc = 0; - - if (!dsi_ctrl || !timing) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - mutex_lock(&dsi_ctrl->ctrl_lock); - - rc = dsi_ctrl_check_state(dsi_ctrl, DSI_CTRL_OP_ASYNC_TIMING, - DSI_CTRL_ENGINE_ON); - if (rc) { - pr_err("[DSI_%d] Controller state check failed, rc=%d\n", - dsi_ctrl->cell_index, rc); - goto exit; - } - - host_mode = &dsi_ctrl->host_config.video_timing; - memcpy(host_mode, timing, sizeof(*host_mode)); - dsi_ctrl->hw.ops.set_timing_db(&dsi_ctrl->hw, true); - dsi_ctrl->hw.ops.set_video_timing(&dsi_ctrl->hw, host_mode); - -exit: - mutex_unlock(&dsi_ctrl->ctrl_lock); - return rc; -} - -/** - * dsi_ctrl_timing_db_update() - update only controller Timing DB - * @dsi_ctrl: DSI controller handle. - * @enable: Enable/disable Timing DB register - * - * Update timing db register value during dfps usecases - * - * Return: error code. - */ -int dsi_ctrl_timing_db_update(struct dsi_ctrl *dsi_ctrl, - bool enable) -{ - int rc = 0; - - if (!dsi_ctrl) { - pr_err("Invalid dsi_ctrl\n"); - return -EINVAL; - } - - mutex_lock(&dsi_ctrl->ctrl_lock); - - rc = dsi_ctrl_check_state(dsi_ctrl, DSI_CTRL_OP_ASYNC_TIMING, - DSI_CTRL_ENGINE_ON); - if (rc) { - pr_err("[DSI_%d] Controller state check failed, rc=%d\n", - dsi_ctrl->cell_index, rc); - goto exit; - } - - /* - * Add HW recommended delay for dfps feature. - * When prefetch is enabled, MDSS HW works on 2 vsync - * boundaries i.e. mdp_vsync and panel_vsync. - * In the current implementation we are only waiting - * for mdp_vsync. We need to make sure that interface - * flush is after panel_vsync. So, added the recommended - * delays after dfps update. - */ - usleep_range(2000, 2010); - - dsi_ctrl->hw.ops.set_timing_db(&dsi_ctrl->hw, enable); - -exit: - mutex_unlock(&dsi_ctrl->ctrl_lock); - return rc; -} - -int dsi_ctrl_setup(struct dsi_ctrl *dsi_ctrl) -{ - int rc = 0; - - if (!dsi_ctrl) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - mutex_lock(&dsi_ctrl->ctrl_lock); - - dsi_ctrl->hw.ops.setup_lane_map(&dsi_ctrl->hw, - &dsi_ctrl->host_config.lane_map); - - dsi_ctrl->hw.ops.host_setup(&dsi_ctrl->hw, - &dsi_ctrl->host_config.common_config); - - if (dsi_ctrl->host_config.panel_mode == DSI_OP_CMD_MODE) { - dsi_ctrl->hw.ops.cmd_engine_setup(&dsi_ctrl->hw, - &dsi_ctrl->host_config.common_config, - &dsi_ctrl->host_config.u.cmd_engine); - - dsi_ctrl->hw.ops.setup_cmd_stream(&dsi_ctrl->hw, - &dsi_ctrl->host_config.video_timing, - dsi_ctrl->host_config.video_timing.h_active * 3, - 0x0, - &dsi_ctrl->roi); - dsi_ctrl->hw.ops.cmd_engine_en(&dsi_ctrl->hw, true); - } else { - dsi_ctrl->hw.ops.video_engine_setup(&dsi_ctrl->hw, - &dsi_ctrl->host_config.common_config, - &dsi_ctrl->host_config.u.video_engine); - dsi_ctrl->hw.ops.set_video_timing(&dsi_ctrl->hw, - &dsi_ctrl->host_config.video_timing); - dsi_ctrl->hw.ops.video_engine_en(&dsi_ctrl->hw, true); - } - - dsi_ctrl->hw.ops.enable_status_interrupts(&dsi_ctrl->hw, 0x0); - dsi_ctrl->hw.ops.enable_error_interrupts(&dsi_ctrl->hw, 0x0); - dsi_ctrl->hw.ops.ctrl_en(&dsi_ctrl->hw, true); - - mutex_unlock(&dsi_ctrl->ctrl_lock); - return rc; -} - -/** - * dsi_ctrl_phy_reset_config() - Mask/unmask propagation of ahb reset signal - * to DSI PHY hardware. - * @dsi_ctrl: DSI controller handle. - * @enable: Mask/unmask the PHY reset signal. - * - * Return: error code. - */ -int dsi_ctrl_phy_reset_config(struct dsi_ctrl *dsi_ctrl, bool enable) -{ - if (!dsi_ctrl) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - if (dsi_ctrl->hw.ops.phy_reset_config) - dsi_ctrl->hw.ops.phy_reset_config(&dsi_ctrl->hw, enable); - - return 0; -} - -static void dsi_ctrl_handle_error_status(struct dsi_ctrl *dsi_ctrl, - unsigned long int error) -{ - pr_err("%s: %lu\n", __func__, error); - - /* DTLN PHY error */ - if (error & 0x3000e00) - if (dsi_ctrl->hw.ops.clear_error_status) - dsi_ctrl->hw.ops.clear_error_status(&dsi_ctrl->hw, - 0x3000e00); - - /* DSI FIFO OVERFLOW error */ - if (error & 0xf0000) { - if (dsi_ctrl->hw.ops.clear_error_status) - dsi_ctrl->hw.ops.clear_error_status(&dsi_ctrl->hw, - 0xf0000); - } - - /* DSI FIFO UNDERFLOW error */ - if (error & 0xf00000) { - if (dsi_ctrl->hw.ops.clear_error_status) - dsi_ctrl->hw.ops.clear_error_status(&dsi_ctrl->hw, - 0xf00000); - } - - /* DSI PLL UNLOCK error */ - if (error & BIT(8)) - if (dsi_ctrl->hw.ops.clear_error_status) - dsi_ctrl->hw.ops.clear_error_status(&dsi_ctrl->hw, - BIT(8)); -} - -/** - * dsi_ctrl_isr - interrupt service routine for DSI CTRL component - * @irq: Incoming IRQ number - * @ptr: Pointer to user data structure (struct dsi_ctrl) - * Returns: IRQ_HANDLED if no further action required - */ -static irqreturn_t dsi_ctrl_isr(int irq, void *ptr) -{ - struct dsi_ctrl *dsi_ctrl; - struct dsi_event_cb_info cb_info; - unsigned long flags; - uint32_t cell_index, status, i; - uint64_t errors; - - if (!ptr) - return IRQ_NONE; - dsi_ctrl = ptr; - - /* clear status interrupts */ - if (dsi_ctrl->hw.ops.get_interrupt_status) - status = dsi_ctrl->hw.ops.get_interrupt_status(&dsi_ctrl->hw); - else - status = 0x0; - - if (dsi_ctrl->hw.ops.clear_interrupt_status) - dsi_ctrl->hw.ops.clear_interrupt_status(&dsi_ctrl->hw, status); - - spin_lock_irqsave(&dsi_ctrl->irq_info.irq_lock, flags); - cell_index = dsi_ctrl->cell_index; - spin_unlock_irqrestore(&dsi_ctrl->irq_info.irq_lock, flags); - - /* clear error interrupts */ - if (dsi_ctrl->hw.ops.get_error_status) - errors = dsi_ctrl->hw.ops.get_error_status(&dsi_ctrl->hw); - else - errors = 0x0; - - if (errors) { - /* handle DSI error recovery */ - dsi_ctrl_handle_error_status(dsi_ctrl, errors); - if (dsi_ctrl->hw.ops.clear_error_status) - dsi_ctrl->hw.ops.clear_error_status(&dsi_ctrl->hw, - errors); - } - - if (status & DSI_CMD_MODE_DMA_DONE) { - dsi_ctrl_disable_status_interrupt(dsi_ctrl, - DSI_SINT_CMD_MODE_DMA_DONE); - complete_all(&dsi_ctrl->irq_info.cmd_dma_done); - } - - if (status & DSI_CMD_FRAME_DONE) { - dsi_ctrl_disable_status_interrupt(dsi_ctrl, - DSI_SINT_CMD_FRAME_DONE); - complete_all(&dsi_ctrl->irq_info.cmd_frame_done); - } - - if (status & DSI_VIDEO_MODE_FRAME_DONE) { - dsi_ctrl_disable_status_interrupt(dsi_ctrl, - DSI_SINT_VIDEO_MODE_FRAME_DONE); - complete_all(&dsi_ctrl->irq_info.vid_frame_done); - } - - if (status & DSI_BTA_DONE) { - dsi_ctrl_disable_status_interrupt(dsi_ctrl, - DSI_SINT_BTA_DONE); - complete_all(&dsi_ctrl->irq_info.bta_done); - } - - for (i = 0; status && i < DSI_STATUS_INTERRUPT_COUNT; ++i) { - if (status & 0x1) { - spin_lock_irqsave(&dsi_ctrl->irq_info.irq_lock, flags); - cb_info = dsi_ctrl->irq_info.irq_stat_cb[i]; - spin_unlock_irqrestore( - &dsi_ctrl->irq_info.irq_lock, flags); - - if (cb_info.event_cb) - (void)cb_info.event_cb(cb_info.event_usr_ptr, - cb_info.event_idx, - cell_index, irq, 0, 0, 0); - } - status >>= 1; - } - - return IRQ_HANDLED; -} - -/** - * _dsi_ctrl_setup_isr - register ISR handler - * @dsi_ctrl: Pointer to associated dsi_ctrl structure - * Returns: Zero on success - */ -static int dsi_ctrl_setup_isr(struct dsi_ctrl *dsi_ctrl) -{ - int irq_num, rc; - - if (!dsi_ctrl) - return -EINVAL; - if (dsi_ctrl->irq_info.irq_num != -1) - return 0; - - init_completion(&dsi_ctrl->irq_info.cmd_dma_done); - init_completion(&dsi_ctrl->irq_info.vid_frame_done); - init_completion(&dsi_ctrl->irq_info.cmd_frame_done); - init_completion(&dsi_ctrl->irq_info.bta_done); - - irq_num = platform_get_irq(dsi_ctrl->pdev, 0); - if (irq_num < 0) { - pr_err("[DSI_%d] Failed to get IRQ number, %d\n", - dsi_ctrl->cell_index, irq_num); - rc = irq_num; - } else { - rc = devm_request_threaded_irq(&dsi_ctrl->pdev->dev, irq_num, - dsi_ctrl_isr, NULL, 0, "dsi_ctrl", dsi_ctrl); - if (rc) { - pr_err("[DSI_%d] Failed to request IRQ, %d\n", - dsi_ctrl->cell_index, rc); - } else { - dsi_ctrl->irq_info.irq_num = irq_num; - disable_irq_nosync(irq_num); - - pr_debug("[DSI_%d] IRQ %d registered\n", - dsi_ctrl->cell_index, irq_num); - } - } - return rc; -} - -/** - * _dsi_ctrl_destroy_isr - unregister ISR handler - * @dsi_ctrl: Pointer to associated dsi_ctrl structure - */ -static void _dsi_ctrl_destroy_isr(struct dsi_ctrl *dsi_ctrl) -{ - if (!dsi_ctrl || !dsi_ctrl->pdev || dsi_ctrl->irq_info.irq_num < 0) - return; - - if (dsi_ctrl->irq_info.irq_num != -1) { - devm_free_irq(&dsi_ctrl->pdev->dev, - dsi_ctrl->irq_info.irq_num, dsi_ctrl); - dsi_ctrl->irq_info.irq_num = -1; - } -} - -void dsi_ctrl_enable_status_interrupt(struct dsi_ctrl *dsi_ctrl, - uint32_t intr_idx, struct dsi_event_cb_info *event_info) -{ - unsigned long flags; - - if (!dsi_ctrl || dsi_ctrl->irq_info.irq_num == -1 || - intr_idx >= DSI_STATUS_INTERRUPT_COUNT) - return; - - spin_lock_irqsave(&dsi_ctrl->irq_info.irq_lock, flags); - - if (dsi_ctrl->irq_info.irq_stat_refcount[intr_idx] == 0) { - /* enable irq on first request */ - if (dsi_ctrl->irq_info.irq_stat_mask == 0) - enable_irq(dsi_ctrl->irq_info.irq_num); - - /* update hardware mask */ - dsi_ctrl->irq_info.irq_stat_mask |= BIT(intr_idx); - dsi_ctrl->hw.ops.enable_status_interrupts(&dsi_ctrl->hw, - dsi_ctrl->irq_info.irq_stat_mask); - } - ++(dsi_ctrl->irq_info.irq_stat_refcount[intr_idx]); - - if (event_info) - dsi_ctrl->irq_info.irq_stat_cb[intr_idx] = *event_info; - - spin_unlock_irqrestore(&dsi_ctrl->irq_info.irq_lock, flags); -} - -void dsi_ctrl_disable_status_interrupt(struct dsi_ctrl *dsi_ctrl, - uint32_t intr_idx) -{ - unsigned long flags; - - if (!dsi_ctrl || dsi_ctrl->irq_info.irq_num == -1 || - intr_idx >= DSI_STATUS_INTERRUPT_COUNT) - return; - - spin_lock_irqsave(&dsi_ctrl->irq_info.irq_lock, flags); - - if (dsi_ctrl->irq_info.irq_stat_refcount[intr_idx]) - if (--(dsi_ctrl->irq_info.irq_stat_refcount[intr_idx]) == 0) { - dsi_ctrl->irq_info.irq_stat_mask &= ~BIT(intr_idx); - dsi_ctrl->hw.ops.enable_status_interrupts(&dsi_ctrl->hw, - dsi_ctrl->irq_info.irq_stat_mask); - - /* don't need irq if no lines are enabled */ - if (dsi_ctrl->irq_info.irq_stat_mask == 0) - disable_irq_nosync(dsi_ctrl->irq_info.irq_num); - } - - spin_unlock_irqrestore(&dsi_ctrl->irq_info.irq_lock, flags); -} - -int dsi_ctrl_host_timing_update(struct dsi_ctrl *dsi_ctrl) -{ - if (!dsi_ctrl) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - if (dsi_ctrl->hw.ops.host_setup) - dsi_ctrl->hw.ops.host_setup(&dsi_ctrl->hw, - &dsi_ctrl->host_config.common_config); - - if (dsi_ctrl->host_config.panel_mode == DSI_OP_CMD_MODE) { - if (dsi_ctrl->hw.ops.cmd_engine_setup) - dsi_ctrl->hw.ops.cmd_engine_setup(&dsi_ctrl->hw, - &dsi_ctrl->host_config.common_config, - &dsi_ctrl->host_config.u.cmd_engine); - - if (dsi_ctrl->hw.ops.setup_cmd_stream) - dsi_ctrl->hw.ops.setup_cmd_stream(&dsi_ctrl->hw, - &dsi_ctrl->host_config.video_timing, - dsi_ctrl->host_config.video_timing.h_active * 3, - 0x0, NULL); - } else { - pr_err("invalid panel mode for resolution switch\n"); - return -EINVAL; - } - - return 0; -} - -/** - * dsi_ctrl_host_init() - Initialize DSI host hardware. - * @dsi_ctrl: DSI controller handle. - * - * Initializes DSI controller hardware with host configuration provided by - * dsi_ctrl_update_host_config(). Initialization can be performed only during - * DSI_CTRL_POWER_CORE_CLK_ON state and after the PHY SW reset has been - * performed. - * - * Return: error code. - */ -int dsi_ctrl_host_init(struct dsi_ctrl *dsi_ctrl) -{ - int rc = 0; - - if (!dsi_ctrl) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - mutex_lock(&dsi_ctrl->ctrl_lock); - rc = dsi_ctrl_check_state(dsi_ctrl, DSI_CTRL_OP_HOST_INIT, 0x1); - if (rc) { - pr_err("[DSI_%d] Controller state check failed, rc=%d\n", - dsi_ctrl->cell_index, rc); - goto error; - } - - dsi_ctrl->hw.ops.setup_lane_map(&dsi_ctrl->hw, - &dsi_ctrl->host_config.lane_map); - - dsi_ctrl->hw.ops.host_setup(&dsi_ctrl->hw, - &dsi_ctrl->host_config.common_config); - - if (dsi_ctrl->host_config.panel_mode == DSI_OP_CMD_MODE) { - dsi_ctrl->hw.ops.cmd_engine_setup(&dsi_ctrl->hw, - &dsi_ctrl->host_config.common_config, - &dsi_ctrl->host_config.u.cmd_engine); - - dsi_ctrl->hw.ops.setup_cmd_stream(&dsi_ctrl->hw, - &dsi_ctrl->host_config.video_timing, - dsi_ctrl->host_config.video_timing.h_active * 3, - 0x0, - NULL); - } else { - dsi_ctrl->hw.ops.video_engine_setup(&dsi_ctrl->hw, - &dsi_ctrl->host_config.common_config, - &dsi_ctrl->host_config.u.video_engine); - dsi_ctrl->hw.ops.set_video_timing(&dsi_ctrl->hw, - &dsi_ctrl->host_config.video_timing); - } - - dsi_ctrl_setup_isr(dsi_ctrl); - - dsi_ctrl->hw.ops.enable_status_interrupts(&dsi_ctrl->hw, 0x0); - dsi_ctrl->hw.ops.enable_error_interrupts(&dsi_ctrl->hw, 0x0); - - pr_debug("[DSI_%d]Host initialization complete\n", - dsi_ctrl->cell_index); - dsi_ctrl_update_state(dsi_ctrl, DSI_CTRL_OP_HOST_INIT, 0x1); -error: - mutex_unlock(&dsi_ctrl->ctrl_lock); - return rc; -} - -int dsi_ctrl_soft_reset(struct dsi_ctrl *dsi_ctrl) -{ - if (!dsi_ctrl) - return -EINVAL; - - mutex_lock(&dsi_ctrl->ctrl_lock); - dsi_ctrl->hw.ops.soft_reset(&dsi_ctrl->hw); - mutex_unlock(&dsi_ctrl->ctrl_lock); - - pr_debug("[DSI_%d]Soft reset complete\n", dsi_ctrl->cell_index); - return 0; -} - -/** - * dsi_ctrl_host_deinit() - De-Initialize DSI host hardware. - * @dsi_ctrl: DSI controller handle. - * - * De-initializes DSI controller hardware. It can be performed only during - * DSI_CTRL_POWER_CORE_CLK_ON state after LINK clocks have been turned off. - * - * Return: error code. - */ -int dsi_ctrl_host_deinit(struct dsi_ctrl *dsi_ctrl) -{ - int rc = 0; - - if (!dsi_ctrl) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - mutex_lock(&dsi_ctrl->ctrl_lock); - - _dsi_ctrl_destroy_isr(dsi_ctrl); - - rc = dsi_ctrl_check_state(dsi_ctrl, DSI_CTRL_OP_HOST_INIT, 0x0); - if (rc) { - pr_err("[DSI_%d] Controller state check failed, rc=%d\n", - dsi_ctrl->cell_index, rc); - pr_err("driver state check failed, rc=%d\n", rc); - goto error; - } - - pr_debug("[DSI_%d] Host deinitization complete\n", - dsi_ctrl->cell_index); - dsi_ctrl_update_state(dsi_ctrl, DSI_CTRL_OP_HOST_INIT, 0x0); -error: - mutex_unlock(&dsi_ctrl->ctrl_lock); - return rc; -} - -/** - * dsi_ctrl_update_host_config() - update dsi host configuration - * @dsi_ctrl: DSI controller handle. - * @config: DSI host configuration. - * @flags: dsi_mode_flags modifying the behavior - * - * Updates driver with new Host configuration to use for host initialization. - * This function call will only update the software context. The stored - * configuration information will be used when the host is initialized. - * - * Return: error code. - */ -int dsi_ctrl_update_host_config(struct dsi_ctrl *ctrl, - struct dsi_host_config *config, - int flags, void *clk_handle) -{ - int rc = 0; - - if (!ctrl || !config) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - mutex_lock(&ctrl->ctrl_lock); - - rc = dsi_ctrl_validate_panel_info(ctrl, config); - if (rc) { - pr_err("panel validation failed, rc=%d\n", rc); - goto error; - } - - if (!(flags & (DSI_MODE_FLAG_SEAMLESS | DSI_MODE_FLAG_VRR))) { - rc = dsi_ctrl_update_link_freqs(ctrl, config, clk_handle); - if (rc) { - pr_err("[%s] failed to update link frequencies, rc=%d\n", - ctrl->name, rc); - goto error; - } - } - - pr_debug("[DSI_%d]Host config updated\n", ctrl->cell_index); - memcpy(&ctrl->host_config, config, sizeof(ctrl->host_config)); - ctrl->mode_bounds.x = ctrl->host_config.video_timing.h_active * - ctrl->horiz_index; - ctrl->mode_bounds.y = 0; - ctrl->mode_bounds.w = ctrl->host_config.video_timing.h_active; - ctrl->mode_bounds.h = ctrl->host_config.video_timing.v_active; - memcpy(&ctrl->roi, &ctrl->mode_bounds, sizeof(ctrl->mode_bounds)); - ctrl->roi.x = 0; -error: - mutex_unlock(&ctrl->ctrl_lock); - return rc; -} - -/** - * dsi_ctrl_validate_timing() - validate a video timing configuration - * @dsi_ctrl: DSI controller handle. - * @timing: Pointer to timing data. - * - * Driver will validate if the timing configuration is supported on the - * controller hardware. - * - * Return: error code if timing is not supported. - */ -int dsi_ctrl_validate_timing(struct dsi_ctrl *dsi_ctrl, - struct dsi_mode_info *mode) -{ - int rc = 0; - - if (!dsi_ctrl || !mode) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - mutex_lock(&dsi_ctrl->ctrl_lock); - mutex_unlock(&dsi_ctrl->ctrl_lock); - - return rc; -} - -/** - * dsi_ctrl_cmd_transfer() - Transfer commands on DSI link - * @dsi_ctrl: DSI controller handle. - * @msg: Message to transfer on DSI link. - * @flags: Modifiers for message transfer. - * - * Command transfer can be done only when command engine is enabled. The - * transfer API will block until either the command transfer finishes or - * the timeout value is reached. If the trigger is deferred, it will return - * without triggering the transfer. Command parameters are programmed to - * hardware. - * - * Return: error code. - */ -int dsi_ctrl_cmd_transfer(struct dsi_ctrl *dsi_ctrl, - const struct mipi_dsi_msg *msg, - u32 flags) -{ - int rc = 0; - - if (!dsi_ctrl || !msg) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - mutex_lock(&dsi_ctrl->ctrl_lock); - - rc = dsi_ctrl_check_state(dsi_ctrl, DSI_CTRL_OP_CMD_TX, 0x0); - if (rc) { - pr_err("[DSI_%d] Controller state check failed, rc=%d\n", - dsi_ctrl->cell_index, rc); - goto error; - } - - if (flags & DSI_CTRL_CMD_READ) { - rc = dsi_message_rx(dsi_ctrl, msg, flags); - if (rc) - pr_err("read message failed, rc=%d\n", rc); - } else { - rc = dsi_message_tx(dsi_ctrl, msg, flags); - if (rc) - pr_err("command msg transfer failed, rc = %d\n", rc); - } - - dsi_ctrl_update_state(dsi_ctrl, DSI_CTRL_OP_CMD_TX, 0x0); - -error: - mutex_unlock(&dsi_ctrl->ctrl_lock); - return rc; -} - -/** - * dsi_ctrl_cmd_tx_trigger() - Trigger a deferred command. - * @dsi_ctrl: DSI controller handle. - * @flags: Modifiers. - * - * Return: error code. - */ -int dsi_ctrl_cmd_tx_trigger(struct dsi_ctrl *dsi_ctrl, u32 flags) -{ - int rc = 0, ret = 0; - u32 status = 0; - u32 mask = (DSI_CMD_MODE_DMA_DONE); - - if (!dsi_ctrl) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - mutex_lock(&dsi_ctrl->ctrl_lock); - - if (!(flags & DSI_CTRL_CMD_BROADCAST_MASTER)) - dsi_ctrl->hw.ops.trigger_command_dma(&dsi_ctrl->hw); - - if ((flags & DSI_CTRL_CMD_BROADCAST) && - (flags & DSI_CTRL_CMD_BROADCAST_MASTER)) { - dsi_ctrl_enable_status_interrupt(dsi_ctrl, - DSI_SINT_CMD_MODE_DMA_DONE, NULL); - reinit_completion(&dsi_ctrl->irq_info.cmd_dma_done); - - /* trigger command */ - dsi_ctrl->hw.ops.trigger_command_dma(&dsi_ctrl->hw); - - ret = wait_for_completion_timeout( - &dsi_ctrl->irq_info.cmd_dma_done, - msecs_to_jiffies(DSI_CTRL_TX_TO_MS)); - - if (ret == 0) { - status = dsi_ctrl->hw.ops.get_interrupt_status( - &dsi_ctrl->hw); - if (status & mask) { - status |= (DSI_CMD_MODE_DMA_DONE | - DSI_BTA_DONE); - dsi_ctrl->hw.ops.clear_interrupt_status( - &dsi_ctrl->hw, - status); - dsi_ctrl_disable_status_interrupt(dsi_ctrl, - DSI_SINT_CMD_MODE_DMA_DONE); - complete_all(&dsi_ctrl->irq_info.cmd_dma_done); - pr_warn("dma_tx done but irq not triggered\n"); - } else { - rc = -ETIMEDOUT; - dsi_ctrl_disable_status_interrupt(dsi_ctrl, - DSI_SINT_CMD_MODE_DMA_DONE); - pr_err("[DSI_%d]Command transfer failed\n", - dsi_ctrl->cell_index); - } - } - } - - mutex_unlock(&dsi_ctrl->ctrl_lock); - return rc; -} - -/** - * _dsi_ctrl_cache_misr - Cache frame MISR value - * @dsi_ctrl: Pointer to associated dsi_ctrl structure - */ -static void _dsi_ctrl_cache_misr(struct dsi_ctrl *dsi_ctrl) -{ - u32 misr; - - if (!dsi_ctrl || !dsi_ctrl->hw.ops.collect_misr) - return; - - misr = dsi_ctrl->hw.ops.collect_misr(&dsi_ctrl->hw, - dsi_ctrl->host_config.panel_mode); - - if (misr) - dsi_ctrl->misr_cache = misr; - - pr_debug("DSI_%d misr_cache = %x\n", dsi_ctrl->cell_index, - dsi_ctrl->misr_cache); - -} - -/** - * dsi_ctrl_set_power_state() - set power state for dsi controller - * @dsi_ctrl: DSI controller handle. - * @state: Power state. - * - * Set power state for DSI controller. Power state can be changed only when - * Controller, Video and Command engines are turned off. - * - * Return: error code. - */ -int dsi_ctrl_set_power_state(struct dsi_ctrl *dsi_ctrl, - enum dsi_power_state state) -{ - int rc = 0; - - if (!dsi_ctrl || (state >= DSI_CTRL_POWER_MAX)) { - pr_err("Invalid Params\n"); - return -EINVAL; - } - - mutex_lock(&dsi_ctrl->ctrl_lock); - - rc = dsi_ctrl_check_state(dsi_ctrl, DSI_CTRL_OP_POWER_STATE_CHANGE, - state); - if (rc) { - pr_err("[DSI_%d] Controller state check failed, rc=%d\n", - dsi_ctrl->cell_index, rc); - goto error; - } - - if (state == DSI_CTRL_POWER_VREG_ON) { - rc = dsi_ctrl_enable_supplies(dsi_ctrl, true); - if (rc) { - pr_err("[%d]failed to enable voltage supplies, rc=%d\n", - dsi_ctrl->cell_index, rc); - goto error; - } - } else if (state == DSI_CTRL_POWER_VREG_OFF) { - if (dsi_ctrl->misr_enable) - _dsi_ctrl_cache_misr(dsi_ctrl); - - rc = dsi_ctrl_enable_supplies(dsi_ctrl, false); - if (rc) { - pr_err("[%d]failed to disable vreg supplies, rc=%d\n", - dsi_ctrl->cell_index, rc); - goto error; - } - } - - pr_debug("[DSI_%d] Power state updated to %d\n", dsi_ctrl->cell_index, - state); - dsi_ctrl_update_state(dsi_ctrl, DSI_CTRL_OP_POWER_STATE_CHANGE, state); -error: - mutex_unlock(&dsi_ctrl->ctrl_lock); - return rc; -} - -/** - * dsi_ctrl_set_tpg_state() - enable/disable test pattern on the controller - * @dsi_ctrl: DSI controller handle. - * @on: enable/disable test pattern. - * - * Test pattern can be enabled only after Video engine (for video mode panels) - * or command engine (for cmd mode panels) is enabled. - * - * Return: error code. - */ -int dsi_ctrl_set_tpg_state(struct dsi_ctrl *dsi_ctrl, bool on) -{ - int rc = 0; - - if (!dsi_ctrl) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - mutex_lock(&dsi_ctrl->ctrl_lock); - - rc = dsi_ctrl_check_state(dsi_ctrl, DSI_CTRL_OP_TPG, on); - if (rc) { - pr_err("[DSI_%d] Controller state check failed, rc=%d\n", - dsi_ctrl->cell_index, rc); - goto error; - } - - if (on) { - if (dsi_ctrl->host_config.panel_mode == DSI_OP_VIDEO_MODE) { - dsi_ctrl->hw.ops.video_test_pattern_setup(&dsi_ctrl->hw, - DSI_TEST_PATTERN_INC, - 0xFFFF); - } else { - dsi_ctrl->hw.ops.cmd_test_pattern_setup( - &dsi_ctrl->hw, - DSI_TEST_PATTERN_INC, - 0xFFFF, - 0x0); - } - } - dsi_ctrl->hw.ops.test_pattern_enable(&dsi_ctrl->hw, on); - - pr_debug("[DSI_%d]Set test pattern state=%d\n", - dsi_ctrl->cell_index, on); - dsi_ctrl_update_state(dsi_ctrl, DSI_CTRL_OP_TPG, on); -error: - mutex_unlock(&dsi_ctrl->ctrl_lock); - return rc; -} - -/** - * dsi_ctrl_set_host_engine_state() - set host engine state - * @dsi_ctrl: DSI Controller handle. - * @state: Engine state. - * - * Host engine state can be modified only when DSI controller power state is - * set to DSI_CTRL_POWER_LINK_CLK_ON and cmd, video engines are disabled. - * - * Return: error code. - */ -int dsi_ctrl_set_host_engine_state(struct dsi_ctrl *dsi_ctrl, - enum dsi_engine_state state) -{ - int rc = 0; - - if (!dsi_ctrl || (state >= DSI_CTRL_ENGINE_MAX)) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - mutex_lock(&dsi_ctrl->ctrl_lock); - - rc = dsi_ctrl_check_state(dsi_ctrl, DSI_CTRL_OP_HOST_ENGINE, state); - if (rc) { - pr_err("[DSI_%d] Controller state check failed, rc=%d\n", - dsi_ctrl->cell_index, rc); - goto error; - } - - if (state == DSI_CTRL_ENGINE_ON) - dsi_ctrl->hw.ops.ctrl_en(&dsi_ctrl->hw, true); - else - dsi_ctrl->hw.ops.ctrl_en(&dsi_ctrl->hw, false); - - pr_debug("[DSI_%d] Set host engine state = %d\n", dsi_ctrl->cell_index, - state); - dsi_ctrl_update_state(dsi_ctrl, DSI_CTRL_OP_HOST_ENGINE, state); -error: - mutex_unlock(&dsi_ctrl->ctrl_lock); - return rc; -} - -/** - * dsi_ctrl_set_cmd_engine_state() - set command engine state - * @dsi_ctrl: DSI Controller handle. - * @state: Engine state. - * - * Command engine state can be modified only when DSI controller power state is - * set to DSI_CTRL_POWER_LINK_CLK_ON. - * - * Return: error code. - */ -int dsi_ctrl_set_cmd_engine_state(struct dsi_ctrl *dsi_ctrl, - enum dsi_engine_state state) -{ - int rc = 0; - - if (!dsi_ctrl || (state >= DSI_CTRL_ENGINE_MAX)) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - mutex_lock(&dsi_ctrl->ctrl_lock); - - rc = dsi_ctrl_check_state(dsi_ctrl, DSI_CTRL_OP_CMD_ENGINE, state); - if (rc) { - pr_err("[DSI_%d] Controller state check failed, rc=%d\n", - dsi_ctrl->cell_index, rc); - goto error; - } - - if (state == DSI_CTRL_ENGINE_ON) - dsi_ctrl->hw.ops.cmd_engine_en(&dsi_ctrl->hw, true); - else - dsi_ctrl->hw.ops.cmd_engine_en(&dsi_ctrl->hw, false); - - pr_debug("[DSI_%d] Set cmd engine state = %d\n", dsi_ctrl->cell_index, - state); - dsi_ctrl_update_state(dsi_ctrl, DSI_CTRL_OP_CMD_ENGINE, state); -error: - mutex_unlock(&dsi_ctrl->ctrl_lock); - return rc; -} - -/** - * dsi_ctrl_set_vid_engine_state() - set video engine state - * @dsi_ctrl: DSI Controller handle. - * @state: Engine state. - * - * Video engine state can be modified only when DSI controller power state is - * set to DSI_CTRL_POWER_LINK_CLK_ON. - * - * Return: error code. - */ -int dsi_ctrl_set_vid_engine_state(struct dsi_ctrl *dsi_ctrl, - enum dsi_engine_state state) -{ - int rc = 0; - bool on; - - if (!dsi_ctrl || (state >= DSI_CTRL_ENGINE_MAX)) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - mutex_lock(&dsi_ctrl->ctrl_lock); - - rc = dsi_ctrl_check_state(dsi_ctrl, DSI_CTRL_OP_VID_ENGINE, state); - if (rc) { - pr_err("[DSI_%d] Controller state check failed, rc=%d\n", - dsi_ctrl->cell_index, rc); - goto error; - } - - on = (state == DSI_CTRL_ENGINE_ON) ? true : false; - dsi_ctrl->hw.ops.video_engine_en(&dsi_ctrl->hw, on); - - /* perform a reset when turning off video engine */ - if (!on) - dsi_ctrl->hw.ops.soft_reset(&dsi_ctrl->hw); - - pr_debug("[DSI_%d] Set video engine state = %d\n", dsi_ctrl->cell_index, - state); - dsi_ctrl_update_state(dsi_ctrl, DSI_CTRL_OP_VID_ENGINE, state); -error: - mutex_unlock(&dsi_ctrl->ctrl_lock); - return rc; -} - -/** - * dsi_ctrl_set_ulps() - set ULPS state for DSI lanes. - * @dsi_ctrl: DSI controller handle. - * @enable: enable/disable ULPS. - * - * ULPS can be enabled/disabled after DSI host engine is turned on. - * - * Return: error code. - */ -int dsi_ctrl_set_ulps(struct dsi_ctrl *dsi_ctrl, bool enable) -{ - int rc = 0; - - if (!dsi_ctrl) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - mutex_lock(&dsi_ctrl->ctrl_lock); - - if (enable) - rc = dsi_enable_ulps(dsi_ctrl); - else - rc = dsi_disable_ulps(dsi_ctrl); - - if (rc) { - pr_err("[DSI_%d] Ulps state change(%d) failed, rc=%d\n", - dsi_ctrl->cell_index, enable, rc); - goto error; - } - pr_debug("[DSI_%d] ULPS state = %d\n", dsi_ctrl->cell_index, enable); - -error: - mutex_unlock(&dsi_ctrl->ctrl_lock); - return rc; -} - -/** - * dsi_ctrl_set_clamp_state() - set clamp state for DSI phy - * @dsi_ctrl: DSI controller handle. - * @enable: enable/disable clamping. - * - * Clamps can be enabled/disabled while DSI controller is still turned on. - * - * Return: error code. - */ -int dsi_ctrl_set_clamp_state(struct dsi_ctrl *dsi_ctrl, - bool enable, bool ulps_enabled) -{ - int rc = 0; - - if (!dsi_ctrl) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - if (!dsi_ctrl->hw.ops.clamp_enable || - !dsi_ctrl->hw.ops.clamp_disable) { - pr_debug("No clamp control for DSI controller\n"); - return 0; - } - - mutex_lock(&dsi_ctrl->ctrl_lock); - - rc = dsi_enable_io_clamp(dsi_ctrl, enable, ulps_enabled); - if (rc) { - pr_err("[DSI_%d] Failed to enable IO clamp\n", - dsi_ctrl->cell_index); - goto error; - } - - pr_debug("[DSI_%d] Clamp state = %d\n", dsi_ctrl->cell_index, enable); -error: - mutex_unlock(&dsi_ctrl->ctrl_lock); - return rc; -} - -/** - * dsi_ctrl_set_clock_source() - set clock source fpr dsi link clocks - * @dsi_ctrl: DSI controller handle. - * @source_clks: Source clocks for DSI link clocks. - * - * Clock source should be changed while link clocks are disabled. - * - * Return: error code. - */ -int dsi_ctrl_set_clock_source(struct dsi_ctrl *dsi_ctrl, - struct dsi_clk_link_set *source_clks) -{ - int rc = 0; - - if (!dsi_ctrl || !source_clks) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - mutex_lock(&dsi_ctrl->ctrl_lock); - - rc = dsi_clk_update_parent(source_clks, &dsi_ctrl->clk_info.rcg_clks); - if (rc) { - pr_err("[DSI_%d]Failed to update link clk parent, rc=%d\n", - dsi_ctrl->cell_index, rc); - (void)dsi_clk_update_parent(&dsi_ctrl->clk_info.pll_op_clks, - &dsi_ctrl->clk_info.rcg_clks); - goto error; - } - - dsi_ctrl->clk_info.pll_op_clks.byte_clk = source_clks->byte_clk; - dsi_ctrl->clk_info.pll_op_clks.pixel_clk = source_clks->pixel_clk; - - pr_debug("[DSI_%d] Source clocks are updated\n", dsi_ctrl->cell_index); - -error: - mutex_unlock(&dsi_ctrl->ctrl_lock); - return rc; -} - -/** - * dsi_ctrl_setup_misr() - Setup frame MISR - * @dsi_ctrl: DSI controller handle. - * @enable: enable/disable MISR. - * @frame_count: Number of frames to accumulate MISR. - * - * Return: error code. - */ -int dsi_ctrl_setup_misr(struct dsi_ctrl *dsi_ctrl, - bool enable, - u32 frame_count) -{ - if (!dsi_ctrl) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - if (!dsi_ctrl->hw.ops.setup_misr) - return 0; - - mutex_lock(&dsi_ctrl->ctrl_lock); - dsi_ctrl->misr_enable = enable; - dsi_ctrl->hw.ops.setup_misr(&dsi_ctrl->hw, - dsi_ctrl->host_config.panel_mode, - enable, frame_count); - mutex_unlock(&dsi_ctrl->ctrl_lock); - return 0; -} - -/** - * dsi_ctrl_collect_misr() - Read frame MISR - * @dsi_ctrl: DSI controller handle. - * - * Return: MISR value. - */ -u32 dsi_ctrl_collect_misr(struct dsi_ctrl *dsi_ctrl) -{ - u32 misr; - - if (!dsi_ctrl || !dsi_ctrl->hw.ops.collect_misr) - return 0; - - misr = dsi_ctrl->hw.ops.collect_misr(&dsi_ctrl->hw, - dsi_ctrl->host_config.panel_mode); - if (!misr) - misr = dsi_ctrl->misr_cache; - - pr_debug("DSI_%d cached misr = %x, final = %x\n", - dsi_ctrl->cell_index, dsi_ctrl->misr_cache, misr); - - return misr; -} - -/** - * dsi_ctrl_drv_register() - register platform driver for dsi controller - */ -void dsi_ctrl_drv_register(void) -{ - platform_driver_register(&dsi_ctrl_driver); -} - -/** - * dsi_ctrl_drv_unregister() - unregister platform driver - */ -void dsi_ctrl_drv_unregister(void) -{ - platform_driver_unregister(&dsi_ctrl_driver); -} diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h deleted file mode 100644 index 1826372..0000000 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h +++ /dev/null @@ -1,623 +0,0 @@ -/* - * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * 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 _DSI_CTRL_H_ -#define _DSI_CTRL_H_ - -#include <linux/debugfs.h> - -#include "dsi_defs.h" -#include "dsi_ctrl_hw.h" -#include "dsi_clk.h" -#include "dsi_pwr.h" -#include <drm/drm_mipi_dsi.h> - -/* - * DSI Command transfer modifiers - * @DSI_CTRL_CMD_READ: The current transfer involves reading data. - * @DSI_CTRL_CMD_BROADCAST: The current transfer needs to be done in - * broadcast mode to multiple slaves. - * @DSI_CTRL_CMD_BROADCAST_MASTER: This controller is the master and the slaves - * sync to this trigger. - * @DSI_CTRL_CMD_DEFER_TRIGGER: Defer the command trigger to later. - * @DSI_CTRL_CMD_FIFO_STORE: Use FIFO for command transfer in place of - * reading data from memory. - * @DSI_CTRL_CMD_FETCH_MEMORY: Fetch command from memory through AXI bus - * and transfer it. - */ -#define DSI_CTRL_CMD_READ 0x1 -#define DSI_CTRL_CMD_BROADCAST 0x2 -#define DSI_CTRL_CMD_BROADCAST_MASTER 0x4 -#define DSI_CTRL_CMD_DEFER_TRIGGER 0x8 -#define DSI_CTRL_CMD_FIFO_STORE 0x10 -#define DSI_CTRL_CMD_FETCH_MEMORY 0x20 - -/** - * enum dsi_power_state - defines power states for dsi controller. - * @DSI_CTRL_POWER_VREG_OFF: Digital and analog supplies for DSI controller - turned off - * @DSI_CTRL_POWER_VREG_ON: Digital and analog supplies for DSI controller - * @DSI_CTRL_POWER_MAX: Maximum value. - */ -enum dsi_power_state { - DSI_CTRL_POWER_VREG_OFF = 0, - DSI_CTRL_POWER_VREG_ON, - DSI_CTRL_POWER_MAX, -}; - -/** - * enum dsi_engine_state - define engine status for dsi controller. - * @DSI_CTRL_ENGINE_OFF: Engine is turned off. - * @DSI_CTRL_ENGINE_ON: Engine is turned on. - * @DSI_CTRL_ENGINE_MAX: Maximum value. - */ -enum dsi_engine_state { - DSI_CTRL_ENGINE_OFF = 0, - DSI_CTRL_ENGINE_ON, - DSI_CTRL_ENGINE_MAX, -}; - -/** - * struct dsi_ctrl_power_info - digital and analog power supplies for dsi host - * @digital: Digital power supply required to turn on DSI controller hardware. - * @host_pwr: Analog power supplies required to turn on DSI controller hardware. - * Even though DSI controller it self does not require an analog - * power supply, supplies required for PLL can be defined here to - * allow proper control over these supplies. - */ -struct dsi_ctrl_power_info { - struct dsi_regulator_info digital; - struct dsi_regulator_info host_pwr; -}; - -/** - * struct dsi_ctrl_clk_info - clock information for DSI controller - * @core_clks: Core clocks needed to access DSI controller registers. - * @link_clks: Link clocks required to transmit data over DSI link. - * @rcg_clks: Root clock generation clocks generated in MMSS_CC. The - * output of the PLL is set as parent for these root - * clocks. These clocks are specific to controller - * instance. - * @mux_clks: Mux clocks used for Dynamic refresh feature. - * @ext_clks: External byte/pixel clocks from the MMSS block. These - * clocks are set as parent to rcg clocks. - * @pll_op_clks: TODO: - * @shadow_clks: TODO: - */ -struct dsi_ctrl_clk_info { - /* Clocks parsed from DT */ - struct dsi_core_clk_info core_clks; - struct dsi_link_clk_info link_clks; - struct dsi_clk_link_set rcg_clks; - - /* Clocks set by DSI Manager */ - struct dsi_clk_link_set mux_clks; - struct dsi_clk_link_set ext_clks; - struct dsi_clk_link_set pll_op_clks; - struct dsi_clk_link_set shadow_clks; -}; - -/** - * struct dsi_ctrl_bus_scale_info - Bus scale info for msm-bus bandwidth voting - * @bus_scale_table: Bus scale voting usecases. - * @bus_handle: Handle used for voting bandwidth. - */ -struct dsi_ctrl_bus_scale_info { - struct msm_bus_scale_pdata *bus_scale_table; - u32 bus_handle; -}; - -/** - * struct dsi_ctrl_state_info - current driver state information - * @power_state: Status of power states on DSI controller. - * @cmd_engine_state: Status of DSI command engine. - * @vid_engine_state: Status of DSI video engine. - * @controller_state: Status of DSI Controller engine. - * @host_initialized: Boolean to indicate status of DSi host Initialization - * @tpg_enabled: Boolean to indicate whether tpg is enabled. - */ -struct dsi_ctrl_state_info { - enum dsi_power_state power_state; - enum dsi_engine_state cmd_engine_state; - enum dsi_engine_state vid_engine_state; - enum dsi_engine_state controller_state; - bool host_initialized; - bool tpg_enabled; -}; - -/** - * struct dsi_ctrl_interrupts - define interrupt information - * @irq_lock: Spinlock for ISR handler. - * @irq_num: Linux interrupt number associated with device. - * @irq_stat_mask: Hardware mask of currently enabled interrupts. - * @irq_stat_refcount: Number of times each interrupt has been requested. - * @irq_stat_cb: Status IRQ callback definitions. - * @cmd_dma_done: Completion signal for DSI_CMD_MODE_DMA_DONE interrupt - * @vid_frame_done: Completion signal for DSI_VIDEO_MODE_FRAME_DONE int. - * @cmd_frame_done: Completion signal for DSI_CMD_FRAME_DONE interrupt. - */ -struct dsi_ctrl_interrupts { - spinlock_t irq_lock; - int irq_num; - uint32_t irq_stat_mask; - int irq_stat_refcount[DSI_STATUS_INTERRUPT_COUNT]; - struct dsi_event_cb_info irq_stat_cb[DSI_STATUS_INTERRUPT_COUNT]; - - struct completion cmd_dma_done; - struct completion vid_frame_done; - struct completion cmd_frame_done; - struct completion bta_done; -}; - -/** - * struct dsi_ctrl - DSI controller object - * @pdev: Pointer to platform device. - * @cell_index: Instance cell id. - * @horiz_index: Index in physical horizontal CTRL layout, 0 = leftmost - * @name: Name of the controller instance. - * @refcount: ref counter. - * @ctrl_lock: Mutex for hardware and object access. - * @drm_dev: Pointer to DRM device. - * @version: DSI controller version. - * @hw: DSI controller hardware object. - * @current_state: Current driver and hardware state. - * @clk_cb: Callback for DSI clock control. - * @irq_info: Interrupt information. - * @clk_info: Clock information. - * @clk_freq: DSi Link clock frequency information. - * @pwr_info: Power information. - * @axi_bus_info: AXI bus information. - * @host_config: Current host configuration. - * @mode_bounds: Boundaries of the default mode ROI. - * Origin is at top left of all CTRLs. - * @roi: Partial update region of interest. - * Origin is top left of this CTRL. - * @tx_cmd_buf: Tx command buffer. - * @cmd_buffer_iova: cmd buffer mapped address. - * @vaddr: CPU virtual address of cmd buffer. - * @cmd_buffer_size: Size of command buffer. - * @debugfs_root: Root for debugfs entries. - * @misr_enable: Frame MISR enable/disable - * @misr_cache: Cached Frame MISR value - * @phy_isolation_enabled: A boolean property allows to isolate the phy from - * dsi controller and run only dsi controller. - */ -struct dsi_ctrl { - struct platform_device *pdev; - u32 cell_index; - u32 horiz_index; - const char *name; - u32 refcount; - struct mutex ctrl_lock; - struct drm_device *drm_dev; - - enum dsi_ctrl_version version; - struct dsi_ctrl_hw hw; - - /* Current state */ - struct dsi_ctrl_state_info current_state; - struct clk_ctrl_cb clk_cb; - - struct dsi_ctrl_interrupts irq_info; - - /* Clock and power states */ - struct dsi_ctrl_clk_info clk_info; - struct link_clk_freq clk_freq; - struct dsi_ctrl_power_info pwr_info; - struct dsi_ctrl_bus_scale_info axi_bus_info; - - struct dsi_host_config host_config; - struct dsi_rect mode_bounds; - struct dsi_rect roi; - - /* Command tx and rx */ - struct drm_gem_object *tx_cmd_buf; - u32 cmd_buffer_size; - u32 cmd_buffer_iova; - void *vaddr; - - /* Debug Information */ - struct dentry *debugfs_root; - - /* MISR */ - bool misr_enable; - u32 misr_cache; - - bool phy_isolation_enabled; -}; - -/** - * dsi_ctrl_get() - get a dsi_ctrl handle from an of_node - * @of_node: of_node of the DSI controller. - * - * Gets the DSI controller handle for the corresponding of_node. The ref count - * is incremented to one and all subsequent gets will fail until the original - * clients calls a put. - * - * Return: DSI Controller handle. - */ -struct dsi_ctrl *dsi_ctrl_get(struct device_node *of_node); - -/** - * dsi_ctrl_put() - releases a dsi controller handle. - * @dsi_ctrl: DSI controller handle. - * - * Releases the DSI controller. Driver will clean up all resources and puts back - * the DSI controller into reset state. - */ -void dsi_ctrl_put(struct dsi_ctrl *dsi_ctrl); - -/** - * dsi_ctrl_drv_init() - initialize dsi controller driver. - * @dsi_ctrl: DSI controller handle. - * @parent: Parent directory for debug fs. - * - * Initializes DSI controller driver. Driver should be initialized after - * dsi_ctrl_get() succeeds. - * - * Return: error code. - */ -int dsi_ctrl_drv_init(struct dsi_ctrl *dsi_ctrl, struct dentry *parent); - -/** - * dsi_ctrl_drv_deinit() - de-initializes dsi controller driver - * @dsi_ctrl: DSI controller handle. - * - * Releases all resources acquired by dsi_ctrl_drv_init(). - * - * Return: error code. - */ -int dsi_ctrl_drv_deinit(struct dsi_ctrl *dsi_ctrl); - -/** - * dsi_ctrl_validate_timing() - validate a video timing configuration - * @dsi_ctrl: DSI controller handle. - * @timing: Pointer to timing data. - * - * Driver will validate if the timing configuration is supported on the - * controller hardware. - * - * Return: error code if timing is not supported. - */ -int dsi_ctrl_validate_timing(struct dsi_ctrl *dsi_ctrl, - struct dsi_mode_info *timing); - -/** - * dsi_ctrl_update_host_config() - update dsi host configuration - * @dsi_ctrl: DSI controller handle. - * @config: DSI host configuration. - * @flags: dsi_mode_flags modifying the behavior - * @clk_handle: Clock handle for DSI clocks - * - * Updates driver with new Host configuration to use for host initialization. - * This function call will only update the software context. The stored - * configuration information will be used when the host is initialized. - * - * Return: error code. - */ -int dsi_ctrl_update_host_config(struct dsi_ctrl *dsi_ctrl, - struct dsi_host_config *config, - int flags, void *clk_handle); - -/** - * dsi_ctrl_timing_db_update() - update only controller Timing DB - * @dsi_ctrl: DSI controller handle. - * @enable: Enable/disable Timing DB register - * - * Update timing db register value during dfps usecases - * - * Return: error code. - */ -int dsi_ctrl_timing_db_update(struct dsi_ctrl *dsi_ctrl, - bool enable); - -/** - * dsi_ctrl_async_timing_update() - update only controller timing - * @dsi_ctrl: DSI controller handle. - * @timing: New DSI timing info - * - * Updates host timing values to asynchronously transition to new timing - * For example, to update the porch values in a seamless/dynamic fps switch. - * - * Return: error code. - */ -int dsi_ctrl_async_timing_update(struct dsi_ctrl *dsi_ctrl, - struct dsi_mode_info *timing); - -/** - * dsi_ctrl_phy_sw_reset() - perform a PHY software reset - * @dsi_ctrl: DSI controller handle. - * - * Performs a PHY software reset on the DSI controller. Reset should be done - * when the controller power state is DSI_CTRL_POWER_CORE_CLK_ON and the PHY is - * not enabled. - * - * This function will fail if driver is in any other state. - * - * Return: error code. - */ -int dsi_ctrl_phy_sw_reset(struct dsi_ctrl *dsi_ctrl); - -/** - * dsi_ctrl_phy_reset_config() - Mask/unmask propagation of ahb reset signal - * to DSI PHY hardware. - * @dsi_ctrl: DSI controller handle. - * @enable: Mask/unmask the PHY reset signal. - * - * Return: error code. - */ -int dsi_ctrl_phy_reset_config(struct dsi_ctrl *dsi_ctrl, bool enable); - -/** - * dsi_ctrl_soft_reset() - perform a soft reset on DSI controller - * @dsi_ctrl: DSI controller handle. - * - * The video, command and controller engines will be disabled before the - * reset is triggered. After, the engines will be re-enabled to the same state - * as before the reset. - * - * If the reset is done while MDP timing engine is turned on, the video - * engine should be re-enabled only during the vertical blanking time. - * - * Return: error code - */ -int dsi_ctrl_soft_reset(struct dsi_ctrl *dsi_ctrl); - -/** - * dsi_ctrl_host_timing_update - reinitialize host with new timing values - * @dsi_ctrl: DSI controller handle. - * - * Reinitialize DSI controller hardware with new display timing values - * when resolution is switched dynamically. - * - * Return: error code - */ -int dsi_ctrl_host_timing_update(struct dsi_ctrl *dsi_ctrl); - -/** - * dsi_ctrl_host_init() - Initialize DSI host hardware. - * @dsi_ctrl: DSI controller handle. - * - * Initializes DSI controller hardware with host configuration provided by - * dsi_ctrl_update_host_config(). Initialization can be performed only during - * DSI_CTRL_POWER_CORE_CLK_ON state and after the PHY SW reset has been - * performed. - * - * Return: error code. - */ -int dsi_ctrl_host_init(struct dsi_ctrl *dsi_ctrl); - -/** - * dsi_ctrl_host_deinit() - De-Initialize DSI host hardware. - * @dsi_ctrl: DSI controller handle. - * - * De-initializes DSI controller hardware. It can be performed only during - * DSI_CTRL_POWER_CORE_CLK_ON state after LINK clocks have been turned off. - * - * Return: error code. - */ -int dsi_ctrl_host_deinit(struct dsi_ctrl *dsi_ctrl); - -/** - * dsi_ctrl_set_ulps() - set ULPS state for DSI lanes. - * @dsi_ctrl: DSI controller handle. - * @enable: enable/disable ULPS. - * - * ULPS can be enabled/disabled after DSI host engine is turned on. - * - * Return: error code. - */ -int dsi_ctrl_set_ulps(struct dsi_ctrl *dsi_ctrl, bool enable); - -/** - * dsi_ctrl_setup() - Setup DSI host hardware while coming out of idle screen. - * @dsi_ctrl: DSI controller handle. - * - * Initializes DSI controller hardware with host configuration provided by - * dsi_ctrl_update_host_config(). Initialization can be performed only during - * DSI_CTRL_POWER_CORE_CLK_ON state and after the PHY SW reset has been - * performed. - * - * Also used to program the video mode timing values. - * - * Return: error code. - */ -int dsi_ctrl_setup(struct dsi_ctrl *dsi_ctrl); - -/** - * dsi_ctrl_set_tpg_state() - enable/disable test pattern on the controller - * @dsi_ctrl: DSI controller handle. - * @on: enable/disable test pattern. - * - * Test pattern can be enabled only after Video engine (for video mode panels) - * or command engine (for cmd mode panels) is enabled. - * - * Return: error code. - */ -int dsi_ctrl_set_tpg_state(struct dsi_ctrl *dsi_ctrl, bool on); - -/** - * dsi_ctrl_cmd_transfer() - Transfer commands on DSI link - * @dsi_ctrl: DSI controller handle. - * @msg: Message to transfer on DSI link. - * @flags: Modifiers for message transfer. - * - * Command transfer can be done only when command engine is enabled. The - * transfer API will until either the command transfer finishes or the timeout - * value is reached. If the trigger is deferred, it will return without - * triggering the transfer. Command parameters are programmed to hardware. - * - * Return: error code. - */ -int dsi_ctrl_cmd_transfer(struct dsi_ctrl *dsi_ctrl, - const struct mipi_dsi_msg *msg, - u32 flags); - -/** - * dsi_ctrl_cmd_tx_trigger() - Trigger a deferred command. - * @dsi_ctrl: DSI controller handle. - * @flags: Modifiers. - * - * Return: error code. - */ -int dsi_ctrl_cmd_tx_trigger(struct dsi_ctrl *dsi_ctrl, u32 flags); - -/** - * dsi_ctrl_set_power_state() - set power state for dsi controller - * @dsi_ctrl: DSI controller handle. - * @state: Power state. - * - * Set power state for DSI controller. Power state can be changed only when - * Controller, Video and Command engines are turned off. - * - * Return: error code. - */ -int dsi_ctrl_set_power_state(struct dsi_ctrl *dsi_ctrl, - enum dsi_power_state state); - -/** - * dsi_ctrl_set_cmd_engine_state() - set command engine state - * @dsi_ctrl: DSI Controller handle. - * @state: Engine state. - * - * Command engine state can be modified only when DSI controller power state is - * set to DSI_CTRL_POWER_LINK_CLK_ON. - * - * Return: error code. - */ -int dsi_ctrl_set_cmd_engine_state(struct dsi_ctrl *dsi_ctrl, - enum dsi_engine_state state); - -/** - * dsi_ctrl_set_vid_engine_state() - set video engine state - * @dsi_ctrl: DSI Controller handle. - * @state: Engine state. - * - * Video engine state can be modified only when DSI controller power state is - * set to DSI_CTRL_POWER_LINK_CLK_ON. - * - * Return: error code. - */ -int dsi_ctrl_set_vid_engine_state(struct dsi_ctrl *dsi_ctrl, - enum dsi_engine_state state); - -/** - * dsi_ctrl_set_host_engine_state() - set host engine state - * @dsi_ctrl: DSI Controller handle. - * @state: Engine state. - * - * Host engine state can be modified only when DSI controller power state is - * set to DSI_CTRL_POWER_LINK_CLK_ON and cmd, video engines are disabled. - * - * Return: error code. - */ -int dsi_ctrl_set_host_engine_state(struct dsi_ctrl *dsi_ctrl, - enum dsi_engine_state state); - -/** - * dsi_ctrl_set_ulps() - set ULPS state for DSI lanes. - * @dsi_ctrl: DSI controller handle. - * @enable: enable/disable ULPS. - * - * ULPS can be enabled/disabled after DSI host engine is turned on. - * - * Return: error code. - */ -int dsi_ctrl_set_ulps(struct dsi_ctrl *dsi_ctrl, bool enable); - -/** - * dsi_ctrl_clk_cb_register() - Register DSI controller clk control callback - * @dsi_ctrl: DSI controller handle. - * @clk__cb: Structure containing callback for clock control. - * - * Register call for DSI clock control - * - * Return: error code. - */ -int dsi_ctrl_clk_cb_register(struct dsi_ctrl *dsi_ctrl, - struct clk_ctrl_cb *clk_cb); - -/** - * dsi_ctrl_set_clamp_state() - set clamp state for DSI phy - * @dsi_ctrl: DSI controller handle. - * @enable: enable/disable clamping. - * @ulps_enabled: ulps state. - * - * Clamps can be enabled/disabled while DSI controller is still turned on. - * - * Return: error code. - */ -int dsi_ctrl_set_clamp_state(struct dsi_ctrl *dsi_Ctrl, - bool enable, bool ulps_enabled); - -/** - * dsi_ctrl_set_clock_source() - set clock source fpr dsi link clocks - * @dsi_ctrl: DSI controller handle. - * @source_clks: Source clocks for DSI link clocks. - * - * Clock source should be changed while link clocks are disabled. - * - * Return: error code. - */ -int dsi_ctrl_set_clock_source(struct dsi_ctrl *dsi_ctrl, - struct dsi_clk_link_set *source_clks); - -/** - * dsi_ctrl_enable_status_interrupt() - enable status interrupts - * @dsi_ctrl: DSI controller handle. - * @intr_idx: Index interrupt to disable. - * @event_info: Pointer to event callback definition - */ -void dsi_ctrl_enable_status_interrupt(struct dsi_ctrl *dsi_ctrl, - uint32_t intr_idx, struct dsi_event_cb_info *event_info); - -/** - * dsi_ctrl_disable_status_interrupt() - disable status interrupts - * @dsi_ctrl: DSI controller handle. - * @intr_idx: Index interrupt to disable. - */ -void dsi_ctrl_disable_status_interrupt( - struct dsi_ctrl *dsi_ctrl, uint32_t intr_idx); - -/** - * dsi_ctrl_setup_misr() - Setup frame MISR - * @dsi_ctrl: DSI controller handle. - * @enable: enable/disable MISR. - * @frame_count: Number of frames to accumulate MISR. - * - * Return: error code. - */ -int dsi_ctrl_setup_misr(struct dsi_ctrl *dsi_ctrl, - bool enable, - u32 frame_count); - -/** - * dsi_ctrl_collect_misr() - Read frame MISR - * @dsi_ctrl: DSI controller handle. - * - * Return: MISR value. - */ -u32 dsi_ctrl_collect_misr(struct dsi_ctrl *dsi_ctrl); - -/** - * dsi_ctrl_drv_register() - register platform driver for dsi controller - */ -void dsi_ctrl_drv_register(void); - -/** - * dsi_ctrl_drv_unregister() - unregister platform driver - */ -void dsi_ctrl_drv_unregister(void); - -#endif /* _DSI_CTRL_H_ */ diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h deleted file mode 100644 index 53b20f4..0000000 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h +++ /dev/null @@ -1,752 +0,0 @@ -/* - * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * 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 _DSI_CTRL_HW_H_ -#define _DSI_CTRL_HW_H_ - -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/bitops.h> -#include <linux/bitmap.h> - -#include "dsi_defs.h" - -/** - * Modifier flag for command transmission. If this flag is set, command - * information is programmed to hardware and transmission is not triggered. - * Caller should call the trigger_command_dma() to start the transmission. This - * flag is valed for kickoff_command() and kickoff_fifo_command() operations. - */ -#define DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER 0x1 - -/** - * enum dsi_ctrl_version - version of the dsi host controller - * @DSI_CTRL_VERSION_UNKNOWN: Unknown controller version - * @DSI_CTRL_VERSION_1_4: DSI host v1.4 controller - * @DSI_CTRL_VERSION_2_0: DSI host v2.0 controller - * @DSI_CTRL_VERSION_MAX: max version - */ -enum dsi_ctrl_version { - DSI_CTRL_VERSION_UNKNOWN, - DSI_CTRL_VERSION_1_4, - DSI_CTRL_VERSION_2_0, - DSI_CTRL_VERSION_2_2, - DSI_CTRL_VERSION_MAX -}; - -/** - * enum dsi_ctrl_hw_features - features supported by dsi host controller - * @DSI_CTRL_VIDEO_TPG: Test pattern support for video mode. - * @DSI_CTRL_CMD_TPG: Test pattern support for command mode. - * @DSI_CTRL_VARIABLE_REFRESH_RATE: variable panel timing - * @DSI_CTRL_DYNAMIC_REFRESH: variable pixel clock rate - * @DSI_CTRL_NULL_PACKET_INSERTION: NULL packet insertion - * @DSI_CTRL_DESKEW_CALIB: Deskew calibration support - * @DSI_CTRL_DPHY: Controller support for DPHY - * @DSI_CTRL_CPHY: Controller support for CPHY - * @DSI_CTRL_MAX_FEATURES: - */ -enum dsi_ctrl_hw_features { - DSI_CTRL_VIDEO_TPG, - DSI_CTRL_CMD_TPG, - DSI_CTRL_VARIABLE_REFRESH_RATE, - DSI_CTRL_DYNAMIC_REFRESH, - DSI_CTRL_NULL_PACKET_INSERTION, - DSI_CTRL_DESKEW_CALIB, - DSI_CTRL_DPHY, - DSI_CTRL_CPHY, - DSI_CTRL_MAX_FEATURES -}; - -/** - * enum dsi_test_pattern - test pattern type - * @DSI_TEST_PATTERN_FIXED: Test pattern is fixed, based on init value. - * @DSI_TEST_PATTERN_INC: Incremental test pattern, base on init value. - * @DSI_TEST_PATTERN_POLY: Pattern generated from polynomial and init val. - * @DSI_TEST_PATTERN_MAX: - */ -enum dsi_test_pattern { - DSI_TEST_PATTERN_FIXED = 0, - DSI_TEST_PATTERN_INC, - DSI_TEST_PATTERN_POLY, - DSI_TEST_PATTERN_MAX -}; - -/** - * enum dsi_status_int_index - index of interrupts generated by DSI controller - * @DSI_SINT_CMD_MODE_DMA_DONE: Command mode DMA packets are sent out. - * @DSI_SINT_CMD_STREAM0_FRAME_DONE: A frame of cmd mode stream0 is sent out. - * @DSI_SINT_CMD_STREAM1_FRAME_DONE: A frame of cmd mode stream1 is sent out. - * @DSI_SINT_CMD_STREAM2_FRAME_DONE: A frame of cmd mode stream2 is sent out. - * @DSI_SINT_VIDEO_MODE_FRAME_DONE: A frame of video mode stream is sent out. - * @DSI_SINT_BTA_DONE: A BTA is completed. - * @DSI_SINT_CMD_FRAME_DONE: A frame of selected cmd mode stream is - * sent out by MDP. - * @DSI_SINT_DYN_REFRESH_DONE: The dynamic refresh operation completed. - * @DSI_SINT_DESKEW_DONE: The deskew calibration operation done. - * @DSI_SINT_DYN_BLANK_DMA_DONE: The dynamic blankin DMA operation has - * completed. - */ -enum dsi_status_int_index { - DSI_SINT_CMD_MODE_DMA_DONE = 0, - DSI_SINT_CMD_STREAM0_FRAME_DONE = 1, - DSI_SINT_CMD_STREAM1_FRAME_DONE = 2, - DSI_SINT_CMD_STREAM2_FRAME_DONE = 3, - DSI_SINT_VIDEO_MODE_FRAME_DONE = 4, - DSI_SINT_BTA_DONE = 5, - DSI_SINT_CMD_FRAME_DONE = 6, - DSI_SINT_DYN_REFRESH_DONE = 7, - DSI_SINT_DESKEW_DONE = 8, - DSI_SINT_DYN_BLANK_DMA_DONE = 9, - - DSI_STATUS_INTERRUPT_COUNT -}; - -/** - * enum dsi_status_int_type - status interrupts generated by DSI controller - * @DSI_CMD_MODE_DMA_DONE: Command mode DMA packets are sent out. - * @DSI_CMD_STREAM0_FRAME_DONE: A frame of command mode stream0 is sent out. - * @DSI_CMD_STREAM1_FRAME_DONE: A frame of command mode stream1 is sent out. - * @DSI_CMD_STREAM2_FRAME_DONE: A frame of command mode stream2 is sent out. - * @DSI_VIDEO_MODE_FRAME_DONE: A frame of video mode stream is sent out. - * @DSI_BTA_DONE: A BTA is completed. - * @DSI_CMD_FRAME_DONE: A frame of selected command mode stream is - * sent out by MDP. - * @DSI_DYN_REFRESH_DONE: The dynamic refresh operation has completed. - * @DSI_DESKEW_DONE: The deskew calibration operation has completed - * @DSI_DYN_BLANK_DMA_DONE: The dynamic blankin DMA operation has - * completed. - */ -enum dsi_status_int_type { - DSI_CMD_MODE_DMA_DONE = BIT(DSI_SINT_CMD_MODE_DMA_DONE), - DSI_CMD_STREAM0_FRAME_DONE = BIT(DSI_SINT_CMD_STREAM0_FRAME_DONE), - DSI_CMD_STREAM1_FRAME_DONE = BIT(DSI_SINT_CMD_STREAM1_FRAME_DONE), - DSI_CMD_STREAM2_FRAME_DONE = BIT(DSI_SINT_CMD_STREAM2_FRAME_DONE), - DSI_VIDEO_MODE_FRAME_DONE = BIT(DSI_SINT_VIDEO_MODE_FRAME_DONE), - DSI_BTA_DONE = BIT(DSI_SINT_BTA_DONE), - DSI_CMD_FRAME_DONE = BIT(DSI_SINT_CMD_FRAME_DONE), - DSI_DYN_REFRESH_DONE = BIT(DSI_SINT_DYN_REFRESH_DONE), - DSI_DESKEW_DONE = BIT(DSI_SINT_DESKEW_DONE), - DSI_DYN_BLANK_DMA_DONE = BIT(DSI_SINT_DYN_BLANK_DMA_DONE) -}; - -/** - * enum dsi_error_int_index - index of error interrupts from DSI controller - * @DSI_EINT_RDBK_SINGLE_ECC_ERR: Single bit ECC error in read packet. - * @DSI_EINT_RDBK_MULTI_ECC_ERR: Multi bit ECC error in read packet. - * @DSI_EINT_RDBK_CRC_ERR: CRC error in read packet. - * @DSI_EINT_RDBK_INCOMPLETE_PKT: Incomplete read packet. - * @DSI_EINT_PERIPH_ERROR_PKT: Error packet returned from peripheral, - * @DSI_EINT_LP_RX_TIMEOUT: Low power reverse transmission timeout. - * @DSI_EINT_HS_TX_TIMEOUT: High speed fwd transmission timeout. - * @DSI_EINT_BTA_TIMEOUT: BTA timeout. - * @DSI_EINT_PLL_UNLOCK: PLL has unlocked. - * @DSI_EINT_DLN0_ESC_ENTRY_ERR: Incorrect LP Rx escape entry. - * @DSI_EINT_DLN0_ESC_SYNC_ERR: LP Rx data is not byte aligned. - * @DSI_EINT_DLN0_LP_CONTROL_ERR: Incorrect LP Rx state sequence. - * @DSI_EINT_PENDING_HS_TX_TIMEOUT: Pending High-speed transfer timeout. - * @DSI_EINT_INTERLEAVE_OP_CONTENTION: Interleave operation contention. - * @DSI_EINT_CMD_DMA_FIFO_UNDERFLOW: Command mode DMA FIFO underflow. - * @DSI_EINT_CMD_MDP_FIFO_UNDERFLOW: Command MDP FIFO underflow (failed to - * receive one complete line from MDP). - * @DSI_EINT_DLN0_HS_FIFO_OVERFLOW: High speed FIFO data lane 0 overflows. - * @DSI_EINT_DLN1_HS_FIFO_OVERFLOW: High speed FIFO data lane 1 overflows. - * @DSI_EINT_DLN2_HS_FIFO_OVERFLOW: High speed FIFO data lane 2 overflows. - * @DSI_EINT_DLN3_HS_FIFO_OVERFLOW: High speed FIFO data lane 3 overflows. - * @DSI_EINT_DLN0_HS_FIFO_UNDERFLOW: High speed FIFO data lane 0 underflows. - * @DSI_EINT_DLN1_HS_FIFO_UNDERFLOW: High speed FIFO data lane 1 underflows. - * @DSI_EINT_DLN2_HS_FIFO_UNDERFLOW: High speed FIFO data lane 2 underflows. - * @DSI_EINT_DLN3_HS_FIFO_UNDERFLOW: High speed FIFO data lane 3 undeflows. - * @DSI_EINT_DLN0_LP0_CONTENTION: PHY level contention while lane 0 low. - * @DSI_EINT_DLN1_LP0_CONTENTION: PHY level contention while lane 1 low. - * @DSI_EINT_DLN2_LP0_CONTENTION: PHY level contention while lane 2 low. - * @DSI_EINT_DLN3_LP0_CONTENTION: PHY level contention while lane 3 low. - * @DSI_EINT_DLN0_LP1_CONTENTION: PHY level contention while lane 0 high. - * @DSI_EINT_DLN1_LP1_CONTENTION: PHY level contention while lane 1 high. - * @DSI_EINT_DLN2_LP1_CONTENTION: PHY level contention while lane 2 high. - * @DSI_EINT_DLN3_LP1_CONTENTION: PHY level contention while lane 3 high. - */ -enum dsi_error_int_index { - DSI_EINT_RDBK_SINGLE_ECC_ERR = 0, - DSI_EINT_RDBK_MULTI_ECC_ERR = 1, - DSI_EINT_RDBK_CRC_ERR = 2, - DSI_EINT_RDBK_INCOMPLETE_PKT = 3, - DSI_EINT_PERIPH_ERROR_PKT = 4, - DSI_EINT_LP_RX_TIMEOUT = 5, - DSI_EINT_HS_TX_TIMEOUT = 6, - DSI_EINT_BTA_TIMEOUT = 7, - DSI_EINT_PLL_UNLOCK = 8, - DSI_EINT_DLN0_ESC_ENTRY_ERR = 9, - DSI_EINT_DLN0_ESC_SYNC_ERR = 10, - DSI_EINT_DLN0_LP_CONTROL_ERR = 11, - DSI_EINT_PENDING_HS_TX_TIMEOUT = 12, - DSI_EINT_INTERLEAVE_OP_CONTENTION = 13, - DSI_EINT_CMD_DMA_FIFO_UNDERFLOW = 14, - DSI_EINT_CMD_MDP_FIFO_UNDERFLOW = 15, - DSI_EINT_DLN0_HS_FIFO_OVERFLOW = 16, - DSI_EINT_DLN1_HS_FIFO_OVERFLOW = 17, - DSI_EINT_DLN2_HS_FIFO_OVERFLOW = 18, - DSI_EINT_DLN3_HS_FIFO_OVERFLOW = 19, - DSI_EINT_DLN0_HS_FIFO_UNDERFLOW = 20, - DSI_EINT_DLN1_HS_FIFO_UNDERFLOW = 21, - DSI_EINT_DLN2_HS_FIFO_UNDERFLOW = 22, - DSI_EINT_DLN3_HS_FIFO_UNDERFLOW = 23, - DSI_EINT_DLN0_LP0_CONTENTION = 24, - DSI_EINT_DLN1_LP0_CONTENTION = 25, - DSI_EINT_DLN2_LP0_CONTENTION = 26, - DSI_EINT_DLN3_LP0_CONTENTION = 27, - DSI_EINT_DLN0_LP1_CONTENTION = 28, - DSI_EINT_DLN1_LP1_CONTENTION = 29, - DSI_EINT_DLN2_LP1_CONTENTION = 30, - DSI_EINT_DLN3_LP1_CONTENTION = 31, - - DSI_ERROR_INTERRUPT_COUNT -}; - -/** - * enum dsi_error_int_type - error interrupts generated by DSI controller - * @DSI_RDBK_SINGLE_ECC_ERR: Single bit ECC error in read packet. - * @DSI_RDBK_MULTI_ECC_ERR: Multi bit ECC error in read packet. - * @DSI_RDBK_CRC_ERR: CRC error in read packet. - * @DSI_RDBK_INCOMPLETE_PKT: Incomplete read packet. - * @DSI_PERIPH_ERROR_PKT: Error packet returned from peripheral, - * @DSI_LP_RX_TIMEOUT: Low power reverse transmission timeout. - * @DSI_HS_TX_TIMEOUT: High speed forward transmission timeout. - * @DSI_BTA_TIMEOUT: BTA timeout. - * @DSI_PLL_UNLOCK: PLL has unlocked. - * @DSI_DLN0_ESC_ENTRY_ERR: Incorrect LP Rx escape entry. - * @DSI_DLN0_ESC_SYNC_ERR: LP Rx data is not byte aligned. - * @DSI_DLN0_LP_CONTROL_ERR: Incorrect LP Rx state sequence. - * @DSI_PENDING_HS_TX_TIMEOUT: Pending High-speed transfer timeout. - * @DSI_INTERLEAVE_OP_CONTENTION: Interleave operation contention. - * @DSI_CMD_DMA_FIFO_UNDERFLOW: Command mode DMA FIFO underflow. - * @DSI_CMD_MDP_FIFO_UNDERFLOW: Command MDP FIFO underflow (failed to - * receive one complete line from MDP). - * @DSI_DLN0_HS_FIFO_OVERFLOW: High speed FIFO for data lane 0 overflows. - * @DSI_DLN1_HS_FIFO_OVERFLOW: High speed FIFO for data lane 1 overflows. - * @DSI_DLN2_HS_FIFO_OVERFLOW: High speed FIFO for data lane 2 overflows. - * @DSI_DLN3_HS_FIFO_OVERFLOW: High speed FIFO for data lane 3 overflows. - * @DSI_DLN0_HS_FIFO_UNDERFLOW: High speed FIFO for data lane 0 underflows. - * @DSI_DLN1_HS_FIFO_UNDERFLOW: High speed FIFO for data lane 1 underflows. - * @DSI_DLN2_HS_FIFO_UNDERFLOW: High speed FIFO for data lane 2 underflows. - * @DSI_DLN3_HS_FIFO_UNDERFLOW: High speed FIFO for data lane 3 undeflows. - * @DSI_DLN0_LP0_CONTENTION: PHY level contention while lane 0 is low. - * @DSI_DLN1_LP0_CONTENTION: PHY level contention while lane 1 is low. - * @DSI_DLN2_LP0_CONTENTION: PHY level contention while lane 2 is low. - * @DSI_DLN3_LP0_CONTENTION: PHY level contention while lane 3 is low. - * @DSI_DLN0_LP1_CONTENTION: PHY level contention while lane 0 is high. - * @DSI_DLN1_LP1_CONTENTION: PHY level contention while lane 1 is high. - * @DSI_DLN2_LP1_CONTENTION: PHY level contention while lane 2 is high. - * @DSI_DLN3_LP1_CONTENTION: PHY level contention while lane 3 is high. - */ -enum dsi_error_int_type { - DSI_RDBK_SINGLE_ECC_ERR = BIT(DSI_EINT_RDBK_SINGLE_ECC_ERR), - DSI_RDBK_MULTI_ECC_ERR = BIT(DSI_EINT_RDBK_MULTI_ECC_ERR), - DSI_RDBK_CRC_ERR = BIT(DSI_EINT_RDBK_CRC_ERR), - DSI_RDBK_INCOMPLETE_PKT = BIT(DSI_EINT_RDBK_INCOMPLETE_PKT), - DSI_PERIPH_ERROR_PKT = BIT(DSI_EINT_PERIPH_ERROR_PKT), - DSI_LP_RX_TIMEOUT = BIT(DSI_EINT_LP_RX_TIMEOUT), - DSI_HS_TX_TIMEOUT = BIT(DSI_EINT_HS_TX_TIMEOUT), - DSI_BTA_TIMEOUT = BIT(DSI_EINT_BTA_TIMEOUT), - DSI_PLL_UNLOCK = BIT(DSI_EINT_PLL_UNLOCK), - DSI_DLN0_ESC_ENTRY_ERR = BIT(DSI_EINT_DLN0_ESC_ENTRY_ERR), - DSI_DLN0_ESC_SYNC_ERR = BIT(DSI_EINT_DLN0_ESC_SYNC_ERR), - DSI_DLN0_LP_CONTROL_ERR = BIT(DSI_EINT_DLN0_LP_CONTROL_ERR), - DSI_PENDING_HS_TX_TIMEOUT = BIT(DSI_EINT_PENDING_HS_TX_TIMEOUT), - DSI_INTERLEAVE_OP_CONTENTION = BIT(DSI_EINT_INTERLEAVE_OP_CONTENTION), - DSI_CMD_DMA_FIFO_UNDERFLOW = BIT(DSI_EINT_CMD_DMA_FIFO_UNDERFLOW), - DSI_CMD_MDP_FIFO_UNDERFLOW = BIT(DSI_EINT_CMD_MDP_FIFO_UNDERFLOW), - DSI_DLN0_HS_FIFO_OVERFLOW = BIT(DSI_EINT_DLN0_HS_FIFO_OVERFLOW), - DSI_DLN1_HS_FIFO_OVERFLOW = BIT(DSI_EINT_DLN1_HS_FIFO_OVERFLOW), - DSI_DLN2_HS_FIFO_OVERFLOW = BIT(DSI_EINT_DLN2_HS_FIFO_OVERFLOW), - DSI_DLN3_HS_FIFO_OVERFLOW = BIT(DSI_EINT_DLN3_HS_FIFO_OVERFLOW), - DSI_DLN0_HS_FIFO_UNDERFLOW = BIT(DSI_EINT_DLN0_HS_FIFO_UNDERFLOW), - DSI_DLN1_HS_FIFO_UNDERFLOW = BIT(DSI_EINT_DLN1_HS_FIFO_UNDERFLOW), - DSI_DLN2_HS_FIFO_UNDERFLOW = BIT(DSI_EINT_DLN2_HS_FIFO_UNDERFLOW), - DSI_DLN3_HS_FIFO_UNDERFLOW = BIT(DSI_EINT_DLN3_HS_FIFO_UNDERFLOW), - DSI_DLN0_LP0_CONTENTION = BIT(DSI_EINT_DLN0_LP0_CONTENTION), - DSI_DLN1_LP0_CONTENTION = BIT(DSI_EINT_DLN1_LP0_CONTENTION), - DSI_DLN2_LP0_CONTENTION = BIT(DSI_EINT_DLN2_LP0_CONTENTION), - DSI_DLN3_LP0_CONTENTION = BIT(DSI_EINT_DLN3_LP0_CONTENTION), - DSI_DLN0_LP1_CONTENTION = BIT(DSI_EINT_DLN0_LP1_CONTENTION), - DSI_DLN1_LP1_CONTENTION = BIT(DSI_EINT_DLN1_LP1_CONTENTION), - DSI_DLN2_LP1_CONTENTION = BIT(DSI_EINT_DLN2_LP1_CONTENTION), - DSI_DLN3_LP1_CONTENTION = BIT(DSI_EINT_DLN3_LP1_CONTENTION), -}; - -/** - * struct dsi_ctrl_cmd_dma_info - command buffer information - * @offset: IOMMU VA for command buffer address. - * @length: Length of the command buffer. - * @en_broadcast: Enable broadcast mode if set to true. - * @is_master: Is master in broadcast mode. - * @use_lpm: Use low power mode for command transmission. - */ -struct dsi_ctrl_cmd_dma_info { - u32 offset; - u32 length; - bool en_broadcast; - bool is_master; - bool use_lpm; -}; - -/** - * struct dsi_ctrl_cmd_dma_fifo_info - command payload tp be sent using FIFO - * @command: VA for command buffer. - * @size: Size of the command buffer. - * @en_broadcast: Enable broadcast mode if set to true. - * @is_master: Is master in broadcast mode. - * @use_lpm: Use low power mode for command transmission. - */ -struct dsi_ctrl_cmd_dma_fifo_info { - u32 *command; - u32 size; - bool en_broadcast; - bool is_master; - bool use_lpm; -}; - -struct dsi_ctrl_hw; - -struct ctrl_ulps_config_ops { - /** - * ulps_request() - request ulps entry for specified lanes - * @ctrl: Pointer to the controller host hardware. - * @lanes: ORed list of lanes (enum dsi_data_lanes) which need - * to enter ULPS. - * - * Caller should check if lanes are in ULPS mode by calling - * get_lanes_in_ulps() operation. - */ - void (*ulps_request)(struct dsi_ctrl_hw *ctrl, u32 lanes); - - /** - * ulps_exit() - exit ULPS on specified lanes - * @ctrl: Pointer to the controller host hardware. - * @lanes: ORed list of lanes (enum dsi_data_lanes) which need - * to exit ULPS. - * - * Caller should check if lanes are in active mode by calling - * get_lanes_in_ulps() operation. - */ - void (*ulps_exit)(struct dsi_ctrl_hw *ctrl, u32 lanes); - - /** - * get_lanes_in_ulps() - returns the list of lanes in ULPS mode - * @ctrl: Pointer to the controller host hardware. - * - * Returns an ORed list of lanes (enum dsi_data_lanes) that are in ULPS - * state. If 0 is returned, all the lanes are active. - * - * Return: List of lanes in ULPS state. - */ - u32 (*get_lanes_in_ulps)(struct dsi_ctrl_hw *ctrl); -}; - -/** - * struct dsi_ctrl_hw_ops - operations supported by dsi host hardware - */ -struct dsi_ctrl_hw_ops { - - /** - * host_setup() - Setup DSI host configuration - * @ctrl: Pointer to controller host hardware. - * @config: Configuration for DSI host controller - */ - void (*host_setup)(struct dsi_ctrl_hw *ctrl, - struct dsi_host_common_cfg *config); - - /** - * video_engine_en() - enable DSI video engine - * @ctrl: Pointer to controller host hardware. - * @on: Enable/disabel video engine. - */ - void (*video_engine_en)(struct dsi_ctrl_hw *ctrl, bool on); - - /** - * video_engine_setup() - Setup dsi host controller for video mode - * @ctrl: Pointer to controller host hardware. - * @common_cfg: Common configuration parameters. - * @cfg: Video mode configuration. - * - * Set up DSI video engine with a specific configuration. Controller and - * video engine are not enabled as part of this function. - */ - void (*video_engine_setup)(struct dsi_ctrl_hw *ctrl, - struct dsi_host_common_cfg *common_cfg, - struct dsi_video_engine_cfg *cfg); - - /** - * set_video_timing() - set up the timing for video frame - * @ctrl: Pointer to controller host hardware. - * @mode: Video mode information. - * - * Set up the video timing parameters for the DSI video mode operation. - */ - void (*set_video_timing)(struct dsi_ctrl_hw *ctrl, - struct dsi_mode_info *mode); - - /** - * cmd_engine_setup() - setup dsi host controller for command mode - * @ctrl: Pointer to the controller host hardware. - * @common_cfg: Common configuration parameters. - * @cfg: Command mode configuration. - * - * Setup DSI CMD engine with a specific configuration. Controller and - * command engine are not enabled as part of this function. - */ - void (*cmd_engine_setup)(struct dsi_ctrl_hw *ctrl, - struct dsi_host_common_cfg *common_cfg, - struct dsi_cmd_engine_cfg *cfg); - - /** - * setup_cmd_stream() - set up parameters for command pixel streams - * @ctrl: Pointer to controller host hardware. - * @mode: Pointer to mode information. - * @h_stride: Horizontal stride in bytes. - * @vc_id: stream_id. - * - * Setup parameters for command mode pixel stream size. - */ - void (*setup_cmd_stream)(struct dsi_ctrl_hw *ctrl, - struct dsi_mode_info *mode, - u32 h_stride, - u32 vc_id, - struct dsi_rect *roi); - - /** - * ctrl_en() - enable DSI controller engine - * @ctrl: Pointer to the controller host hardware. - * @on: turn on/off the DSI controller engine. - */ - void (*ctrl_en)(struct dsi_ctrl_hw *ctrl, bool on); - - /** - * cmd_engine_en() - enable DSI controller command engine - * @ctrl: Pointer to the controller host hardware. - * @on: Turn on/off the DSI command engine. - */ - void (*cmd_engine_en)(struct dsi_ctrl_hw *ctrl, bool on); - - /** - * phy_sw_reset() - perform a soft reset on the PHY. - * @ctrl: Pointer to the controller host hardware. - */ - void (*phy_sw_reset)(struct dsi_ctrl_hw *ctrl); - - /** - * debug_bus() - get dsi debug bus status. - * @ctrl: Pointer to the controller host hardware. - */ - void (*debug_bus)(struct dsi_ctrl_hw *ctrl); - - /** - * soft_reset() - perform a soft reset on DSI controller - * @ctrl: Pointer to the controller host hardware. - * - * The video, command and controller engines will be disabled before the - * reset is triggered. After, the engines will be re-enabled to the same - * state as before the reset. - * - * If the reset is done while MDP timing engine is turned on, the video - * engine should be re-enabled only during the vertical blanking time. - */ - void (*soft_reset)(struct dsi_ctrl_hw *ctrl); - - /** - * setup_lane_map() - setup mapping between logical and physical lanes - * @ctrl: Pointer to the controller host hardware. - * @lane_map: Structure defining the mapping between DSI logical - * lanes and physical lanes. - */ - void (*setup_lane_map)(struct dsi_ctrl_hw *ctrl, - struct dsi_lane_map *lane_map); - - /** - * kickoff_command() - transmits commands stored in memory - * @ctrl: Pointer to the controller host hardware. - * @cmd: Command information. - * @flags: Modifiers for command transmission. - * - * The controller hardware is programmed with address and size of the - * command buffer. The transmission is kicked off if - * DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER flag is not set. If this flag is - * set, caller should make a separate call to trigger_command_dma() to - * transmit the command. - */ - void (*kickoff_command)(struct dsi_ctrl_hw *ctrl, - struct dsi_ctrl_cmd_dma_info *cmd, - u32 flags); - - /** - * kickoff_fifo_command() - transmits a command using FIFO in dsi - * hardware. - * @ctrl: Pointer to the controller host hardware. - * @cmd: Command information. - * @flags: Modifiers for command transmission. - * - * The controller hardware FIFO is programmed with command header and - * payload. The transmission is kicked off if - * DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER flag is not set. If this flag is - * set, caller should make a separate call to trigger_command_dma() to - * transmit the command. - */ - void (*kickoff_fifo_command)(struct dsi_ctrl_hw *ctrl, - struct dsi_ctrl_cmd_dma_fifo_info *cmd, - u32 flags); - - void (*reset_cmd_fifo)(struct dsi_ctrl_hw *ctrl); - /** - * trigger_command_dma() - trigger transmission of command buffer. - * @ctrl: Pointer to the controller host hardware. - * - * This trigger can be only used if there was a prior call to - * kickoff_command() of kickoff_fifo_command() with - * DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER flag. - */ - void (*trigger_command_dma)(struct dsi_ctrl_hw *ctrl); - - /** - * get_cmd_read_data() - get data read from the peripheral - * @ctrl: Pointer to the controller host hardware. - * @rd_buf: Buffer where data will be read into. - * @total_read_len: Number of bytes to read. - */ - u32 (*get_cmd_read_data)(struct dsi_ctrl_hw *ctrl, - u8 *rd_buf, - u32 total_read_len); - - /** - * wait_for_lane_idle() - wait for DSI lanes to go to idle state - * @ctrl: Pointer to the controller host hardware. - * @lanes: ORed list of lanes (enum dsi_data_lanes) which need - * to be checked to be in idle state. - */ - int (*wait_for_lane_idle)(struct dsi_ctrl_hw *ctrl, u32 lanes); - - struct ctrl_ulps_config_ops ulps_ops; - - /** - * clamp_enable() - enable DSI clamps - * @ctrl: Pointer to the controller host hardware. - * @lanes: ORed list of lanes which need to have clamps released. - * @enable_ulps: ulps state. - */ - - /** - * clamp_enable() - enable DSI clamps to keep PHY driving a stable link - * @ctrl: Pointer to the controller host hardware. - * @lanes: ORed list of lanes which need to have clamps released. - * @enable_ulps: TODO:?? - */ - void (*clamp_enable)(struct dsi_ctrl_hw *ctrl, - u32 lanes, - bool enable_ulps); - - /** - * clamp_disable() - disable DSI clamps - * @ctrl: Pointer to the controller host hardware. - * @lanes: ORed list of lanes which need to have clamps released. - * @disable_ulps: ulps state. - */ - void (*clamp_disable)(struct dsi_ctrl_hw *ctrl, - u32 lanes, - bool disable_ulps); - - /** - * phy_reset_config() - Disable/enable propagation of reset signal - * from ahb domain to DSI PHY - * @ctrl: Pointer to the controller host hardware. - * @enable: True to mask the reset signal, false to unmask - */ - void (*phy_reset_config)(struct dsi_ctrl_hw *ctrl, - bool enable); - - /** - * get_interrupt_status() - returns the interrupt status - * @ctrl: Pointer to the controller host hardware. - * - * Returns the ORed list of interrupts(enum dsi_status_int_type) that - * are active. This list does not include any error interrupts. Caller - * should call get_error_status for error interrupts. - * - * Return: List of active interrupts. - */ - u32 (*get_interrupt_status)(struct dsi_ctrl_hw *ctrl); - - /** - * clear_interrupt_status() - clears the specified interrupts - * @ctrl: Pointer to the controller host hardware. - * @ints: List of interrupts to be cleared. - */ - void (*clear_interrupt_status)(struct dsi_ctrl_hw *ctrl, u32 ints); - - /** - * enable_status_interrupts() - enable the specified interrupts - * @ctrl: Pointer to the controller host hardware. - * @ints: List of interrupts to be enabled. - * - * Enables the specified interrupts. This list will override the - * previous interrupts enabled through this function. Caller has to - * maintain the state of the interrupts enabled. To disable all - * interrupts, set ints to 0. - */ - void (*enable_status_interrupts)(struct dsi_ctrl_hw *ctrl, u32 ints); - - /** - * get_error_status() - returns the error status - * @ctrl: Pointer to the controller host hardware. - * - * Returns the ORed list of errors(enum dsi_error_int_type) that are - * active. This list does not include any status interrupts. Caller - * should call get_interrupt_status for status interrupts. - * - * Return: List of active error interrupts. - */ - u64 (*get_error_status)(struct dsi_ctrl_hw *ctrl); - - /** - * clear_error_status() - clears the specified errors - * @ctrl: Pointer to the controller host hardware. - * @errors: List of errors to be cleared. - */ - void (*clear_error_status)(struct dsi_ctrl_hw *ctrl, u64 errors); - - /** - * enable_error_interrupts() - enable the specified interrupts - * @ctrl: Pointer to the controller host hardware. - * @errors: List of errors to be enabled. - * - * Enables the specified interrupts. This list will override the - * previous interrupts enabled through this function. Caller has to - * maintain the state of the interrupts enabled. To disable all - * interrupts, set errors to 0. - */ - void (*enable_error_interrupts)(struct dsi_ctrl_hw *ctrl, u64 errors); - - /** - * video_test_pattern_setup() - setup test pattern engine for video mode - * @ctrl: Pointer to the controller host hardware. - * @type: Type of test pattern. - * @init_val: Initial value to use for generating test pattern. - */ - void (*video_test_pattern_setup)(struct dsi_ctrl_hw *ctrl, - enum dsi_test_pattern type, - u32 init_val); - - /** - * cmd_test_pattern_setup() - setup test patttern engine for cmd mode - * @ctrl: Pointer to the controller host hardware. - * @type: Type of test pattern. - * @init_val: Initial value to use for generating test pattern. - * @stream_id: Stream Id on which packets are generated. - */ - void (*cmd_test_pattern_setup)(struct dsi_ctrl_hw *ctrl, - enum dsi_test_pattern type, - u32 init_val, - u32 stream_id); - - /** - * test_pattern_enable() - enable test pattern engine - * @ctrl: Pointer to the controller host hardware. - * @enable: Enable/Disable test pattern engine. - */ - void (*test_pattern_enable)(struct dsi_ctrl_hw *ctrl, bool enable); - - /** - * clear_phy0_ln_err() - clear DSI PHY lane-0 errors - * @ctrl: Pointer to the controller host hardware. - */ - void (*clear_phy0_ln_err)(struct dsi_ctrl_hw *ctrl); - - /** - * trigger_cmd_test_pattern() - trigger a command mode frame update with - * test pattern - * @ctrl: Pointer to the controller host hardware. - * @stream_id: Stream on which frame update is sent. - */ - void (*trigger_cmd_test_pattern)(struct dsi_ctrl_hw *ctrl, - u32 stream_id); - - ssize_t (*reg_dump_to_buffer)(struct dsi_ctrl_hw *ctrl, - char *buf, - u32 size); - - /** - * setup_misr() - Setup frame MISR - * @ctrl: Pointer to the controller host hardware. - * @panel_mode: CMD or VIDEO mode indicator - * @enable: Enable/disable MISR. - * @frame_count: Number of frames to accumulate MISR. - */ - void (*setup_misr)(struct dsi_ctrl_hw *ctrl, - enum dsi_op_mode panel_mode, - bool enable, u32 frame_count); - - /** - * collect_misr() - Read frame MISR - * @ctrl: Pointer to the controller host hardware. - * @panel_mode: CMD or VIDEO mode indicator - */ - u32 (*collect_misr)(struct dsi_ctrl_hw *ctrl, - enum dsi_op_mode panel_mode); - - /** - * set_timing_db() - enable/disable Timing DB register - * @ctrl: Pointer to controller host hardware. - * @enable: Enable/Disable flag. - * - * Enable or Disabe the Timing DB register. - */ - void (*set_timing_db)(struct dsi_ctrl_hw *ctrl, - bool enable); -}; - -/* - * struct dsi_ctrl_hw - DSI controller hardware object specific to an instance - * @base: VA for the DSI controller base address. - * @length: Length of the DSI controller register map. - * @mmss_misc_base: Base address of mmss_misc register map. - * @mmss_misc_length: Length of mmss_misc register map. - * @disp_cc_base: Base address of disp_cc register map. - * @disp_cc_length: Length of disp_cc register map. - * @index: Instance ID of the controller. - * @feature_map: Features supported by the DSI controller. - * @ops: Function pointers to the operations supported by the - * controller. - * @supported_interrupts: Number of supported interrupts. - * @supported_errors: Number of supported errors. - * @phy_isolation_enabled: A boolean property allows to isolate the phy from - * dsi controller and run only dsi controller. - */ -struct dsi_ctrl_hw { - void __iomem *base; - u32 length; - void __iomem *mmss_misc_base; - u32 mmss_misc_length; - void __iomem *disp_cc_base; - u32 disp_cc_length; - u32 index; - - /* features */ - DECLARE_BITMAP(feature_map, DSI_CTRL_MAX_FEATURES); - struct dsi_ctrl_hw_ops ops; - - /* capabilities */ - u32 supported_interrupts; - u64 supported_errors; - - bool phy_isolation_enabled; -}; - -#endif /* _DSI_CTRL_HW_H_ */ diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_1_4.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_1_4.c deleted file mode 100644 index 142105f..0000000 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_1_4.c +++ /dev/null @@ -1,480 +0,0 @@ -/* - * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * 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) "dsi-hw:" fmt -#include <linux/delay.h> -#include <linux/iopoll.h> - -#include "dsi_ctrl_hw.h" -#include "dsi_ctrl_reg.h" -#include "dsi_hw.h" - -#define MMSS_MISC_CLAMP_REG_OFF 0x0014 - -/** - * dsi_ctrl_hw_14_setup_lane_map() - setup mapping between - * logical and physical lanes - * @ctrl: Pointer to the controller host hardware. - * @lane_map: Structure defining the mapping between DSI logical - * lanes and physical lanes. - */ -void dsi_ctrl_hw_14_setup_lane_map(struct dsi_ctrl_hw *ctrl, - struct dsi_lane_map *lane_map) -{ - DSI_W32(ctrl, DSI_LANE_SWAP_CTRL, lane_map->lane_map_v1); - - pr_debug("[DSI_%d] Lane swap setup complete\n", ctrl->index); -} - -/** - * dsi_ctrl_hw_14_wait_for_lane_idle() - * This function waits for all the active DSI lanes to be idle by polling all - * the FIFO_EMPTY bits and polling he lane status to ensure that all the lanes - * are in stop state. This function assumes that the bus clocks required to - * access the registers are already turned on. - * - * @ctrl: Pointer to the controller host hardware. - * @lanes: ORed list of lanes (enum dsi_data_lanes) which need - * to be stopped. - * - * return: Error code. - */ -int dsi_ctrl_hw_14_wait_for_lane_idle(struct dsi_ctrl_hw *ctrl, u32 lanes) -{ - int rc = 0, val = 0; - u32 stop_state_mask = 0, fifo_empty_mask = 0; - u32 const sleep_us = 10; - u32 const timeout_us = 100; - - if (lanes & DSI_DATA_LANE_0) { - stop_state_mask |= BIT(0); - fifo_empty_mask |= (BIT(12) | BIT(16)); - } - if (lanes & DSI_DATA_LANE_1) { - stop_state_mask |= BIT(1); - fifo_empty_mask |= BIT(20); - } - if (lanes & DSI_DATA_LANE_2) { - stop_state_mask |= BIT(2); - fifo_empty_mask |= BIT(24); - } - if (lanes & DSI_DATA_LANE_3) { - stop_state_mask |= BIT(3); - fifo_empty_mask |= BIT(28); - } - - pr_debug("%s: polling for fifo empty, mask=0x%08x\n", __func__, - fifo_empty_mask); - rc = readl_poll_timeout(ctrl->base + DSI_FIFO_STATUS, val, - (val & fifo_empty_mask), sleep_us, timeout_us); - if (rc) { - pr_err("%s: fifo not empty, FIFO_STATUS=0x%08x\n", - __func__, val); - goto error; - } - - pr_debug("%s: polling for lanes to be in stop state, mask=0x%08x\n", - __func__, stop_state_mask); - rc = readl_poll_timeout(ctrl->base + DSI_LANE_STATUS, val, - (val & stop_state_mask), sleep_us, timeout_us); - if (rc) { - pr_err("%s: lanes not in stop state, LANE_STATUS=0x%08x\n", - __func__, val); - goto error; - } - -error: - return rc; - -} - -/** - * ulps_request() - request ulps entry for specified lanes - * @ctrl: Pointer to the controller host hardware. - * @lanes: ORed list of lanes (enum dsi_data_lanes) which need - * to enter ULPS. - * - * Caller should check if lanes are in ULPS mode by calling - * get_lanes_in_ulps() operation. - */ -void dsi_ctrl_hw_14_ulps_request(struct dsi_ctrl_hw *ctrl, u32 lanes) -{ - u32 reg = 0; - - if (lanes & DSI_CLOCK_LANE) - reg = BIT(4); - if (lanes & DSI_DATA_LANE_0) - reg |= BIT(0); - if (lanes & DSI_DATA_LANE_1) - reg |= BIT(1); - if (lanes & DSI_DATA_LANE_2) - reg |= BIT(2); - if (lanes & DSI_DATA_LANE_3) - reg |= BIT(3); - - /* - * ULPS entry request. Wait for short time to make sure - * that the lanes enter ULPS. Recommended as per HPG. - */ - DSI_W32(ctrl, DSI_LANE_CTRL, reg); - usleep_range(100, 110); - - pr_debug("[DSI_%d] ULPS requested for lanes 0x%x\n", ctrl->index, - lanes); -} - -/** - * ulps_exit() - exit ULPS on specified lanes - * @ctrl: Pointer to the controller host hardware. - * @lanes: ORed list of lanes (enum dsi_data_lanes) which need - * to exit ULPS. - * - * Caller should check if lanes are in active mode by calling - * get_lanes_in_ulps() operation. - */ -void dsi_ctrl_hw_14_ulps_exit(struct dsi_ctrl_hw *ctrl, u32 lanes) -{ - u32 reg = 0; - - if (lanes & DSI_CLOCK_LANE) - reg = BIT(12); - if (lanes & DSI_DATA_LANE_0) - reg |= BIT(8); - if (lanes & DSI_DATA_LANE_1) - reg |= BIT(9); - if (lanes & DSI_DATA_LANE_2) - reg |= BIT(10); - if (lanes & DSI_DATA_LANE_3) - reg |= BIT(11); - - /* - * ULPS Exit Request - * Hardware requirement is to wait for at least 1ms - */ - DSI_W32(ctrl, DSI_LANE_CTRL, reg); - usleep_range(1000, 1010); - /* - * Sometimes when exiting ULPS, it is possible that some DSI - * lanes are not in the stop state which could lead to DSI - * commands not going through. To avoid this, force the lanes - * to be in stop state. - */ - DSI_W32(ctrl, DSI_LANE_CTRL, reg << 8); - DSI_W32(ctrl, DSI_LANE_CTRL, 0x0); - - pr_debug("[DSI_%d] ULPS exit request for lanes=0x%x\n", - ctrl->index, lanes); -} - -/** - * get_lanes_in_ulps() - returns the list of lanes in ULPS mode - * @ctrl: Pointer to the controller host hardware. - * - * Returns an ORed list of lanes (enum dsi_data_lanes) that are in ULPS - * state. If 0 is returned, all the lanes are active. - * - * Return: List of lanes in ULPS state. - */ -u32 dsi_ctrl_hw_14_get_lanes_in_ulps(struct dsi_ctrl_hw *ctrl) -{ - u32 reg = 0; - u32 lanes = 0; - - reg = DSI_R32(ctrl, DSI_LANE_STATUS); - if (!(reg & BIT(8))) - lanes |= DSI_DATA_LANE_0; - if (!(reg & BIT(9))) - lanes |= DSI_DATA_LANE_1; - if (!(reg & BIT(10))) - lanes |= DSI_DATA_LANE_2; - if (!(reg & BIT(11))) - lanes |= DSI_DATA_LANE_3; - if (!(reg & BIT(12))) - lanes |= DSI_CLOCK_LANE; - - pr_debug("[DSI_%d] lanes in ulps = 0x%x\n", ctrl->index, lanes); - return lanes; -} - -/** - * clamp_enable() - enable DSI clamps to keep PHY driving a stable link - * @ctrl: Pointer to the controller host hardware. - * @lanes: ORed list of lanes which need to be clamped. - * @enable_ulps: Boolean to specify if ULPS is enabled in DSI controller - */ -void dsi_ctrl_hw_14_clamp_enable(struct dsi_ctrl_hw *ctrl, - u32 lanes, - bool enable_ulps) -{ - u32 clamp_reg = 0; - u32 bit_shift = 0; - u32 reg = 0; - - if (ctrl->index == 1) - bit_shift = 16; - - if (lanes & DSI_CLOCK_LANE) { - clamp_reg |= BIT(9); - if (enable_ulps) - clamp_reg |= BIT(8); - } - - if (lanes & DSI_DATA_LANE_0) { - clamp_reg |= BIT(7); - if (enable_ulps) - clamp_reg |= BIT(6); - } - - if (lanes & DSI_DATA_LANE_1) { - clamp_reg |= BIT(5); - if (enable_ulps) - clamp_reg |= BIT(4); - } - - if (lanes & DSI_DATA_LANE_2) { - clamp_reg |= BIT(3); - if (enable_ulps) - clamp_reg |= BIT(2); - } - - if (lanes & DSI_DATA_LANE_3) { - clamp_reg |= BIT(1); - if (enable_ulps) - clamp_reg |= BIT(0); - } - - reg = DSI_MMSS_MISC_R32(ctrl, MMSS_MISC_CLAMP_REG_OFF); - reg |= (clamp_reg << bit_shift); - DSI_MMSS_MISC_W32(ctrl, MMSS_MISC_CLAMP_REG_OFF, reg); - - reg = DSI_MMSS_MISC_R32(ctrl, MMSS_MISC_CLAMP_REG_OFF); - reg |= (BIT(15) << bit_shift); /* Enable clamp */ - DSI_MMSS_MISC_W32(ctrl, MMSS_MISC_CLAMP_REG_OFF, reg); - - pr_debug("[DSI_%d] Clamps enabled for lanes=0x%x\n", ctrl->index, - lanes); -} - -/** - * clamp_disable() - disable DSI clamps - * @ctrl: Pointer to the controller host hardware. - * @lanes: ORed list of lanes which need to have clamps released. - * @disable_ulps: Boolean to specify if ULPS is enabled in DSI controller - */ -void dsi_ctrl_hw_14_clamp_disable(struct dsi_ctrl_hw *ctrl, - u32 lanes, - bool disable_ulps) -{ - u32 clamp_reg = 0; - u32 bit_shift = 0; - u32 reg = 0; - - if (ctrl->index == 1) - bit_shift = 16; - - if (lanes & DSI_CLOCK_LANE) { - clamp_reg |= BIT(9); - if (disable_ulps) - clamp_reg |= BIT(8); - } - - if (lanes & DSI_DATA_LANE_0) { - clamp_reg |= BIT(7); - if (disable_ulps) - clamp_reg |= BIT(6); - } - - if (lanes & DSI_DATA_LANE_1) { - clamp_reg |= BIT(5); - if (disable_ulps) - clamp_reg |= BIT(4); - } - - if (lanes & DSI_DATA_LANE_2) { - clamp_reg |= BIT(3); - if (disable_ulps) - clamp_reg |= BIT(2); - } - - if (lanes & DSI_DATA_LANE_3) { - clamp_reg |= BIT(1); - if (disable_ulps) - clamp_reg |= BIT(0); - } - - clamp_reg |= BIT(15); /* Enable clamp */ - clamp_reg <<= bit_shift; - - reg = DSI_MMSS_MISC_R32(ctrl, MMSS_MISC_CLAMP_REG_OFF); - reg &= ~(clamp_reg); - DSI_MMSS_MISC_W32(ctrl, MMSS_MISC_CLAMP_REG_OFF, reg); - - pr_debug("[DSI_%d] Disable clamps for lanes=%d\n", ctrl->index, lanes); -} - -#define DUMP_REG_VALUE(off) "\t%-30s: 0x%08x\n", #off, DSI_R32(ctrl, off) -ssize_t dsi_ctrl_hw_14_reg_dump_to_buffer(struct dsi_ctrl_hw *ctrl, - char *buf, - u32 size) -{ - u32 len = 0; - - len += snprintf((buf + len), (size - len), "CONFIGURATION REGS:\n"); - - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_HW_VERSION)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_STATUS)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_FIFO_STATUS)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_VIDEO_MODE_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_VIDEO_MODE_SYNC_DATATYPE)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_VIDEO_MODE_PIXEL_DATATYPE)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_VIDEO_MODE_BLANKING_DATATYPE)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_VIDEO_MODE_DATA_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_VIDEO_MODE_ACTIVE_H)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_VIDEO_MODE_ACTIVE_V)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_VIDEO_MODE_TOTAL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_VIDEO_MODE_HSYNC)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_VIDEO_MODE_VSYNC)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_VIDEO_MODE_VSYNC_VPOS)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_COMMAND_MODE_DMA_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_COMMAND_MODE_MDP_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_COMMAND_MODE_MDP_DCS_CMD_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_DMA_CMD_OFFSET)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_DMA_CMD_LENGTH)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_DMA_FIFO_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_DMA_NULL_PACKET_DATA)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_COMMAND_MODE_MDP_STREAM0_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_COMMAND_MODE_MDP_STREAM0_TOTAL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_COMMAND_MODE_MDP_STREAM1_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_COMMAND_MODE_MDP_STREAM1_TOTAL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_ACK_ERR_STATUS)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_RDBK_DATA0)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_RDBK_DATA1)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_RDBK_DATA2)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_RDBK_DATA3)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_RDBK_DATATYPE0)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_RDBK_DATATYPE1)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_TRIG_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_EXT_MUX)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_EXT_MUX_TE_PULSE_DETECT_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_CMD_MODE_DMA_SW_TRIGGER)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_CMD_MODE_MDP_SW_TRIGGER)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_CMD_MODE_BTA_SW_TRIGGER)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_RESET_SW_TRIGGER)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_LANE_STATUS)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_LANE_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_LANE_SWAP_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_DLN0_PHY_ERR)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_LP_TIMER_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_HS_TIMER_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_TIMEOUT_STATUS)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_CLKOUT_TIMING_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_EOT_PACKET)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_EOT_PACKET_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_GENERIC_ESC_TX_TRIGGER)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_ERR_INT_MASK0)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_INT_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_SOFT_RESET)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_CLK_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_CLK_STATUS)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_PHY_SW_RESET)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_AXI2AHB_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_COMMAND_MODE_MDP_CTRL2)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_COMMAND_MODE_MDP_STREAM2_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_COMMAND_MODE_MDP_STREAM2_TOTAL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_VBIF_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_AES_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_RDBK_DATA_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_TEST_PATTERN_GEN_CMD_DMA_INIT_VAL2)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_TPG_DMA_FIFO_STATUS)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_TPG_DMA_FIFO_WRITE_TRIGGER)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_DSI_TIMING_FLUSH)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_DSI_TIMING_DB_MODE)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_TPG_DMA_FIFO_RESET)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_VERSION)); - - pr_err("LLENGTH = %d\n", len); - return len; -} diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_2_0.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_2_0.c deleted file mode 100644 index bfd6378..0000000 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_2_0.c +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * 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) "dsi-hw:" fmt -#include <linux/delay.h> -#include <linux/iopoll.h> - -#include "dsi_ctrl_hw.h" -#include "dsi_ctrl_reg.h" -#include "dsi_hw.h" - -void dsi_ctrl_hw_20_setup_lane_map(struct dsi_ctrl_hw *ctrl, - struct dsi_lane_map *lane_map) -{ - u32 reg_value = lane_map->lane_map_v2[DSI_LOGICAL_LANE_0] | - (lane_map->lane_map_v2[DSI_LOGICAL_LANE_1] << 4) | - (lane_map->lane_map_v2[DSI_LOGICAL_LANE_2] << 8) | - (lane_map->lane_map_v2[DSI_LOGICAL_LANE_3] << 12); - - DSI_W32(ctrl, DSI_LANE_SWAP_CTRL, reg_value); - - pr_debug("[DSI_%d] Lane swap setup complete\n", ctrl->index); -} - -int dsi_ctrl_hw_20_wait_for_lane_idle(struct dsi_ctrl_hw *ctrl, - u32 lanes) -{ - int rc = 0, val = 0; - u32 fifo_empty_mask = 0; - u32 const sleep_us = 10; - u32 const timeout_us = 100; - - if (lanes & DSI_DATA_LANE_0) - fifo_empty_mask |= (BIT(12) | BIT(16)); - - if (lanes & DSI_DATA_LANE_1) - fifo_empty_mask |= BIT(20); - - if (lanes & DSI_DATA_LANE_2) - fifo_empty_mask |= BIT(24); - - if (lanes & DSI_DATA_LANE_3) - fifo_empty_mask |= BIT(28); - - pr_debug("%s: polling for fifo empty, mask=0x%08x\n", __func__, - fifo_empty_mask); - rc = readl_poll_timeout(ctrl->base + DSI_FIFO_STATUS, val, - (val & fifo_empty_mask), sleep_us, timeout_us); - if (rc) { - pr_err("%s: fifo not empty, FIFO_STATUS=0x%08x\n", - __func__, val); - goto error; - } - -error: - return rc; -} - -#define DUMP_REG_VALUE(off) "\t%-30s: 0x%08x\n", #off, DSI_R32(ctrl, off) -ssize_t dsi_ctrl_hw_20_reg_dump_to_buffer(struct dsi_ctrl_hw *ctrl, - char *buf, - u32 size) -{ - u32 len = 0; - - len += snprintf((buf + len), (size - len), "CONFIGURATION REGS:\n"); - - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_HW_VERSION)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_STATUS)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_FIFO_STATUS)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_VIDEO_MODE_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_VIDEO_MODE_SYNC_DATATYPE)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_VIDEO_MODE_PIXEL_DATATYPE)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_VIDEO_MODE_BLANKING_DATATYPE)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_VIDEO_MODE_DATA_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_VIDEO_MODE_ACTIVE_H)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_VIDEO_MODE_ACTIVE_V)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_VIDEO_MODE_TOTAL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_VIDEO_MODE_HSYNC)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_VIDEO_MODE_VSYNC)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_VIDEO_MODE_VSYNC_VPOS)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_COMMAND_MODE_DMA_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_COMMAND_MODE_MDP_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_COMMAND_MODE_MDP_DCS_CMD_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_DMA_CMD_OFFSET)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_DMA_CMD_LENGTH)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_DMA_FIFO_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_DMA_NULL_PACKET_DATA)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_COMMAND_MODE_MDP_STREAM0_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_COMMAND_MODE_MDP_STREAM0_TOTAL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_COMMAND_MODE_MDP_STREAM1_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_COMMAND_MODE_MDP_STREAM1_TOTAL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_ACK_ERR_STATUS)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_RDBK_DATA0)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_RDBK_DATA1)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_RDBK_DATA2)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_RDBK_DATA3)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_RDBK_DATATYPE0)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_RDBK_DATATYPE1)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_TRIG_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_EXT_MUX)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_EXT_MUX_TE_PULSE_DETECT_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_CMD_MODE_DMA_SW_TRIGGER)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_CMD_MODE_MDP_SW_TRIGGER)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_CMD_MODE_BTA_SW_TRIGGER)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_RESET_SW_TRIGGER)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_MISR_CMD_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_MISR_VIDEO_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_LANE_STATUS)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_LANE_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_LANE_SWAP_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_DLN0_PHY_ERR)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_LP_TIMER_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_HS_TIMER_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_TIMEOUT_STATUS)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_CLKOUT_TIMING_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_EOT_PACKET)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_EOT_PACKET_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_GENERIC_ESC_TX_TRIGGER)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_ERR_INT_MASK0)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_INT_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_SOFT_RESET)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_CLK_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_CLK_STATUS)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_PHY_SW_RESET)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_AXI2AHB_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_MISR_CMD_MDP0_32BIT)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_MISR_CMD_MDP1_32BIT)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_MISR_VIDEO_32BIT)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_COMMAND_MODE_MDP_CTRL2)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_COMMAND_MODE_MDP_STREAM2_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_COMMAND_MODE_MDP_STREAM2_TOTAL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_VBIF_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_AES_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_RDBK_DATA_CTRL)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_TEST_PATTERN_GEN_CMD_DMA_INIT_VAL2)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_TPG_DMA_FIFO_STATUS)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_TPG_DMA_FIFO_WRITE_TRIGGER)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_DSI_TIMING_FLUSH)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_DSI_TIMING_DB_MODE)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_TPG_DMA_FIFO_RESET)); - len += snprintf((buf + len), (size - len), - DUMP_REG_VALUE(DSI_VERSION)); - - pr_err("LLENGTH = %d\n", len); - return len; -} diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_2_2.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_2_2.c deleted file mode 100644 index 2c1913f..0000000 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_2_2.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * 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) "dsi-hw:" fmt - -#include "dsi_ctrl_hw.h" -#include "dsi_ctrl_reg.h" -#include "dsi_hw.h" - -/* Equivalent to register DISP_CC_MISC_CMD */ -#define DISP_CC_CLAMP_REG_OFF 0x00 - -/** - * dsi_ctrl_hw_22_phy_reset_config() - to configure clamp control during ulps - * @ctrl: Pointer to the controller host hardware. - * @enable: boolean to specify enable/disable. - */ -void dsi_ctrl_hw_22_phy_reset_config(struct dsi_ctrl_hw *ctrl, - bool enable) -{ - u32 reg = 0; - - reg = DSI_DISP_CC_R32(ctrl, DISP_CC_CLAMP_REG_OFF); - - /* Mask/unmask disable PHY reset bit */ - if (enable) - reg &= ~BIT(ctrl->index); - else - reg |= BIT(ctrl->index); - DSI_DISP_CC_W32(ctrl, DISP_CC_CLAMP_REG_OFF, reg); -} diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c deleted file mode 100644 index af7842f..0000000 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c +++ /dev/null @@ -1,1312 +0,0 @@ -/* - * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * 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) "dsi-hw:" fmt -#include <linux/delay.h> -#include <linux/iopoll.h> - -#include "dsi_ctrl_hw.h" -#include "dsi_ctrl_reg.h" -#include "dsi_hw.h" -#include "dsi_panel.h" -#include "dsi_catalog.h" -#include "dpu_dbg.h" - -#define MMSS_MISC_CLAMP_REG_OFF 0x0014 -#define DSI_CTRL_DYNAMIC_FORCE_ON (0x23F|BIT(8)|BIT(9)|BIT(11)|BIT(21)) -#define DSI_CTRL_CMD_MISR_ENABLE BIT(28) -#define DSI_CTRL_VIDEO_MISR_ENABLE BIT(16) - -/* Unsupported formats default to RGB888 */ -static const u8 cmd_mode_format_map[DSI_PIXEL_FORMAT_MAX] = { - 0x6, 0x7, 0x8, 0x8, 0x0, 0x3, 0x4 }; -static const u8 video_mode_format_map[DSI_PIXEL_FORMAT_MAX] = { - 0x0, 0x1, 0x2, 0x3, 0x3, 0x3, 0x3 }; - -/** - * dsi_setup_trigger_controls() - setup dsi trigger configurations - * @ctrl: Pointer to the controller host hardware. - * @cfg: DSI host configuration that is common to both video and - * command modes. - */ -static void dsi_setup_trigger_controls(struct dsi_ctrl_hw *ctrl, - struct dsi_host_common_cfg *cfg) -{ - u32 reg = 0; - const u8 trigger_map[DSI_TRIGGER_MAX] = { - 0x0, 0x2, 0x1, 0x4, 0x5, 0x6 }; - - reg |= (cfg->te_mode == DSI_TE_ON_EXT_PIN) ? BIT(31) : 0; - reg |= (trigger_map[cfg->dma_cmd_trigger] & 0x7); - reg |= (trigger_map[cfg->mdp_cmd_trigger] & 0x7) << 4; - DSI_W32(ctrl, DSI_TRIG_CTRL, reg); -} - -/** - * dsi_ctrl_hw_cmn_host_setup() - setup dsi host configuration - * @ctrl: Pointer to the controller host hardware. - * @cfg: DSI host configuration that is common to both video and - * command modes. - */ -void dsi_ctrl_hw_cmn_host_setup(struct dsi_ctrl_hw *ctrl, - struct dsi_host_common_cfg *cfg) -{ - u32 reg_value = 0; - - dsi_setup_trigger_controls(ctrl, cfg); - - /* Setup clocking timing controls */ - reg_value = ((cfg->t_clk_post & 0x3F) << 8); - reg_value |= (cfg->t_clk_pre & 0x3F); - DSI_W32(ctrl, DSI_CLKOUT_TIMING_CTRL, reg_value); - - /* EOT packet control */ - reg_value = cfg->append_tx_eot ? 1 : 0; - reg_value |= (cfg->ignore_rx_eot ? (1 << 4) : 0); - DSI_W32(ctrl, DSI_EOT_PACKET_CTRL, reg_value); - - /* Turn on dsi clocks */ - DSI_W32(ctrl, DSI_CLK_CTRL, 0x23F); - - /* Setup DSI control register */ - reg_value = DSI_R32(ctrl, DSI_CTRL); - reg_value |= (cfg->en_crc_check ? BIT(24) : 0); - reg_value |= (cfg->en_ecc_check ? BIT(20) : 0); - reg_value |= BIT(8); /* Clock lane */ - reg_value |= ((cfg->data_lanes & DSI_DATA_LANE_3) ? BIT(7) : 0); - reg_value |= ((cfg->data_lanes & DSI_DATA_LANE_2) ? BIT(6) : 0); - reg_value |= ((cfg->data_lanes & DSI_DATA_LANE_1) ? BIT(5) : 0); - reg_value |= ((cfg->data_lanes & DSI_DATA_LANE_0) ? BIT(4) : 0); - - DSI_W32(ctrl, DSI_CTRL, reg_value); - - if (ctrl->phy_isolation_enabled) - DSI_W32(ctrl, DSI_DEBUG_CTRL, BIT(28)); - pr_debug("[DSI_%d]Host configuration complete\n", ctrl->index); -} - -/** - * phy_sw_reset() - perform a soft reset on the PHY. - * @ctrl: Pointer to the controller host hardware. - */ -void dsi_ctrl_hw_cmn_phy_sw_reset(struct dsi_ctrl_hw *ctrl) -{ - DSI_W32(ctrl, DSI_PHY_SW_RESET, BIT(24)|BIT(0)); - wmb(); /* make sure reset is asserted */ - udelay(1000); - DSI_W32(ctrl, DSI_PHY_SW_RESET, 0x0); - wmb(); /* ensure reset is cleared before waiting */ - udelay(100); - - pr_debug("[DSI_%d] phy sw reset done\n", ctrl->index); -} - -/** - * soft_reset() - perform a soft reset on DSI controller - * @ctrl: Pointer to the controller host hardware. - * - * The video, command and controller engines will be disabled before the - * reset is triggered and re-enabled after the reset is complete. - * - * If the reset is done while MDP timing engine is turned on, the video - * enigne should be re-enabled only during the vertical blanking time. - */ -void dsi_ctrl_hw_cmn_soft_reset(struct dsi_ctrl_hw *ctrl) -{ - u32 reg = 0; - u32 reg_ctrl = 0; - - /* Clear DSI_EN, VIDEO_MODE_EN, CMD_MODE_EN */ - reg_ctrl = DSI_R32(ctrl, DSI_CTRL); - DSI_W32(ctrl, DSI_CTRL, reg_ctrl & ~0x7); - wmb(); /* wait controller to be disabled before reset */ - - /* Force enable PCLK, BYTECLK, AHBM_HCLK */ - reg = DSI_R32(ctrl, DSI_CLK_CTRL); - DSI_W32(ctrl, DSI_CLK_CTRL, reg | DSI_CTRL_DYNAMIC_FORCE_ON); - wmb(); /* wait for clocks to be enabled */ - - /* Trigger soft reset */ - DSI_W32(ctrl, DSI_SOFT_RESET, 0x1); - wmb(); /* wait for reset to assert before waiting */ - udelay(1); - DSI_W32(ctrl, DSI_SOFT_RESET, 0x0); - wmb(); /* ensure reset is cleared */ - - /* Disable force clock on */ - DSI_W32(ctrl, DSI_CLK_CTRL, reg); - wmb(); /* make sure clocks are restored */ - - /* Re-enable DSI controller */ - DSI_W32(ctrl, DSI_CTRL, reg_ctrl); - wmb(); /* make sure DSI controller is enabled again */ - pr_debug("[DSI_%d] ctrl soft reset done\n", ctrl->index); -} - -/** - * setup_misr() - Setup frame MISR - * @ctrl: Pointer to the controller host hardware. - * @panel_mode: CMD or VIDEO mode indicator - * @enable: Enable/disable MISR. - * @frame_count: Number of frames to accumulate MISR. - */ -void dsi_ctrl_hw_cmn_setup_misr(struct dsi_ctrl_hw *ctrl, - enum dsi_op_mode panel_mode, - bool enable, - u32 frame_count) -{ - u32 addr; - u32 config = 0; - - if (panel_mode == DSI_OP_CMD_MODE) { - addr = DSI_MISR_CMD_CTRL; - if (enable) - config = DSI_CTRL_CMD_MISR_ENABLE; - } else { - addr = DSI_MISR_VIDEO_CTRL; - if (enable) - config = DSI_CTRL_VIDEO_MISR_ENABLE; - if (frame_count > 255) - frame_count = 255; - config |= frame_count << 8; - } - - pr_debug("[DSI_%d] MISR ctrl: 0x%x\n", ctrl->index, - config); - DSI_W32(ctrl, addr, config); - wmb(); /* make sure MISR is configured */ -} - -/** - * collect_misr() - Read frame MISR - * @ctrl: Pointer to the controller host hardware. - * @panel_mode: CMD or VIDEO mode indicator - */ -u32 dsi_ctrl_hw_cmn_collect_misr(struct dsi_ctrl_hw *ctrl, - enum dsi_op_mode panel_mode) -{ - u32 addr; - u32 enabled; - u32 misr = 0; - - if (panel_mode == DSI_OP_CMD_MODE) { - addr = DSI_MISR_CMD_MDP0_32BIT; - enabled = DSI_R32(ctrl, DSI_MISR_CMD_CTRL) & - DSI_CTRL_CMD_MISR_ENABLE; - } else { - addr = DSI_MISR_VIDEO_32BIT; - enabled = DSI_R32(ctrl, DSI_MISR_VIDEO_CTRL) & - DSI_CTRL_VIDEO_MISR_ENABLE; - } - - if (enabled) - misr = DSI_R32(ctrl, addr); - - pr_debug("[DSI_%d] MISR enabled %x value: 0x%x\n", ctrl->index, - enabled, misr); - return misr; -} - -/** - * set_timing_db() - enable/disable Timing DB register - * @ctrl: Pointer to controller host hardware. - * @enable: Enable/Disable flag. - * - * Enable or Disabe the Timing DB register. - */ -void dsi_ctrl_hw_cmn_set_timing_db(struct dsi_ctrl_hw *ctrl, - bool enable) -{ - if (enable) - DSI_W32(ctrl, DSI_DSI_TIMING_DB_MODE, 0x1); - else - DSI_W32(ctrl, DSI_DSI_TIMING_DB_MODE, 0x0); - - wmb(); /* make sure timing db registers are set */ - pr_debug("[DSI_%d] ctrl timing DB set:%d\n", ctrl->index, - enable); - DPU_EVT32(ctrl->index, enable); -} - -/** - * set_video_timing() - set up the timing for video frame - * @ctrl: Pointer to controller host hardware. - * @mode: Video mode information. - * - * Set up the video timing parameters for the DSI video mode operation. - */ -void dsi_ctrl_hw_cmn_set_video_timing(struct dsi_ctrl_hw *ctrl, - struct dsi_mode_info *mode) -{ - u32 reg = 0; - u32 hs_start = 0; - u32 hs_end, active_h_start, active_h_end, h_total, width = 0; - u32 vs_start = 0, vs_end = 0; - u32 vpos_start = 0, vpos_end, active_v_start, active_v_end, v_total; - - if (mode->dsc_enabled && mode->dsc) { - width = mode->dsc->pclk_per_line; - reg = mode->dsc->bytes_per_pkt << 16; - reg |= (0x0b << 8); /* dtype of compressed image */ - /* - * pkt_per_line: - * 0 == 1 pkt - * 1 == 2 pkt - * 2 == 4 pkt - * 3 pkt is not support - */ - if (mode->dsc->pkt_per_line == 4) - reg |= (mode->dsc->pkt_per_line - 2) << 6; - else - reg |= (mode->dsc->pkt_per_line - 1) << 6; - reg |= mode->dsc->eol_byte_num << 4; - reg |= 1; - DSI_W32(ctrl, DSI_VIDEO_COMPRESSION_MODE_CTRL, reg); - } else { - width = mode->h_active; - } - - hs_end = mode->h_sync_width; - active_h_start = mode->h_sync_width + mode->h_back_porch; - active_h_end = active_h_start + width; - h_total = (mode->h_sync_width + mode->h_back_porch + width + - mode->h_front_porch) - 1; - - vpos_end = mode->v_sync_width; - active_v_start = mode->v_sync_width + mode->v_back_porch; - active_v_end = active_v_start + mode->v_active; - v_total = (mode->v_sync_width + mode->v_back_porch + mode->v_active + - mode->v_front_porch) - 1; - - reg = ((active_h_end & 0xFFFF) << 16) | (active_h_start & 0xFFFF); - DSI_W32(ctrl, DSI_VIDEO_MODE_ACTIVE_H, reg); - - reg = ((active_v_end & 0xFFFF) << 16) | (active_v_start & 0xFFFF); - DSI_W32(ctrl, DSI_VIDEO_MODE_ACTIVE_V, reg); - - reg = ((v_total & 0xFFFF) << 16) | (h_total & 0xFFFF); - DSI_W32(ctrl, DSI_VIDEO_MODE_TOTAL, reg); - - reg = ((hs_end & 0xFFFF) << 16) | (hs_start & 0xFFFF); - DSI_W32(ctrl, DSI_VIDEO_MODE_HSYNC, reg); - - reg = ((vs_end & 0xFFFF) << 16) | (vs_start & 0xFFFF); - DSI_W32(ctrl, DSI_VIDEO_MODE_VSYNC, reg); - - reg = ((vpos_end & 0xFFFF) << 16) | (vpos_start & 0xFFFF); - DSI_W32(ctrl, DSI_VIDEO_MODE_VSYNC_VPOS, reg); - - /* TODO: HS TIMER value? */ - DSI_W32(ctrl, DSI_HS_TIMER_CTRL, 0x3FD08); - DSI_W32(ctrl, DSI_MISR_VIDEO_CTRL, 0x10100); - DSI_W32(ctrl, DSI_DSI_TIMING_FLUSH, 0x1); - pr_debug("[DSI_%d] ctrl video parameters updated\n", ctrl->index); - DPU_EVT32(v_total, h_total); -} - -/** - * setup_cmd_stream() - set up parameters for command pixel streams - * @ctrl: Pointer to controller host hardware. - * @mode: Pointer to mode information. - * @h_stride: Horizontal stride in bytes. - * @vc_id: stream_id - * - * Setup parameters for command mode pixel stream size. - */ -void dsi_ctrl_hw_cmn_setup_cmd_stream(struct dsi_ctrl_hw *ctrl, - struct dsi_mode_info *mode, - u32 h_stride, - u32 vc_id, - struct dsi_rect *roi) -{ - u32 width_final, stride_final; - u32 height_final; - u32 stream_total = 0, stream_ctrl = 0; - u32 reg_ctrl = 0, reg_ctrl2 = 0; - - if (roi && (!roi->w || !roi->h)) - return; - - if (mode->dsc_enabled && mode->dsc) { - u32 reg = 0; - u32 offset = 0; - int pic_width, this_frame_slices, intf_ip_w; - struct msm_display_dsc_info dsc; - - memcpy(&dsc, mode->dsc, sizeof(dsc)); - pic_width = roi ? roi->w : mode->h_active; - this_frame_slices = pic_width / dsc.slice_width; - intf_ip_w = this_frame_slices * dsc.slice_width; - dsi_dsc_pclk_param_calc(&dsc, intf_ip_w); - - if (vc_id != 0) - offset = 16; - reg_ctrl = DSI_R32(ctrl, DSI_COMMAND_COMPRESSION_MODE_CTRL); - reg_ctrl2 = DSI_R32(ctrl, DSI_COMMAND_COMPRESSION_MODE_CTRL2); - width_final = dsc.pclk_per_line; - stride_final = dsc.bytes_per_pkt; - height_final = roi ? roi->h : mode->v_active; - - reg = 0x39 << 8; - /* - * pkt_per_line: - * 0 == 1 pkt - * 1 == 2 pkt - * 2 == 4 pkt - * 3 pkt is not support - */ - if (dsc.pkt_per_line == 4) - reg |= (dsc.pkt_per_line - 2) << 6; - else - reg |= (dsc.pkt_per_line - 1) << 6; - reg |= dsc.eol_byte_num << 4; - reg |= 1; - - reg_ctrl &= ~(0xFFFF << offset); - reg_ctrl |= (reg << offset); - reg_ctrl2 &= ~(0xFFFF << offset); - reg_ctrl2 |= (dsc.bytes_in_slice << offset); - - pr_debug("ctrl %d reg_ctrl 0x%x reg_ctrl2 0x%x\n", ctrl->index, - reg_ctrl, reg_ctrl2); - } else if (roi) { - width_final = roi->w; - stride_final = roi->w * 3; - height_final = roi->h; - } else { - width_final = mode->h_active; - stride_final = h_stride; - height_final = mode->v_active; - } - - stream_ctrl = (stride_final + 1) << 16; - stream_ctrl |= (vc_id & 0x3) << 8; - stream_ctrl |= 0x39; /* packet data type */ - - DSI_W32(ctrl, DSI_COMMAND_COMPRESSION_MODE_CTRL, reg_ctrl); - DSI_W32(ctrl, DSI_COMMAND_COMPRESSION_MODE_CTRL2, reg_ctrl2); - - DSI_W32(ctrl, DSI_COMMAND_MODE_MDP_STREAM0_CTRL, stream_ctrl); - DSI_W32(ctrl, DSI_COMMAND_MODE_MDP_STREAM1_CTRL, stream_ctrl); - - stream_total = (height_final << 16) | width_final; - DSI_W32(ctrl, DSI_COMMAND_MODE_MDP_STREAM0_TOTAL, stream_total); - DSI_W32(ctrl, DSI_COMMAND_MODE_MDP_STREAM1_TOTAL, stream_total); - - pr_debug("ctrl %d stream_ctrl 0x%x stream_total 0x%x\n", ctrl->index, - stream_ctrl, stream_total); -} - -/** - * video_engine_setup() - Setup dsi host controller for video mode - * @ctrl: Pointer to controller host hardware. - * @common_cfg: Common configuration parameters. - * @cfg: Video mode configuration. - * - * Set up DSI video engine with a specific configuration. Controller and - * video engine are not enabled as part of this function. - */ -void dsi_ctrl_hw_cmn_video_engine_setup(struct dsi_ctrl_hw *ctrl, - struct dsi_host_common_cfg *common_cfg, - struct dsi_video_engine_cfg *cfg) -{ - u32 reg = 0; - - reg |= (cfg->last_line_interleave_en ? BIT(31) : 0); - reg |= (cfg->pulse_mode_hsa_he ? BIT(28) : 0); - reg |= (cfg->hfp_lp11_en ? BIT(24) : 0); - reg |= (cfg->hbp_lp11_en ? BIT(20) : 0); - reg |= (cfg->hsa_lp11_en ? BIT(16) : 0); - reg |= (cfg->eof_bllp_lp11_en ? BIT(15) : 0); - reg |= (cfg->bllp_lp11_en ? BIT(12) : 0); - reg |= (cfg->traffic_mode & 0x3) << 8; - reg |= (cfg->vc_id & 0x3); - reg |= (video_mode_format_map[common_cfg->dst_format] & 0x3) << 4; - DSI_W32(ctrl, DSI_VIDEO_MODE_CTRL, reg); - - reg = (common_cfg->swap_mode & 0x7) << 12; - reg |= (common_cfg->bit_swap_red ? BIT(0) : 0); - reg |= (common_cfg->bit_swap_green ? BIT(4) : 0); - reg |= (common_cfg->bit_swap_blue ? BIT(8) : 0); - DSI_W32(ctrl, DSI_VIDEO_MODE_DATA_CTRL, reg); - /* Disable Timing double buffering */ - DSI_W32(ctrl, DSI_DSI_TIMING_DB_MODE, 0x0); - - - pr_debug("[DSI_%d] Video engine setup done\n", ctrl->index); -} - -void dsi_ctrl_hw_cmn_debug_bus(struct dsi_ctrl_hw *ctrl) -{ - u32 reg = 0; - - DSI_W32(ctrl, DSI_DEBUG_BUS_CTL, 0x181); - - /* make sure that debug test point is enabled */ - wmb(); - reg = DSI_R32(ctrl, DSI_DEBUG_BUS_STATUS); - - pr_err("[DSI_%d] debug bus status:0x%x\n", ctrl->index, reg); -} -/** - * cmd_engine_setup() - setup dsi host controller for command mode - * @ctrl: Pointer to the controller host hardware. - * @common_cfg: Common configuration parameters. - * @cfg: Command mode configuration. - * - * Setup DSI CMD engine with a specific configuration. Controller and - * command engine are not enabled as part of this function. - */ -void dsi_ctrl_hw_cmn_cmd_engine_setup(struct dsi_ctrl_hw *ctrl, - struct dsi_host_common_cfg *common_cfg, - struct dsi_cmd_engine_cfg *cfg) -{ - u32 reg = 0; - - reg = (cfg->max_cmd_packets_interleave & 0xF) << 20; - reg |= (common_cfg->bit_swap_red ? BIT(4) : 0); - reg |= (common_cfg->bit_swap_green ? BIT(8) : 0); - reg |= (common_cfg->bit_swap_blue ? BIT(12) : 0); - reg |= cmd_mode_format_map[common_cfg->dst_format]; - DSI_W32(ctrl, DSI_COMMAND_MODE_MDP_CTRL, reg); - - reg = DSI_R32(ctrl, DSI_COMMAND_MODE_MDP_CTRL2); - reg |= BIT(16); - DSI_W32(ctrl, DSI_COMMAND_MODE_MDP_CTRL2, reg); - - reg = cfg->wr_mem_start & 0xFF; - reg |= (cfg->wr_mem_continue & 0xFF) << 8; - reg |= (cfg->insert_dcs_command ? BIT(16) : 0); - DSI_W32(ctrl, DSI_COMMAND_MODE_MDP_DCS_CMD_CTRL, reg); - - pr_debug("[DSI_%d] Cmd engine setup done\n", ctrl->index); -} - -/** - * video_engine_en() - enable DSI video engine - * @ctrl: Pointer to controller host hardware. - * @on: Enable/disabel video engine. - */ -void dsi_ctrl_hw_cmn_video_engine_en(struct dsi_ctrl_hw *ctrl, bool on) -{ - u32 reg = 0; - - /* Set/Clear VIDEO_MODE_EN bit */ - reg = DSI_R32(ctrl, DSI_CTRL); - if (on) - reg |= BIT(1); - else - reg &= ~BIT(1); - - DSI_W32(ctrl, DSI_CTRL, reg); - - pr_debug("[DSI_%d] Video engine = %d\n", ctrl->index, on); -} - -/** - * ctrl_en() - enable DSI controller engine - * @ctrl: Pointer to the controller host hardware. - * @on: turn on/off the DSI controller engine. - */ -void dsi_ctrl_hw_cmn_ctrl_en(struct dsi_ctrl_hw *ctrl, bool on) -{ - u32 reg = 0; - u32 clk_ctrl; - - clk_ctrl = DSI_R32(ctrl, DSI_CLK_CTRL); - DSI_W32(ctrl, DSI_CLK_CTRL, clk_ctrl | DSI_CTRL_DYNAMIC_FORCE_ON); - wmb(); /* wait for clocks to enable */ - - /* Set/Clear DSI_EN bit */ - reg = DSI_R32(ctrl, DSI_CTRL); - if (on) - reg |= BIT(0); - else - reg &= ~BIT(0); - - DSI_W32(ctrl, DSI_CTRL, reg); - wmb(); /* wait for DSI_EN update before disabling clocks */ - - DSI_W32(ctrl, DSI_CLK_CTRL, clk_ctrl); - wmb(); /* make sure clocks are restored */ - - pr_debug("[DSI_%d] Controller engine = %d\n", ctrl->index, on); -} - -/** - * cmd_engine_en() - enable DSI controller command engine - * @ctrl: Pointer to the controller host hardware. - * @on: Turn on/off the DSI command engine. - */ -void dsi_ctrl_hw_cmn_cmd_engine_en(struct dsi_ctrl_hw *ctrl, bool on) -{ - u32 reg = 0; - - /* Set/Clear CMD_MODE_EN bit */ - reg = DSI_R32(ctrl, DSI_CTRL); - if (on) - reg |= BIT(2); - else - reg &= ~BIT(2); - - DSI_W32(ctrl, DSI_CTRL, reg); - - pr_debug("[DSI_%d] command engine = %d\n", ctrl->index, on); -} - -/** - * kickoff_command() - transmits commands stored in memory - * @ctrl: Pointer to the controller host hardware. - * @cmd: Command information. - * @flags: Modifiers for command transmission. - * - * The controller hardware is programmed with address and size of the - * command buffer. The transmission is kicked off if - * DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER flag is not set. If this flag is - * set, caller should make a separate call to trigger_command_dma() to - * transmit the command. - */ -void dsi_ctrl_hw_cmn_kickoff_command(struct dsi_ctrl_hw *ctrl, - struct dsi_ctrl_cmd_dma_info *cmd, - u32 flags) -{ - u32 reg = 0; - - /*Set BROADCAST_EN and EMBEDDED_MODE */ - reg = DSI_R32(ctrl, DSI_COMMAND_MODE_DMA_CTRL); - if (cmd->en_broadcast) - reg |= BIT(31); - else - reg &= ~BIT(31); - - if (cmd->is_master) - reg |= BIT(30); - else - reg &= ~BIT(30); - - if (cmd->use_lpm) - reg |= BIT(26); - else - reg &= ~BIT(26); - - reg |= BIT(28); - DSI_W32(ctrl, DSI_COMMAND_MODE_DMA_CTRL, reg); - - DSI_W32(ctrl, DSI_DMA_CMD_OFFSET, cmd->offset); - DSI_W32(ctrl, DSI_DMA_CMD_LENGTH, (cmd->length & 0xFFFFFF)); - - /* wait for writes to complete before kick off */ - wmb(); - - if (!(flags & DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER)) - DSI_W32(ctrl, DSI_CMD_MODE_DMA_SW_TRIGGER, 0x1); -} - -/** - * kickoff_fifo_command() - transmits a command using FIFO in dsi - * hardware. - * @ctrl: Pointer to the controller host hardware. - * @cmd: Command information. - * @flags: Modifiers for command transmission. - * - * The controller hardware FIFO is programmed with command header and - * payload. The transmission is kicked off if - * DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER flag is not set. If this flag is - * set, caller should make a separate call to trigger_command_dma() to - * transmit the command. - */ -void dsi_ctrl_hw_cmn_kickoff_fifo_command(struct dsi_ctrl_hw *ctrl, - struct dsi_ctrl_cmd_dma_fifo_info *cmd, - u32 flags) -{ - u32 reg = 0, i = 0; - u32 *ptr = cmd->command; - /* - * Set CMD_DMA_TPG_EN, TPG_DMA_FIFO_MODE and - * CMD_DMA_PATTERN_SEL = custom pattern stored in TPG DMA FIFO - */ - reg = (BIT(1) | BIT(2) | (0x3 << 16)); - DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CTRL, reg); - - /* - * Program the FIFO with command buffer. Hardware requires an extra - * DWORD (set to zero) if the length of command buffer is odd DWORDS. - */ - for (i = 0; i < cmd->size; i += 4) { - DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CMD_DMA_INIT_VAL, *ptr); - ptr++; - } - - if ((cmd->size / 4) & 0x1) - DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CMD_DMA_INIT_VAL, 0); - - /*Set BROADCAST_EN and EMBEDDED_MODE */ - reg = DSI_R32(ctrl, DSI_COMMAND_MODE_DMA_CTRL); - if (cmd->en_broadcast) - reg |= BIT(31); - else - reg &= ~BIT(31); - - if (cmd->is_master) - reg |= BIT(30); - else - reg &= ~BIT(30); - - if (cmd->use_lpm) - reg |= BIT(26); - else - reg &= ~BIT(26); - - reg |= BIT(28); - - DSI_W32(ctrl, DSI_COMMAND_MODE_DMA_CTRL, reg); - - DSI_W32(ctrl, DSI_DMA_CMD_LENGTH, (cmd->size & 0xFFFFFFFF)); - /* Finish writes before command trigger */ - wmb(); - - if (!(flags & DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER)) - DSI_W32(ctrl, DSI_CMD_MODE_DMA_SW_TRIGGER, 0x1); - - pr_debug("[DSI_%d]size=%d, trigger = %d\n", - ctrl->index, cmd->size, - (flags & DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER) ? false : true); -} - -void dsi_ctrl_hw_cmn_reset_cmd_fifo(struct dsi_ctrl_hw *ctrl) -{ - /* disable cmd dma tpg */ - DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CTRL, 0x0); - - DSI_W32(ctrl, DSI_TPG_DMA_FIFO_RESET, 0x1); - udelay(1); - DSI_W32(ctrl, DSI_TPG_DMA_FIFO_RESET, 0x0); -} - -/** - * trigger_command_dma() - trigger transmission of command buffer. - * @ctrl: Pointer to the controller host hardware. - * - * This trigger can be only used if there was a prior call to - * kickoff_command() of kickoff_fifo_command() with - * DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER flag. - */ -void dsi_ctrl_hw_cmn_trigger_command_dma(struct dsi_ctrl_hw *ctrl) -{ - DSI_W32(ctrl, DSI_CMD_MODE_DMA_SW_TRIGGER, 0x1); - pr_debug("[DSI_%d] CMD DMA triggered\n", ctrl->index); -} - -/** - * get_cmd_read_data() - get data read from the peripheral - * @ctrl: Pointer to the controller host hardware. - * @rd_buf: Buffer where data will be read into. - * @total_read_len: Number of bytes to read. - * - * return: number of bytes read. - */ -u32 dsi_ctrl_hw_cmn_get_cmd_read_data(struct dsi_ctrl_hw *ctrl, - u8 *rd_buf, - u32 read_offset, - u32 total_read_len) -{ - u32 *lp, *temp, data; - int i, j = 0, cnt; - u32 read_cnt; - u32 rx_byte = 0; - u32 repeated_bytes = 0; - u8 reg[16] = {0}; - u32 pkt_size = 0; - int buf_offset = read_offset; - - lp = (u32 *)rd_buf; - temp = (u32 *)reg; - cnt = (rx_byte + 3) >> 2; - - if (cnt > 4) - cnt = 4; - - if (rx_byte == 4) - read_cnt = 4; - else - read_cnt = pkt_size + 6; - - if (read_cnt > 16) { - int bytes_shifted; - - bytes_shifted = read_cnt - 16; - repeated_bytes = buf_offset - bytes_shifted; - } - - for (i = cnt - 1; i >= 0; i--) { - data = DSI_R32(ctrl, DSI_RDBK_DATA0 + i*4); - *temp++ = ntohl(data); - } - - for (i = repeated_bytes; i < 16; i++) - rd_buf[j++] = reg[i]; - - pr_debug("[DSI_%d] Read %d bytes\n", ctrl->index, j); - return j; -} - -/** - * get_interrupt_status() - returns the interrupt status - * @ctrl: Pointer to the controller host hardware. - * - * Returns the ORed list of interrupts(enum dsi_status_int_type) that - * are active. This list does not include any error interrupts. Caller - * should call get_error_status for error interrupts. - * - * Return: List of active interrupts. - */ -u32 dsi_ctrl_hw_cmn_get_interrupt_status(struct dsi_ctrl_hw *ctrl) -{ - u32 reg = 0; - u32 ints = 0; - - reg = DSI_R32(ctrl, DSI_INT_CTRL); - - if (reg & BIT(0)) - ints |= DSI_CMD_MODE_DMA_DONE; - if (reg & BIT(8)) - ints |= DSI_CMD_FRAME_DONE; - if (reg & BIT(10)) - ints |= DSI_CMD_STREAM0_FRAME_DONE; - if (reg & BIT(12)) - ints |= DSI_CMD_STREAM1_FRAME_DONE; - if (reg & BIT(14)) - ints |= DSI_CMD_STREAM2_FRAME_DONE; - if (reg & BIT(16)) - ints |= DSI_VIDEO_MODE_FRAME_DONE; - if (reg & BIT(20)) - ints |= DSI_BTA_DONE; - if (reg & BIT(28)) - ints |= DSI_DYN_REFRESH_DONE; - if (reg & BIT(30)) - ints |= DSI_DESKEW_DONE; - - pr_debug("[DSI_%d] Interrupt status = 0x%x, INT_CTRL=0x%x\n", - ctrl->index, ints, reg); - return ints; -} - -/** - * clear_interrupt_status() - clears the specified interrupts - * @ctrl: Pointer to the controller host hardware. - * @ints: List of interrupts to be cleared. - */ -void dsi_ctrl_hw_cmn_clear_interrupt_status(struct dsi_ctrl_hw *ctrl, u32 ints) -{ - u32 reg = 0; - - reg = DSI_R32(ctrl, DSI_INT_CTRL); - - if (ints & DSI_CMD_MODE_DMA_DONE) - reg |= BIT(0); - if (ints & DSI_CMD_FRAME_DONE) - reg |= BIT(8); - if (ints & DSI_CMD_STREAM0_FRAME_DONE) - reg |= BIT(10); - if (ints & DSI_CMD_STREAM1_FRAME_DONE) - reg |= BIT(12); - if (ints & DSI_CMD_STREAM2_FRAME_DONE) - reg |= BIT(14); - if (ints & DSI_VIDEO_MODE_FRAME_DONE) - reg |= BIT(16); - if (ints & DSI_BTA_DONE) - reg |= BIT(20); - if (ints & DSI_DYN_REFRESH_DONE) - reg |= BIT(28); - if (ints & DSI_DESKEW_DONE) - reg |= BIT(30); - - DSI_W32(ctrl, DSI_INT_CTRL, reg); - - pr_debug("[DSI_%d] Clear interrupts, ints = 0x%x, INT_CTRL=0x%x\n", - ctrl->index, ints, reg); -} - -/** - * enable_status_interrupts() - enable the specified interrupts - * @ctrl: Pointer to the controller host hardware. - * @ints: List of interrupts to be enabled. - * - * Enables the specified interrupts. This list will override the - * previous interrupts enabled through this function. Caller has to - * maintain the state of the interrupts enabled. To disable all - * interrupts, set ints to 0. - */ -void dsi_ctrl_hw_cmn_enable_status_interrupts( - struct dsi_ctrl_hw *ctrl, u32 ints) -{ - u32 reg = 0; - - /* Do not change value of DSI_ERROR_MASK bit */ - reg |= (DSI_R32(ctrl, DSI_INT_CTRL) & BIT(25)); - if (ints & DSI_CMD_MODE_DMA_DONE) - reg |= BIT(1); - if (ints & DSI_CMD_FRAME_DONE) - reg |= BIT(9); - if (ints & DSI_CMD_STREAM0_FRAME_DONE) - reg |= BIT(11); - if (ints & DSI_CMD_STREAM1_FRAME_DONE) - reg |= BIT(13); - if (ints & DSI_CMD_STREAM2_FRAME_DONE) - reg |= BIT(15); - if (ints & DSI_VIDEO_MODE_FRAME_DONE) - reg |= BIT(17); - if (ints & DSI_BTA_DONE) - reg |= BIT(21); - if (ints & DSI_DYN_REFRESH_DONE) - reg |= BIT(29); - if (ints & DSI_DESKEW_DONE) - reg |= BIT(31); - - DSI_W32(ctrl, DSI_INT_CTRL, reg); - - pr_debug("[DSI_%d] Enable interrupts 0x%x, INT_CTRL=0x%x\n", - ctrl->index, ints, reg); -} - -/** - * get_error_status() - returns the error status - * @ctrl: Pointer to the controller host hardware. - * - * Returns the ORed list of errors(enum dsi_error_int_type) that are - * active. This list does not include any status interrupts. Caller - * should call get_interrupt_status for status interrupts. - * - * Return: List of active error interrupts. - */ -u64 dsi_ctrl_hw_cmn_get_error_status(struct dsi_ctrl_hw *ctrl) -{ - u32 dln0_phy_err; - u32 fifo_status; - u32 ack_error; - u32 timeout_errors; - u32 clk_error; - u32 dsi_status; - u64 errors = 0; - - dln0_phy_err = DSI_R32(ctrl, DSI_DLN0_PHY_ERR); - if (dln0_phy_err & BIT(0)) - errors |= DSI_DLN0_ESC_ENTRY_ERR; - if (dln0_phy_err & BIT(4)) - errors |= DSI_DLN0_ESC_SYNC_ERR; - if (dln0_phy_err & BIT(8)) - errors |= DSI_DLN0_LP_CONTROL_ERR; - if (dln0_phy_err & BIT(12)) - errors |= DSI_DLN0_LP0_CONTENTION; - if (dln0_phy_err & BIT(16)) - errors |= DSI_DLN0_LP1_CONTENTION; - - fifo_status = DSI_R32(ctrl, DSI_FIFO_STATUS); - if (fifo_status & BIT(7)) - errors |= DSI_CMD_MDP_FIFO_UNDERFLOW; - if (fifo_status & BIT(10)) - errors |= DSI_CMD_DMA_FIFO_UNDERFLOW; - if (fifo_status & BIT(18)) - errors |= DSI_DLN0_HS_FIFO_OVERFLOW; - if (fifo_status & BIT(19)) - errors |= DSI_DLN0_HS_FIFO_UNDERFLOW; - if (fifo_status & BIT(22)) - errors |= DSI_DLN1_HS_FIFO_OVERFLOW; - if (fifo_status & BIT(23)) - errors |= DSI_DLN1_HS_FIFO_UNDERFLOW; - if (fifo_status & BIT(26)) - errors |= DSI_DLN2_HS_FIFO_OVERFLOW; - if (fifo_status & BIT(27)) - errors |= DSI_DLN2_HS_FIFO_UNDERFLOW; - if (fifo_status & BIT(30)) - errors |= DSI_DLN3_HS_FIFO_OVERFLOW; - if (fifo_status & BIT(31)) - errors |= DSI_DLN3_HS_FIFO_UNDERFLOW; - - ack_error = DSI_R32(ctrl, DSI_ACK_ERR_STATUS); - if (ack_error & BIT(16)) - errors |= DSI_RDBK_SINGLE_ECC_ERR; - if (ack_error & BIT(17)) - errors |= DSI_RDBK_MULTI_ECC_ERR; - if (ack_error & BIT(20)) - errors |= DSI_RDBK_CRC_ERR; - if (ack_error & BIT(23)) - errors |= DSI_RDBK_INCOMPLETE_PKT; - if (ack_error & BIT(24)) - errors |= DSI_PERIPH_ERROR_PKT; - - timeout_errors = DSI_R32(ctrl, DSI_TIMEOUT_STATUS); - if (timeout_errors & BIT(0)) - errors |= DSI_HS_TX_TIMEOUT; - if (timeout_errors & BIT(4)) - errors |= DSI_LP_RX_TIMEOUT; - if (timeout_errors & BIT(8)) - errors |= DSI_BTA_TIMEOUT; - - clk_error = DSI_R32(ctrl, DSI_CLK_STATUS); - if (clk_error & BIT(16)) - errors |= DSI_PLL_UNLOCK; - - dsi_status = DSI_R32(ctrl, DSI_STATUS); - if (dsi_status & BIT(31)) - errors |= DSI_INTERLEAVE_OP_CONTENTION; - - pr_debug("[DSI_%d] Error status = 0x%llx, phy=0x%x, fifo=0x%x", - ctrl->index, errors, dln0_phy_err, fifo_status); - pr_debug("[DSI_%d] ack=0x%x, timeout=0x%x, clk=0x%x, dsi=0x%x\n", - ctrl->index, ack_error, timeout_errors, clk_error, dsi_status); - return errors; -} - -/** - * clear_error_status() - clears the specified errors - * @ctrl: Pointer to the controller host hardware. - * @errors: List of errors to be cleared. - */ -void dsi_ctrl_hw_cmn_clear_error_status(struct dsi_ctrl_hw *ctrl, u64 errors) -{ - u32 dln0_phy_err = 0; - u32 fifo_status = 0; - u32 ack_error = 0; - u32 timeout_error = 0; - u32 clk_error = 0; - u32 dsi_status = 0; - u32 int_ctrl = 0; - - if (errors & DSI_RDBK_SINGLE_ECC_ERR) - ack_error |= BIT(16); - if (errors & DSI_RDBK_MULTI_ECC_ERR) - ack_error |= BIT(17); - if (errors & DSI_RDBK_CRC_ERR) - ack_error |= BIT(20); - if (errors & DSI_RDBK_INCOMPLETE_PKT) - ack_error |= BIT(23); - if (errors & DSI_PERIPH_ERROR_PKT) - ack_error |= BIT(24); - - if (errors & DSI_LP_RX_TIMEOUT) - timeout_error |= BIT(4); - if (errors & DSI_HS_TX_TIMEOUT) - timeout_error |= BIT(0); - if (errors & DSI_BTA_TIMEOUT) - timeout_error |= BIT(8); - - if (errors & DSI_PLL_UNLOCK) - clk_error |= BIT(16); - - if (errors & DSI_DLN0_LP0_CONTENTION) - dln0_phy_err |= BIT(12); - if (errors & DSI_DLN0_LP1_CONTENTION) - dln0_phy_err |= BIT(16); - if (errors & DSI_DLN0_ESC_ENTRY_ERR) - dln0_phy_err |= BIT(0); - if (errors & DSI_DLN0_ESC_SYNC_ERR) - dln0_phy_err |= BIT(4); - if (errors & DSI_DLN0_LP_CONTROL_ERR) - dln0_phy_err |= BIT(8); - - if (errors & DSI_CMD_DMA_FIFO_UNDERFLOW) - fifo_status |= BIT(10); - if (errors & DSI_CMD_MDP_FIFO_UNDERFLOW) - fifo_status |= BIT(7); - if (errors & DSI_DLN0_HS_FIFO_OVERFLOW) - fifo_status |= BIT(18); - if (errors & DSI_DLN1_HS_FIFO_OVERFLOW) - fifo_status |= BIT(22); - if (errors & DSI_DLN2_HS_FIFO_OVERFLOW) - fifo_status |= BIT(26); - if (errors & DSI_DLN3_HS_FIFO_OVERFLOW) - fifo_status |= BIT(30); - if (errors & DSI_DLN0_HS_FIFO_UNDERFLOW) - fifo_status |= BIT(19); - if (errors & DSI_DLN1_HS_FIFO_UNDERFLOW) - fifo_status |= BIT(23); - if (errors & DSI_DLN2_HS_FIFO_UNDERFLOW) - fifo_status |= BIT(27); - if (errors & DSI_DLN3_HS_FIFO_UNDERFLOW) - fifo_status |= BIT(31); - - if (errors & DSI_INTERLEAVE_OP_CONTENTION) - dsi_status |= BIT(31); - - DSI_W32(ctrl, DSI_DLN0_PHY_ERR, dln0_phy_err); - DSI_W32(ctrl, DSI_FIFO_STATUS, fifo_status); - DSI_W32(ctrl, DSI_ACK_ERR_STATUS, ack_error); - DSI_W32(ctrl, DSI_TIMEOUT_STATUS, timeout_error); - DSI_W32(ctrl, DSI_CLK_STATUS, clk_error); - DSI_W32(ctrl, DSI_STATUS, dsi_status); - - int_ctrl = DSI_R32(ctrl, DSI_INT_CTRL); - int_ctrl |= BIT(24); - DSI_W32(ctrl, DSI_INT_CTRL, int_ctrl); - pr_debug("[DSI_%d] clear errors = 0x%llx, phy=0x%x, fifo=0x%x", - ctrl->index, errors, dln0_phy_err, fifo_status); - pr_debug("[DSI_%d] ack=0x%x, timeout=0x%x, clk=0x%x, dsi=0x%x\n", - ctrl->index, ack_error, timeout_error, clk_error, dsi_status); -} - -/** - * enable_error_interrupts() - enable the specified interrupts - * @ctrl: Pointer to the controller host hardware. - * @errors: List of errors to be enabled. - * - * Enables the specified interrupts. This list will override the - * previous interrupts enabled through this function. Caller has to - * maintain the state of the interrupts enabled. To disable all - * interrupts, set errors to 0. - */ -void dsi_ctrl_hw_cmn_enable_error_interrupts(struct dsi_ctrl_hw *ctrl, - u64 errors) -{ - u32 int_ctrl = 0; - u32 int_mask0 = 0x7FFF3BFF; - - int_ctrl = DSI_R32(ctrl, DSI_INT_CTRL); - if (errors) - int_ctrl |= BIT(25); - else - int_ctrl &= ~BIT(25); - - if (errors & DSI_RDBK_SINGLE_ECC_ERR) - int_mask0 &= ~BIT(0); - if (errors & DSI_RDBK_MULTI_ECC_ERR) - int_mask0 &= ~BIT(1); - if (errors & DSI_RDBK_CRC_ERR) - int_mask0 &= ~BIT(2); - if (errors & DSI_RDBK_INCOMPLETE_PKT) - int_mask0 &= ~BIT(3); - if (errors & DSI_PERIPH_ERROR_PKT) - int_mask0 &= ~BIT(4); - - if (errors & DSI_LP_RX_TIMEOUT) - int_mask0 &= ~BIT(5); - if (errors & DSI_HS_TX_TIMEOUT) - int_mask0 &= ~BIT(6); - if (errors & DSI_BTA_TIMEOUT) - int_mask0 &= ~BIT(7); - - if (errors & DSI_PLL_UNLOCK) - int_mask0 &= ~BIT(28); - - if (errors & DSI_DLN0_LP0_CONTENTION) - int_mask0 &= ~BIT(24); - if (errors & DSI_DLN0_LP1_CONTENTION) - int_mask0 &= ~BIT(25); - if (errors & DSI_DLN0_ESC_ENTRY_ERR) - int_mask0 &= ~BIT(21); - if (errors & DSI_DLN0_ESC_SYNC_ERR) - int_mask0 &= ~BIT(22); - if (errors & DSI_DLN0_LP_CONTROL_ERR) - int_mask0 &= ~BIT(23); - - if (errors & DSI_CMD_DMA_FIFO_UNDERFLOW) - int_mask0 &= ~BIT(9); - if (errors & DSI_CMD_MDP_FIFO_UNDERFLOW) - int_mask0 &= ~BIT(11); - if (errors & DSI_DLN0_HS_FIFO_OVERFLOW) - int_mask0 &= ~BIT(16); - if (errors & DSI_DLN1_HS_FIFO_OVERFLOW) - int_mask0 &= ~BIT(17); - if (errors & DSI_DLN2_HS_FIFO_OVERFLOW) - int_mask0 &= ~BIT(18); - if (errors & DSI_DLN3_HS_FIFO_OVERFLOW) - int_mask0 &= ~BIT(19); - if (errors & DSI_DLN0_HS_FIFO_UNDERFLOW) - int_mask0 &= ~BIT(26); - if (errors & DSI_DLN1_HS_FIFO_UNDERFLOW) - int_mask0 &= ~BIT(27); - if (errors & DSI_DLN2_HS_FIFO_UNDERFLOW) - int_mask0 &= ~BIT(29); - if (errors & DSI_DLN3_HS_FIFO_UNDERFLOW) - int_mask0 &= ~BIT(30); - - if (errors & DSI_INTERLEAVE_OP_CONTENTION) - int_mask0 &= ~BIT(8); - - DSI_W32(ctrl, DSI_INT_CTRL, int_ctrl); - DSI_W32(ctrl, DSI_ERR_INT_MASK0, int_mask0); - - pr_debug("[DSI_%d] enable errors = 0x%llx, int_mask0=0x%x\n", - ctrl->index, errors, int_mask0); -} - -/** - * video_test_pattern_setup() - setup test pattern engine for video mode - * @ctrl: Pointer to the controller host hardware. - * @type: Type of test pattern. - * @init_val: Initial value to use for generating test pattern. - */ -void dsi_ctrl_hw_cmn_video_test_pattern_setup(struct dsi_ctrl_hw *ctrl, - enum dsi_test_pattern type, - u32 init_val) -{ - u32 reg = 0; - - DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_VIDEO_INIT_VAL, init_val); - - switch (type) { - case DSI_TEST_PATTERN_FIXED: - reg |= (0x2 << 4); - break; - case DSI_TEST_PATTERN_INC: - reg |= (0x1 << 4); - break; - case DSI_TEST_PATTERN_POLY: - DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_VIDEO_POLY, 0xF0F0F); - break; - default: - break; - } - - DSI_W32(ctrl, DSI_TPG_MAIN_CONTROL, 0x100); - DSI_W32(ctrl, DSI_TPG_VIDEO_CONFIG, 0x5); - DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CTRL, reg); - - pr_debug("[DSI_%d] Video test pattern setup done\n", ctrl->index); -} - -/** - * cmd_test_pattern_setup() - setup test patttern engine for cmd mode - * @ctrl: Pointer to the controller host hardware. - * @type: Type of test pattern. - * @init_val: Initial value to use for generating test pattern. - * @stream_id: Stream Id on which packets are generated. - */ -void dsi_ctrl_hw_cmn_cmd_test_pattern_setup(struct dsi_ctrl_hw *ctrl, - enum dsi_test_pattern type, - u32 init_val, - u32 stream_id) -{ - u32 reg = 0; - u32 init_offset; - u32 poly_offset; - u32 pattern_sel_shift; - - switch (stream_id) { - case 0: - init_offset = DSI_TEST_PATTERN_GEN_CMD_MDP_INIT_VAL0; - poly_offset = DSI_TEST_PATTERN_GEN_CMD_MDP_STREAM0_POLY; - pattern_sel_shift = 8; - break; - case 1: - init_offset = DSI_TEST_PATTERN_GEN_CMD_MDP_INIT_VAL1; - poly_offset = DSI_TEST_PATTERN_GEN_CMD_MDP_STREAM1_POLY; - pattern_sel_shift = 12; - break; - case 2: - init_offset = DSI_TEST_PATTERN_GEN_CMD_MDP_INIT_VAL2; - poly_offset = DSI_TEST_PATTERN_GEN_CMD_MDP_STREAM2_POLY; - pattern_sel_shift = 20; - break; - default: - return; - } - - DSI_W32(ctrl, init_offset, init_val); - - switch (type) { - case DSI_TEST_PATTERN_FIXED: - reg |= (0x2 << pattern_sel_shift); - break; - case DSI_TEST_PATTERN_INC: - reg |= (0x1 << pattern_sel_shift); - break; - case DSI_TEST_PATTERN_POLY: - DSI_W32(ctrl, poly_offset, 0xF0F0F); - break; - default: - break; - } - - DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CTRL, reg); - pr_debug("[DSI_%d] Cmd test pattern setup done\n", ctrl->index); -} - -/** - * test_pattern_enable() - enable test pattern engine - * @ctrl: Pointer to the controller host hardware. - * @enable: Enable/Disable test pattern engine. - */ -void dsi_ctrl_hw_cmn_test_pattern_enable(struct dsi_ctrl_hw *ctrl, - bool enable) -{ - u32 reg = DSI_R32(ctrl, DSI_TEST_PATTERN_GEN_CTRL); - - if (enable) - reg |= BIT(0); - else - reg &= ~BIT(0); - - DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CTRL, reg); - - pr_debug("[DSI_%d] Test pattern enable=%d\n", ctrl->index, enable); -} - -/** - * trigger_cmd_test_pattern() - trigger a command mode frame update with - * test pattern - * @ctrl: Pointer to the controller host hardware. - * @stream_id: Stream on which frame update is sent. - */ -void dsi_ctrl_hw_cmn_trigger_cmd_test_pattern(struct dsi_ctrl_hw *ctrl, - u32 stream_id) -{ - switch (stream_id) { - case 0: - DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CMD_STREAM0_TRIGGER, 0x1); - break; - case 1: - DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CMD_STREAM1_TRIGGER, 0x1); - break; - case 2: - DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CMD_STREAM2_TRIGGER, 0x1); - break; - default: - break; - } - - pr_debug("[DSI_%d] Cmd Test pattern trigger\n", ctrl->index); -} - -void dsi_ctrl_hw_dln0_phy_err(struct dsi_ctrl_hw *ctrl) -{ - u32 status = 0; - /* - * Clear out any phy errors prior to exiting ULPS - * This fixes certain instances where phy does not exit - * ULPS cleanly. Also, do not print error during such cases. - */ - status = DSI_R32(ctrl, DSI_DLN0_PHY_ERR); - if (status & 0x011111) { - DSI_W32(ctrl, DSI_DLN0_PHY_ERR, status); - pr_err("%s: phy_err_status = %x\n", __func__, status); - } -} - -void dsi_ctrl_hw_cmn_phy_reset_config(struct dsi_ctrl_hw *ctrl, - bool enable) -{ - u32 reg = 0; - - reg = DSI_MMSS_MISC_R32(ctrl, MMSS_MISC_CLAMP_REG_OFF); - - /* Mask/unmask disable PHY reset bit */ - if (enable) - reg |= BIT(30); - else - reg &= ~BIT(30); - - DSI_MMSS_MISC_W32(ctrl, MMSS_MISC_CLAMP_REG_OFF, reg); -} - diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_reg.h b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_reg.h deleted file mode 100644 index aa4d5750..0000000 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_reg.h +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * 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 _DSI_CTRL_REG_H_ -#define _DSI_CTRL_REG_H_ - -#define DSI_HW_VERSION (0x0000) -#define DSI_CTRL (0x0004) -#define DSI_STATUS (0x0008) -#define DSI_FIFO_STATUS (0x000C) -#define DSI_VIDEO_MODE_CTRL (0x0010) -#define DSI_VIDEO_MODE_SYNC_DATATYPE (0x0014) -#define DSI_VIDEO_MODE_PIXEL_DATATYPE (0x0018) -#define DSI_VIDEO_MODE_BLANKING_DATATYPE (0x001C) -#define DSI_VIDEO_MODE_DATA_CTRL (0x0020) -#define DSI_VIDEO_MODE_ACTIVE_H (0x0024) -#define DSI_VIDEO_MODE_ACTIVE_V (0x0028) -#define DSI_VIDEO_MODE_TOTAL (0x002C) -#define DSI_VIDEO_MODE_HSYNC (0x0030) -#define DSI_VIDEO_MODE_VSYNC (0x0034) -#define DSI_VIDEO_MODE_VSYNC_VPOS (0x0038) -#define DSI_COMMAND_MODE_DMA_CTRL (0x003C) -#define DSI_COMMAND_MODE_MDP_CTRL (0x0040) -#define DSI_COMMAND_MODE_MDP_DCS_CMD_CTRL (0x0044) -#define DSI_DMA_CMD_OFFSET (0x0048) -#define DSI_DMA_CMD_LENGTH (0x004C) -#define DSI_DMA_FIFO_CTRL (0x0050) -#define DSI_DMA_NULL_PACKET_DATA (0x0054) -#define DSI_COMMAND_MODE_MDP_STREAM0_CTRL (0x0058) -#define DSI_COMMAND_MODE_MDP_STREAM0_TOTAL (0x005C) -#define DSI_COMMAND_MODE_MDP_STREAM1_CTRL (0x0060) -#define DSI_COMMAND_MODE_MDP_STREAM1_TOTAL (0x0064) -#define DSI_ACK_ERR_STATUS (0x0068) -#define DSI_RDBK_DATA0 (0x006C) -#define DSI_RDBK_DATA1 (0x0070) -#define DSI_RDBK_DATA2 (0x0074) -#define DSI_RDBK_DATA3 (0x0078) -#define DSI_RDBK_DATATYPE0 (0x007C) -#define DSI_RDBK_DATATYPE1 (0x0080) -#define DSI_TRIG_CTRL (0x0084) -#define DSI_EXT_MUX (0x0088) -#define DSI_EXT_MUX_TE_PULSE_DETECT_CTRL (0x008C) -#define DSI_CMD_MODE_DMA_SW_TRIGGER (0x0090) -#define DSI_CMD_MODE_MDP_SW_TRIGGER (0x0094) -#define DSI_CMD_MODE_BTA_SW_TRIGGER (0x0098) -#define DSI_RESET_SW_TRIGGER (0x009C) -#define DSI_MISR_CMD_CTRL (0x00A0) -#define DSI_MISR_VIDEO_CTRL (0x00A4) -#define DSI_LANE_STATUS (0x00A8) -#define DSI_LANE_CTRL (0x00AC) -#define DSI_LANE_SWAP_CTRL (0x00B0) -#define DSI_DLN0_PHY_ERR (0x00B4) -#define DSI_LP_TIMER_CTRL (0x00B8) -#define DSI_HS_TIMER_CTRL (0x00BC) -#define DSI_TIMEOUT_STATUS (0x00C0) -#define DSI_CLKOUT_TIMING_CTRL (0x00C4) -#define DSI_EOT_PACKET (0x00C8) -#define DSI_EOT_PACKET_CTRL (0x00CC) -#define DSI_GENERIC_ESC_TX_TRIGGER (0x00D0) -#define DSI_CAM_BIST_CTRL (0x00D4) -#define DSI_CAM_BIST_FRAME_SIZE (0x00D8) -#define DSI_CAM_BIST_BLOCK_SIZE (0x00DC) -#define DSI_CAM_BIST_FRAME_CONFIG (0x00E0) -#define DSI_CAM_BIST_LSFR_CTRL (0x00E4) -#define DSI_CAM_BIST_LSFR_INIT (0x00E8) -#define DSI_CAM_BIST_START (0x00EC) -#define DSI_CAM_BIST_STATUS (0x00F0) -#define DSI_ERR_INT_MASK0 (0x010C) -#define DSI_INT_CTRL (0x0110) -#define DSI_IOBIST_CTRL (0x0114) -#define DSI_SOFT_RESET (0x0118) -#define DSI_CLK_CTRL (0x011C) -#define DSI_CLK_STATUS (0x0120) -#define DSI_DEBUG_BUS_CTL (0x0124) -#define DSI_DEBUG_BUS_STATUS (0x0128) -#define DSI_PHY_SW_RESET (0x012C) -#define DSI_AXI2AHB_CTRL (0x0130) -#define DSI_MISR_CMD_MDP0_32BIT (0x0134) -#define DSI_MISR_CMD_MDP1_32BIT (0x0138) -#define DSI_MISR_CMD_DMA_32BIT (0x013C) -#define DSI_MISR_VIDEO_32BIT (0x0140) -#define DSI_LANE_MISR_CTRL (0x0144) -#define DSI_LANE0_MISR (0x0148) -#define DSI_LANE1_MISR (0x014C) -#define DSI_LANE2_MISR (0x0150) -#define DSI_LANE3_MISR (0x0154) -#define DSI_TEST_PATTERN_GEN_CTRL (0x015C) -#define DSI_TEST_PATTERN_GEN_VIDEO_POLY (0x0160) -#define DSI_TEST_PATTERN_GEN_VIDEO_INIT_VAL (0x0164) -#define DSI_TEST_PATTERN_GEN_CMD_MDP_STREAM0_POLY (0x0168) -#define DSI_TEST_PATTERN_GEN_CMD_MDP_INIT_VAL0 (0x016C) -#define DSI_TEST_PATTERN_GEN_CMD_MDP_STREAM1_POLY (0x0170) -#define DSI_TEST_PATTERN_GEN_CMD_MDP_INIT_VAL1 (0x0174) -#define DSI_TEST_PATTERN_GEN_CMD_DMA_POLY (0x0178) -#define DSI_TEST_PATTERN_GEN_CMD_DMA_INIT_VAL (0x017C) -#define DSI_TEST_PATTERN_GEN_VIDEO_ENABLE (0x0180) -#define DSI_TEST_PATTERN_GEN_CMD_STREAM0_TRIGGER (0x0184) -#define DSI_TEST_PATTERN_GEN_CMD_STREAM1_TRIGGER (0x0188) -#define DSI_TEST_PATTERN_GEN_CMD_MDP_INIT_VAL2 (0x018C) -#define DSI_TEST_PATTERN_GEN_CMD_MDP_STREAM2_POLY (0x0190) -#define DSI_TEST_PATTERN_GEN_CMD_MDP_STREAM2_POLY (0x0190) -#define DSI_COMMAND_MODE_MDP_IDLE_CTRL (0x0194) -#define DSI_TEST_PATTERN_GEN_CMD_STREAM2_TRIGGER (0x0198) -#define DSI_TPG_MAIN_CONTROL (0x019C) -#define DSI_TPG_MAIN_CONTROL2 (0x01A0) -#define DSI_TPG_VIDEO_CONFIG (0x01A4) -#define DSI_TPG_COMPONENT_LIMITS (0x01A8) -#define DSI_TPG_RECTANGLE (0x01AC) -#define DSI_TPG_BLACK_WHITE_PATTERN_FRAMES (0x01B0) -#define DSI_TPG_RGB_MAPPING (0x01B4) -#define DSI_COMMAND_MODE_MDP_CTRL2 (0x01B8) -#define DSI_COMMAND_MODE_MDP_STREAM2_CTRL (0x01BC) -#define DSI_COMMAND_MODE_MDP_STREAM2_TOTAL (0x01C0) -#define DSI_MISR_CMD_MDP2_8BIT (0x01C4) -#define DSI_MISR_CMD_MDP2_32BIT (0x01C8) -#define DSI_VBIF_CTRL (0x01CC) -#define DSI_AES_CTRL (0x01D0) -#define DSI_RDBK_DATA_CTRL (0x01D4) -#define DSI_TEST_PATTERN_GEN_CMD_DMA_INIT_VAL2 (0x01D8) -#define DSI_TPG_DMA_FIFO_STATUS (0x01DC) -#define DSI_TPG_DMA_FIFO_WRITE_TRIGGER (0x01E0) -#define DSI_DSI_TIMING_FLUSH (0x01E4) -#define DSI_DSI_TIMING_DB_MODE (0x01E8) -#define DSI_TPG_DMA_FIFO_RESET (0x01EC) -#define DSI_SCRATCH_REGISTER_0 (0x01F0) -#define DSI_VERSION (0x01F4) -#define DSI_SCRATCH_REGISTER_1 (0x01F8) -#define DSI_SCRATCH_REGISTER_2 (0x01FC) -#define DSI_DYNAMIC_REFRESH_CTRL (0x0200) -#define DSI_DYNAMIC_REFRESH_PIPE_DELAY (0x0204) -#define DSI_DYNAMIC_REFRESH_PIPE_DELAY2 (0x0208) -#define DSI_DYNAMIC_REFRESH_PLL_DELAY (0x020C) -#define DSI_DYNAMIC_REFRESH_STATUS (0x0210) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL0 (0x0214) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL1 (0x0218) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL2 (0x021C) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL3 (0x0220) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL4 (0x0224) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL5 (0x0228) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL6 (0x022C) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL7 (0x0230) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL8 (0x0234) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL9 (0x0238) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL10 (0x023C) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL11 (0x0240) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL12 (0x0244) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL13 (0x0248) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL14 (0x024C) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL15 (0x0250) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL16 (0x0254) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL17 (0x0258) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL18 (0x025C) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL19 (0x0260) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL20 (0x0264) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL21 (0x0268) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL22 (0x026C) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL23 (0x0270) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL24 (0x0274) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL25 (0x0278) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL26 (0x027C) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL27 (0x0280) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL28 (0x0284) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL29 (0x0288) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL30 (0x028C) -#define DSI_DYNAMIC_REFRESH_PLL_CTRL31 (0x0290) -#define DSI_DYNAMIC_REFRESH_PLL_UPPER_ADDR (0x0294) -#define DSI_DYNAMIC_REFRESH_PLL_UPPER_ADDR2 (0x0298) -#define DSI_VIDEO_COMPRESSION_MODE_CTRL (0x02A0) -#define DSI_VIDEO_COMPRESSION_MODE_CTRL2 (0x02A4) -#define DSI_COMMAND_COMPRESSION_MODE_CTRL (0x02A8) -#define DSI_COMMAND_COMPRESSION_MODE_CTRL2 (0x02AC) -#define DSI_COMMAND_COMPRESSION_MODE_CTRL3 (0x02B0) -#define DSI_COMMAND_MODE_NULL_INSERTION_CTRL (0x02B4) -#define DSI_READ_BACK_DISABLE_STATUS (0x02B8) -#define DSI_DESKEW_CTRL (0x02BC) -#define DSI_DESKEW_DELAY_CTRL (0x02C0) -#define DSI_DESKEW_SW_TRIGGER (0x02C4) -#define DSI_DEBUG_CTRL (0x02C8) -#define DSI_SECURE_DISPLAY_STATUS (0x02CC) -#define DSI_SECURE_DISPLAY_BLOCK_COMMAND_COLOR (0x02D0) -#define DSI_SECURE_DISPLAY_BLOCK_VIDEO_COLOR (0x02D4) -#define DSI_LOGICAL_LANE_SWAP_CTRL (0x0310) - - -#endif /* _DSI_CTRL_REG_H_ */ diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h b/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h deleted file mode 100644 index 02c8d76..0000000 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h +++ /dev/null @@ -1,579 +0,0 @@ -/* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * 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 _DSI_DEFS_H_ -#define _DSI_DEFS_H_ - -#include <linux/types.h> -#include <drm/drm_mipi_dsi.h> -#include "msm_drv.h" - -#define DSI_H_TOTAL(t) (((t)->h_active) + ((t)->h_back_porch) + \ - ((t)->h_sync_width) + ((t)->h_front_porch)) - -#define DSI_V_TOTAL(t) (((t)->v_active) + ((t)->v_back_porch) + \ - ((t)->v_sync_width) + ((t)->v_front_porch)) - -#define DSI_H_TOTAL_DSC(t) \ - ({\ - u64 value;\ - if ((t)->dsc_enabled && (t)->dsc)\ - value = (t)->dsc->pclk_per_line;\ - else\ - value = (t)->h_active;\ - value = value + (t)->h_back_porch + (t)->h_sync_width +\ - (t)->h_front_porch;\ - value;\ - }) - -#define DSI_DEBUG_NAME_LEN 32 -/** - * enum dsi_pixel_format - DSI pixel formats - * @DSI_PIXEL_FORMAT_RGB565: - * @DSI_PIXEL_FORMAT_RGB666: - * @DSI_PIXEL_FORMAT_RGB666_LOOSE: - * @DSI_PIXEL_FORMAT_RGB888: - * @DSI_PIXEL_FORMAT_RGB111: - * @DSI_PIXEL_FORMAT_RGB332: - * @DSI_PIXEL_FORMAT_RGB444: - * @DSI_PIXEL_FORMAT_MAX: - */ -enum dsi_pixel_format { - DSI_PIXEL_FORMAT_RGB565 = 0, - DSI_PIXEL_FORMAT_RGB666, - DSI_PIXEL_FORMAT_RGB666_LOOSE, - DSI_PIXEL_FORMAT_RGB888, - DSI_PIXEL_FORMAT_RGB111, - DSI_PIXEL_FORMAT_RGB332, - DSI_PIXEL_FORMAT_RGB444, - DSI_PIXEL_FORMAT_MAX -}; - -/** - * enum dsi_op_mode - dsi operation mode - * @DSI_OP_VIDEO_MODE: DSI video mode operation - * @DSI_OP_CMD_MODE: DSI Command mode operation - * @DSI_OP_MODE_MAX: - */ -enum dsi_op_mode { - DSI_OP_VIDEO_MODE = 0, - DSI_OP_CMD_MODE, - DSI_OP_MODE_MAX -}; - -/** - * enum dsi_mode_flags - flags to signal other drm components via private flags - * @DSI_MODE_FLAG_SEAMLESS: Seamless transition requested by user - * @DSI_MODE_FLAG_DFPS: Seamless transition is DynamicFPS - * @DSI_MODE_FLAG_VBLANK_PRE_MODESET: Transition needs VBLANK before Modeset - * @DSI_MODE_FLAG_DMS: Seamless transition is dynamic mode switch - * @DSI_MODE_FLAG_VRR: Seamless transition is DynamicFPS. - * New timing values are sent from DAL. - */ -enum dsi_mode_flags { - DSI_MODE_FLAG_SEAMLESS = BIT(0), - DSI_MODE_FLAG_DFPS = BIT(1), - DSI_MODE_FLAG_VBLANK_PRE_MODESET = BIT(2), - DSI_MODE_FLAG_DMS = BIT(3), - DSI_MODE_FLAG_VRR = BIT(4), -}; - -/** - * enum dsi_logical_lane - dsi logical lanes - * @DSI_LOGICAL_LANE_0: Logical lane 0 - * @DSI_LOGICAL_LANE_1: Logical lane 1 - * @DSI_LOGICAL_LANE_2: Logical lane 2 - * @DSI_LOGICAL_LANE_3: Logical lane 3 - * @DSI_LOGICAL_CLOCK_LANE: Clock lane - * @DSI_LANE_MAX: Maximum lanes supported - */ -enum dsi_logical_lane { - DSI_LOGICAL_LANE_0 = 0, - DSI_LOGICAL_LANE_1, - DSI_LOGICAL_LANE_2, - DSI_LOGICAL_LANE_3, - DSI_LOGICAL_CLOCK_LANE, - DSI_LANE_MAX -}; - -/** - * enum dsi_data_lanes - BIT map for DSI data lanes - * This is used to identify the active DSI data lanes for - * various operations like DSI data lane enable/ULPS/clamp - * configurations. - * @DSI_DATA_LANE_0: BIT(DSI_LOGICAL_LANE_0) - * @DSI_DATA_LANE_1: BIT(DSI_LOGICAL_LANE_1) - * @DSI_DATA_LANE_2: BIT(DSI_LOGICAL_LANE_2) - * @DSI_DATA_LANE_3: BIT(DSI_LOGICAL_LANE_3) - * @DSI_CLOCK_LANE: BIT(DSI_LOGICAL_CLOCK_LANE) - */ -enum dsi_data_lanes { - DSI_DATA_LANE_0 = BIT(DSI_LOGICAL_LANE_0), - DSI_DATA_LANE_1 = BIT(DSI_LOGICAL_LANE_1), - DSI_DATA_LANE_2 = BIT(DSI_LOGICAL_LANE_2), - DSI_DATA_LANE_3 = BIT(DSI_LOGICAL_LANE_3), - DSI_CLOCK_LANE = BIT(DSI_LOGICAL_CLOCK_LANE) -}; - -/** - * enum dsi_phy_data_lanes - dsi physical lanes - * used for DSI logical to physical lane mapping - * @DSI_PHYSICAL_LANE_INVALID: Physical lane valid/invalid - * @DSI_PHYSICAL_LANE_0: Physical lane 0 - * @DSI_PHYSICAL_LANE_1: Physical lane 1 - * @DSI_PHYSICAL_LANE_2: Physical lane 2 - * @DSI_PHYSICAL_LANE_3: Physical lane 3 - */ -enum dsi_phy_data_lanes { - DSI_PHYSICAL_LANE_INVALID = 0, - DSI_PHYSICAL_LANE_0 = BIT(0), - DSI_PHYSICAL_LANE_1 = BIT(1), - DSI_PHYSICAL_LANE_2 = BIT(2), - DSI_PHYSICAL_LANE_3 = BIT(3) -}; - -enum dsi_lane_map_type_v1 { - DSI_LANE_MAP_0123, - DSI_LANE_MAP_3012, - DSI_LANE_MAP_2301, - DSI_LANE_MAP_1230, - DSI_LANE_MAP_0321, - DSI_LANE_MAP_1032, - DSI_LANE_MAP_2103, - DSI_LANE_MAP_3210, -}; - -/** - * lane_map: DSI logical <-> physical lane mapping - * lane_map_v1: Lane mapping for DSI controllers < v2.0 - * lane_map_v2: Lane mapping for DSI controllers >= 2.0 - */ -struct dsi_lane_map { - enum dsi_lane_map_type_v1 lane_map_v1; - u8 lane_map_v2[DSI_LANE_MAX - 1]; -}; - -/** - * enum dsi_trigger_type - dsi trigger type - * @DSI_TRIGGER_NONE: No trigger. - * @DSI_TRIGGER_TE: TE trigger. - * @DSI_TRIGGER_SEOF: Start or End of frame. - * @DSI_TRIGGER_SW: Software trigger. - * @DSI_TRIGGER_SW_SEOF: Software trigger and start/end of frame. - * @DSI_TRIGGER_SW_TE: Software and TE triggers. - * @DSI_TRIGGER_MAX: Max trigger values. - */ -enum dsi_trigger_type { - DSI_TRIGGER_NONE = 0, - DSI_TRIGGER_TE, - DSI_TRIGGER_SEOF, - DSI_TRIGGER_SW, - DSI_TRIGGER_SW_SEOF, - DSI_TRIGGER_SW_TE, - DSI_TRIGGER_MAX -}; - -/** - * enum dsi_color_swap_mode - color swap mode - * @DSI_COLOR_SWAP_RGB: - * @DSI_COLOR_SWAP_RBG: - * @DSI_COLOR_SWAP_BGR: - * @DSI_COLOR_SWAP_BRG: - * @DSI_COLOR_SWAP_GRB: - * @DSI_COLOR_SWAP_GBR: - */ -enum dsi_color_swap_mode { - DSI_COLOR_SWAP_RGB = 0, - DSI_COLOR_SWAP_RBG, - DSI_COLOR_SWAP_BGR, - DSI_COLOR_SWAP_BRG, - DSI_COLOR_SWAP_GRB, - DSI_COLOR_SWAP_GBR -}; - -/** - * enum dsi_dfps_type - Dynamic FPS support type - * @DSI_DFPS_NONE: Dynamic FPS is not supported. - * @DSI_DFPS_SUSPEND_RESUME: - * @DSI_DFPS_IMMEDIATE_CLK: - * @DSI_DFPS_IMMEDIATE_HFP: - * @DSI_DFPS_IMMEDIATE_VFP: - * @DSI_DPFS_MAX: - */ -enum dsi_dfps_type { - DSI_DFPS_NONE = 0, - DSI_DFPS_SUSPEND_RESUME, - DSI_DFPS_IMMEDIATE_CLK, - DSI_DFPS_IMMEDIATE_HFP, - DSI_DFPS_IMMEDIATE_VFP, - DSI_DFPS_MAX -}; - -/** - * enum dsi_cmd_set_type - DSI command set type - * @DSI_CMD_SET_PRE_ON: Panel pre on - * @DSI_CMD_SET_ON: Panel on - * @DSI_CMD_SET_POST_ON: Panel post on - * @DSI_CMD_SET_PRE_OFF: Panel pre off - * @DSI_CMD_SET_OFF: Panel off - * @DSI_CMD_SET_POST_OFF: Panel post off - * @DSI_CMD_SET_PRE_RES_SWITCH: Pre resolution switch - * @DSI_CMD_SET_RES_SWITCH: Resolution switch - * @DSI_CMD_SET_POST_RES_SWITCH: Post resolution switch - * @DSI_CMD_SET_CMD_TO_VID_SWITCH: Cmd to video mode switch - * @DSI_CMD_SET_POST_CMD_TO_VID_SWITCH: Post cmd to vid switch - * @DSI_CMD_SET_VID_TO_CMD_SWITCH: Video to cmd mode switch - * @DSI_CMD_SET_POST_VID_TO_CMD_SWITCH: Post vid to cmd switch - * @DSI_CMD_SET_PANEL_STATUS: Panel status - * @DSI_CMD_SET_LP1: Low power mode 1 - * @DSI_CMD_SET_LP2: Low power mode 2 - * @DSI_CMD_SET_NOLP: Low power mode disable - * @DSI_CMD_SET_PPS: DSC PPS command - * @DSI_CMD_SET_TIMING_SWITCH: Timing switch - * @DSI_CMD_SET_POST_TIMING_SWITCH: Post timing switch - * @DSI_CMD_SET_MAX - */ -enum dsi_cmd_set_type { - DSI_CMD_SET_PRE_ON = 0, - DSI_CMD_SET_ON, - DSI_CMD_SET_POST_ON, - DSI_CMD_SET_PRE_OFF, - DSI_CMD_SET_OFF, - DSI_CMD_SET_POST_OFF, - DSI_CMD_SET_PRE_RES_SWITCH, - DSI_CMD_SET_RES_SWITCH, - DSI_CMD_SET_POST_RES_SWITCH, - DSI_CMD_SET_CMD_TO_VID_SWITCH, - DSI_CMD_SET_POST_CMD_TO_VID_SWITCH, - DSI_CMD_SET_VID_TO_CMD_SWITCH, - DSI_CMD_SET_POST_VID_TO_CMD_SWITCH, - DSI_CMD_SET_PANEL_STATUS, - DSI_CMD_SET_LP1, - DSI_CMD_SET_LP2, - DSI_CMD_SET_NOLP, - DSI_CMD_SET_PPS, - DSI_CMD_SET_TIMING_SWITCH, - DSI_CMD_SET_POST_TIMING_SWITCH, - DSI_CMD_SET_MAX -}; - -/** - * enum dsi_cmd_set_state - command set state - * @DSI_CMD_SET_STATE_LP: dsi low power mode - * @DSI_CMD_SET_STATE_HS: dsi high speed mode - * @DSI_CMD_SET_STATE_MAX - */ -enum dsi_cmd_set_state { - DSI_CMD_SET_STATE_LP = 0, - DSI_CMD_SET_STATE_HS, - DSI_CMD_SET_STATE_MAX -}; - -/** - * enum dsi_phy_type - DSI phy types - * @DSI_PHY_TYPE_DPHY: - * @DSI_PHY_TYPE_CPHY: - */ -enum dsi_phy_type { - DSI_PHY_TYPE_DPHY, - DSI_PHY_TYPE_CPHY -}; - -/** - * enum dsi_te_mode - dsi te source - * @DSI_TE_ON_DATA_LINK: TE read from DSI link - * @DSI_TE_ON_EXT_PIN: TE signal on an external GPIO - */ -enum dsi_te_mode { - DSI_TE_ON_DATA_LINK = 0, - DSI_TE_ON_EXT_PIN, -}; - -/** - * enum dsi_video_traffic_mode - video mode pixel transmission type - * @DSI_VIDEO_TRAFFIC_SYNC_PULSES: Non-burst mode with sync pulses. - * @DSI_VIDEO_TRAFFIC_SYNC_START_EVENTS: Non-burst mode with sync start events. - * @DSI_VIDEO_TRAFFIC_BURST_MODE: Burst mode using sync start events. - */ -enum dsi_video_traffic_mode { - DSI_VIDEO_TRAFFIC_SYNC_PULSES = 0, - DSI_VIDEO_TRAFFIC_SYNC_START_EVENTS, - DSI_VIDEO_TRAFFIC_BURST_MODE, -}; - -/** - * struct dsi_cmd_desc - description of a dsi command - * @msg: dsi mipi msg packet - * @last_command: indicates whether the cmd is the last one to send - * @post_wait_ms: post wait duration - */ -struct dsi_cmd_desc { - struct mipi_dsi_msg msg; - bool last_command; - u32 post_wait_ms; -}; - -/** - * struct dsi_panel_cmd_set - command set of the panel - * @type: type of the command - * @state: state of the command - * @count: number of cmds - * @ctrl_idx: index of the dsi control - * @cmds: arry of cmds - */ -struct dsi_panel_cmd_set { - enum dsi_cmd_set_type type; - enum dsi_cmd_set_state state; - u32 count; - u32 ctrl_idx; - struct dsi_cmd_desc *cmds; -}; - -/** - * struct dsi_mode_info - video mode information dsi frame - * @h_active: Active width of one frame in pixels. - * @h_back_porch: Horizontal back porch in pixels. - * @h_sync_width: HSYNC width in pixels. - * @h_front_porch: Horizontal fron porch in pixels. - * @h_skew: - * @h_sync_polarity: Polarity of HSYNC (false is active low). - * @v_active: Active height of one frame in lines. - * @v_back_porch: Vertical back porch in lines. - * @v_sync_width: VSYNC width in lines. - * @v_front_porch: Vertical front porch in lines. - * @v_sync_polarity: Polarity of VSYNC (false is active low). - * @refresh_rate: Refresh rate in Hz. - * @dsc_enabled: DSC compression enabled. - * @dsc: DSC compression configuration. - */ -struct dsi_mode_info { - u32 h_active; - u32 h_back_porch; - u32 h_sync_width; - u32 h_front_porch; - u32 h_skew; - bool h_sync_polarity; - - u32 v_active; - u32 v_back_porch; - u32 v_sync_width; - u32 v_front_porch; - bool v_sync_polarity; - - u32 refresh_rate; - - bool dsc_enabled; - struct msm_display_dsc_info *dsc; -}; - -/** - * struct dsi_host_common_cfg - Host configuration common to video and cmd mode - * @dst_format: Destination pixel format. - * @data_lanes: Physical data lanes to be enabled. - * @en_crc_check: Enable CRC checks. - * @en_ecc_check: Enable ECC checks. - * @te_mode: Source for TE signalling. - * @mdp_cmd_trigger: MDP frame update trigger for command mode. - * @dma_cmd_trigger: Command DMA trigger. - * @cmd_trigger_stream: Command mode stream to trigger. - * @swap_mode: DSI color swap mode. - * @bit_swap_read: Is red color bit swapped. - * @bit_swap_green: Is green color bit swapped. - * @bit_swap_blue: Is blue color bit swapped. - * @t_clk_post: Number of byte clock cycles that the transmitter shall - * continue sending after last data lane has transitioned - * to LP mode. - * @t_clk_pre: Number of byte clock cycles that the high spped clock - * shall be driven prior to data lane transitions from LP - * to HS mode. - * @ignore_rx_eot: Ignore Rx EOT packets if set to true. - * @append_tx_eot: Append EOT packets for forward transmissions if set to - * true. - */ -struct dsi_host_common_cfg { - enum dsi_pixel_format dst_format; - enum dsi_data_lanes data_lanes; - bool en_crc_check; - bool en_ecc_check; - enum dsi_te_mode te_mode; - enum dsi_trigger_type mdp_cmd_trigger; - enum dsi_trigger_type dma_cmd_trigger; - u32 cmd_trigger_stream; - enum dsi_color_swap_mode swap_mode; - bool bit_swap_red; - bool bit_swap_green; - bool bit_swap_blue; - u32 t_clk_post; - u32 t_clk_pre; - bool ignore_rx_eot; - bool append_tx_eot; -}; - -/** - * struct dsi_video_engine_cfg - DSI video engine configuration - * @last_line_interleave_en: Allow command mode op interleaved on last line of - * video stream. - * @pulse_mode_hsa_he: Send HSA and HE following VS/VE packet if set to - * true. - * @hfp_lp11_en: Enter low power stop mode (LP-11) during HFP. - * @hbp_lp11_en: Enter low power stop mode (LP-11) during HBP. - * @hsa_lp11_en: Enter low power stop mode (LP-11) during HSA. - * @eof_bllp_lp11_en: Enter low power stop mode (LP-11) during BLLP of - * last line of a frame. - * @bllp_lp11_en: Enter low power stop mode (LP-11) during BLLP. - * @traffic_mode: Traffic mode for video stream. - * @vc_id: Virtual channel identifier. - */ -struct dsi_video_engine_cfg { - bool last_line_interleave_en; - bool pulse_mode_hsa_he; - bool hfp_lp11_en; - bool hbp_lp11_en; - bool hsa_lp11_en; - bool eof_bllp_lp11_en; - bool bllp_lp11_en; - enum dsi_video_traffic_mode traffic_mode; - u32 vc_id; -}; - -/** - * struct dsi_cmd_engine_cfg - DSI command engine configuration - * @max_cmd_packets_interleave Maximum number of command mode RGB packets to - * send with in one horizontal blanking period - * of the video mode frame. - * @wr_mem_start: DCS command for write_memory_start. - * @wr_mem_continue: DCS command for write_memory_continue. - * @insert_dcs_command: Insert DCS command as first byte of payload - * of the pixel data. - * @mdp_transfer_time_us Specifies the mdp transfer time for command mode - * panels in microseconds - */ -struct dsi_cmd_engine_cfg { - u32 max_cmd_packets_interleave; - u32 wr_mem_start; - u32 wr_mem_continue; - bool insert_dcs_command; - u32 mdp_transfer_time_us; -}; - -/** - * struct dsi_host_config - DSI host configuration parameters. - * @panel_mode: Operation mode for panel (video or cmd mode). - * @common_config: Host configuration common to both Video and Cmd mode. - * @video_engine: Video engine configuration if panel is in video mode. - * @cmd_engine: Cmd engine configuration if panel is in cmd mode. - * @esc_clk_rate_khz: Esc clock frequency in Hz. - * @bit_clk_rate_hz: Bit clock frequency in Hz. - * @video_timing: Video timing information of a frame. - * @lane_map: Mapping between logical and physical lanes. - */ -struct dsi_host_config { - enum dsi_op_mode panel_mode; - struct dsi_host_common_cfg common_config; - union { - struct dsi_video_engine_cfg video_engine; - struct dsi_cmd_engine_cfg cmd_engine; - } u; - u64 esc_clk_rate_hz; - u64 bit_clk_rate_hz; - struct dsi_mode_info video_timing; - struct dsi_lane_map lane_map; -}; - -/** - * struct dsi_display_mode_priv_info - private mode info that will be attached - * with each drm mode - * @cmd_sets: Command sets of the mode - * @phy_timing_val: Phy timing values - * @phy_timing_len: Phy timing array length - * @panel_jitter: Panel jitter for RSC backoff - * @panel_prefill_lines: Panel prefill lines for RSC - * @topology: Topology selected for the panel - * @dsc: DSC compression info - * @dsc_enabled: DSC compression enabled - */ -struct dsi_display_mode_priv_info { - struct dsi_panel_cmd_set cmd_sets[DSI_CMD_SET_MAX]; - - u32 *phy_timing_val; - u32 phy_timing_len; - - u32 panel_jitter_numer; - u32 panel_jitter_denom; - u32 panel_prefill_lines; - - struct msm_display_topology topology; - struct msm_display_dsc_info dsc; - bool dsc_enabled; -}; - -/** - * struct dsi_display_mode - specifies mode for dsi display - * @timing: Timing parameters for the panel. - * @pixel_clk_khz: Pixel clock in Khz. - * @dsi_mode_flags: Flags to signal other drm components via private flags - * @priv_info: Mode private info - */ -struct dsi_display_mode { - struct dsi_mode_info timing; - u32 pixel_clk_khz; - u32 dsi_mode_flags; - struct dsi_display_mode_priv_info *priv_info; -}; - -/** - * struct dsi_rect - dsi rectangle representation - * Note: dpu_rect is also using u16, this must be maintained for memcpy - */ -struct dsi_rect { - u16 x; - u16 y; - u16 w; - u16 h; -}; - -/** - * dsi_rect_intersect - intersect two rectangles - * @r1: first rectangle - * @r2: scissor rectangle - * @result: result rectangle, all 0's on no intersection found - */ -void dsi_rect_intersect(const struct dsi_rect *r1, - const struct dsi_rect *r2, - struct dsi_rect *result); - -/** - * dsi_rect_is_equal - compares two rects - * @r1: rect value to compare - * @r2: rect value to compare - * - * Returns true if the rects are same - */ -static inline bool dsi_rect_is_equal(struct dsi_rect *r1, - struct dsi_rect *r2) -{ - return r1->x == r2->x && r1->y == r2->y && r1->w == r2->w && - r1->h == r2->h; -} - -struct dsi_event_cb_info { - uint32_t event_idx; - void *event_usr_ptr; - - int (*event_cb)(void *event_usr_ptr, - uint32_t event_idx, uint32_t instance_idx, - uint32_t data0, uint32_t data1, - uint32_t data2, uint32_t data3); -}; - -#endif /* _DSI_DEFS_H_ */ diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c deleted file mode 100644 index 31b7d7e..0000000 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c +++ /dev/null @@ -1,4221 +0,0 @@ -/* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * 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) "msm-dsi-display:[%s] " fmt, __func__ - -#include <linux/list.h> -#include <linux/of.h> -#include <linux/err.h> - -#include "msm_drv.h" -#include "dpu_connector.h" -#include "msm_mmu.h" -#include "dsi_display.h" -#include "dsi_panel.h" -#include "dsi_ctrl.h" -#include "dsi_ctrl_hw.h" -#include "dsi_drm.h" -#include "dsi_clk.h" -#include "dsi_pwr.h" -#include "dpu_dbg.h" - -#define to_dsi_display(x) container_of(x, struct dsi_display, host) -#define INT_BASE_10 10 -#define NO_OVERRIDE -1 - -#define MISR_BUFF_SIZE 256 - -static DEFINE_MUTEX(dsi_display_list_lock); -static LIST_HEAD(dsi_display_list); -static char dsi_display_primary[MAX_CMDLINE_PARAM_LEN]; -static char dsi_display_secondary[MAX_CMDLINE_PARAM_LEN]; -static struct dsi_display_boot_param boot_displays[MAX_DSI_ACTIVE_DISPLAY]; -static struct device_node *default_active_node; -static const struct of_device_id dsi_display_dt_match[] = { - {.compatible = "qcom,dsi-display"}, - {} -}; - -static struct dsi_display *main_display; - -void dsi_rect_intersect(const struct dsi_rect *r1, - const struct dsi_rect *r2, - struct dsi_rect *result) -{ - int l, t, r, b; - - if (!r1 || !r2 || !result) - return; - - l = max(r1->x, r2->x); - t = max(r1->y, r2->y); - r = min((r1->x + r1->w), (r2->x + r2->w)); - b = min((r1->y + r1->h), (r2->y + r2->h)); - - if (r <= l || b <= t) { - memset(result, 0, sizeof(*result)); - } else { - result->x = l; - result->y = t; - result->w = r - l; - result->h = b - t; - } -} - -int dsi_display_set_backlight(void *display, u32 bl_lvl) -{ - struct dsi_display *dsi_display = display; - struct dsi_panel *panel; - u32 bl_scale, bl_scale_ad; - u64 bl_temp; - int rc = 0; - - if (dsi_display == NULL || dsi_display->panel == NULL) - return -EINVAL; - - panel = dsi_display->panel; - - if (!dsi_panel_initialized(panel)) - return -EINVAL; - - panel->bl_config.bl_level = bl_lvl; - - /* scale backlight */ - bl_scale = panel->bl_config.bl_scale; - bl_temp = bl_lvl * bl_scale / MAX_BL_SCALE_LEVEL; - - bl_scale_ad = panel->bl_config.bl_scale_ad; - bl_temp = (u32)bl_temp * bl_scale_ad / MAX_AD_BL_SCALE_LEVEL; - - pr_debug("bl_scale = %u, bl_scale_ad = %u, bl_lvl = %u\n", - bl_scale, bl_scale_ad, (u32)bl_temp); - - rc = dsi_display_clk_ctrl(dsi_display->dsi_clk_handle, - DSI_CORE_CLK, DSI_CLK_ON); - if (rc) { - pr_err("[%s] failed to enable DSI core clocks, rc=%d\n", - dsi_display->name, rc); - goto error; - } - - rc = dsi_panel_set_backlight(panel, (u32)bl_temp); - if (rc) - pr_err("unable to set backlight\n"); - - rc = dsi_display_clk_ctrl(dsi_display->dsi_clk_handle, - DSI_CORE_CLK, DSI_CLK_OFF); - if (rc) { - pr_err("[%s] failed to disable DSI core clocks, rc=%d\n", - dsi_display->name, rc); - goto error; - } - -error: - return rc; -} - -int dsi_display_soft_reset(void *display) -{ - struct dsi_display *dsi_display; - struct dsi_display_ctrl *ctrl; - int rc = 0; - int i; - - if (!display) - return -EINVAL; - - dsi_display = display; - - for (i = 0 ; i < dsi_display->ctrl_count; i++) { - ctrl = &dsi_display->ctrl[i]; - rc = dsi_ctrl_soft_reset(ctrl->ctrl); - if (rc) { - pr_err("[%s] failed to soft reset host_%d, rc=%d\n", - dsi_display->name, i, rc); - break; - } - } - - return rc; -} - -enum dsi_pixel_format dsi_display_get_dst_format(void *display) -{ - enum dsi_pixel_format format = DSI_PIXEL_FORMAT_MAX; - struct dsi_display *dsi_display = (struct dsi_display *)display; - - if (!dsi_display || !dsi_display->panel) { - pr_err("Invalid params(s) dsi_display %pK, panel %pK\n", - dsi_display, - ((dsi_display) ? dsi_display->panel : NULL)); - return format; - } - - format = dsi_display->panel->host_config.dst_format; - return format; -} - -static void _dsi_display_setup_misr(struct dsi_display *display) -{ - int i; - - for (i = 0; i < display->ctrl_count; i++) { - dsi_ctrl_setup_misr(display->ctrl[i].ctrl, - display->misr_enable, - display->misr_frame_count); - } -} - -int dsi_display_set_power(struct drm_connector *connector, - int power_mode, void *disp) -{ - struct dsi_display *display = disp; - int rc = 0; - - if (!display || !display->panel) { - pr_err("invalid display/panel\n"); - return -EINVAL; - } - - switch (power_mode) { - case DPU_MODE_DPMS_LP1: - rc = dsi_panel_set_lp1(display->panel); - break; - case DPU_MODE_DPMS_LP2: - rc = dsi_panel_set_lp2(display->panel); - break; - default: - rc = dsi_panel_set_nolp(display->panel); - break; - } - return rc; -} - -static ssize_t debugfs_dump_info_read(struct file *file, - char __user *user_buf, - size_t user_len, - loff_t *ppos) -{ - struct dsi_display *display = file->private_data; - char *buf; - u32 len = 0; - int i; - - if (!display) - return -ENODEV; - - if (*ppos) - return 0; - - buf = kzalloc(SZ_4K, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - len += snprintf(buf + len, (SZ_4K - len), "name = %s\n", display->name); - len += snprintf(buf + len, (SZ_4K - len), - "\tResolution = %dx%d\n", - display->config.video_timing.h_active, - display->config.video_timing.v_active); - - for (i = 0; i < display->ctrl_count; i++) { - len += snprintf(buf + len, (SZ_4K - len), - "\tCTRL_%d:\n\t\tctrl = %s\n\t\tphy = %s\n", - i, display->ctrl[i].ctrl->name, - display->ctrl[i].phy->name); - } - - len += snprintf(buf + len, (SZ_4K - len), - "\tPanel = %s\n", display->panel->name); - - len += snprintf(buf + len, (SZ_4K - len), - "\tClock master = %s\n", - display->ctrl[display->clk_master_idx].ctrl->name); - - if (copy_to_user(user_buf, buf, len)) { - kfree(buf); - return -EFAULT; - } - - *ppos += len; - - kfree(buf); - return len; -} - -static ssize_t debugfs_misr_setup(struct file *file, - const char __user *user_buf, - size_t user_len, - loff_t *ppos) -{ - struct dsi_display *display = file->private_data; - char *buf; - int rc = 0; - size_t len; - u32 enable, frame_count; - - if (!display) - return -ENODEV; - - if (*ppos) - return 0; - - buf = kzalloc(MISR_BUFF_SIZE, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - /* leave room for termination char */ - len = min_t(size_t, user_len, MISR_BUFF_SIZE - 1); - if (copy_from_user(buf, user_buf, len)) { - rc = -EINVAL; - goto error; - } - - buf[len] = '\0'; /* terminate the string */ - - if (sscanf(buf, "%u %u", &enable, &frame_count) != 2) { - rc = -EINVAL; - goto error; - } - - display->misr_enable = enable; - display->misr_frame_count = frame_count; - - mutex_lock(&display->display_lock); - rc = dsi_display_clk_ctrl(display->dsi_clk_handle, - DSI_CORE_CLK, DSI_CLK_ON); - if (rc) { - pr_err("[%s] failed to enable DSI core clocks, rc=%d\n", - display->name, rc); - goto unlock; - } - - _dsi_display_setup_misr(display); - - rc = dsi_display_clk_ctrl(display->dsi_clk_handle, - DSI_CORE_CLK, DSI_CLK_OFF); - if (rc) { - pr_err("[%s] failed to disable DSI core clocks, rc=%d\n", - display->name, rc); - goto unlock; - } - - rc = user_len; -unlock: - mutex_unlock(&display->display_lock); -error: - kfree(buf); - return rc; -} - -static ssize_t debugfs_misr_read(struct file *file, - char __user *user_buf, - size_t user_len, - loff_t *ppos) -{ - struct dsi_display *display = file->private_data; - char *buf; - u32 len = 0; - int rc = 0; - struct dsi_ctrl *dsi_ctrl; - int i; - u32 misr; - size_t max_len = min_t(size_t, user_len, MISR_BUFF_SIZE); - - if (!display) - return -ENODEV; - - if (*ppos) - return 0; - - buf = kzalloc(max_len, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - mutex_lock(&display->display_lock); - rc = dsi_display_clk_ctrl(display->dsi_clk_handle, - DSI_CORE_CLK, DSI_CLK_ON); - if (rc) { - pr_err("[%s] failed to enable DSI core clocks, rc=%d\n", - display->name, rc); - goto error; - } - - for (i = 0; i < display->ctrl_count; i++) { - dsi_ctrl = display->ctrl[i].ctrl; - misr = dsi_ctrl_collect_misr(display->ctrl[i].ctrl); - - len += snprintf((buf + len), max_len - len, - "DSI_%d MISR: 0x%x\n", dsi_ctrl->cell_index, misr); - - if (len >= max_len) - break; - } - - rc = dsi_display_clk_ctrl(display->dsi_clk_handle, - DSI_CORE_CLK, DSI_CLK_OFF); - if (rc) { - pr_err("[%s] failed to disable DSI core clocks, rc=%d\n", - display->name, rc); - goto error; - } - - if (copy_to_user(user_buf, buf, len)) { - rc = -EFAULT; - goto error; - } - - *ppos += len; - -error: - mutex_unlock(&display->display_lock); - kfree(buf); - return len; -} - -static const struct file_operations dump_info_fops = { - .open = simple_open, - .read = debugfs_dump_info_read, -}; - -static const struct file_operations misr_data_fops = { - .open = simple_open, - .read = debugfs_misr_read, - .write = debugfs_misr_setup, -}; - -static int dsi_display_debugfs_init(struct dsi_display *display) -{ - int rc = 0; - struct dentry *dir, *dump_file, *misr_data; - - dir = debugfs_create_dir(display->name, NULL); - if (IS_ERR_OR_NULL(dir)) { - rc = PTR_ERR(dir); - pr_err("[%s] debugfs create dir failed, rc = %d\n", - display->name, rc); - goto error; - } - - dump_file = debugfs_create_file("dump_info", - 0400, - dir, - display, - &dump_info_fops); - if (IS_ERR_OR_NULL(dump_file)) { - rc = PTR_ERR(dump_file); - pr_err("[%s] debugfs create dump info file failed, rc=%d\n", - display->name, rc); - goto error_remove_dir; - } - - misr_data = debugfs_create_file("misr_data", - 0600, - dir, - display, - &misr_data_fops); - if (IS_ERR_OR_NULL(misr_data)) { - rc = PTR_ERR(misr_data); - pr_err("[%s] debugfs create misr datafile failed, rc=%d\n", - display->name, rc); - goto error_remove_dir; - } - - display->root = dir; - return rc; -error_remove_dir: - debugfs_remove(dir); -error: - return rc; -} - -static int dsi_display_debugfs_deinit(struct dsi_display *display) -{ - debugfs_remove_recursive(display->root); - - return 0; -} - -static void adjust_timing_by_ctrl_count(const struct dsi_display *display, - struct dsi_display_mode *mode) -{ - if (display->ctrl_count > 1) { - mode->timing.h_active /= display->ctrl_count; - mode->timing.h_front_porch /= display->ctrl_count; - mode->timing.h_sync_width /= display->ctrl_count; - mode->timing.h_back_porch /= display->ctrl_count; - mode->timing.h_skew /= display->ctrl_count; - mode->pixel_clk_khz /= display->ctrl_count; - } -} - -static int dsi_display_is_ulps_req_valid(struct dsi_display *display, - bool enable) -{ - /* TODO: make checks based on cont. splash */ - int splash_enabled = false; - - pr_debug("checking ulps req validity\n"); - - if (!dsi_panel_ulps_feature_enabled(display->panel)) - return false; - - /* TODO: ULPS during suspend */ - if (!dsi_panel_initialized(display->panel)) - return false; - - if (enable && display->ulps_enabled) { - pr_debug("ULPS already enabled\n"); - return false; - } else if (!enable && !display->ulps_enabled) { - pr_debug("ULPS already disabled\n"); - return false; - } - - /* - * No need to enter ULPS when transitioning from splash screen to - * boot animation since it is expected that the clocks would be turned - * right back on. - */ - if (enable && splash_enabled) - return false; - - return true; -} - - -/** - * dsi_display_set_ulps() - set ULPS state for DSI lanes. - * @dsi_display: DSI display handle. - * @enable: enable/disable ULPS. - * - * ULPS can be enabled/disabled after DSI host engine is turned on. - * - * Return: error code. - */ -static int dsi_display_set_ulps(struct dsi_display *display, bool enable) -{ - int rc = 0; - int i = 0; - struct dsi_display_ctrl *m_ctrl, *ctrl; - - - if (!display) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - if (!dsi_display_is_ulps_req_valid(display, enable)) { - pr_debug("%s: skipping ULPS config, enable=%d\n", - __func__, enable); - return 0; - } - - m_ctrl = &display->ctrl[display->cmd_master_idx]; - - rc = dsi_ctrl_set_ulps(m_ctrl->ctrl, enable); - if (rc) { - pr_err("Ulps controller state change(%d) failed\n", enable); - return rc; - } - - rc = dsi_phy_set_ulps(m_ctrl->phy, &display->config, enable, - display->clamp_enabled); - if (rc) { - pr_err("Ulps PHY state change(%d) failed\n", enable); - return rc; - } - - for (i = 0; i < display->ctrl_count; i++) { - ctrl = &display->ctrl[i]; - if (!ctrl->ctrl || (ctrl == m_ctrl)) - continue; - - rc = dsi_ctrl_set_ulps(ctrl->ctrl, enable); - if (rc) { - pr_err("Ulps controller state change(%d) failed\n", - enable); - return rc; - } - - rc = dsi_phy_set_ulps(ctrl->phy, &display->config, enable, - display->clamp_enabled); - if (rc) { - pr_err("Ulps PHY state change(%d) failed\n", enable); - return rc; - } - - } - display->ulps_enabled = enable; - return 0; -} - -/** - * dsi_display_set_clamp() - set clamp state for DSI IO. - * @dsi_display: DSI display handle. - * @enable: enable/disable clamping. - * - * Return: error code. - */ -static int dsi_display_set_clamp(struct dsi_display *display, bool enable) -{ - int rc = 0; - int i = 0; - struct dsi_display_ctrl *m_ctrl, *ctrl; - bool ulps_enabled = false; - - - if (!display) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - m_ctrl = &display->ctrl[display->cmd_master_idx]; - ulps_enabled = display->ulps_enabled; - - rc = dsi_ctrl_set_clamp_state(m_ctrl->ctrl, enable, ulps_enabled); - if (rc) { - pr_err("DSI Clamp state change(%d) failed\n", enable); - return rc; - } - - for (i = 0; i < display->ctrl_count; i++) { - ctrl = &display->ctrl[i]; - if (!ctrl->ctrl || (ctrl == m_ctrl)) - continue; - - rc = dsi_ctrl_set_clamp_state(ctrl->ctrl, enable, ulps_enabled); - if (rc) { - pr_err("DSI Clamp state change(%d) failed\n", enable); - return rc; - } - } - display->clamp_enabled = enable; - return 0; -} - -/** - * dsi_display_setup_ctrl() - setup DSI controller. - * @dsi_display: DSI display handle. - * - * Return: error code. - */ -static int dsi_display_ctrl_setup(struct dsi_display *display) -{ - int rc = 0; - int i = 0; - struct dsi_display_ctrl *ctrl, *m_ctrl; - - - if (!display) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - m_ctrl = &display->ctrl[display->cmd_master_idx]; - rc = dsi_ctrl_setup(m_ctrl->ctrl); - if (rc) { - pr_err("DSI controller setup failed\n"); - return rc; - } - - for (i = 0; i < display->ctrl_count; i++) { - ctrl = &display->ctrl[i]; - if (!ctrl->ctrl || (ctrl == m_ctrl)) - continue; - - rc = dsi_ctrl_setup(ctrl->ctrl); - if (rc) { - pr_err("DSI controller setup failed\n"); - return rc; - } - } - return 0; -} - -static int dsi_display_phy_enable(struct dsi_display *display); - -/** - * dsi_display_phy_idle_on() - enable DSI PHY while coming out of idle screen. - * @dsi_display: DSI display handle. - * @enable: enable/disable DSI PHY. - * - * Return: error code. - */ -static int dsi_display_phy_idle_on(struct dsi_display *display, - bool mmss_clamp) -{ - int rc = 0; - int i = 0; - struct dsi_display_ctrl *m_ctrl, *ctrl; - - - if (!display) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - if (mmss_clamp && !display->phy_idle_power_off) { - dsi_display_phy_enable(display); - return 0; - } - - m_ctrl = &display->ctrl[display->cmd_master_idx]; - rc = dsi_phy_idle_ctrl(m_ctrl->phy, true); - if (rc) { - pr_err("DSI controller setup failed\n"); - return rc; - } - - for (i = 0; i < display->ctrl_count; i++) { - ctrl = &display->ctrl[i]; - if (!ctrl->ctrl || (ctrl == m_ctrl)) - continue; - - rc = dsi_phy_idle_ctrl(ctrl->phy, true); - if (rc) { - pr_err("DSI controller setup failed\n"); - return rc; - } - } - display->phy_idle_power_off = false; - return 0; -} - -/** - * dsi_display_phy_idle_off() - disable DSI PHY while going to idle screen. - * @dsi_display: DSI display handle. - * @enable: enable/disable DSI PHY. - * - * Return: error code. - */ -static int dsi_display_phy_idle_off(struct dsi_display *display) -{ - int rc = 0; - int i = 0; - struct dsi_display_ctrl *m_ctrl, *ctrl; - - if (!display) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - if (!display->panel->allow_phy_power_off) { - pr_debug("panel doesn't support this feature\n"); - return 0; - } - - m_ctrl = &display->ctrl[display->cmd_master_idx]; - - rc = dsi_phy_idle_ctrl(m_ctrl->phy, false); - if (rc) { - pr_err("[%s] failed to enable cmd engine, rc=%d\n", - display->name, rc); - return rc; - } - - for (i = 0; i < display->ctrl_count; i++) { - ctrl = &display->ctrl[i]; - if (!ctrl->ctrl || (ctrl == m_ctrl)) - continue; - - rc = dsi_phy_idle_ctrl(ctrl->phy, false); - if (rc) { - pr_err("DSI controller setup failed\n"); - return rc; - } - } - display->phy_idle_power_off = true; - return 0; -} - -void dsi_display_enable_event(struct dsi_display *display, - uint32_t event_idx, struct dsi_event_cb_info *event_info, - bool enable) -{ - uint32_t irq_status_idx = DSI_STATUS_INTERRUPT_COUNT; - int i; - - if (!display) { - pr_err("invalid display\n"); - return; - } - - if (event_info) - event_info->event_idx = event_idx; - - switch (event_idx) { - case DPU_CONN_EVENT_VID_DONE: - irq_status_idx = DSI_SINT_VIDEO_MODE_FRAME_DONE; - break; - case DPU_CONN_EVENT_CMD_DONE: - irq_status_idx = DSI_SINT_CMD_FRAME_DONE; - break; - default: - /* nothing to do */ - pr_debug("[%s] unhandled event %d\n", display->name, event_idx); - return; - } - - if (enable) { - for (i = 0; i < display->ctrl_count; i++) - dsi_ctrl_enable_status_interrupt( - display->ctrl[i].ctrl, irq_status_idx, - event_info); - } else { - for (i = 0; i < display->ctrl_count; i++) - dsi_ctrl_disable_status_interrupt( - display->ctrl[i].ctrl, irq_status_idx); - } -} - -static int dsi_display_ctrl_power_on(struct dsi_display *display) -{ - int rc = 0; - int i; - struct dsi_display_ctrl *ctrl; - - /* Sequence does not matter for split dsi usecases */ - for (i = 0; i < display->ctrl_count; i++) { - ctrl = &display->ctrl[i]; - if (!ctrl->ctrl) - continue; - - rc = dsi_ctrl_set_power_state(ctrl->ctrl, - DSI_CTRL_POWER_VREG_ON); - if (rc) { - pr_err("[%s] Failed to set power state, rc=%d\n", - ctrl->ctrl->name, rc); - goto error; - } - } - - return rc; -error: - for (i = i - 1; i >= 0; i--) { - ctrl = &display->ctrl[i]; - if (!ctrl->ctrl) - continue; - (void)dsi_ctrl_set_power_state(ctrl->ctrl, - DSI_CTRL_POWER_VREG_OFF); - } - return rc; -} - -static int dsi_display_ctrl_power_off(struct dsi_display *display) -{ - int rc = 0; - int i; - struct dsi_display_ctrl *ctrl; - - /* Sequence does not matter for split dsi usecases */ - for (i = 0; i < display->ctrl_count; i++) { - ctrl = &display->ctrl[i]; - if (!ctrl->ctrl) - continue; - - rc = dsi_ctrl_set_power_state(ctrl->ctrl, - DSI_CTRL_POWER_VREG_OFF); - if (rc) { - pr_err("[%s] Failed to power off, rc=%d\n", - ctrl->ctrl->name, rc); - goto error; - } - } -error: - return rc; -} - -static void dsi_display_parse_cmdline_topology(struct dsi_display *display, - unsigned int display_type) -{ - char *boot_str = NULL; - char *str = NULL; - unsigned long value; - - if (display_type >= MAX_DSI_ACTIVE_DISPLAY) { - pr_err("display_type=%d not supported\n", display_type); - return; - } - - if (display_type == DSI_PRIMARY) - boot_str = dsi_display_primary; - else - boot_str = dsi_display_secondary; - - str = strnstr(boot_str, ":config", strlen(boot_str)); - if (!str) - return; - - if (kstrtol(str + strlen(":config"), INT_BASE_10, - (unsigned long *)&value)) { - pr_err("invalid config index override: %s\n", boot_str); - return; - } - display->cmdline_topology = value; - - str = strnstr(boot_str, ":timing", strlen(boot_str)); - if (!str) - return; - - if (kstrtol(str + strlen(":timing"), INT_BASE_10, - (unsigned long *)&value)) { - pr_err("invalid timing index override: %s. resetting both timing and config\n", - boot_str); - display->cmdline_topology = NO_OVERRIDE; - return; - } - display->cmdline_timing = value; -} - -/** - * dsi_display_name_compare()- compare whether DSI display name matches. - * @node: Pointer to device node structure - * @display_name: Name of display to validate - * - * Return: returns a bool specifying whether given display is active - */ -static bool dsi_display_name_compare(struct device_node *node, - const char *display_name, int index) -{ - if (index >= MAX_DSI_ACTIVE_DISPLAY) { - pr_err("Invalid Index\n"); - return false; - } - - if (boot_displays[index].boot_disp_en) { - if (!(strcmp(&boot_displays[index].name[0], display_name))) { - boot_displays[index].node = node; - return true; - } - } - return false; -} - -/** - * dsi_display_parse_boot_display_selection()- Parse DSI boot display name - * - * Return: returns error status - */ -static int dsi_display_parse_boot_display_selection(void) -{ - char *pos = NULL; - char disp_buf[MAX_CMDLINE_PARAM_LEN] = {'\0'}; - int i, j, num_displays; - - if (strlen(dsi_display_primary) == 0) - return -EINVAL; - - if ((strlen(dsi_display_secondary) > 0)) - num_displays = MAX_DSI_ACTIVE_DISPLAY; - else { - /* - * Initialize secondary dsi variables - * for the senario where dsi_display1 - * is null but dsi_display0 is valid - */ - - /* Max number of displays will be one->only Primary */ - num_displays = 1; - boot_displays[DSI_SECONDARY].is_primary = false; - boot_displays[DSI_SECONDARY].name[0] = '\0'; - } - - for (i = 0; i < num_displays; i++) { - boot_displays[i].is_primary = false; - if (i == DSI_PRIMARY) { - strlcpy(disp_buf, &dsi_display_primary[0], - sizeof(dsi_display_primary)); - pos = strnstr(disp_buf, ":", - sizeof(dsi_display_primary)); - } else { - strlcpy(disp_buf, &dsi_display_secondary[0], - sizeof(dsi_display_secondary)); - pos = strnstr(disp_buf, ":", - sizeof(dsi_display_secondary)); - } - /* Use ':' as a delimiter to retrieve the display name */ - if (!pos) { - pr_debug("display name[%s]is not valid\n", disp_buf); - continue; - } - - for (j = 0; (disp_buf + j) < pos; j++) - boot_displays[i].name[j] = *(disp_buf + j); - boot_displays[i].name[j] = '\0'; - - if (i == DSI_PRIMARY) { - boot_displays[i].is_primary = true; - /* Currently, secondary DSI display is not supported */ - boot_displays[i].boot_disp_en = true; - } - } - return 0; -} - -/** - * validate_dsi_display_selection()- validate boot DSI display selection - * - * Return: returns true when both displays have unique configurations - */ -static bool validate_dsi_display_selection(void) -{ - int i, j; - int rc = 0; - int phy_count = 0; - int ctrl_count = 0; - int index = 0; - bool ctrl_flags[MAX_DSI_ACTIVE_DISPLAY] = {false, false}; - bool phy_flags[MAX_DSI_ACTIVE_DISPLAY] = {false, false}; - struct device_node *node, *ctrl_node, *phy_node; - - for (i = 0; i < MAX_DSI_ACTIVE_DISPLAY; i++) { - node = boot_displays[i].node; - ctrl_count = of_count_phandle_with_args(node, "qcom,dsi-ctrl", - NULL); - - for (j = 0; j < ctrl_count; j++) { - ctrl_node = of_parse_phandle(node, "qcom,dsi-ctrl", j); - rc = of_property_read_u32(ctrl_node, "cell-index", - &index); - of_node_put(ctrl_node); - if (rc) { - pr_err("cell index not set for ctrl_nodes\n"); - return false; - } - if (ctrl_flags[index]) - return false; - ctrl_flags[index] = true; - } - - phy_count = of_count_phandle_with_args(node, "qcom,dsi-phy", - NULL); - for (j = 0; j < phy_count; j++) { - phy_node = of_parse_phandle(node, "qcom,dsi-phy", j); - rc = of_property_read_u32(phy_node, "cell-index", - &index); - of_node_put(phy_node); - if (rc) { - pr_err("cell index not set phy_nodes\n"); - return false; - } - if (phy_flags[index]) - return false; - phy_flags[index] = true; - } - } - return true; -} - -struct device_node *dsi_display_get_boot_display(int index) -{ - - pr_err("index = %d\n", index); - - if (boot_displays[index].node) - return boot_displays[index].node; - else if ((index == (MAX_DSI_ACTIVE_DISPLAY - 1)) - && (default_active_node)) - return default_active_node; - else - return NULL; -} - -static int dsi_display_phy_power_on(struct dsi_display *display) -{ - int rc = 0; - int i; - struct dsi_display_ctrl *ctrl; - - /* Sequence does not matter for split dsi usecases */ - for (i = 0; i < display->ctrl_count; i++) { - ctrl = &display->ctrl[i]; - if (!ctrl->ctrl) - continue; - - rc = dsi_phy_set_power_state(ctrl->phy, true); - if (rc) { - pr_err("[%s] Failed to set power state, rc=%d\n", - ctrl->phy->name, rc); - goto error; - } - } - - return rc; -error: - for (i = i - 1; i >= 0; i--) { - ctrl = &display->ctrl[i]; - if (!ctrl->phy) - continue; - (void)dsi_phy_set_power_state(ctrl->phy, false); - } - return rc; -} - -static int dsi_display_phy_power_off(struct dsi_display *display) -{ - int rc = 0; - int i; - struct dsi_display_ctrl *ctrl; - - /* Sequence does not matter for split dsi usecases */ - for (i = 0; i < display->ctrl_count; i++) { - ctrl = &display->ctrl[i]; - if (!ctrl->phy) - continue; - - rc = dsi_phy_set_power_state(ctrl->phy, false); - if (rc) { - pr_err("[%s] Failed to power off, rc=%d\n", - ctrl->ctrl->name, rc); - goto error; - } - } -error: - return rc; -} - -static int dsi_display_set_clk_src(struct dsi_display *display) -{ - int rc = 0; - int i; - struct dsi_display_ctrl *m_ctrl, *ctrl; - - /* - * In case of split DSI usecases, the clock for master controller should - * be enabled before the other controller. Master controller in the - * clock context refers to the controller that sources the clock. - */ - m_ctrl = &display->ctrl[display->clk_master_idx]; - - rc = dsi_ctrl_set_clock_source(m_ctrl->ctrl, - &display->clock_info.src_clks); - if (rc) { - pr_err("[%s] failed to set source clocks for master, rc=%d\n", - display->name, rc); - return rc; - } - - /* Turn on rest of the controllers */ - for (i = 0; i < display->ctrl_count; i++) { - ctrl = &display->ctrl[i]; - if (!ctrl->ctrl || (ctrl == m_ctrl)) - continue; - - rc = dsi_ctrl_set_clock_source(ctrl->ctrl, - &display->clock_info.src_clks); - if (rc) { - pr_err("[%s] failed to set source clocks, rc=%d\n", - display->name, rc); - return rc; - } - } - return 0; -} - -static int dsi_display_phy_reset_config(struct dsi_display *display, - bool enable) -{ - int rc = 0; - int i; - struct dsi_display_ctrl *ctrl; - - for (i = 0 ; i < display->ctrl_count; i++) { - ctrl = &display->ctrl[i]; - rc = dsi_ctrl_phy_reset_config(ctrl->ctrl, enable); - if (rc) { - pr_err("[%s] failed to %s phy reset, rc=%d\n", - display->name, enable ? "mask" : "unmask", rc); - return rc; - } - } - return 0; -} - -static int dsi_display_ctrl_update(struct dsi_display *display) -{ - int rc = 0; - int i; - struct dsi_display_ctrl *ctrl; - - for (i = 0 ; i < display->ctrl_count; i++) { - ctrl = &display->ctrl[i]; - rc = dsi_ctrl_host_timing_update(ctrl->ctrl); - if (rc) { - pr_err("[%s] failed to update host_%d, rc=%d\n", - display->name, i, rc); - goto error_host_deinit; - } - } - - return 0; -error_host_deinit: - for (i = i - 1; i >= 0; i--) { - ctrl = &display->ctrl[i]; - (void)dsi_ctrl_host_deinit(ctrl->ctrl); - } - - return rc; -} - -static int dsi_display_ctrl_init(struct dsi_display *display) -{ - int rc = 0; - int i; - struct dsi_display_ctrl *ctrl; - - for (i = 0 ; i < display->ctrl_count; i++) { - ctrl = &display->ctrl[i]; - rc = dsi_ctrl_host_init(ctrl->ctrl); - if (rc) { - pr_err("[%s] failed to init host_%d, rc=%d\n", - display->name, i, rc); - goto error_host_deinit; - } - } - - return 0; -error_host_deinit: - for (i = i - 1; i >= 0; i--) { - ctrl = &display->ctrl[i]; - (void)dsi_ctrl_host_deinit(ctrl->ctrl); - } - return rc; -} - -static int dsi_display_ctrl_deinit(struct dsi_display *display) -{ - int rc = 0; - int i; - struct dsi_display_ctrl *ctrl; - - for (i = 0 ; i < display->ctrl_count; i++) { - ctrl = &display->ctrl[i]; - rc = dsi_ctrl_host_deinit(ctrl->ctrl); - if (rc) { - pr_err("[%s] failed to deinit host_%d, rc=%d\n", - display->name, i, rc); - } - } - - return rc; -} - -static int dsi_display_cmd_engine_enable(struct dsi_display *display) -{ - int rc = 0; - int i; - struct dsi_display_ctrl *m_ctrl, *ctrl; - - if (display->cmd_engine_refcount > 0) { - display->cmd_engine_refcount++; - return 0; - } - - m_ctrl = &display->ctrl[display->cmd_master_idx]; - - rc = dsi_ctrl_set_cmd_engine_state(m_ctrl->ctrl, DSI_CTRL_ENGINE_ON); - if (rc) { - pr_err("[%s] failed to enable cmd engine, rc=%d\n", - display->name, rc); - goto error; - } - - for (i = 0; i < display->ctrl_count; i++) { - ctrl = &display->ctrl[i]; - if (!ctrl->ctrl || (ctrl == m_ctrl)) - continue; - - rc = dsi_ctrl_set_cmd_engine_state(ctrl->ctrl, - DSI_CTRL_ENGINE_ON); - if (rc) { - pr_err("[%s] failed to enable cmd engine, rc=%d\n", - display->name, rc); - goto error_disable_master; - } - } - - display->cmd_engine_refcount++; - return rc; -error_disable_master: - (void)dsi_ctrl_set_cmd_engine_state(m_ctrl->ctrl, DSI_CTRL_ENGINE_OFF); -error: - return rc; -} - -static int dsi_display_cmd_engine_disable(struct dsi_display *display) -{ - int rc = 0; - int i; - struct dsi_display_ctrl *m_ctrl, *ctrl; - - if (display->cmd_engine_refcount == 0) { - pr_err("[%s] Invalid refcount\n", display->name); - return 0; - } else if (display->cmd_engine_refcount > 1) { - display->cmd_engine_refcount--; - return 0; - } - - m_ctrl = &display->ctrl[display->cmd_master_idx]; - for (i = 0; i < display->ctrl_count; i++) { - ctrl = &display->ctrl[i]; - if (!ctrl->ctrl || (ctrl == m_ctrl)) - continue; - - rc = dsi_ctrl_set_cmd_engine_state(ctrl->ctrl, - DSI_CTRL_ENGINE_OFF); - if (rc) - pr_err("[%s] failed to enable cmd engine, rc=%d\n", - display->name, rc); - } - - rc = dsi_ctrl_set_cmd_engine_state(m_ctrl->ctrl, DSI_CTRL_ENGINE_OFF); - if (rc) { - pr_err("[%s] failed to enable cmd engine, rc=%d\n", - display->name, rc); - goto error; - } - -error: - display->cmd_engine_refcount = 0; - return rc; -} - -static int dsi_display_ctrl_host_enable(struct dsi_display *display) -{ - int rc = 0; - int i; - struct dsi_display_ctrl *m_ctrl, *ctrl; - - m_ctrl = &display->ctrl[display->cmd_master_idx]; - - rc = dsi_ctrl_set_host_engine_state(m_ctrl->ctrl, DSI_CTRL_ENGINE_ON); - if (rc) { - pr_err("[%s] failed to enable host engine, rc=%d\n", - display->name, rc); - goto error; - } - - for (i = 0; i < display->ctrl_count; i++) { - ctrl = &display->ctrl[i]; - if (!ctrl->ctrl || (ctrl == m_ctrl)) - continue; - - rc = dsi_ctrl_set_host_engine_state(ctrl->ctrl, - DSI_CTRL_ENGINE_ON); - if (rc) { - pr_err("[%s] failed to enable sl host engine, rc=%d\n", - display->name, rc); - goto error_disable_master; - } - } - - return rc; -error_disable_master: - (void)dsi_ctrl_set_host_engine_state(m_ctrl->ctrl, DSI_CTRL_ENGINE_OFF); -error: - return rc; -} - -static int dsi_display_ctrl_host_disable(struct dsi_display *display) -{ - int rc = 0; - int i; - struct dsi_display_ctrl *m_ctrl, *ctrl; - - m_ctrl = &display->ctrl[display->cmd_master_idx]; - for (i = 0; i < display->ctrl_count; i++) { - ctrl = &display->ctrl[i]; - if (!ctrl->ctrl || (ctrl == m_ctrl)) - continue; - - rc = dsi_ctrl_set_host_engine_state(ctrl->ctrl, - DSI_CTRL_ENGINE_OFF); - if (rc) - pr_err("[%s] failed to disable host engine, rc=%d\n", - display->name, rc); - } - - rc = dsi_ctrl_set_host_engine_state(m_ctrl->ctrl, DSI_CTRL_ENGINE_OFF); - if (rc) { - pr_err("[%s] failed to disable host engine, rc=%d\n", - display->name, rc); - goto error; - } - -error: - return rc; -} - -static int dsi_display_vid_engine_enable(struct dsi_display *display) -{ - int rc = 0; - int i; - struct dsi_display_ctrl *m_ctrl, *ctrl; - - m_ctrl = &display->ctrl[display->video_master_idx]; - - rc = dsi_ctrl_set_vid_engine_state(m_ctrl->ctrl, DSI_CTRL_ENGINE_ON); - if (rc) { - pr_err("[%s] failed to enable vid engine, rc=%d\n", - display->name, rc); - goto error; - } - - for (i = 0; i < display->ctrl_count; i++) { - ctrl = &display->ctrl[i]; - if (!ctrl->ctrl || (ctrl == m_ctrl)) - continue; - - rc = dsi_ctrl_set_vid_engine_state(ctrl->ctrl, - DSI_CTRL_ENGINE_ON); - if (rc) { - pr_err("[%s] failed to enable vid engine, rc=%d\n", - display->name, rc); - goto error_disable_master; - } - } - - return rc; -error_disable_master: - (void)dsi_ctrl_set_vid_engine_state(m_ctrl->ctrl, DSI_CTRL_ENGINE_OFF); -error: - return rc; -} - -static int dsi_display_vid_engine_disable(struct dsi_display *display) -{ - int rc = 0; - int i; - struct dsi_display_ctrl *m_ctrl, *ctrl; - - m_ctrl = &display->ctrl[display->video_master_idx]; - - for (i = 0; i < display->ctrl_count; i++) { - ctrl = &display->ctrl[i]; - if (!ctrl->ctrl || (ctrl == m_ctrl)) - continue; - - rc = dsi_ctrl_set_vid_engine_state(ctrl->ctrl, - DSI_CTRL_ENGINE_OFF); - if (rc) - pr_err("[%s] failed to disable vid engine, rc=%d\n", - display->name, rc); - } - - rc = dsi_ctrl_set_vid_engine_state(m_ctrl->ctrl, DSI_CTRL_ENGINE_OFF); - if (rc) - pr_err("[%s] failed to disable mvid engine, rc=%d\n", - display->name, rc); - - return rc; -} - -static int dsi_display_phy_enable(struct dsi_display *display) -{ - int rc = 0; - int i; - struct dsi_display_ctrl *m_ctrl, *ctrl; - enum dsi_phy_pll_source m_src = DSI_PLL_SOURCE_STANDALONE; - - m_ctrl = &display->ctrl[display->clk_master_idx]; - if (display->ctrl_count > 1) - m_src = DSI_PLL_SOURCE_NATIVE; - - rc = dsi_phy_enable(m_ctrl->phy, - &display->config, - m_src, - true); - if (rc) { - pr_err("[%s] failed to enable DSI PHY, rc=%d\n", - display->name, rc); - goto error; - } - - for (i = 0; i < display->ctrl_count; i++) { - ctrl = &display->ctrl[i]; - if (!ctrl->ctrl || (ctrl == m_ctrl)) - continue; - - rc = dsi_phy_enable(ctrl->phy, - &display->config, - DSI_PLL_SOURCE_NON_NATIVE, - true); - if (rc) { - pr_err("[%s] failed to enable DSI PHY, rc=%d\n", - display->name, rc); - goto error_disable_master; - } - } - - return rc; - -error_disable_master: - (void)dsi_phy_disable(m_ctrl->phy); -error: - return rc; -} - -static int dsi_display_phy_disable(struct dsi_display *display) -{ - int rc = 0; - int i; - struct dsi_display_ctrl *m_ctrl, *ctrl; - - m_ctrl = &display->ctrl[display->clk_master_idx]; - - for (i = 0; i < display->ctrl_count; i++) { - ctrl = &display->ctrl[i]; - if (!ctrl->ctrl || (ctrl == m_ctrl)) - continue; - - rc = dsi_phy_disable(ctrl->phy); - if (rc) - pr_err("[%s] failed to disable DSI PHY, rc=%d\n", - display->name, rc); - } - - rc = dsi_phy_disable(m_ctrl->phy); - if (rc) - pr_err("[%s] failed to disable DSI PHY, rc=%d\n", - display->name, rc); - - return rc; -} - -static int dsi_display_wake_up(struct dsi_display *display) -{ - return 0; -} - -static int dsi_display_broadcast_cmd(struct dsi_display *display, - const struct mipi_dsi_msg *msg) -{ - int rc = 0; - u32 flags, m_flags; - struct dsi_display_ctrl *ctrl, *m_ctrl; - int i; - - m_flags = (DSI_CTRL_CMD_BROADCAST | DSI_CTRL_CMD_BROADCAST_MASTER | - DSI_CTRL_CMD_DEFER_TRIGGER | DSI_CTRL_CMD_FETCH_MEMORY); - flags = (DSI_CTRL_CMD_BROADCAST | DSI_CTRL_CMD_DEFER_TRIGGER | - DSI_CTRL_CMD_FETCH_MEMORY); - - /* - * 1. Setup commands in FIFO - * 2. Trigger commands - */ - m_ctrl = &display->ctrl[display->cmd_master_idx]; - rc = dsi_ctrl_cmd_transfer(m_ctrl->ctrl, msg, m_flags); - if (rc) { - pr_err("[%s] cmd transfer failed on master,rc=%d\n", - display->name, rc); - goto error; - } - - for (i = 0; i < display->ctrl_count; i++) { - ctrl = &display->ctrl[i]; - if (ctrl == m_ctrl) - continue; - - rc = dsi_ctrl_cmd_transfer(ctrl->ctrl, msg, flags); - if (rc) { - pr_err("[%s] cmd transfer failed, rc=%d\n", - display->name, rc); - goto error; - } - - rc = dsi_ctrl_cmd_tx_trigger(ctrl->ctrl, flags); - if (rc) { - pr_err("[%s] cmd trigger failed, rc=%d\n", - display->name, rc); - goto error; - } - } - - rc = dsi_ctrl_cmd_tx_trigger(m_ctrl->ctrl, m_flags); - if (rc) { - pr_err("[%s] cmd trigger failed for master, rc=%d\n", - display->name, rc); - goto error; - } - -error: - return rc; -} - -static int dsi_display_phy_sw_reset(struct dsi_display *display) -{ - int rc = 0; - int i; - struct dsi_display_ctrl *m_ctrl, *ctrl; - - m_ctrl = &display->ctrl[display->cmd_master_idx]; - - rc = dsi_ctrl_phy_sw_reset(m_ctrl->ctrl); - if (rc) { - pr_err("[%s] failed to reset phy, rc=%d\n", display->name, rc); - goto error; - } - - for (i = 0; i < display->ctrl_count; i++) { - ctrl = &display->ctrl[i]; - if (!ctrl->ctrl || (ctrl == m_ctrl)) - continue; - - rc = dsi_ctrl_phy_sw_reset(ctrl->ctrl); - if (rc) { - pr_err("[%s] failed to reset phy, rc=%d\n", - display->name, rc); - goto error; - } - } - -error: - return rc; -} - -static int dsi_host_attach(struct mipi_dsi_host *host, - struct mipi_dsi_device *dsi) -{ - return 0; -} - -static int dsi_host_detach(struct mipi_dsi_host *host, - struct mipi_dsi_device *dsi) -{ - return 0; -} - -static ssize_t dsi_host_transfer(struct mipi_dsi_host *host, - const struct mipi_dsi_msg *msg) -{ - struct dsi_display *display = to_dsi_display(host); - struct dsi_display_ctrl *display_ctrl; - struct msm_gem_address_space *aspace = NULL; - int rc = 0, cnt = 0; - - if (!host || !msg) { - pr_err("Invalid params\n"); - return 0; - } - - rc = dsi_display_clk_ctrl(display->dsi_clk_handle, - DSI_ALL_CLKS, DSI_CLK_ON); - if (rc) { - pr_err("[%s] failed to enable all DSI clocks, rc=%d\n", - display->name, rc); - goto error; - } - - rc = dsi_display_wake_up(display); - if (rc) { - pr_err("[%s] failed to wake up display, rc=%d\n", - display->name, rc); - goto error_disable_clks; - } - - rc = dsi_display_cmd_engine_enable(display); - if (rc) { - pr_err("[%s] failed to enable cmd engine, rc=%d\n", - display->name, rc); - goto error_disable_clks; - } - - if (display->tx_cmd_buf == NULL) { - display->tx_cmd_buf = msm_gem_new(display->drm_dev, - SZ_4K, - MSM_BO_UNCACHED); - - display->cmd_buffer_size = SZ_4K; - - if ((display->tx_cmd_buf) == NULL) { - pr_err("value of display->tx_cmd_buf is NULL"); - goto error_disable_cmd_engine; - } - - aspace = msm_gem_smmu_address_space_get(display->drm_dev, - MSM_SMMU_DOMAIN_UNSECURE); - if (!aspace) { - pr_err("failed to get aspace\n"); - rc = -EINVAL; - goto free_gem; - } - - rc = msm_gem_get_iova(display->tx_cmd_buf, aspace, - &(display->cmd_buffer_iova)); - if (rc) { - pr_err("failed to get the iova rc %d\n", rc); - goto free_gem; - } - - display->vaddr = - (void *) msm_gem_get_vaddr(display->tx_cmd_buf); - - if (IS_ERR_OR_NULL(display->vaddr)) { - pr_err("failed to get va rc %d\n", rc); - rc = -EINVAL; - goto put_iova; - } - - for (cnt = 0; cnt < display->ctrl_count; cnt++) { - display_ctrl = &display->ctrl[cnt]; - display_ctrl->ctrl->cmd_buffer_size = SZ_4K; - display_ctrl->ctrl->cmd_buffer_iova = - display->cmd_buffer_iova; - display_ctrl->ctrl->vaddr = display->vaddr; - } - } - - if (display->ctrl_count > 1 && !(msg->flags & MIPI_DSI_MSG_UNICAST)) { - rc = dsi_display_broadcast_cmd(display, msg); - if (rc) { - pr_err("[%s] cmd broadcast failed, rc=%d\n", - display->name, rc); - goto error_disable_cmd_engine; - } - } else { - int ctrl_idx = (msg->flags & MIPI_DSI_MSG_UNICAST) ? - msg->ctrl : 0; - - rc = dsi_ctrl_cmd_transfer(display->ctrl[ctrl_idx].ctrl, msg, - DSI_CTRL_CMD_FETCH_MEMORY); - if (rc) { - pr_err("[%s] cmd transfer failed, rc=%d\n", - display->name, rc); - goto error_disable_cmd_engine; - } - } - -error_disable_cmd_engine: - (void)dsi_display_cmd_engine_disable(display); -error_disable_clks: - rc = dsi_display_clk_ctrl(display->dsi_clk_handle, - DSI_ALL_CLKS, DSI_CLK_OFF); - if (rc) { - pr_err("[%s] failed to disable all DSI clocks, rc=%d\n", - display->name, rc); - } - return rc; -put_iova: - msm_gem_put_iova(display->tx_cmd_buf, aspace); -free_gem: - mutex_lock(&display->drm_dev->struct_mutex); - msm_gem_free_object(display->tx_cmd_buf); - mutex_unlock(&display->drm_dev->struct_mutex); -error: - return rc; -} - - -static struct mipi_dsi_host_ops dsi_host_ops = { - .attach = dsi_host_attach, - .detach = dsi_host_detach, - .transfer = dsi_host_transfer, -}; - -static int dsi_display_mipi_host_init(struct dsi_display *display) -{ - int rc = 0; - struct mipi_dsi_host *host = &display->host; - - host->dev = &display->pdev->dev; - host->ops = &dsi_host_ops; - - rc = mipi_dsi_host_register(host); - if (rc) { - pr_err("[%s] failed to register mipi dsi host, rc=%d\n", - display->name, rc); - goto error; - } - -error: - return rc; -} -static int dsi_display_mipi_host_deinit(struct dsi_display *display) -{ - int rc = 0; - struct mipi_dsi_host *host = &display->host; - - mipi_dsi_host_unregister(host); - - host->dev = NULL; - host->ops = NULL; - - return rc; -} - -static int dsi_display_clocks_deinit(struct dsi_display *display) -{ - int rc = 0; - struct dsi_clk_link_set *src = &display->clock_info.src_clks; - struct dsi_clk_link_set *mux = &display->clock_info.mux_clks; - struct dsi_clk_link_set *shadow = &display->clock_info.shadow_clks; - - if (src->byte_clk) { - devm_clk_put(&display->pdev->dev, src->byte_clk); - src->byte_clk = NULL; - } - - if (src->pixel_clk) { - devm_clk_put(&display->pdev->dev, src->pixel_clk); - src->pixel_clk = NULL; - } - - if (mux->byte_clk) { - devm_clk_put(&display->pdev->dev, mux->byte_clk); - mux->byte_clk = NULL; - } - - if (mux->pixel_clk) { - devm_clk_put(&display->pdev->dev, mux->pixel_clk); - mux->pixel_clk = NULL; - } - - if (shadow->byte_clk) { - devm_clk_put(&display->pdev->dev, shadow->byte_clk); - shadow->byte_clk = NULL; - } - - if (shadow->pixel_clk) { - devm_clk_put(&display->pdev->dev, shadow->pixel_clk); - shadow->pixel_clk = NULL; - } - - return rc; -} - -static int dsi_display_clocks_init(struct dsi_display *display) -{ - int rc = 0; - struct dsi_clk_link_set *src = &display->clock_info.src_clks; - struct dsi_clk_link_set *mux = &display->clock_info.mux_clks; - struct dsi_clk_link_set *shadow = &display->clock_info.shadow_clks; - - src->byte_clk = devm_clk_get(&display->pdev->dev, "src_byte_clk"); - if (IS_ERR_OR_NULL(src->byte_clk)) { - rc = PTR_ERR(src->byte_clk); - src->byte_clk = NULL; - pr_err("failed to get src_byte_clk, rc=%d\n", rc); - goto error; - } - - src->pixel_clk = devm_clk_get(&display->pdev->dev, "src_pixel_clk"); - if (IS_ERR_OR_NULL(src->pixel_clk)) { - rc = PTR_ERR(src->pixel_clk); - src->pixel_clk = NULL; - pr_err("failed to get src_pixel_clk, rc=%d\n", rc); - goto error; - } - - mux->byte_clk = devm_clk_get(&display->pdev->dev, "mux_byte_clk"); - if (IS_ERR_OR_NULL(mux->byte_clk)) { - rc = PTR_ERR(mux->byte_clk); - pr_debug("failed to get mux_byte_clk, rc=%d\n", rc); - mux->byte_clk = NULL; - /* - * Skip getting rest of clocks since one failed. This is a - * non-critical failure since these clocks are requied only for - * dynamic refresh use cases. - */ - rc = 0; - goto done; - }; - - mux->pixel_clk = devm_clk_get(&display->pdev->dev, "mux_pixel_clk"); - if (IS_ERR_OR_NULL(mux->pixel_clk)) { - rc = PTR_ERR(mux->pixel_clk); - mux->pixel_clk = NULL; - pr_debug("failed to get mux_pixel_clk, rc=%d\n", rc); - /* - * Skip getting rest of clocks since one failed. This is a - * non-critical failure since these clocks are requied only for - * dynamic refresh use cases. - */ - rc = 0; - goto done; - }; - - shadow->byte_clk = devm_clk_get(&display->pdev->dev, "shadow_byte_clk"); - if (IS_ERR_OR_NULL(shadow->byte_clk)) { - rc = PTR_ERR(shadow->byte_clk); - shadow->byte_clk = NULL; - pr_err("failed to get shadow_byte_clk, rc=%d\n", rc); - /* - * Skip getting rest of clocks since one failed. This is a - * non-critical failure since these clocks are requied only for - * dynamic refresh use cases. - */ - rc = 0; - goto done; - }; - - shadow->pixel_clk = devm_clk_get(&display->pdev->dev, - "shadow_pixel_clk"); - if (IS_ERR_OR_NULL(shadow->pixel_clk)) { - rc = PTR_ERR(shadow->pixel_clk); - shadow->pixel_clk = NULL; - pr_err("failed to get shadow_pixel_clk, rc=%d\n", rc); - /* - * Skip getting rest of clocks since one failed. This is a - * non-critical failure since these clocks are requied only for - * dynamic refresh use cases. - */ - rc = 0; - goto done; - }; - -done: - return 0; -error: - (void)dsi_display_clocks_deinit(display); - return rc; -} - -static int dsi_display_clk_ctrl_cb(void *priv, - struct dsi_clk_ctrl_info clk_state_info) -{ - int rc = 0; - struct dsi_display *display = NULL; - void *clk_handle = NULL; - - if (!priv) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - display = priv; - - if (clk_state_info.client == DSI_CLK_REQ_MDP_CLIENT) { - clk_handle = display->mdp_clk_handle; - } else if (clk_state_info.client == DSI_CLK_REQ_DSI_CLIENT) { - clk_handle = display->dsi_clk_handle; - } else { - pr_err("invalid clk handle, return error\n"); - return -EINVAL; - } - - /* - * TODO: Wait for CMD_MDP_DONE interrupt if MDP client tries - * to turn off DSI clocks. - */ - rc = dsi_display_clk_ctrl(clk_handle, - clk_state_info.clk_type, clk_state_info.clk_state); - if (rc) { - pr_err("[%s] failed to %d DSI %d clocks, rc=%d\n", - display->name, clk_state_info.clk_state, - clk_state_info.clk_type, rc); - return rc; - } - return 0; -} - -int dsi_pre_clkoff_cb(void *priv, - enum dsi_clk_type clk, - enum dsi_clk_state new_state) -{ - int rc = 0; - struct dsi_display *display = priv; - - if ((clk & DSI_LINK_CLK) && (new_state == DSI_CLK_OFF)) { - /* - * If ULPS feature is enabled, enter ULPS first. - */ - if (dsi_panel_initialized(display->panel) && - dsi_panel_ulps_feature_enabled(display->panel)) { - rc = dsi_display_set_ulps(display, true); - if (rc) { - pr_err("%s: failed enable ulps, rc = %d\n", - __func__, rc); - } - } - } - - if ((clk & DSI_CORE_CLK) && (new_state == DSI_CLK_OFF)) { - /* - * Enable DSI clamps only if entering idle power collapse. - */ - if (dsi_panel_initialized(display->panel)) { - dsi_display_phy_idle_off(display); - rc = dsi_display_set_clamp(display, true); - if (rc) - pr_err("%s: Failed to enable dsi clamps. rc=%d\n", - __func__, rc); - - rc = dsi_display_phy_reset_config(display, false); - if (rc) - pr_err("%s: Failed to reset phy, rc=%d\n", - __func__, rc); - } else { - /* Make sure that controller is not in ULPS state when - * the DSI link is not active. - */ - rc = dsi_display_set_ulps(display, false); - if (rc) - pr_err("%s: failed to disable ulps. rc=%d\n", - __func__, rc); - } - } - - return rc; -} - -int dsi_post_clkon_cb(void *priv, - enum dsi_clk_type clk, - enum dsi_clk_state curr_state) -{ - int rc = 0; - struct dsi_display *display = priv; - bool mmss_clamp = false; - - if (clk & DSI_CORE_CLK) { - mmss_clamp = display->clamp_enabled; - /* - * controller setup is needed if coming out of idle - * power collapse with clamps enabled. - */ - if (mmss_clamp) - dsi_display_ctrl_setup(display); - - if (display->ulps_enabled && mmss_clamp) { - /* - * ULPS Entry Request. This is needed if the lanes were - * in ULPS prior to power collapse, since after - * power collapse and reset, the DSI controller resets - * back to idle state and not ULPS. This ulps entry - * request will transition the state of the DSI - * controller to ULPS which will match the state of the - * DSI phy. This needs to be done prior to disabling - * the DSI clamps. - * - * Also, reset the ulps flag so that ulps_config - * function would reconfigure the controller state to - * ULPS. - */ - display->ulps_enabled = false; - rc = dsi_display_set_ulps(display, true); - if (rc) { - pr_err("%s: Failed to enter ULPS. rc=%d\n", - __func__, rc); - goto error; - } - } - - rc = dsi_display_phy_reset_config(display, true); - if (rc) { - pr_err("%s: Failed to reset phy, rc=%d\n", - __func__, rc); - goto error; - } - - rc = dsi_display_set_clamp(display, false); - if (rc) { - pr_err("%s: Failed to disable dsi clamps. rc=%d\n", - __func__, rc); - goto error; - } - - /* - * Phy setup is needed if coming out of idle - * power collapse with clamps enabled. - */ - if (display->phy_idle_power_off || mmss_clamp) - dsi_display_phy_idle_on(display, mmss_clamp); - } - if (clk & DSI_LINK_CLK) { - if (display->ulps_enabled) { - rc = dsi_display_set_ulps(display, false); - if (rc) { - pr_err("%s: failed to disable ulps, rc= %d\n", - __func__, rc); - goto error; - } - } - } -error: - return rc; -} - -int dsi_post_clkoff_cb(void *priv, - enum dsi_clk_type clk_type, - enum dsi_clk_state curr_state) -{ - int rc = 0; - struct dsi_display *display = priv; - - if (!display) { - pr_err("%s: Invalid arg\n", __func__); - return -EINVAL; - } - - if ((clk_type & DSI_CORE_CLK) && - (curr_state == DSI_CLK_OFF)) { - - rc = dsi_display_phy_power_off(display); - if (rc) - pr_err("[%s] failed to power off PHY, rc=%d\n", - display->name, rc); - - rc = dsi_display_ctrl_power_off(display); - if (rc) - pr_err("[%s] failed to power DSI vregs, rc=%d\n", - display->name, rc); - } - return rc; -} - -int dsi_pre_clkon_cb(void *priv, - enum dsi_clk_type clk_type, - enum dsi_clk_state new_state) -{ - int rc = 0; - struct dsi_display *display = priv; - - if (!display) { - pr_err("%s: invalid input\n", __func__); - return -EINVAL; - } - - if ((clk_type & DSI_CORE_CLK) && (new_state == DSI_CLK_ON)) { - /* - * Enable DSI core power - * 1.> PANEL_PM are controlled as part of - * panel_power_ctrl. Needed not be handled here. - * 2.> CORE_PM are controlled by dsi clk manager. - * 3.> CTRL_PM need to be enabled/disabled - * only during unblank/blank. Their state should - * not be changed during static screen. - */ - - rc = dsi_display_ctrl_power_on(display); - if (rc) { - pr_err("[%s] failed to power on dsi controllers, rc=%d\n", - display->name, rc); - return rc; - } - - rc = dsi_display_phy_power_on(display); - if (rc) { - pr_err("[%s] failed to power on dsi phy, rc = %d\n", - display->name, rc); - return rc; - } - - pr_debug("%s: Enable DSI core power\n", __func__); - } - - return rc; -} - -static void __set_lane_map_v2(u8 *lane_map_v2, - enum dsi_phy_data_lanes lane0, - enum dsi_phy_data_lanes lane1, - enum dsi_phy_data_lanes lane2, - enum dsi_phy_data_lanes lane3) -{ - lane_map_v2[DSI_LOGICAL_LANE_0] = lane0; - lane_map_v2[DSI_LOGICAL_LANE_1] = lane1; - lane_map_v2[DSI_LOGICAL_LANE_2] = lane2; - lane_map_v2[DSI_LOGICAL_LANE_3] = lane3; -} - -static int dsi_display_parse_lane_map(struct dsi_display *display) -{ - int rc = 0, i = 0; - const char *data; - u8 temp[DSI_LANE_MAX - 1]; - - if (!display) { - pr_err("invalid params\n"); - return -EINVAL; - } - - /* lane-map-v2 supersedes lane-map-v1 setting */ - rc = of_property_read_u8_array(display->pdev->dev.of_node, - "qcom,lane-map-v2", temp, (DSI_LANE_MAX - 1)); - if (!rc) { - for (i = DSI_LOGICAL_LANE_0; i < (DSI_LANE_MAX - 1); i++) - display->lane_map.lane_map_v2[i] = BIT(temp[i]); - return 0; - } else if (rc != EINVAL) { - pr_debug("Incorrect mapping, configure default\n"); - goto set_default; - } - - /* lane-map older version, for DSI controller version < 2.0 */ - data = of_get_property(display->pdev->dev.of_node, - "qcom,lane-map", NULL); - if (!data) - goto set_default; - - if (!strcmp(data, "lane_map_3012")) { - display->lane_map.lane_map_v1 = DSI_LANE_MAP_3012; - __set_lane_map_v2(display->lane_map.lane_map_v2, - DSI_PHYSICAL_LANE_1, - DSI_PHYSICAL_LANE_2, - DSI_PHYSICAL_LANE_3, - DSI_PHYSICAL_LANE_0); - } else if (!strcmp(data, "lane_map_2301")) { - display->lane_map.lane_map_v1 = DSI_LANE_MAP_2301; - __set_lane_map_v2(display->lane_map.lane_map_v2, - DSI_PHYSICAL_LANE_2, - DSI_PHYSICAL_LANE_3, - DSI_PHYSICAL_LANE_0, - DSI_PHYSICAL_LANE_1); - } else if (!strcmp(data, "lane_map_1230")) { - display->lane_map.lane_map_v1 = DSI_LANE_MAP_1230; - __set_lane_map_v2(display->lane_map.lane_map_v2, - DSI_PHYSICAL_LANE_3, - DSI_PHYSICAL_LANE_0, - DSI_PHYSICAL_LANE_1, - DSI_PHYSICAL_LANE_2); - } else if (!strcmp(data, "lane_map_0321")) { - display->lane_map.lane_map_v1 = DSI_LANE_MAP_0321; - __set_lane_map_v2(display->lane_map.lane_map_v2, - DSI_PHYSICAL_LANE_0, - DSI_PHYSICAL_LANE_3, - DSI_PHYSICAL_LANE_2, - DSI_PHYSICAL_LANE_1); - } else if (!strcmp(data, "lane_map_1032")) { - display->lane_map.lane_map_v1 = DSI_LANE_MAP_1032; - __set_lane_map_v2(display->lane_map.lane_map_v2, - DSI_PHYSICAL_LANE_1, - DSI_PHYSICAL_LANE_0, - DSI_PHYSICAL_LANE_3, - DSI_PHYSICAL_LANE_2); - } else if (!strcmp(data, "lane_map_2103")) { - display->lane_map.lane_map_v1 = DSI_LANE_MAP_2103; - __set_lane_map_v2(display->lane_map.lane_map_v2, - DSI_PHYSICAL_LANE_2, - DSI_PHYSICAL_LANE_1, - DSI_PHYSICAL_LANE_0, - DSI_PHYSICAL_LANE_3); - } else if (!strcmp(data, "lane_map_3210")) { - display->lane_map.lane_map_v1 = DSI_LANE_MAP_3210; - __set_lane_map_v2(display->lane_map.lane_map_v2, - DSI_PHYSICAL_LANE_3, - DSI_PHYSICAL_LANE_2, - DSI_PHYSICAL_LANE_1, - DSI_PHYSICAL_LANE_0); - } else { - pr_warn("%s: invalid lane map %s specified. defaulting to lane_map0123\n", - __func__, data); - goto set_default; - } - return 0; - -set_default: - /* default lane mapping */ - __set_lane_map_v2(display->lane_map.lane_map_v2, DSI_PHYSICAL_LANE_0, - DSI_PHYSICAL_LANE_1, DSI_PHYSICAL_LANE_2, DSI_PHYSICAL_LANE_3); - display->lane_map.lane_map_v1 = DSI_LANE_MAP_0123; - return 0; -} - -static int dsi_display_parse_dt(struct dsi_display *display) -{ - int rc = 0; - int i; - u32 phy_count = 0; - struct device_node *of_node; - - /* Parse controllers */ - for (i = 0; i < MAX_DSI_CTRLS_PER_DISPLAY; i++) { - of_node = of_parse_phandle(display->pdev->dev.of_node, - "qcom,dsi-ctrl", i); - if (!of_node) { - if (!i) { - pr_err("No controllers present\n"); - return -ENODEV; - } - break; - } - - display->ctrl[i].ctrl_of_node = of_node; - display->ctrl_count++; - } - - /* Parse Phys */ - for (i = 0; i < MAX_DSI_CTRLS_PER_DISPLAY; i++) { - of_node = of_parse_phandle(display->pdev->dev.of_node, - "qcom,dsi-phy", i); - if (!of_node) { - if (!i) { - pr_err("No PHY devices present\n"); - rc = -ENODEV; - goto error; - } - break; - } - - display->ctrl[i].phy_of_node = of_node; - phy_count++; - } - - if (phy_count != display->ctrl_count) { - pr_err("Number of controllers does not match PHYs\n"); - rc = -ENODEV; - goto error; - } - - of_node = of_parse_phandle(display->pdev->dev.of_node, - "qcom,dsi-panel", 0); - if (!of_node) { - pr_err("No Panel device present\n"); - rc = -ENODEV; - goto error; - } else { - display->panel_of = of_node; - } - -error: - return rc; -} - -static int dsi_display_res_init(struct dsi_display *display) -{ - int rc = 0; - int i; - struct dsi_display_ctrl *ctrl; - - for (i = 0; i < display->ctrl_count; i++) { - ctrl = &display->ctrl[i]; - ctrl->ctrl = dsi_ctrl_get(ctrl->ctrl_of_node); - if (IS_ERR_OR_NULL(ctrl->ctrl)) { - rc = PTR_ERR(ctrl->ctrl); - pr_err("failed to get dsi controller, rc=%d\n", rc); - ctrl->ctrl = NULL; - goto error_ctrl_put; - } - - ctrl->phy = dsi_phy_get(ctrl->phy_of_node); - if (IS_ERR_OR_NULL(ctrl->phy)) { - rc = PTR_ERR(ctrl->phy); - pr_err("failed to get phy controller, rc=%d\n", rc); - dsi_ctrl_put(ctrl->ctrl); - ctrl->phy = NULL; - goto error_ctrl_put; - } - } - - display->panel = dsi_panel_get(&display->pdev->dev, display->panel_of, - display->cmdline_topology); - if (IS_ERR_OR_NULL(display->panel)) { - rc = PTR_ERR(display->panel); - pr_err("failed to get panel, rc=%d\n", rc); - display->panel = NULL; - goto error_ctrl_put; - } - - rc = dsi_display_parse_lane_map(display); - if (rc) { - pr_err("Lane map not found, rc=%d\n", rc); - goto error_ctrl_put; - } - - rc = dsi_display_clocks_init(display); - if (rc) { - pr_err("Failed to parse clock data, rc=%d\n", rc); - goto error_ctrl_put; - } - - return 0; -error_ctrl_put: - for (i = i - 1; i >= 0; i--) { - ctrl = &display->ctrl[i]; - dsi_ctrl_put(ctrl->ctrl); - dsi_phy_put(ctrl->phy); - } - return rc; -} - -static int dsi_display_res_deinit(struct dsi_display *display) -{ - int rc = 0; - int i; - struct dsi_display_ctrl *ctrl; - - rc = dsi_display_clocks_deinit(display); - if (rc) - pr_err("clocks deinit failed, rc=%d\n", rc); - - for (i = 0; i < display->ctrl_count; i++) { - ctrl = &display->ctrl[i]; - dsi_phy_put(ctrl->phy); - dsi_ctrl_put(ctrl->ctrl); - } - - if (display->panel) - dsi_panel_put(display->panel); - - return rc; -} - -static int dsi_display_validate_mode_set(struct dsi_display *display, - struct dsi_display_mode *mode, - u32 flags) -{ - int rc = 0; - int i; - struct dsi_display_ctrl *ctrl; - - /* - * To set a mode: - * 1. Controllers should be turned off. - * 2. Link clocks should be off. - * 3. Phy should be disabled. - */ - - for (i = 0; i < display->ctrl_count; i++) { - ctrl = &display->ctrl[i]; - if ((ctrl->power_state > DSI_CTRL_POWER_VREG_ON) || - (ctrl->phy_enabled)) { - rc = -EINVAL; - goto error; - } - } - -error: - return rc; -} - -static bool dsi_display_is_seamless_dfps_possible( - const struct dsi_display *display, - const struct dsi_display_mode *tgt, - const enum dsi_dfps_type dfps_type) -{ - struct dsi_display_mode *cur; - - if (!display || !tgt || !display->panel) { - pr_err("Invalid params\n"); - return false; - } - - cur = display->panel->cur_mode; - - if (cur->timing.h_active != tgt->timing.h_active) { - pr_debug("timing.h_active differs %d %d\n", - cur->timing.h_active, tgt->timing.h_active); - return false; - } - - if (cur->timing.h_back_porch != tgt->timing.h_back_porch) { - pr_debug("timing.h_back_porch differs %d %d\n", - cur->timing.h_back_porch, - tgt->timing.h_back_porch); - return false; - } - - if (cur->timing.h_sync_width != tgt->timing.h_sync_width) { - pr_debug("timing.h_sync_width differs %d %d\n", - cur->timing.h_sync_width, - tgt->timing.h_sync_width); - return false; - } - - if (cur->timing.h_front_porch != tgt->timing.h_front_porch) { - pr_debug("timing.h_front_porch differs %d %d\n", - cur->timing.h_front_porch, - tgt->timing.h_front_porch); - if (dfps_type != DSI_DFPS_IMMEDIATE_HFP) - return false; - } - - if (cur->timing.h_skew != tgt->timing.h_skew) { - pr_debug("timing.h_skew differs %d %d\n", - cur->timing.h_skew, - tgt->timing.h_skew); - return false; - } - - /* skip polarity comparison */ - - if (cur->timing.v_active != tgt->timing.v_active) { - pr_debug("timing.v_active differs %d %d\n", - cur->timing.v_active, - tgt->timing.v_active); - return false; - } - - if (cur->timing.v_back_porch != tgt->timing.v_back_porch) { - pr_debug("timing.v_back_porch differs %d %d\n", - cur->timing.v_back_porch, - tgt->timing.v_back_porch); - return false; - } - - if (cur->timing.v_sync_width != tgt->timing.v_sync_width) { - pr_debug("timing.v_sync_width differs %d %d\n", - cur->timing.v_sync_width, - tgt->timing.v_sync_width); - return false; - } - - if (cur->timing.v_front_porch != tgt->timing.v_front_porch) { - pr_debug("timing.v_front_porch differs %d %d\n", - cur->timing.v_front_porch, - tgt->timing.v_front_porch); - if (dfps_type != DSI_DFPS_IMMEDIATE_VFP) - return false; - } - - /* skip polarity comparison */ - - if (cur->timing.refresh_rate == tgt->timing.refresh_rate) - pr_debug("timing.refresh_rate identical %d %d\n", - cur->timing.refresh_rate, - tgt->timing.refresh_rate); - - if (cur->pixel_clk_khz != tgt->pixel_clk_khz) - pr_debug("pixel_clk_khz differs %d %d\n", - cur->pixel_clk_khz, tgt->pixel_clk_khz); - - if (cur->dsi_mode_flags != tgt->dsi_mode_flags) - pr_debug("flags differs %d %d\n", - cur->dsi_mode_flags, tgt->dsi_mode_flags); - - return true; -} - -static int dsi_display_dfps_update(struct dsi_display *display, - struct dsi_display_mode *dsi_mode) -{ - struct dsi_mode_info *timing; - struct dsi_display_ctrl *m_ctrl, *ctrl; - struct dsi_display_mode *panel_mode; - struct dsi_dfps_capabilities dfps_caps; - int rc = 0; - int i = 0; - - if (!display || !dsi_mode || !display->panel) { - pr_err("Invalid params\n"); - return -EINVAL; - } - timing = &dsi_mode->timing; - - dsi_panel_get_dfps_caps(display->panel, &dfps_caps); - if (!dfps_caps.dfps_support) { - pr_err("dfps not supported\n"); - return -ENOTSUPP; - } - - if (dfps_caps.type == DSI_DFPS_IMMEDIATE_CLK) { - pr_err("dfps clock method not supported\n"); - return -ENOTSUPP; - } - - /* For split DSI, update the clock master first */ - - pr_debug("configuring seamless dynamic fps\n\n"); - - m_ctrl = &display->ctrl[display->clk_master_idx]; - rc = dsi_ctrl_async_timing_update(m_ctrl->ctrl, timing); - if (rc) { - pr_err("[%s] failed to dfps update host_%d, rc=%d\n", - display->name, i, rc); - goto error; - } - - /* Update the rest of the controllers */ - for (i = 0; i < display->ctrl_count; i++) { - ctrl = &display->ctrl[i]; - if (!ctrl->ctrl || (ctrl == m_ctrl)) - continue; - - rc = dsi_ctrl_async_timing_update(ctrl->ctrl, timing); - if (rc) { - pr_err("[%s] failed to dfps update host_%d, rc=%d\n", - display->name, i, rc); - goto error; - } - } - - panel_mode = display->panel->cur_mode; - memcpy(panel_mode, dsi_mode, sizeof(*panel_mode)); - /* - * dsi_mode_flags flags are used to communicate with other drm driver - * components, and are transient. They aren't inherently part of the - * display panel's mode and shouldn't be saved into the cached currently - * active mode. - */ - panel_mode->dsi_mode_flags = 0; - -error: - return rc; -} - -static int dsi_display_dfps_calc_front_porch( - u32 old_fps, - u32 new_fps, - u32 a_total, - u32 b_total, - u32 b_fp, - u32 *b_fp_out) -{ - s32 b_fp_new; - int add_porches, diff; - - if (!b_fp_out) { - pr_err("Invalid params"); - return -EINVAL; - } - - if (!a_total || !new_fps) { - pr_err("Invalid pixel total or new fps in mode request\n"); - return -EINVAL; - } - - /* - * Keep clock, other porches constant, use new fps, calc front porch - * new_vtotal = old_vtotal * (old_fps / new_fps ) - * new_vfp - old_vfp = new_vtotal - old_vtotal - * new_vfp = old_vfp + old_vtotal * ((old_fps - new_fps)/ new_fps) - */ - diff = abs(old_fps - new_fps); - add_porches = mult_frac(b_total, diff, new_fps); - - if (old_fps > new_fps) - b_fp_new = b_fp + add_porches; - else - b_fp_new = b_fp - add_porches; - - pr_debug("fps %u a %u b %u b_fp %u new_fp %d\n", - new_fps, a_total, b_total, b_fp, b_fp_new); - - if (b_fp_new < 0) { - pr_err("Invalid new_hfp calcluated%d\n", b_fp_new); - return -EINVAL; - } - - /** - * TODO: To differentiate from clock method when communicating to the - * other components, perhaps we should set clk here to original value - */ - *b_fp_out = b_fp_new; - - return 0; -} - -/** - * dsi_display_get_dfps_timing() - Get the new dfps values. - * @display: DSI display handle. - * @adj_mode: Mode value structure to be changed. - * It contains old timing values and latest fps value. - * New timing values are updated based on new fps. - * @curr_refresh_rate: Current fps rate. - * If zero , current fps rate is taken from - * display->panel->cur_mode. - * Return: error code. - */ -static int dsi_display_get_dfps_timing(struct dsi_display *display, - struct dsi_display_mode *adj_mode, - u32 curr_refresh_rate) -{ - struct dsi_dfps_capabilities dfps_caps; - struct dsi_display_mode per_ctrl_mode; - struct dsi_mode_info *timing; - struct dsi_ctrl *m_ctrl; - - int rc = 0; - - if (!display || !adj_mode) { - pr_err("Invalid params\n"); - return -EINVAL; - } - m_ctrl = display->ctrl[display->clk_master_idx].ctrl; - - dsi_panel_get_dfps_caps(display->panel, &dfps_caps); - if (!dfps_caps.dfps_support) { - pr_err("dfps not supported by panel\n"); - return -EINVAL; - } - - per_ctrl_mode = *adj_mode; - adjust_timing_by_ctrl_count(display, &per_ctrl_mode); - - if (!curr_refresh_rate) { - if (!dsi_display_is_seamless_dfps_possible(display, - &per_ctrl_mode, dfps_caps.type)) { - pr_err("seamless dynamic fps not supported for mode\n"); - return -EINVAL; - } - if (display->panel->cur_mode) { - curr_refresh_rate = - display->panel->cur_mode->timing.refresh_rate; - } else { - pr_err("cur_mode is not initialized\n"); - return -EINVAL; - } - } - /* TODO: Remove this direct reference to the dsi_ctrl */ - timing = &per_ctrl_mode.timing; - - switch (dfps_caps.type) { - case DSI_DFPS_IMMEDIATE_VFP: - rc = dsi_display_dfps_calc_front_porch( - curr_refresh_rate, - timing->refresh_rate, - DSI_H_TOTAL(timing), - DSI_V_TOTAL(timing), - timing->v_front_porch, - &adj_mode->timing.v_front_porch); - break; - - case DSI_DFPS_IMMEDIATE_HFP: - rc = dsi_display_dfps_calc_front_porch( - curr_refresh_rate, - timing->refresh_rate, - DSI_V_TOTAL(timing), - DSI_H_TOTAL(timing), - timing->h_front_porch, - &adj_mode->timing.h_front_porch); - if (!rc) - adj_mode->timing.h_front_porch *= display->ctrl_count; - break; - - default: - pr_err("Unsupported DFPS mode %d\n", dfps_caps.type); - rc = -ENOTSUPP; - } - - return rc; -} - -static bool dsi_display_validate_mode_seamless(struct dsi_display *display, - struct dsi_display_mode *adj_mode) -{ - int rc = 0; - - if (!display || !adj_mode) { - pr_err("Invalid params\n"); - return false; - } - - /* Currently the only seamless transition is dynamic fps */ - rc = dsi_display_get_dfps_timing(display, adj_mode, 0); - if (rc) { - pr_debug("Dynamic FPS not supported for seamless\n"); - } else { - pr_debug("Mode switch is seamless Dynamic FPS\n"); - adj_mode->dsi_mode_flags |= DSI_MODE_FLAG_DFPS | - DSI_MODE_FLAG_VBLANK_PRE_MODESET; - } - - return rc; -} - -static int dsi_display_set_mode_sub(struct dsi_display *display, - struct dsi_display_mode *mode, - u32 flags) -{ - int rc = 0; - int i; - struct dsi_display_ctrl *ctrl; - struct dsi_display_mode_priv_info *priv_info; - - priv_info = mode->priv_info; - if (!priv_info) { - pr_err("[%s] failed to get private info of the display mode", - display->name); - return -EINVAL; - } - - rc = dsi_panel_get_host_cfg_for_mode(display->panel, - mode, - &display->config); - if (rc) { - pr_err("[%s] failed to get host config for mode, rc=%d\n", - display->name, rc); - goto error; - } - - memcpy(&display->config.lane_map, &display->lane_map, - sizeof(display->lane_map)); - - if (mode->dsi_mode_flags & - (DSI_MODE_FLAG_DFPS | DSI_MODE_FLAG_VRR)) { - rc = dsi_display_dfps_update(display, mode); - if (rc) { - pr_err("[%s]DSI dfps update failed, rc=%d\n", - display->name, rc); - goto error; - } - } - - for (i = 0; i < display->ctrl_count; i++) { - ctrl = &display->ctrl[i]; - rc = dsi_ctrl_update_host_config(ctrl->ctrl, &display->config, - mode->dsi_mode_flags, display->dsi_clk_handle); - if (rc) { - pr_err("[%s] failed to update ctrl config, rc=%d\n", - display->name, rc); - goto error; - } - } - - if (priv_info->phy_timing_len) { - for (i = 0; i < display->ctrl_count; i++) { - ctrl = &display->ctrl[i]; - rc = dsi_phy_set_timing_params(ctrl->phy, - priv_info->phy_timing_val, - priv_info->phy_timing_len); - if (rc) - pr_err("failed to add DSI PHY timing params"); - } - } -error: - return rc; -} - -/** - * _dsi_display_dev_init - initializes the display device - * Initialization will acquire references to the resources required for the - * display hardware to function. - * @display: Handle to the display - * Returns: Zero on success - */ -static int _dsi_display_dev_init(struct dsi_display *display) -{ - int rc = 0; - - if (!display) { - pr_err("invalid display\n"); - return -EINVAL; - } - - mutex_lock(&display->display_lock); - - rc = dsi_display_parse_dt(display); - if (rc) { - pr_err("[%s] failed to parse dt, rc=%d\n", display->name, rc); - goto error; - } - - rc = dsi_display_res_init(display); - if (rc) { - pr_err("[%s] failed to initialize resources, rc=%d\n", - display->name, rc); - goto error; - } -error: - mutex_unlock(&display->display_lock); - return rc; -} - -/** - * _dsi_display_dev_deinit - deinitializes the display device - * All the resources acquired during device init will be released. - * @display: Handle to the display - * Returns: Zero on success - */ -static int _dsi_display_dev_deinit(struct dsi_display *display) -{ - int rc = 0; - - if (!display) { - pr_err("invalid display\n"); - return -EINVAL; - } - - mutex_lock(&display->display_lock); - - rc = dsi_display_res_deinit(display); - if (rc) - pr_err("[%s] failed to deinitialize resource, rc=%d\n", - display->name, rc); - - mutex_unlock(&display->display_lock); - - return rc; -} - -/** - * dsi_display_bind - bind dsi device with controlling device - * @dev: Pointer to base of platform device - * @master: Pointer to container of drm device - * @data: Pointer to private data - * Returns: Zero on success - */ -static int dsi_display_bind(struct device *dev, - struct device *master, - void *data) -{ - struct dsi_display_ctrl *display_ctrl; - struct drm_device *drm; - struct dsi_display *display; - struct dsi_clk_info info; - struct clk_ctrl_cb clk_cb; - struct msm_drm_private *priv; - void *handle = NULL; - struct platform_device *pdev = to_platform_device(dev); - char *client1 = "dsi_clk_client"; - char *client2 = "mdp_event_client"; - char dsi_client_name[DSI_CLIENT_NAME_SIZE]; - int i, rc = 0; - - if (!dev || !pdev || !master) { - pr_err("invalid param(s), dev %pK, pdev %pK, master %pK\n", - dev, pdev, master); - return -EINVAL; - } - - drm = dev_get_drvdata(master); - display = platform_get_drvdata(pdev); - if (!drm || !display) { - pr_err("invalid param(s), drm %pK, display %pK\n", - drm, display); - return -EINVAL; - } - priv = drm->dev_private; - - mutex_lock(&display->display_lock); - - rc = dsi_display_debugfs_init(display); - if (rc) { - pr_err("[%s] debugfs init failed, rc=%d\n", display->name, rc); - goto error; - } - - memset(&info, 0x0, sizeof(info)); - - for (i = 0; i < display->ctrl_count; i++) { - display_ctrl = &display->ctrl[i]; - rc = dsi_ctrl_drv_init(display_ctrl->ctrl, display->root); - if (rc) { - pr_err("[%s] failed to initialize ctrl[%d], rc=%d\n", - display->name, i, rc); - goto error_ctrl_deinit; - } - display_ctrl->ctrl->horiz_index = i; - - rc = dsi_phy_drv_init(display_ctrl->phy); - if (rc) { - pr_err("[%s] Failed to initialize phy[%d], rc=%d\n", - display->name, i, rc); - (void)dsi_ctrl_drv_deinit(display_ctrl->ctrl); - goto error_ctrl_deinit; - } - - memcpy(&info.c_clks[i], &display_ctrl->ctrl->clk_info.core_clks, - sizeof(struct dsi_core_clk_info)); - memcpy(&info.l_clks[i], &display_ctrl->ctrl->clk_info.link_clks, - sizeof(struct dsi_link_clk_info)); - info.c_clks[i].phandle = &priv->phandle; - info.bus_handle[i] = - display_ctrl->ctrl->axi_bus_info.bus_handle; - info.ctrl_index[i] = display_ctrl->ctrl->cell_index; - snprintf(dsi_client_name, DSI_CLIENT_NAME_SIZE, - "dsi_core_client%u", i); - info.c_clks[i].dsi_core_client = dpu_power_client_create( - info.c_clks[i].phandle, dsi_client_name); - if (IS_ERR_OR_NULL(info.c_clks[i].dsi_core_client)) { - pr_err("[%s] client creation failed for ctrl[%d]", - dsi_client_name, i); - goto error_ctrl_deinit; - } - } - - info.pre_clkoff_cb = dsi_pre_clkoff_cb; - info.pre_clkon_cb = dsi_pre_clkon_cb; - info.post_clkoff_cb = dsi_post_clkoff_cb; - info.post_clkon_cb = dsi_post_clkon_cb; - info.priv_data = display; - info.master_ndx = display->clk_master_idx; - info.dsi_ctrl_count = display->ctrl_count; - snprintf(info.name, MAX_STRING_LEN, - "DSI_MNGR-%s", display->name); - - display->clk_mngr = dsi_display_clk_mngr_register(&info); - if (IS_ERR_OR_NULL(display->clk_mngr)) { - rc = PTR_ERR(display->clk_mngr); - display->clk_mngr = NULL; - pr_err("dsi clock registration failed, rc = %d\n", rc); - goto error_ctrl_deinit; - } - - handle = dsi_register_clk_handle(display->clk_mngr, client1); - if (IS_ERR_OR_NULL(handle)) { - rc = PTR_ERR(handle); - pr_err("failed to register %s client, rc = %d\n", - client1, rc); - goto error_clk_deinit; - } else { - display->dsi_clk_handle = handle; - } - - handle = dsi_register_clk_handle(display->clk_mngr, client2); - if (IS_ERR_OR_NULL(handle)) { - rc = PTR_ERR(handle); - pr_err("failed to register %s client, rc = %d\n", - client2, rc); - goto error_clk_client_deinit; - } else { - display->mdp_clk_handle = handle; - } - - clk_cb.priv = display; - clk_cb.dsi_clk_cb = dsi_display_clk_ctrl_cb; - - for (i = 0; i < display->ctrl_count; i++) { - display_ctrl = &display->ctrl[i]; - - rc = dsi_ctrl_clk_cb_register(display_ctrl->ctrl, &clk_cb); - if (rc) { - pr_err("[%s] failed to register ctrl clk_cb[%d], rc=%d\n", - display->name, i, rc); - goto error_ctrl_deinit; - } - - rc = dsi_phy_clk_cb_register(display_ctrl->phy, &clk_cb); - if (rc) { - pr_err("[%s] failed to register phy clk_cb[%d], rc=%d\n", - display->name, i, rc); - goto error_ctrl_deinit; - } - } - - rc = dsi_display_mipi_host_init(display); - if (rc) { - pr_err("[%s] failed to initialize mipi host, rc=%d\n", - display->name, rc); - goto error_ctrl_deinit; - } - - rc = dsi_panel_drv_init(display->panel, &display->host); - if (rc) { - if (rc != -EPROBE_DEFER) - pr_err("[%s] failed to initialize panel driver, rc=%d\n", - display->name, rc); - goto error_host_deinit; - } - - pr_info("Successfully bind display panel '%s'\n", display->name); - display->drm_dev = drm; - goto error; - -error_host_deinit: - (void)dsi_display_mipi_host_deinit(display); -error_clk_client_deinit: - (void)dsi_deregister_clk_handle(display->dsi_clk_handle); -error_clk_deinit: - (void)dsi_display_clk_mngr_deregister(display->clk_mngr); -error_ctrl_deinit: - for (i = i - 1; i >= 0; i--) { - display_ctrl = &display->ctrl[i]; - (void)dsi_phy_drv_deinit(display_ctrl->phy); - (void)dsi_ctrl_drv_deinit(display_ctrl->ctrl); - } - (void)dsi_display_debugfs_deinit(display); -error: - mutex_unlock(&display->display_lock); - return rc; -} - -/** - * dsi_display_unbind - unbind dsi from controlling device - * @dev: Pointer to base of platform device - * @master: Pointer to container of drm device - * @data: Pointer to private data - */ -static void dsi_display_unbind(struct device *dev, - struct device *master, void *data) -{ - struct dsi_display_ctrl *display_ctrl; - struct dsi_display *display; - struct platform_device *pdev = to_platform_device(dev); - int i, rc = 0; - - if (!dev || !pdev) { - pr_err("invalid param(s)\n"); - return; - } - - display = platform_get_drvdata(pdev); - if (!display) { - pr_err("invalid display\n"); - return; - } - - mutex_lock(&display->display_lock); - - rc = dsi_panel_drv_deinit(display->panel); - if (rc) - pr_err("[%s] failed to deinit panel driver, rc=%d\n", - display->name, rc); - - rc = dsi_display_mipi_host_deinit(display); - if (rc) - pr_err("[%s] failed to deinit mipi hosts, rc=%d\n", - display->name, - rc); - - for (i = 0; i < display->ctrl_count; i++) { - display_ctrl = &display->ctrl[i]; - - rc = dsi_phy_drv_deinit(display_ctrl->phy); - if (rc) - pr_err("[%s] failed to deinit phy%d driver, rc=%d\n", - display->name, i, rc); - - rc = dsi_ctrl_drv_deinit(display_ctrl->ctrl); - if (rc) - pr_err("[%s] failed to deinit ctrl%d driver, rc=%d\n", - display->name, i, rc); - } - (void)dsi_display_debugfs_deinit(display); - - mutex_unlock(&display->display_lock); -} - -static const struct component_ops dsi_display_comp_ops = { - .bind = dsi_display_bind, - .unbind = dsi_display_unbind, -}; - -static struct platform_driver dsi_display_driver = { - .probe = dsi_display_dev_probe, - .remove = dsi_display_dev_remove, - .driver = { - .name = "msm-dsi-display", - .of_match_table = dsi_display_dt_match, - }, -}; - -int dsi_display_dev_probe(struct platform_device *pdev) -{ - int rc = 0; - struct dsi_display *display; - static bool display_from_cmdline, boot_displays_parsed; - static bool comp_add_success; - static struct device_node *primary_np, *secondary_np; - - if (!pdev || !pdev->dev.of_node) { - pr_err("pdev not found\n"); - return -ENODEV; - } - - display = devm_kzalloc(&pdev->dev, sizeof(*display), GFP_KERNEL); - if (!display) - return -ENOMEM; - - display->name = of_get_property(pdev->dev.of_node, "label", NULL); - - if (!boot_displays_parsed) { - boot_displays[DSI_PRIMARY].boot_disp_en = false; - boot_displays[DSI_SECONDARY].boot_disp_en = false; - if (dsi_display_parse_boot_display_selection()) - pr_debug("Display Boot param not valid/available\n"); - - boot_displays_parsed = true; - } - - /* use default topology of every mode if not overridden */ - display->cmdline_topology = NO_OVERRIDE; - display->cmdline_timing = 0; - - if ((!display_from_cmdline) && - (boot_displays[DSI_PRIMARY].boot_disp_en)) { - display->is_active = dsi_display_name_compare(pdev->dev.of_node, - display->name, DSI_PRIMARY); - if (display->is_active) { - if (comp_add_success) { - (void)_dsi_display_dev_deinit(main_display); - component_del(&main_display->pdev->dev, - &dsi_display_comp_ops); - mutex_lock(&dsi_display_list_lock); - list_del(&main_display->list); - mutex_unlock(&dsi_display_list_lock); - comp_add_success = false; - default_active_node = NULL; - pr_debug("removed the existing comp ops\n"); - } - /* - * Need to add component for - * the secondary DSI display - * when more than one DSI display - * is supported. - */ - pr_debug("cmdline primary dsi: %s\n", - display->name); - display_from_cmdline = true; - dsi_display_parse_cmdline_topology(display, - DSI_PRIMARY); - primary_np = pdev->dev.of_node; - } - } - - if (boot_displays[DSI_SECONDARY].boot_disp_en - && !secondary_np - && dsi_display_name_compare(pdev->dev.of_node, - display->name, DSI_SECONDARY)) { - pr_debug("cmdline secondary dsi: %s\n", - display->name); - secondary_np = pdev->dev.of_node; - if (primary_np) { - if (validate_dsi_display_selection()) { - display->is_active = true; - dsi_display_parse_cmdline_topology( - display, DSI_SECONDARY); - } else { - boot_displays[DSI_SECONDARY] - .boot_disp_en = false; - } - } - } - display->display_type = of_get_property(pdev->dev.of_node, - "qcom,display-type", NULL); - if (!display->display_type) - display->display_type = "unknown"; - - mutex_init(&display->display_lock); - display->pdev = pdev; - platform_set_drvdata(pdev, display); - mutex_lock(&dsi_display_list_lock); - list_add(&display->list, &dsi_display_list); - mutex_unlock(&dsi_display_list_lock); - - if (!display_from_cmdline) - display->is_active = of_property_read_bool(pdev->dev.of_node, - "qcom,dsi-display-active"); - - if (display->is_active) { - main_display = display; - rc = _dsi_display_dev_init(display); - if (rc) { - pr_err("device init failed, rc=%d\n", rc); - return rc; - } - - rc = component_add(&pdev->dev, &dsi_display_comp_ops); - if (rc) - pr_err("component add failed, rc=%d\n", rc); - - comp_add_success = true; - pr_debug("Component_add success: %s\n", display->name); - if (!display_from_cmdline) - default_active_node = pdev->dev.of_node; - } - return rc; -} - -int dsi_display_dev_remove(struct platform_device *pdev) -{ - int rc = 0; - struct dsi_display *display; - struct dsi_display *pos, *tmp; - - if (!pdev) { - pr_err("Invalid device\n"); - return -EINVAL; - } - - display = platform_get_drvdata(pdev); - - (void)_dsi_display_dev_deinit(display); - - mutex_lock(&dsi_display_list_lock); - list_for_each_entry_safe(pos, tmp, &dsi_display_list, list) { - if (pos == display) { - list_del(&display->list); - break; - } - } - mutex_unlock(&dsi_display_list_lock); - - platform_set_drvdata(pdev, NULL); - devm_kfree(&pdev->dev, display); - return rc; -} - -int dsi_display_get_num_of_displays(void) -{ - int count = 0; - struct dsi_display *display; - - mutex_lock(&dsi_display_list_lock); - - list_for_each_entry(display, &dsi_display_list, list) { - count++; - } - - mutex_unlock(&dsi_display_list_lock); - return count; -} - -int dsi_display_get_active_displays(void **display_array, u32 max_display_count) -{ - struct dsi_display *pos; - int i = 0; - - if (!display_array || !max_display_count) { - if (!display_array) - pr_err("invalid params\n"); - return 0; - } - - mutex_lock(&dsi_display_list_lock); - - list_for_each_entry(pos, &dsi_display_list, list) { - if (i >= max_display_count) { - pr_err("capping display count to %d\n", i); - break; - } - if (pos->is_active) - display_array[i++] = pos; - } - - mutex_unlock(&dsi_display_list_lock); - return i; -} - -struct dsi_display *dsi_display_get_display_by_name(const char *name) -{ - struct dsi_display *display = NULL, *pos; - - mutex_lock(&dsi_display_list_lock); - - list_for_each_entry(pos, &dsi_display_list, list) { - if (!strcmp(name, pos->name)) - display = pos; - } - - mutex_unlock(&dsi_display_list_lock); - - return display; -} - -void dsi_display_set_active_state(struct dsi_display *display, bool is_active) -{ - mutex_lock(&display->display_lock); - display->is_active = is_active; - mutex_unlock(&display->display_lock); -} - -int dsi_display_drm_bridge_init(struct dsi_display *display, - struct drm_encoder *enc) -{ - int rc = 0; - struct dsi_bridge *bridge; - struct msm_drm_private *priv = NULL; - - if (!display || !display->drm_dev || !enc) { - pr_err("invalid param(s)\n"); - return -EINVAL; - } - - mutex_lock(&display->display_lock); - priv = display->drm_dev->dev_private; - - if (!priv) { - pr_err("Private data is not present\n"); - rc = -EINVAL; - goto error; - } - - if (display->bridge) { - pr_err("display is already initialize\n"); - goto error; - } - - bridge = dsi_drm_bridge_init(display, display->drm_dev, enc); - if (IS_ERR_OR_NULL(bridge)) { - rc = PTR_ERR(bridge); - pr_err("[%s] brige init failed, %d\n", display->name, rc); - goto error; - } - - display->bridge = bridge; - priv->bridges[priv->num_bridges++] = &bridge->base; - -error: - mutex_unlock(&display->display_lock); - return rc; -} - -int dsi_display_drm_bridge_deinit(struct dsi_display *display) -{ - int rc = 0; - - if (!display) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - mutex_lock(&display->display_lock); - - dsi_drm_bridge_cleanup(display->bridge); - display->bridge = NULL; - - mutex_unlock(&display->display_lock); - return rc; -} - -int dsi_display_get_info(struct msm_display_info *info, void *disp) -{ - struct dsi_display *display; - struct dsi_panel_phy_props phy_props; - int i, rc; - - if (!info || !disp) { - pr_err("invalid params\n"); - return -EINVAL; - } - - display = disp; - if (!display->panel) { - pr_err("invalid display panel\n"); - return -EINVAL; - } - - mutex_lock(&display->display_lock); - rc = dsi_panel_get_phy_props(display->panel, &phy_props); - if (rc) { - pr_err("[%s] failed to get panel phy props, rc=%d\n", - display->name, rc); - goto error; - } - - memset(info, 0, sizeof(struct msm_display_info)); - info->intf_type = DRM_MODE_CONNECTOR_DSI; - info->num_of_h_tiles = display->ctrl_count; - for (i = 0; i < info->num_of_h_tiles; i++) - info->h_tile_instance[i] = display->ctrl[i].ctrl->cell_index; - - info->is_connected = true; - info->is_primary = true; - info->width_mm = phy_props.panel_width_mm; - info->height_mm = phy_props.panel_height_mm; - info->max_width = 1920; - info->max_height = 1080; - - switch (display->panel->panel_mode) { - case DSI_OP_VIDEO_MODE: - info->capabilities |= MSM_DISPLAY_CAP_VID_MODE; - break; - case DSI_OP_CMD_MODE: - info->capabilities |= MSM_DISPLAY_CAP_CMD_MODE; - info->is_te_using_watchdog_timer = - display->panel->te_using_watchdog_timer; - break; - default: - pr_err("unknwown dsi panel mode %d\n", - display->panel->panel_mode); - break; - } - -error: - mutex_unlock(&display->display_lock); - return rc; -} - -int dsi_display_get_mode_count(struct dsi_display *display, - u32 *count) -{ - struct dsi_dfps_capabilities dfps_caps; - int num_dfps_rates, rc = 0; - - if (!display || !display->panel) { - pr_err("invalid display:%d panel:%d\n", display != NULL, - display ? display->panel != NULL : 0); - return -EINVAL; - } - - mutex_lock(&display->display_lock); - - *count = display->panel->num_timing_nodes; - - rc = dsi_panel_get_dfps_caps(display->panel, &dfps_caps); - if (rc) { - pr_err("[%s] failed to get dfps caps from panel\n", - display->name); - goto done; - } - - num_dfps_rates = !dfps_caps.dfps_support ? 1 : - dfps_caps.max_refresh_rate - - dfps_caps.min_refresh_rate + 1; - - /* Inflate num_of_modes by fps in dfps */ - *count = display->panel->num_timing_nodes * num_dfps_rates; - -done: - mutex_unlock(&display->display_lock); - - return 0; -} - -void dsi_display_put_mode(struct dsi_display *display, - struct dsi_display_mode *mode) -{ - dsi_panel_put_mode(mode); -} - -int dsi_display_get_modes(struct dsi_display *display, - struct dsi_display_mode *modes) -{ - struct dsi_dfps_capabilities dfps_caps; - u32 num_dfps_rates, panel_mode_count; - u32 mode_idx, array_idx = 0; - int i, rc = 0; - - if (!display || !modes) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - mutex_lock(&display->display_lock); - - rc = dsi_panel_get_dfps_caps(display->panel, &dfps_caps); - if (rc) { - pr_err("[%s] failed to get dfps caps from panel\n", - display->name); - goto error; - } - - num_dfps_rates = !dfps_caps.dfps_support ? 1 : - dfps_caps.max_refresh_rate - - dfps_caps.min_refresh_rate + 1; - - panel_mode_count = display->panel->num_timing_nodes; - - for (mode_idx = 0; mode_idx < panel_mode_count; mode_idx++) { - struct dsi_display_mode panel_mode; - int topology_override = NO_OVERRIDE; - - if (display->cmdline_timing == mode_idx) - topology_override = display->cmdline_topology; - - memset(&panel_mode, 0, sizeof(panel_mode)); - - rc = dsi_panel_get_mode(display->panel, mode_idx, - &panel_mode, topology_override); - if (rc) { - pr_err("[%s] failed to get mode idx %d from panel\n", - display->name, mode_idx); - goto error; - } - - if (display->ctrl_count > 1) { /* TODO: remove if */ - panel_mode.timing.h_active *= display->ctrl_count; - panel_mode.timing.h_front_porch *= display->ctrl_count; - panel_mode.timing.h_sync_width *= display->ctrl_count; - panel_mode.timing.h_back_porch *= display->ctrl_count; - panel_mode.timing.h_skew *= display->ctrl_count; - panel_mode.pixel_clk_khz *= display->ctrl_count; - } - - for (i = 0; i < num_dfps_rates; i++) { - struct dsi_display_mode *sub_mode = &modes[array_idx]; - u32 curr_refresh_rate; - - if (!sub_mode) { - pr_err("invalid mode data\n"); - return -EFAULT; - } - - memcpy(sub_mode, &panel_mode, sizeof(panel_mode)); - - if (dfps_caps.dfps_support) { - curr_refresh_rate = - sub_mode->timing.refresh_rate; - sub_mode->timing.refresh_rate = - dfps_caps.min_refresh_rate + - (i % num_dfps_rates); - - dsi_display_get_dfps_timing(display, - sub_mode, curr_refresh_rate); - - sub_mode->pixel_clk_khz = - (DSI_H_TOTAL(&sub_mode->timing) * - DSI_V_TOTAL(&sub_mode->timing) * - sub_mode->timing.refresh_rate) / 1000; - } - array_idx++; - } - } - -error: - mutex_unlock(&display->display_lock); - return rc; -} - -/** - * dsi_display_validate_mode_vrr() - Validate if varaible refresh case. - * @display: DSI display handle. - * @cur_dsi_mode: Current DSI mode. - * @mode: Mode value structure to be validated. - * MSM_MODE_FLAG_SEAMLESS_VRR flag is set if there - * is change in fps but vactive and hactive are same. - * Return: error code. - */ -int dsi_display_validate_mode_vrr(struct dsi_display *display, - struct dsi_display_mode *cur_dsi_mode, - struct dsi_display_mode *mode) -{ - int rc = 0; - struct dsi_display_mode adj_mode, cur_mode; - struct dsi_dfps_capabilities dfps_caps; - u32 curr_refresh_rate; - - if (!display || !mode) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - if (!display->panel || !display->panel->cur_mode) { - pr_debug("Current panel mode not set\n"); - return rc; - } - - mutex_lock(&display->display_lock); - - adj_mode = *mode; - cur_mode = *cur_dsi_mode; - - if ((cur_mode.timing.refresh_rate != adj_mode.timing.refresh_rate) && - (cur_mode.timing.v_active == adj_mode.timing.v_active) && - (cur_mode.timing.h_active == adj_mode.timing.h_active)) { - - curr_refresh_rate = cur_mode.timing.refresh_rate; - rc = dsi_panel_get_dfps_caps(display->panel, &dfps_caps); - if (rc) { - pr_err("[%s] failed to get dfps caps from panel\n", - display->name); - goto error; - } - - cur_mode.timing.refresh_rate = - adj_mode.timing.refresh_rate; - - rc = dsi_display_get_dfps_timing(display, - &cur_mode, curr_refresh_rate); - if (rc) { - pr_err("[%s] seamless vrr not possible rc=%d\n", - display->name, rc); - goto error; - } - switch (dfps_caps.type) { - /* - * Ignore any round off factors in porch calculation. - * Worse case is set to 5. - */ - case DSI_DFPS_IMMEDIATE_VFP: - if (abs(DSI_V_TOTAL(&cur_mode.timing) - - DSI_V_TOTAL(&adj_mode.timing)) > 5) - pr_err("Mismatch vfp fps:%d new:%d given:%d\n", - adj_mode.timing.refresh_rate, - cur_mode.timing.v_front_porch, - adj_mode.timing.v_front_porch); - break; - - case DSI_DFPS_IMMEDIATE_HFP: - if (abs(DSI_H_TOTAL(&cur_mode.timing) - - DSI_H_TOTAL(&adj_mode.timing)) > 5) - pr_err("Mismatch hfp fps:%d new:%d given:%d\n", - adj_mode.timing.refresh_rate, - cur_mode.timing.h_front_porch, - adj_mode.timing.h_front_porch); - break; - - default: - pr_err("Unsupported DFPS mode %d\n", - dfps_caps.type); - rc = -ENOTSUPP; - } - - pr_debug("Mode switch is seamless variable refresh\n"); - mode->dsi_mode_flags |= DSI_MODE_FLAG_VRR; - DPU_EVT32(curr_refresh_rate, adj_mode.timing.refresh_rate, - cur_mode.timing.h_front_porch, - adj_mode.timing.h_front_porch); - } - -error: - mutex_unlock(&display->display_lock); - return rc; -} - -int dsi_display_validate_mode(struct dsi_display *display, - struct dsi_display_mode *mode, - u32 flags) -{ - int rc = 0; - int i; - struct dsi_display_ctrl *ctrl; - struct dsi_display_mode adj_mode; - - if (!display || !mode) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - mutex_lock(&display->display_lock); - - adj_mode = *mode; - adjust_timing_by_ctrl_count(display, &adj_mode); - - rc = dsi_panel_validate_mode(display->panel, &adj_mode); - if (rc) { - pr_err("[%s] panel mode validation failed, rc=%d\n", - display->name, rc); - goto error; - } - - for (i = 0; i < display->ctrl_count; i++) { - ctrl = &display->ctrl[i]; - rc = dsi_ctrl_validate_timing(ctrl->ctrl, &adj_mode.timing); - if (rc) { - pr_err("[%s] ctrl mode validation failed, rc=%d\n", - display->name, rc); - goto error; - } - - rc = dsi_phy_validate_mode(ctrl->phy, &adj_mode.timing); - if (rc) { - pr_err("[%s] phy mode validation failed, rc=%d\n", - display->name, rc); - goto error; - } - } - - if ((flags & DSI_VALIDATE_FLAG_ALLOW_ADJUST) && - (mode->dsi_mode_flags & DSI_MODE_FLAG_SEAMLESS)) { - rc = dsi_display_validate_mode_seamless(display, mode); - if (rc) { - pr_err("[%s] seamless not possible rc=%d\n", - display->name, rc); - goto error; - } - } - -error: - mutex_unlock(&display->display_lock); - return rc; -} - -int dsi_display_set_mode(struct dsi_display *display, - struct dsi_display_mode *mode, - u32 flags) -{ - int rc = 0; - struct dsi_display_mode adj_mode; - - if (!display || !mode || !display->panel) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - mutex_lock(&display->display_lock); - - adj_mode = *mode; - adjust_timing_by_ctrl_count(display, &adj_mode); - - rc = dsi_display_validate_mode_set(display, &adj_mode, flags); - if (rc) { - pr_err("[%s] mode cannot be set\n", display->name); - goto error; - } - - rc = dsi_display_set_mode_sub(display, &adj_mode, flags); - if (rc) { - pr_err("[%s] failed to set mode\n", display->name); - goto error; - } - - if (!display->panel->cur_mode) { - display->panel->cur_mode = - kzalloc(sizeof(struct dsi_display_mode), GFP_KERNEL); - if (!display->panel->cur_mode) { - rc = -ENOMEM; - goto error; - } - } - - memcpy(display->panel->cur_mode, &adj_mode, sizeof(adj_mode)); -error: - mutex_unlock(&display->display_lock); - return rc; -} - -int dsi_display_set_tpg_state(struct dsi_display *display, bool enable) -{ - int rc = 0; - int i; - struct dsi_display_ctrl *ctrl; - - if (!display) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - for (i = 0; i < display->ctrl_count; i++) { - ctrl = &display->ctrl[i]; - rc = dsi_ctrl_set_tpg_state(ctrl->ctrl, enable); - if (rc) { - pr_err("[%s] failed to set tpg state for host_%d\n", - display->name, i); - goto error; - } - } - - display->is_tpg_enabled = enable; -error: - return rc; -} - -static int dsi_display_pre_switch(struct dsi_display *display) -{ - int rc = 0; - - rc = dsi_display_clk_ctrl(display->dsi_clk_handle, - DSI_CORE_CLK, DSI_CLK_ON); - if (rc) { - pr_err("[%s] failed to enable DSI core clocks, rc=%d\n", - display->name, rc); - goto error; - } - - rc = dsi_display_ctrl_update(display); - if (rc) { - pr_err("[%s] failed to update DSI controller, rc=%d\n", - display->name, rc); - goto error_ctrl_clk_off; - } - - rc = dsi_display_set_clk_src(display); - if (rc) { - pr_err("[%s] failed to set DSI link clock source, rc=%d\n", - display->name, rc); - goto error_ctrl_deinit; - } - - rc = dsi_display_clk_ctrl(display->dsi_clk_handle, - DSI_LINK_CLK, DSI_CLK_ON); - if (rc) { - pr_err("[%s] failed to enable DSI link clocks, rc=%d\n", - display->name, rc); - goto error_ctrl_deinit; - } - - goto error; - -error_ctrl_deinit: - (void)dsi_display_ctrl_deinit(display); -error_ctrl_clk_off: - (void)dsi_display_clk_ctrl(display->dsi_clk_handle, - DSI_CORE_CLK, DSI_CLK_OFF); -error: - return rc; -} - -int dsi_display_prepare(struct dsi_display *display) -{ - int rc = 0; - struct dsi_display_mode *mode; - - if (!display) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - if (!display->panel->cur_mode) { - pr_err("no valid mode set for the display"); - return -EINVAL; - } - - mutex_lock(&display->display_lock); - - mode = display->panel->cur_mode; - - if (mode->dsi_mode_flags & DSI_MODE_FLAG_DMS) { - /* update dsi ctrl for new mode */ - rc = dsi_display_pre_switch(display); - if (rc) - pr_err("[%s] panel pre-prepare-res-switch failed, rc=%d\n", - display->name, rc); - - goto error; - } - - rc = dsi_panel_pre_prepare(display->panel); - if (rc) { - pr_err("[%s] panel pre-prepare failed, rc=%d\n", - display->name, rc); - goto error; - } - - rc = dsi_display_clk_ctrl(display->dsi_clk_handle, - DSI_CORE_CLK, DSI_CLK_ON); - if (rc) { - pr_err("[%s] failed to enable DSI core clocks, rc=%d\n", - display->name, rc); - goto error_panel_post_unprep; - } - - rc = dsi_display_phy_sw_reset(display); - if (rc) { - pr_err("[%s] failed to reset phy, rc=%d\n", display->name, rc); - goto error_ctrl_clk_off; - } - - rc = dsi_display_phy_enable(display); - if (rc) { - pr_err("[%s] failed to enable DSI PHY, rc=%d\n", - display->name, rc); - goto error_ctrl_clk_off; - } - - rc = dsi_display_set_clk_src(display); - if (rc) { - pr_err("[%s] failed to set DSI link clock source, rc=%d\n", - display->name, rc); - goto error_phy_disable; - } - - rc = dsi_display_ctrl_init(display); - if (rc) { - pr_err("[%s] failed to setup DSI controller, rc=%d\n", - display->name, rc); - goto error_phy_disable; - } - - rc = dsi_display_ctrl_host_enable(display); - if (rc) { - pr_err("[%s] failed to enable DSI host, rc=%d\n", - display->name, rc); - goto error_ctrl_deinit; - } - - rc = dsi_display_clk_ctrl(display->dsi_clk_handle, - DSI_LINK_CLK, DSI_CLK_ON); - if (rc) { - pr_err("[%s] failed to enable DSI link clocks, rc=%d\n", - display->name, rc); - goto error_host_engine_off; - } - - rc = dsi_display_soft_reset(display); - if (rc) { - pr_err("[%s] failed soft reset, rc=%d\n", display->name, rc); - goto error_ctrl_link_off; - } - - rc = dsi_panel_prepare(display->panel); - if (rc) { - pr_err("[%s] panel prepare failed, rc=%d\n", display->name, rc); - goto error_ctrl_link_off; - } - - goto error; - -error_ctrl_link_off: - (void)dsi_display_clk_ctrl(display->dsi_clk_handle, - DSI_LINK_CLK, DSI_CLK_OFF); -error_host_engine_off: - (void)dsi_display_ctrl_host_disable(display); -error_ctrl_deinit: - (void)dsi_display_ctrl_deinit(display); -error_phy_disable: - (void)dsi_display_phy_disable(display); -error_ctrl_clk_off: - (void)dsi_display_clk_ctrl(display->dsi_clk_handle, - DSI_CORE_CLK, DSI_CLK_OFF); -error_panel_post_unprep: - (void)dsi_panel_post_unprepare(display->panel); -error: - mutex_unlock(&display->display_lock); - return rc; -} - -int dsi_display_pre_kickoff(struct dsi_display *display) -{ - int rc = 0; - - /* check and setup MISR */ - if (display->misr_enable) - _dsi_display_setup_misr(display); - - return rc; -} - -int dsi_display_enable(struct dsi_display *display) -{ - int rc = 0; - struct dsi_display_mode *mode; - - if (!display || !display->panel) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - if (!display->panel->cur_mode) { - pr_err("no valid mode set for the display"); - return -EINVAL; - } - - mutex_lock(&display->display_lock); - - mode = display->panel->cur_mode; - - if (mode->dsi_mode_flags & DSI_MODE_FLAG_DMS) { - rc = dsi_panel_post_switch(display->panel); - if (rc) { - pr_err("[%s] failed to switch DSI panel mode, rc=%d\n", - display->name, rc); - goto error; - } - } else { - rc = dsi_panel_enable(display->panel); - if (rc) { - pr_err("[%s] failed to enable DSI panel, rc=%d\n", - display->name, rc); - goto error; - } - } - - if (mode->priv_info->dsc_enabled) { - mode->priv_info->dsc.pic_width *= display->ctrl_count; - rc = dsi_panel_update_pps(display->panel); - if (rc) { - pr_err("[%s] panel pps cmd update failed, rc=%d\n", - display->name, rc); - goto error; - } - } - - if (mode->dsi_mode_flags & DSI_MODE_FLAG_DMS) { - rc = dsi_panel_switch(display->panel); - if (rc) - pr_err("[%s] failed to switch DSI panel mode, rc=%d\n", - display->name, rc); - - goto error; - } - - if (display->config.panel_mode == DSI_OP_VIDEO_MODE) { - rc = dsi_display_vid_engine_enable(display); - if (rc) { - pr_err("[%s]failed to enable DSI video engine, rc=%d\n", - display->name, rc); - goto error_disable_panel; - } - } else if (display->config.panel_mode == DSI_OP_CMD_MODE) { - rc = dsi_display_cmd_engine_enable(display); - if (rc) { - pr_err("[%s]failed to enable DSI cmd engine, rc=%d\n", - display->name, rc); - goto error_disable_panel; - } - } else { - pr_err("[%s] Invalid configuration\n", display->name); - rc = -EINVAL; - goto error_disable_panel; - } - - goto error; - -error_disable_panel: - (void)dsi_panel_disable(display->panel); -error: - mutex_unlock(&display->display_lock); - return rc; -} - -int dsi_display_post_enable(struct dsi_display *display) -{ - int rc = 0; - - if (!display) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - mutex_lock(&display->display_lock); - - rc = dsi_panel_post_enable(display->panel); - if (rc) - pr_err("[%s] panel post-enable failed, rc=%d\n", - display->name, rc); - - /* remove the clk vote for CMD mode panels */ - if (display->config.panel_mode == DSI_OP_CMD_MODE) - dsi_display_clk_ctrl(display->dsi_clk_handle, - DSI_ALL_CLKS, DSI_CLK_OFF); - - mutex_unlock(&display->display_lock); - return rc; -} - -int dsi_display_pre_disable(struct dsi_display *display) -{ - int rc = 0; - - if (!display) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - mutex_lock(&display->display_lock); - - /* enable the clk vote for CMD mode panels */ - if (display->config.panel_mode == DSI_OP_CMD_MODE) - dsi_display_clk_ctrl(display->dsi_clk_handle, - DSI_ALL_CLKS, DSI_CLK_ON); - - rc = dsi_panel_pre_disable(display->panel); - if (rc) - pr_err("[%s] panel pre-disable failed, rc=%d\n", - display->name, rc); - - mutex_unlock(&display->display_lock); - return rc; -} - -int dsi_display_disable(struct dsi_display *display) -{ - int rc = 0; - - if (!display) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - mutex_lock(&display->display_lock); - - rc = dsi_display_wake_up(display); - if (rc) - pr_err("[%s] display wake up failed, rc=%d\n", - display->name, rc); - - if (display->config.panel_mode == DSI_OP_VIDEO_MODE) { - rc = dsi_display_vid_engine_disable(display); - if (rc) - pr_err("[%s]failed to disable DSI vid engine, rc=%d\n", - display->name, rc); - } else if (display->config.panel_mode == DSI_OP_CMD_MODE) { - rc = dsi_display_cmd_engine_disable(display); - if (rc) - pr_err("[%s]failed to disable DSI cmd engine, rc=%d\n", - display->name, rc); - } else { - pr_err("[%s] Invalid configuration\n", display->name); - rc = -EINVAL; - } - - rc = dsi_panel_disable(display->panel); - if (rc) - pr_err("[%s] failed to disable DSI panel, rc=%d\n", - display->name, rc); - - mutex_unlock(&display->display_lock); - return rc; -} - -int dsi_display_update_pps(char *pps_cmd, void *disp) -{ - struct dsi_display *display; - - if (pps_cmd == NULL || disp == NULL) { - pr_err("Invalid parameter\n"); - return -EINVAL; - } - - display = disp; - mutex_lock(&display->display_lock); - memcpy(display->panel->dsc_pps_cmd, pps_cmd, DSI_CMD_PPS_SIZE); - mutex_unlock(&display->display_lock); - - return 0; -} - -int dsi_display_unprepare(struct dsi_display *display) -{ - int rc = 0; - - if (!display) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - mutex_lock(&display->display_lock); - - rc = dsi_display_wake_up(display); - if (rc) - pr_err("[%s] display wake up failed, rc=%d\n", - display->name, rc); - - rc = dsi_panel_unprepare(display->panel); - if (rc) - pr_err("[%s] panel unprepare failed, rc=%d\n", - display->name, rc); - - rc = dsi_display_ctrl_host_disable(display); - if (rc) - pr_err("[%s] failed to disable DSI host, rc=%d\n", - display->name, rc); - - rc = dsi_display_clk_ctrl(display->dsi_clk_handle, - DSI_LINK_CLK, DSI_CLK_OFF); - if (rc) - pr_err("[%s] failed to disable Link clocks, rc=%d\n", - display->name, rc); - - rc = dsi_display_ctrl_deinit(display); - if (rc) - pr_err("[%s] failed to deinit controller, rc=%d\n", - display->name, rc); - - rc = dsi_display_phy_disable(display); - if (rc) - pr_err("[%s] failed to disable DSI PHY, rc=%d\n", - display->name, rc); - - rc = dsi_display_clk_ctrl(display->dsi_clk_handle, - DSI_CORE_CLK, DSI_CLK_OFF); - if (rc) - pr_err("[%s] failed to disable DSI clocks, rc=%d\n", - display->name, rc); - - rc = dsi_panel_post_unprepare(display->panel); - if (rc) - pr_err("[%s] panel post-unprepare failed, rc=%d\n", - display->name, rc); - - mutex_unlock(&display->display_lock); - return rc; -} - -static int __init dsi_display_register(void) -{ - dsi_phy_drv_register(); - dsi_ctrl_drv_register(); - return platform_driver_register(&dsi_display_driver); -} - -static void __exit dsi_display_unregister(void) -{ - platform_driver_unregister(&dsi_display_driver); - dsi_ctrl_drv_unregister(); - dsi_phy_drv_unregister(); -} -module_param_string(dsi_display0, dsi_display_primary, MAX_CMDLINE_PARAM_LEN, - 0600); -MODULE_PARM_DESC(dsi_display0, - "msm_drm.dsi_display0=<display node>:<configX> where <display node> is 'primary dsi display node name' and <configX> where x represents index in the topology list"); -module_param_string(dsi_display1, dsi_display_secondary, MAX_CMDLINE_PARAM_LEN, - 0600); -MODULE_PARM_DESC(dsi_display1, - "msm_drm.dsi_display1=<display node>:<configX> where <display node> is 'secondary dsi display node name' and <configX> where x represents index in the topology list"); -module_init(dsi_display_register); -module_exit(dsi_display_unregister); diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.h b/drivers/gpu/drm/msm/dsi-staging/dsi_display.h deleted file mode 100644 index a0f9ccf..0000000 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.h +++ /dev/null @@ -1,556 +0,0 @@ -/* - * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * 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 _DSI_DISPLAY_H_ -#define _DSI_DISPLAY_H_ - -#include <linux/types.h> -#include <linux/bitops.h> -#include <linux/debugfs.h> -#include <linux/of_device.h> -#include <drm/drmP.h> -#include <drm/drm_crtc.h> - -#include "msm_drv.h" -#include "dsi_defs.h" -#include "dsi_ctrl.h" -#include "dsi_phy.h" -#include "dsi_panel.h" - -#define MAX_DSI_CTRLS_PER_DISPLAY 2 -#define DSI_CLIENT_NAME_SIZE 20 -#define MAX_CMDLINE_PARAM_LEN 512 -/* - * DSI Validate Mode modifiers - * @DSI_VALIDATE_FLAG_ALLOW_ADJUST: Allow mode validation to also do fixup - */ -#define DSI_VALIDATE_FLAG_ALLOW_ADJUST 0x1 - -/** - * enum dsi_display_selection_type - enumerates DSI display selection types - * @DSI_PRIMARY: primary DSI display selected from module parameter - * @DSI_SECONDARY: Secondary DSI display selected from module parameter - * @MAX_DSI_ACTIVE_DISPLAY: Maximum acive displays that can be selected - */ -enum dsi_display_selection_type { - DSI_PRIMARY = 0, - DSI_SECONDARY, - MAX_DSI_ACTIVE_DISPLAY, -}; - -/** - * enum dsi_display_type - enumerates DSI display types - * @DSI_DISPLAY_SINGLE: A panel connected on a single DSI interface. - * @DSI_DISPLAY_EXT_BRIDGE: A bridge is connected between panel and DSI host. - * It utilizes a single DSI interface. - * @DSI_DISPLAY_SPLIT: A panel that utilizes more than one DSI - * interfaces. - * @DSI_DISPLAY_SPLIT_EXT_BRIDGE: A bridge is present between panel and DSI - * host. It utilizes more than one DSI interface. - */ -enum dsi_display_type { - DSI_DISPLAY_SINGLE = 0, - DSI_DISPLAY_EXT_BRIDGE, - DSI_DISPLAY_SPLIT, - DSI_DISPLAY_SPLIT_EXT_BRIDGE, - DSI_DISPLAY_MAX, -}; - -/** - * struct dsi_display_ctrl - dsi ctrl/phy information for the display - * @ctrl: Handle to the DSI controller device. - * @ctrl_of_node: pHandle to the DSI controller device. - * @dsi_ctrl_idx: DSI controller instance id. - * @power_state: Current power state of the DSI controller. - * @phy: Handle to the DSI PHY device. - * @phy_of_node: pHandle to the DSI PHY device. - * @phy_enabled: PHY power status. - */ -struct dsi_display_ctrl { - /* controller info */ - struct dsi_ctrl *ctrl; - struct device_node *ctrl_of_node; - u32 dsi_ctrl_idx; - - enum dsi_power_state power_state; - - /* phy info */ - struct msm_dsi_phy *phy; - struct device_node *phy_of_node; - - bool phy_enabled; -}; -/** - * struct dsi_display_boot_param - defines DSI boot display selection - * @name:Name of DSI display selected as a boot param. - * @boot_disp_en:bool to indicate dtsi availability of display node - * @is_primary:bool to indicate whether current display is primary display - * @length:length of DSI display. - * @cmdline_topology: Display topology shared from kernel command line. - */ -struct dsi_display_boot_param { - char name[MAX_CMDLINE_PARAM_LEN]; - bool boot_disp_en; - bool is_primary; - int length; - struct device_node *node; - int cmdline_topology; -}; - -/** - * struct dsi_display_clk_info - dsi display clock source information - * @src_clks: Source clocks for DSI display. - * @mux_clks: Mux clocks used for DFPS. - * @shadow_clks: Used for DFPS. - */ -struct dsi_display_clk_info { - struct dsi_clk_link_set src_clks; - struct dsi_clk_link_set mux_clks; - struct dsi_clk_link_set shadow_clks; -}; - -/** - * struct dsi_display - dsi display information - * @pdev: Pointer to platform device. - * @drm_dev: DRM device associated with the display. - * @name: Name of the display. - * @display_type: Display type as defined in device tree. - * @list: List pointer. - * @is_active: Is display active. - * @display_lock: Mutex for dsi_display interface. - * @ctrl_count: Number of DSI interfaces required by panel. - * @ctrl: Controller information for DSI display. - * @panel: Handle to DSI panel. - * @panel_of: pHandle to DSI panel. - * @type: DSI display type. - * @clk_master_idx: The master controller for controlling clocks. This is an - * index into the ctrl[MAX_DSI_CTRLS_PER_DISPLAY] array. - * @cmd_master_idx: The master controller for sending DSI commands to panel. - * @video_master_idx: The master controller for enabling video engine. - * @clock_info: Clock sourcing for DSI display. - * @config: DSI host configuration information. - * @lane_map: Lane mapping between DSI host and Panel. - * @cmdline_topology: Display topology shared from kernel command line. - * @cmdline_timing: Display timing shared from kernel command line. - * @is_tpg_enabled: TPG state. - * @ulps_enabled: ulps state. - * @clamp_enabled: clamp state. - * @phy_idle_power_off: PHY power state. - * @host: DRM MIPI DSI Host. - * @bridge: Pointer to DRM bridge object. - * @cmd_engine_refcount: Reference count enforcing single instance of cmd eng - * @clk_mngr: DSI clock manager. - * @dsi_clk_handle: DSI clock handle. - * @mdp_clk_handle: MDP clock handle. - * @root: Debugfs root directory - * @misr_enable Frame MISR enable/disable - * @misr_frame_count Number of frames to accumulate the MISR value - */ -struct dsi_display { - struct platform_device *pdev; - struct drm_device *drm_dev; - - const char *name; - const char *display_type; - struct list_head list; - bool is_active; - struct mutex display_lock; - - u32 ctrl_count; - struct dsi_display_ctrl ctrl[MAX_DSI_CTRLS_PER_DISPLAY]; - - /* panel info */ - struct dsi_panel *panel; - struct device_node *panel_of; - - enum dsi_display_type type; - u32 clk_master_idx; - u32 cmd_master_idx; - u32 video_master_idx; - - struct dsi_display_clk_info clock_info; - struct dsi_host_config config; - struct dsi_lane_map lane_map; - int cmdline_topology; - int cmdline_timing; - bool is_tpg_enabled; - bool ulps_enabled; - bool clamp_enabled; - bool phy_idle_power_off; - struct drm_gem_object *tx_cmd_buf; - u32 cmd_buffer_size; - u64 cmd_buffer_iova; - void *vaddr; - - struct mipi_dsi_host host; - struct dsi_bridge *bridge; - u32 cmd_engine_refcount; - - void *clk_mngr; - void *dsi_clk_handle; - void *mdp_clk_handle; - - /* DEBUG FS */ - struct dentry *root; - - bool misr_enable; - u32 misr_frame_count; -}; - -#ifdef CONFIG_DRM_MSM_DSI_STAGING - -int dsi_display_dev_probe(struct platform_device *pdev); -int dsi_display_dev_remove(struct platform_device *pdev); - -/** - * dsi_display_get_num_of_displays() - returns number of display devices - * supported. - * - * Return: number of displays. - */ -int dsi_display_get_num_of_displays(void); - -/** - * dsi_display_get_active_displays - returns pointers for active display devices - * @display_array: Pointer to display array to be filled - * @max_display_count: Size of display_array - * @Returns: Number of display entries filled - */ -int dsi_display_get_active_displays(void **display_array, - u32 max_display_count); - -/** - * dsi_display_get_boot_display()- get DSI boot display name - * @index: index of display selection - * - * Return: returns the display node pointer - */ -struct device_node *dsi_display_get_boot_display(int index); - -/** - * dsi_display_get_display_by_name()- finds display by name - * @name: name of the display. - * - * Return: handle to the display or error code. - */ -struct dsi_display *dsi_display_get_display_by_name(const char *name); - -/** - * dsi_display_set_active_state() - sets the state of the display - * @display: Handle to display. - * @is_active: state - */ -void dsi_display_set_active_state(struct dsi_display *display, bool is_active); - -/** - * dsi_display_drm_bridge_init() - initializes DRM bridge object for DSI - * @display: Handle to the display. - * @encoder: Pointer to the encoder object which is connected to the - * display. - * - * Return: error code. - */ -int dsi_display_drm_bridge_init(struct dsi_display *display, - struct drm_encoder *enc); - -/** - * dsi_display_drm_bridge_deinit() - destroys DRM bridge for the display - * @display: Handle to the display. - * - * Return: error code. - */ -int dsi_display_drm_bridge_deinit(struct dsi_display *display); - -/** - * dsi_display_get_info() - returns the display properties - * @info: Pointer to the structure where info is stored. - * @disp: Handle to the display. - * - * Return: error code. - */ -int dsi_display_get_info(struct msm_display_info *info, void *disp); - -/** - * dsi_display_get_mode_count() - get number of modes supported by the display - * @display: Handle to display. - * @count: Number of modes supported - * - * Return: error code. - */ -int dsi_display_get_mode_count(struct dsi_display *display, u32 *count); - -/** - * dsi_display_get_modes() - get modes supported by display - * @display: Handle to display. - * @modes; Pointer to array of modes. Memory allocated should be - * big enough to store (count * struct dsi_display_mode) - * elements. If modes pointer is NULL, number of modes will - * be stored in the memory pointed to by count. - * - * Return: error code. - */ -int dsi_display_get_modes(struct dsi_display *display, - struct dsi_display_mode *modes); - -/** - * dsi_display_put_mode() - free up mode created for the display - * @display: Handle to display. - * @mode: Display mode to be freed up - * - * Return: error code. - */ -void dsi_display_put_mode(struct dsi_display *display, - struct dsi_display_mode *mode); - -/** - * dsi_display_validate_mode() - validates if mode is supported by display - * @display: Handle to display. - * @mode: Mode to be validated. - * @flags: Modifier flags. - * - * Return: 0 if supported or error code. - */ -int dsi_display_validate_mode(struct dsi_display *display, - struct dsi_display_mode *mode, - u32 flags); - -/** - * dsi_display_validate_mode_vrr() - validates mode if variable refresh case - * @display: Handle to display. - * @mode: Mode to be validated.. - * - * Return: 0 if error code. - */ -int dsi_display_validate_mode_vrr(struct dsi_display *display, - struct dsi_display_mode *cur_dsi_mode, - struct dsi_display_mode *mode); - -/** - * dsi_display_set_mode() - Set mode on the display. - * @display: Handle to display. - * @mode: mode to be set. - * @flags: Modifier flags. - * - * Return: error code. - */ -int dsi_display_set_mode(struct dsi_display *display, - struct dsi_display_mode *mode, - u32 flags); - -/** - * dsi_display_prepare() - prepare display - * @display: Handle to display. - * - * Prepare will perform power up sequences for the host and panel hardware. - * Power and clock resources might be turned on (depending on the panel mode). - * The video engine is not enabled. - * - * Return: error code. - */ -int dsi_display_prepare(struct dsi_display *display); - -/** - * dsi_display_enable() - enable display - * @display: Handle to display. - * - * Enable will turn on the host engine and the panel. At the end of the enable - * function, Host and panel hardware are ready to accept pixel data from - * upstream. - * - * Return: error code. - */ -int dsi_display_enable(struct dsi_display *display); - -/** - * dsi_display_post_enable() - perform post enable operations. - * @display: Handle to display. - * - * Some panels might require some commands to be sent after pixel data - * transmission has started. Such commands are sent as part of the post_enable - * function. - * - * Return: error code. - */ -int dsi_display_post_enable(struct dsi_display *display); - -/** - * dsi_display_pre_disable() - perform pre disable operations. - * @display: Handle to display. - * - * If a panel requires commands to be sent before pixel data transmission is - * stopped, those can be sent as part of pre_disable. - * - * Return: error code. - */ -int dsi_display_pre_disable(struct dsi_display *display); - -/** - * dsi_display_disable() - disable panel and host hardware. - * @display: Handle to display. - * - * Disable host and panel hardware and pixel data transmission can not continue. - * - * Return: error code. - */ -int dsi_display_disable(struct dsi_display *display); - -/** - * dsi_pre_clkoff_cb() - Callback before clock is turned off - * @priv: private data pointer. - * @clk_type: clock which is being turned on. - * @new_state: next state for the clock. - * - * @return: error code. - */ -int dsi_pre_clkoff_cb(void *priv, enum dsi_clk_type clk_type, - enum dsi_clk_state new_state); - -/** - * dsi_display_update_pps() - update PPS buffer. - * @pps_cmd: PPS buffer. - * @display: Handle to display. - * - * Copies new PPS buffer into display structure. - * - * Return: error code. - */ -int dsi_display_update_pps(char *pps_cmd, void *display); - -/** - * dsi_post_clkoff_cb() - Callback after clock is turned off - * @priv: private data pointer. - * @clk_type: clock which is being turned on. - * @curr_state: current state for the clock. - * - * @return: error code. - */ -int dsi_post_clkoff_cb(void *priv, enum dsi_clk_type clk_type, - enum dsi_clk_state curr_state); - -/** - * dsi_post_clkon_cb() - Callback after clock is turned on - * @priv: private data pointer. - * @clk_type: clock which is being turned on. - * @curr_state: current state for the clock. - * - * @return: error code. - */ -int dsi_post_clkon_cb(void *priv, enum dsi_clk_type clk_type, - enum dsi_clk_state curr_state); - - -/** - * dsi_pre_clkon_cb() - Callback before clock is turned on - * @priv: private data pointer. - * @clk_type: clock which is being turned on. - * @new_state: next state for the clock. - * - * @return: error code. - */ -int dsi_pre_clkon_cb(void *priv, enum dsi_clk_type clk_type, - enum dsi_clk_state new_state); - -/** - * dsi_display_unprepare() - power off display hardware. - * @display: Handle to display. - * - * Host and panel hardware is turned off. Panel will be in reset state at the - * end of the function. - * - * Return: error code. - */ -int dsi_display_unprepare(struct dsi_display *display); - -int dsi_display_set_tpg_state(struct dsi_display *display, bool enable); - -int dsi_display_clock_gate(struct dsi_display *display, bool enable); -int dsi_dispaly_static_frame(struct dsi_display *display, bool enable); - -/** - * dsi_display_enable_event() - enable interrupt based connector event - * @display: Handle to display. - * @event_idx: Event index. - * @event_info: Event callback definition. - * @enable: Whether to enable/disable the event interrupt. - */ -void dsi_display_enable_event(struct dsi_display *display, - uint32_t event_idx, struct dsi_event_cb_info *event_info, - bool enable); - -int dsi_display_set_backlight(void *display, u32 bl_lvl); - -/** - * dsi_display_soft_reset() - perform a soft reset on DSI controller - * @display: Handle to display - * - * The video, command and controller engines will be disabled before the - * reset is triggered. After, the engines will be re-enabled to the same state - * as before the reset. - * - * If the reset is done while MDP timing engine is turned on, the video - * engine should be re-enabled only during the vertical blanking time. - * - * Return: error code - */ -int dsi_display_soft_reset(void *display); - -/** - * dsi_display_set_power - update power/dpms setting - * @connector: Pointer to drm connector structure - * @power_mode: One of the following, - * DPU_MODE_DPMS_ON - * DPU_MODE_DPMS_LP1 - * DPU_MODE_DPMS_LP2 - * DPU_MODE_DPMS_STANDBY - * DPU_MODE_DPMS_SUSPEND - * DPU_MODE_DPMS_OFF - * @display: Pointer to private display structure - * Returns: Zero on success - */ -int dsi_display_set_power(struct drm_connector *connector, - int power_mode, void *display); - -/* - * dsi_display_pre_kickoff - program kickoff-time features - * @display: Pointer to private display structure - * Returns: Zero on success - */ -int dsi_display_pre_kickoff(struct dsi_display *display); - -/** - * dsi_display_get_dst_format() - get dst_format from DSI display - * @display: Handle to display - * - * Return: enum dsi_pixel_format type - */ -enum dsi_pixel_format dsi_display_get_dst_format(void *display); - -#else - -static inline int dsi_display_get_num_of_displays(void) { return 0; } -static inline int dsi_display_get_active_displays(void **display_array, u32 max_display_count) { return 0; } -static inline int dsi_display_drm_bridge_init(struct dsi_display *display, - struct drm_encoder *enc) -{ - return -EINVAL; -} -static inline int dsi_display_drm_bridge_deinit(struct dsi_display *display) { return 0; } -static inline int dsi_display_get_info(struct msm_display_info *info, void *disp) -{ - return -EINVAL; -} - -#endif - -#endif /* _DSI_DISPLAY_H_ */ diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display_test.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display_test.c deleted file mode 100644 index 4be2570..0000000 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_display_test.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * 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/delay.h> -#include <linux/slab.h> - -#include "dsi_display_test.h" - -static void dsi_display_test_dump_modes(struct dsi_display_mode *mode, u32 - count) -{ -} - -static void dsi_display_test_work(struct work_struct *work) -{ - struct dsi_display_test *test; - struct dsi_display *display; - struct dsi_display_mode *modes; - u32 count = 0; - u32 size = 0; - int rc = 0; - - test = container_of(work, struct dsi_display_test, test_work); - - display = test->display; - rc = dsi_display_get_mode_count(display, &count); - if (rc) { - pr_err("failed to get modes count, rc=%d\n", rc); - goto test_fail; - } - - size = count * sizeof(*modes); - modes = kzalloc(size, GFP_KERNEL); - if (!modes) { - rc = -ENOMEM; - goto test_fail; - } - - rc = dsi_display_get_modes(display, modes); - if (rc) { - pr_err("failed to get modes, rc=%d\n", rc); - goto test_fail_free_modes; - } - - dsi_display_test_dump_modes(modes, count); - - rc = dsi_display_set_mode(display, &modes[0], 0x0); - if (rc) { - pr_err("failed to set mode, rc=%d\n", rc); - goto test_fail_free_modes; - } - - rc = dsi_display_prepare(display); - if (rc) { - pr_err("failed to prepare display, rc=%d\n", rc); - goto test_fail_free_modes; - } - - rc = dsi_display_enable(display); - if (rc) { - pr_err("failed to enable display, rc=%d\n", rc); - goto test_fail_unprep_disp; - } - return; - -test_fail_unprep_disp: - if (rc) { - pr_err("failed to unprep display, rc=%d\n", rc); - goto test_fail_free_modes; - } - -test_fail_free_modes: - kfree(modes); -test_fail: - return; -} - -int dsi_display_test_init(struct dsi_display *display) -{ - static int done; - int rc = 0; - struct dsi_display_test *test; - - if (done) - return rc; - - done = 1; - if (!display) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - test = kzalloc(sizeof(*test), GFP_KERNEL); - if (!test) - return -ENOMEM; - - test->display = display; - INIT_WORK(&test->test_work, dsi_display_test_work); - - dsi_display_test_work(&test->test_work); - return rc; -} - diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display_test.h b/drivers/gpu/drm/msm/dsi-staging/dsi_display_test.h deleted file mode 100644 index a2f0861..0000000 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_display_test.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * 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 _DSI_DISPLAY_TEST_H_ -#define _DSI_DISPLAY_TEST_H_ - -#include "dsi_display.h" -#include "dsi_ctrl_hw.h" -#include "dsi_ctrl.h" - -struct dsi_display_test { - struct dsi_display *display; - - struct work_struct test_work; -}; - -int dsi_display_test_init(struct dsi_display *display); - - -#endif /* _DSI_DISPLAY_TEST_H_ */ diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c deleted file mode 100644 index 017f881..0000000 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c +++ /dev/null @@ -1,688 +0,0 @@ -/* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * 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) "dsi-drm:[%s] " fmt, __func__ -#include <drm/drm_atomic_helper.h> -#include <drm/drm_atomic.h> - -#include "msm_kms.h" -#include "dpu_connector.h" -#include "dsi_drm.h" -#include "dpu_trace.h" - -#define to_dsi_bridge(x) container_of((x), struct dsi_bridge, base) -#define to_dsi_state(x) container_of((x), struct dsi_connector_state, base) - -static void convert_to_dsi_mode(const struct drm_display_mode *drm_mode, - struct dsi_display_mode *dsi_mode) -{ - memset(dsi_mode, 0, sizeof(*dsi_mode)); - - dsi_mode->timing.h_active = drm_mode->hdisplay; - dsi_mode->timing.h_back_porch = drm_mode->htotal - drm_mode->hsync_end; - dsi_mode->timing.h_sync_width = drm_mode->htotal - - (drm_mode->hsync_start + dsi_mode->timing.h_back_porch); - dsi_mode->timing.h_front_porch = drm_mode->hsync_start - - drm_mode->hdisplay; - dsi_mode->timing.h_skew = drm_mode->hskew; - - dsi_mode->timing.v_active = drm_mode->vdisplay; - dsi_mode->timing.v_back_porch = drm_mode->vtotal - drm_mode->vsync_end; - dsi_mode->timing.v_sync_width = drm_mode->vtotal - - (drm_mode->vsync_start + dsi_mode->timing.v_back_porch); - - dsi_mode->timing.v_front_porch = drm_mode->vsync_start - - drm_mode->vdisplay; - - dsi_mode->timing.refresh_rate = drm_mode->vrefresh; - - dsi_mode->pixel_clk_khz = drm_mode->clock; - - dsi_mode->priv_info = - (struct dsi_display_mode_priv_info *)drm_mode->private; - - if (msm_is_mode_seamless(drm_mode)) - dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_SEAMLESS; - if (msm_is_mode_dynamic_fps(drm_mode)) - dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_DFPS; - if (msm_needs_vblank_pre_modeset(drm_mode)) - dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_VBLANK_PRE_MODESET; - if (msm_is_mode_seamless_dms(drm_mode)) - dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_DMS; - if (msm_is_mode_seamless_vrr(drm_mode)) - dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_VRR; -} - -static void convert_to_drm_mode(const struct dsi_display_mode *dsi_mode, - struct drm_display_mode *drm_mode) -{ - memset(drm_mode, 0, sizeof(*drm_mode)); - - drm_mode->hdisplay = dsi_mode->timing.h_active; - drm_mode->hsync_start = drm_mode->hdisplay + - dsi_mode->timing.h_front_porch; - drm_mode->hsync_end = drm_mode->hsync_start + - dsi_mode->timing.h_sync_width; - drm_mode->htotal = drm_mode->hsync_end + dsi_mode->timing.h_back_porch; - drm_mode->hskew = dsi_mode->timing.h_skew; - - drm_mode->vdisplay = dsi_mode->timing.v_active; - drm_mode->vsync_start = drm_mode->vdisplay + - dsi_mode->timing.v_front_porch; - drm_mode->vsync_end = drm_mode->vsync_start + - dsi_mode->timing.v_sync_width; - drm_mode->vtotal = drm_mode->vsync_end + dsi_mode->timing.v_back_porch; - - drm_mode->vrefresh = dsi_mode->timing.refresh_rate; - drm_mode->clock = dsi_mode->pixel_clk_khz; - - drm_mode->private = (int *)dsi_mode->priv_info; - - if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_SEAMLESS) - drm_mode->flags |= DRM_MODE_FLAG_SEAMLESS; - if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_DFPS) - drm_mode->private_flags |= MSM_MODE_FLAG_SEAMLESS_DYNAMIC_FPS; - if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_VBLANK_PRE_MODESET) - drm_mode->private_flags |= MSM_MODE_FLAG_VBLANK_PRE_MODESET; - if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_DMS) - drm_mode->private_flags |= MSM_MODE_FLAG_SEAMLESS_DMS; - if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_VRR) - drm_mode->private_flags |= MSM_MODE_FLAG_SEAMLESS_VRR; - - drm_mode_set_name(drm_mode); -} - -static int dsi_bridge_attach(struct drm_bridge *bridge) -{ - struct dsi_bridge *c_bridge = to_dsi_bridge(bridge); - - if (!bridge) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - pr_debug("[%d] attached\n", c_bridge->id); - - return 0; - -} - -static void dsi_bridge_pre_enable(struct drm_bridge *bridge) -{ - int rc = 0; - struct dsi_bridge *c_bridge = to_dsi_bridge(bridge); - - if (!bridge) { - pr_err("Invalid params\n"); - return; - } - - /* By this point mode should have been validated through mode_fixup */ - rc = dsi_display_set_mode(c_bridge->display, - &(c_bridge->dsi_mode), 0x0); - if (rc) { - pr_err("[%d] failed to perform a mode set, rc=%d\n", - c_bridge->id, rc); - return; - } - - if (c_bridge->dsi_mode.dsi_mode_flags & - (DSI_MODE_FLAG_SEAMLESS | DSI_MODE_FLAG_VRR)) { - pr_debug("[%d] seamless pre-enable\n", c_bridge->id); - return; - } - - DPU_ATRACE_BEGIN("dsi_bridge_pre_enable"); - rc = dsi_display_prepare(c_bridge->display); - if (rc) { - pr_err("[%d] DSI display prepare failed, rc=%d\n", - c_bridge->id, rc); - DPU_ATRACE_END("dsi_bridge_pre_enable"); - return; - } - - DPU_ATRACE_BEGIN("dsi_display_enable"); - rc = dsi_display_enable(c_bridge->display); - if (rc) { - pr_err("[%d] DSI display enable failed, rc=%d\n", - c_bridge->id, rc); - (void)dsi_display_unprepare(c_bridge->display); - } - DPU_ATRACE_END("dsi_display_enable"); - DPU_ATRACE_END("dsi_bridge_pre_enable"); -} - -static void dsi_bridge_enable(struct drm_bridge *bridge) -{ - int rc = 0; - struct dsi_bridge *c_bridge = to_dsi_bridge(bridge); - - if (!bridge) { - pr_err("Invalid params\n"); - return; - } - - if (c_bridge->dsi_mode.dsi_mode_flags & - (DSI_MODE_FLAG_SEAMLESS | DSI_MODE_FLAG_VRR)) { - pr_debug("[%d] seamless enable\n", c_bridge->id); - return; - } - - rc = dsi_display_post_enable(c_bridge->display); - if (rc) - pr_err("[%d] DSI display post enabled failed, rc=%d\n", - c_bridge->id, rc); -} - -static void dsi_bridge_disable(struct drm_bridge *bridge) -{ - int rc = 0; - struct dsi_bridge *c_bridge = to_dsi_bridge(bridge); - - if (!bridge) { - pr_err("Invalid params\n"); - return; - } - - rc = dsi_display_pre_disable(c_bridge->display); - if (rc) { - pr_err("[%d] DSI display pre disable failed, rc=%d\n", - c_bridge->id, rc); - } -} - -static void dsi_bridge_post_disable(struct drm_bridge *bridge) -{ - int rc = 0; - struct dsi_bridge *c_bridge = to_dsi_bridge(bridge); - - if (!bridge) { - pr_err("Invalid params\n"); - return; - } - - DPU_ATRACE_BEGIN("dsi_bridge_post_disable"); - DPU_ATRACE_BEGIN("dsi_display_disable"); - rc = dsi_display_disable(c_bridge->display); - if (rc) { - pr_err("[%d] DSI display disable failed, rc=%d\n", - c_bridge->id, rc); - DPU_ATRACE_END("dsi_display_disable"); - return; - } - DPU_ATRACE_END("dsi_display_disable"); - - rc = dsi_display_unprepare(c_bridge->display); - if (rc) { - pr_err("[%d] DSI display unprepare failed, rc=%d\n", - c_bridge->id, rc); - DPU_ATRACE_END("dsi_bridge_post_disable"); - return; - } - DPU_ATRACE_END("dsi_bridge_post_disable"); -} - -static void dsi_bridge_mode_set(struct drm_bridge *bridge, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - struct dsi_bridge *c_bridge = to_dsi_bridge(bridge); - - if (!bridge || !mode || !adjusted_mode) { - pr_err("Invalid params\n"); - return; - } - - memset(&(c_bridge->dsi_mode), 0x0, sizeof(struct dsi_display_mode)); - convert_to_dsi_mode(adjusted_mode, &(c_bridge->dsi_mode)); -} - -static bool dsi_bridge_mode_fixup(struct drm_bridge *bridge, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - int rc = 0; - struct dsi_bridge *c_bridge = to_dsi_bridge(bridge); - struct dsi_display_mode dsi_mode, cur_dsi_mode; - struct drm_display_mode cur_mode; - - if (!bridge || !mode || !adjusted_mode) { - pr_err("Invalid params\n"); - return false; - } - - convert_to_dsi_mode(mode, &dsi_mode); - - rc = dsi_display_validate_mode(c_bridge->display, &dsi_mode, - DSI_VALIDATE_FLAG_ALLOW_ADJUST); - if (rc) { - pr_err("[%d] mode is not valid, rc=%d\n", c_bridge->id, rc); - return false; - } - - if (bridge->encoder && bridge->encoder->crtc) { - - convert_to_dsi_mode(&bridge->encoder->crtc->mode, - &cur_dsi_mode); - rc = dsi_display_validate_mode_vrr(c_bridge->display, - &cur_dsi_mode, &dsi_mode); - if (rc) - pr_debug("[%s] vrr mode mismatch failure rc=%d\n", - c_bridge->display->name, rc); - - cur_mode = bridge->encoder->crtc->mode; - - if (!drm_mode_equal(&cur_mode, adjusted_mode) && - (!(dsi_mode.dsi_mode_flags & - DSI_MODE_FLAG_VRR))) - dsi_mode.dsi_mode_flags |= DSI_MODE_FLAG_DMS; - } - - convert_to_drm_mode(&dsi_mode, adjusted_mode); - - return true; -} - -int dsi_conn_get_mode_info(const struct drm_display_mode *drm_mode, - struct msm_mode_info *mode_info, - u32 max_mixer_width) -{ - struct dsi_display_mode dsi_mode; - struct dsi_mode_info *timing; - - if (!drm_mode || !mode_info) - return -EINVAL; - - convert_to_dsi_mode(drm_mode, &dsi_mode); - - if (!dsi_mode.priv_info) - return -EINVAL; - - memset(mode_info, 0, sizeof(*mode_info)); - - timing = &dsi_mode.timing; - mode_info->frame_rate = dsi_mode.timing.refresh_rate; - mode_info->vtotal = DSI_V_TOTAL(timing); - mode_info->prefill_lines = dsi_mode.priv_info->panel_prefill_lines; - mode_info->jitter_numer = dsi_mode.priv_info->panel_jitter_numer; - mode_info->jitter_denom = dsi_mode.priv_info->panel_jitter_denom; - - memcpy(&mode_info->topology, &dsi_mode.priv_info->topology, - sizeof(struct msm_display_topology)); - - mode_info->comp_info.comp_type = MSM_DISPLAY_COMPRESSION_NONE; - if (dsi_mode.priv_info->dsc_enabled) { - mode_info->comp_info.comp_type = MSM_DISPLAY_COMPRESSION_DSC; - memcpy(&mode_info->comp_info.dsc_info, &dsi_mode.priv_info->dsc, - sizeof(dsi_mode.priv_info->dsc)); - } - - return 0; -} - -static const struct drm_bridge_funcs dsi_bridge_ops = { - .attach = dsi_bridge_attach, - .mode_fixup = dsi_bridge_mode_fixup, - .pre_enable = dsi_bridge_pre_enable, - .enable = dsi_bridge_enable, - .disable = dsi_bridge_disable, - .post_disable = dsi_bridge_post_disable, - .mode_set = dsi_bridge_mode_set, -}; - -int dsi_conn_post_init(struct drm_connector *connector, - void *info, - void *display) -{ - struct dsi_display *dsi_display = display; - struct dsi_panel *panel; - - if (!info || !dsi_display) - return -EINVAL; - - dpu_kms_info_add_keystr(info, - "display type", dsi_display->display_type); - - switch (dsi_display->type) { - case DSI_DISPLAY_SINGLE: - dpu_kms_info_add_keystr(info, "display config", - "single display"); - break; - case DSI_DISPLAY_EXT_BRIDGE: - dpu_kms_info_add_keystr(info, "display config", "ext bridge"); - break; - case DSI_DISPLAY_SPLIT: - dpu_kms_info_add_keystr(info, "display config", - "split display"); - break; - case DSI_DISPLAY_SPLIT_EXT_BRIDGE: - dpu_kms_info_add_keystr(info, "display config", - "split ext bridge"); - break; - default: - pr_debug("invalid display type:%d\n", dsi_display->type); - break; - } - - if (!dsi_display->panel) { - pr_debug("invalid panel data\n"); - goto end; - } - - panel = dsi_display->panel; - dpu_kms_info_add_keystr(info, "panel name", panel->name); - - switch (panel->panel_mode) { - case DSI_OP_VIDEO_MODE: - dpu_kms_info_add_keystr(info, "panel mode", "video"); - break; - case DSI_OP_CMD_MODE: - dpu_kms_info_add_keystr(info, "panel mode", "command"); - dpu_kms_info_add_keyint(info, "mdp_transfer_time_us", - panel->cmd_config.mdp_transfer_time_us); - break; - default: - pr_debug("invalid panel type:%d\n", panel->panel_mode); - break; - } - dpu_kms_info_add_keystr(info, "dfps support", - panel->dfps_caps.dfps_support ? "true" : "false"); - - if (panel->dfps_caps.dfps_support) { - dpu_kms_info_add_keyint(info, "min_fps", - panel->dfps_caps.min_refresh_rate); - dpu_kms_info_add_keyint(info, "max_fps", - panel->dfps_caps.max_refresh_rate); - } - - switch (panel->phy_props.rotation) { - case DSI_PANEL_ROTATE_NONE: - dpu_kms_info_add_keystr(info, "panel orientation", "none"); - break; - case DSI_PANEL_ROTATE_H_FLIP: - dpu_kms_info_add_keystr(info, "panel orientation", "horz flip"); - break; - case DSI_PANEL_ROTATE_V_FLIP: - dpu_kms_info_add_keystr(info, "panel orientation", "vert flip"); - break; - case DSI_PANEL_ROTATE_HV_FLIP: - dpu_kms_info_add_keystr(info, "panel orientation", - "horz & vert flip"); - break; - default: - pr_debug("invalid panel rotation:%d\n", - panel->phy_props.rotation); - break; - } - - switch (panel->bl_config.type) { - case DSI_BACKLIGHT_PWM: - dpu_kms_info_add_keystr(info, "backlight type", "pwm"); - break; - case DSI_BACKLIGHT_WLED: - dpu_kms_info_add_keystr(info, "backlight type", "wled"); - break; - case DSI_BACKLIGHT_DCS: - dpu_kms_info_add_keystr(info, "backlight type", "dcs"); - break; - default: - pr_debug("invalid panel backlight type:%d\n", - panel->bl_config.type); - break; - } - -end: - return 0; -} - -enum drm_connector_status dsi_conn_detect(struct drm_connector *conn, - bool force, - void *display) -{ - enum drm_connector_status status = connector_status_unknown; - struct msm_display_info info; - int rc; - - if (!conn || !display) - return status; - - /* get display dsi_info */ - memset(&info, 0x0, sizeof(info)); - rc = dsi_display_get_info(&info, display); - if (rc) { - pr_err("failed to get display info, rc=%d\n", rc); - return connector_status_disconnected; - } - - if (info.capabilities & MSM_DISPLAY_CAP_HOT_PLUG) - status = (info.is_connected ? connector_status_connected : - connector_status_disconnected); - else - status = connector_status_connected; - - conn->display_info.width_mm = info.width_mm; - conn->display_info.height_mm = info.height_mm; - - return status; -} - -void dsi_connector_put_modes(struct drm_connector *connector, - void *display) -{ - struct drm_display_mode *drm_mode; - struct dsi_display_mode dsi_mode; - - if (!connector || !display) - return; - - list_for_each_entry(drm_mode, &connector->modes, head) { - convert_to_dsi_mode(drm_mode, &dsi_mode); - dsi_display_put_mode(display, &dsi_mode); - } -} - -int dsi_connector_get_modes(struct drm_connector *connector, - void *display) -{ - u32 count = 0; - u32 size = 0; - struct dsi_display_mode *modes = NULL; - struct drm_display_mode drm_mode; - int rc, i; - - if (dpu_connector_get_panel(connector)) { - /* - * TODO: If drm_panel is attached, query modes from the panel. - * This is complicated in split dsi cases because panel is not - * attached to both connectors. - */ - goto end; - } - rc = dsi_display_get_mode_count(display, &count); - if (rc) { - pr_err("failed to get num of modes, rc=%d\n", rc); - goto error; - } - - size = count * sizeof(*modes); - modes = kzalloc(size, GFP_KERNEL); - if (!modes) { - count = 0; - goto end; - } - - rc = dsi_display_get_modes(display, modes); - if (rc) { - pr_err("failed to get modes, rc=%d\n", rc); - count = 0; - goto error; - } - - for (i = 0; i < count; i++) { - struct drm_display_mode *m; - - memset(&drm_mode, 0x0, sizeof(drm_mode)); - convert_to_drm_mode(&modes[i], &drm_mode); - m = drm_mode_duplicate(connector->dev, &drm_mode); - if (!m) { - pr_err("failed to add mode %ux%u\n", - drm_mode.hdisplay, - drm_mode.vdisplay); - count = -ENOMEM; - goto error; - } - m->width_mm = connector->display_info.width_mm; - m->height_mm = connector->display_info.height_mm; - drm_mode_probed_add(connector, m); - } -error: - kfree(modes); -end: - pr_debug("MODE COUNT =%d\n\n", count); - return count; -} - -enum drm_mode_status dsi_conn_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode, - void *display) -{ - struct dsi_display_mode dsi_mode; - int rc; - - if (!connector || !mode) { - pr_err("Invalid params\n"); - return MODE_ERROR; - } - - convert_to_dsi_mode(mode, &dsi_mode); - - rc = dsi_display_validate_mode(display, &dsi_mode, - DSI_VALIDATE_FLAG_ALLOW_ADJUST); - if (rc) { - pr_err("mode not supported, rc=%d\n", rc); - return MODE_BAD; - } - - return MODE_OK; -} - -int dsi_conn_pre_kickoff(struct drm_connector *connector, - void *display) -{ - if (!connector || !display) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - return dsi_display_pre_kickoff(display); -} - -void dsi_conn_enable_event(struct drm_connector *connector, - uint32_t event_idx, bool enable, void *display) -{ - struct dsi_event_cb_info event_info; - - memset(&event_info, 0, sizeof(event_info)); - - event_info.event_cb = dpu_connector_trigger_event; - event_info.event_usr_ptr = connector; - - dsi_display_enable_event(display, event_idx, &event_info, enable); -} - -int dsi_conn_post_kickoff(struct drm_connector *connector) -{ - struct drm_encoder *encoder; - struct dsi_bridge *c_bridge; - struct dsi_display_mode adj_mode; - struct dsi_display *display; - struct dsi_display_ctrl *m_ctrl, *ctrl; - int i, rc = 0; - - if (!connector || !connector->state->best_encoder) - return -EINVAL; - - encoder = connector->state->best_encoder; - c_bridge = to_dsi_bridge(encoder->bridge); - adj_mode = c_bridge->dsi_mode; - display = c_bridge->display; - - if (adj_mode.dsi_mode_flags & DSI_MODE_FLAG_VRR) { - m_ctrl = &display->ctrl[display->clk_master_idx]; - rc = dsi_ctrl_timing_db_update(m_ctrl->ctrl, false); - if (rc) { - pr_err("[%s] failed to dfps update rc=%d\n", - display->name, rc); - return -EINVAL; - } - - /* Update the rest of the controllers */ - for (i = 0; i < display->ctrl_count; i++) { - ctrl = &display->ctrl[i]; - if (!ctrl->ctrl || (ctrl == m_ctrl)) - continue; - - rc = dsi_ctrl_timing_db_update(ctrl->ctrl, false); - if (rc) { - pr_err("[%s] failed to dfps update rc=%d\n", - display->name, rc); - return -EINVAL; - } - } - - c_bridge->dsi_mode.dsi_mode_flags &= ~DSI_MODE_FLAG_VRR; - } - - return 0; -} - -struct dsi_bridge *dsi_drm_bridge_init(struct dsi_display *display, - struct drm_device *dev, - struct drm_encoder *encoder) -{ - int rc = 0; - struct dsi_bridge *bridge; - - bridge = kzalloc(sizeof(*bridge), GFP_KERNEL); - if (!bridge) { - rc = -ENOMEM; - goto error; - } - - bridge->display = display; - bridge->base.funcs = &dsi_bridge_ops; - bridge->base.encoder = encoder; - - rc = drm_bridge_attach(encoder, &bridge->base, NULL); - if (rc) { - pr_err("failed to attach bridge, rc=%d\n", rc); - goto error_free_bridge; - } - - encoder->bridge = &bridge->base; - return bridge; -error_free_bridge: - kfree(bridge); -error: - return ERR_PTR(rc); -} - -void dsi_drm_bridge_cleanup(struct dsi_bridge *bridge) -{ - if (bridge && bridge->base.encoder) - bridge->base.encoder->bridge = NULL; - - kfree(bridge); -} diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.h b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.h deleted file mode 100644 index 38de33c..0000000 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * 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 _DSI_DRM_H_ -#define _DSI_DRM_H_ - -#include <linux/types.h> -#include <drm/drmP.h> -#include <drm/drm_crtc.h> -#include <drm/drm_crtc_helper.h> - -#include "msm_drv.h" - -#include "dsi_display.h" - -struct dsi_bridge { - struct drm_bridge base; - u32 id; - - struct dsi_display *display; - struct dsi_display_mode dsi_mode; -}; - -/** - * dsi_conn_post_init - callback to perform additional initialization steps - * @connector: Pointer to drm connector structure - * @info: Pointer to dpu connector info structure - * @display: Pointer to private display handle - * Returns: Zero on success - */ -int dsi_conn_post_init(struct drm_connector *connector, - void *info, - void *display); - -/** - * dsi_conn_detect - callback to determine if connector is connected - * @connector: Pointer to drm connector structure - * @force: Force detect setting from drm framework - * @display: Pointer to private display handle - * Returns: Connector 'is connected' status - */ -enum drm_connector_status dsi_conn_detect(struct drm_connector *conn, - bool force, - void *display); - -/** - * dsi_connector_get_modes - callback to add drm modes via drm_mode_probed_add() - * @connector: Pointer to drm connector structure - * @display: Pointer to private display handle - * Returns: Number of modes added - */ -int dsi_connector_get_modes(struct drm_connector *connector, - void *display); - -/** - * dsi_connector_put_modes - callback to free up drm modes of the connector - * @connector: Pointer to drm connector structure - * @display: Pointer to private display handle - */ -void dsi_connector_put_modes(struct drm_connector *connector, - void *display); - -/** - * dsi_conn_get_mode_info - retrieve information on the mode selected - * @drm_mode: Display mode set for the display - * @mode_info: Out parameter. information of the mode. - * @max_mixer_width: max width supported by HW layer mixer - * Returns: Zero on success - */ -int dsi_conn_get_mode_info(const struct drm_display_mode *drm_mode, - struct msm_mode_info *mode_info, u32 max_mixer_width); - -/** - * dsi_conn_mode_valid - callback to determine if specified mode is valid - * @connector: Pointer to drm connector structure - * @mode: Pointer to drm mode structure - * @display: Pointer to private display handle - * Returns: Validity status for specified mode - */ -enum drm_mode_status dsi_conn_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode, - void *display); - -/** - * dsi_conn_enable_event - callback to notify DSI driver of event registeration - * @connector: Pointer to drm connector structure - * @event_idx: Connector event index - * @enable: Whether or not the event is enabled - * @display: Pointer to private display handle - */ -void dsi_conn_enable_event(struct drm_connector *connector, - uint32_t event_idx, bool enable, void *display); - -struct dsi_bridge *dsi_drm_bridge_init(struct dsi_display *display, - struct drm_device *dev, - struct drm_encoder *encoder); - -void dsi_drm_bridge_cleanup(struct dsi_bridge *bridge); - -/** - * dsi_display_pre_kickoff - program kickoff-time features - * @connector: Pointer to drm connector structure - * @display: Pointer to private display structure - * Returns: Zero on success - */ -int dsi_conn_pre_kickoff(struct drm_connector *connector, - void *display); - -/** - * dsi_display_post_kickoff - program post kickoff-time features - * @connector: Pointer to drm connector structure - * Returns: Zero on success - */ -int dsi_conn_post_kickoff(struct drm_connector *connector); - -#endif /* _DSI_DRM_H_ */ diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_hw.h b/drivers/gpu/drm/msm/dsi-staging/dsi_hw.h deleted file mode 100644 index 950a001..0000000 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_hw.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * 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 _DSI_HW_H_ -#define _DSI_HW_H_ -#include <linux/io.h> - -#define DSI_R32(dsi_hw, off) readl_relaxed((dsi_hw)->base + (off)) -#define DSI_W32(dsi_hw, off, val) \ - do {\ - pr_debug("[DSI_%d][%s] - [0x%08x]\n", \ - (dsi_hw)->index, #off, (uint32_t)(val)); \ - writel_relaxed((val), (dsi_hw)->base + (off)); \ - } while (0) - -#define DSI_MMSS_MISC_R32(dsi_hw, off) \ - readl_relaxed((dsi_hw)->mmss_misc_base + (off)) -#define DSI_MMSS_MISC_W32(dsi_hw, off, val) \ - do {\ - pr_debug("[DSI_%d][%s] - [0x%08x]\n", \ - (dsi_hw)->index, #off, val); \ - writel_relaxed((val), (dsi_hw)->mmss_misc_base + (off)); \ - } while (0) - -#define DSI_DISP_CC_R32(dsi_hw, off) \ - readl_relaxed((dsi_hw)->disp_cc_base + (off)) -#define DSI_DISP_CC_W32(dsi_hw, off, val) \ - do {\ - pr_debug("[DSI_%d][%s] - [0x%08x]\n", \ - (dsi_hw)->index, #off, val); \ - writel_relaxed((val), (dsi_hw)->disp_cc_base + (off)); \ - } while (0) - -#define DSI_R64(dsi_hw, off) readq_relaxed((dsi_hw)->base + (off)) -#define DSI_W64(dsi_hw, off, val) writeq_relaxed((val), (dsi_hw)->base + (off)) - -#endif /* _DSI_HW_H_ */ diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c deleted file mode 100644 index 2e777f8..0000000 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c +++ /dev/null @@ -1,3321 +0,0 @@ -/* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * 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) "msm-dsi-panel:[%s:%d] " fmt, __func__, __LINE__ -#include <linux/delay.h> -#include <linux/slab.h> -#include <linux/gpio.h> -#include <linux/of_gpio.h> -#include <video/mipi_display.h> - -#include "dsi_panel.h" -#include "dsi_ctrl_hw.h" - -/** - * topology is currently defined by a set of following 3 values: - * 1. num of layer mixers - * 2. num of compression encoders - * 3. num of interfaces - */ -#define TOPOLOGY_SET_LEN 3 -#define MAX_TOPOLOGY 5 - -#define DSI_PANEL_DEFAULT_LABEL "Default dsi panel" - -#define DEFAULT_MDP_TRANSFER_TIME 14000 - -#define DEFAULT_PANEL_JITTER_NUMERATOR 2 -#define DEFAULT_PANEL_JITTER_DENOMINATOR 1 -#define DEFAULT_PANEL_JITTER_ARRAY_SIZE 2 -#define MAX_PANEL_JITTER 10 -#define DEFAULT_PANEL_PREFILL_LINES 25 - -enum dsi_dsc_ratio_type { - DSC_8BPC_8BPP, - DSC_10BPC_8BPP, - DSC_12BPC_8BPP, - DSC_RATIO_TYPE_MAX -}; - -static u32 dsi_dsc_rc_buf_thresh[] = {0x0e, 0x1c, 0x2a, 0x38, 0x46, 0x54, - 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b, 0x7d, 0x7e}; - -/* - * DSC 1.1 - * Rate control - Min QP values for each ratio type in dsi_dsc_ratio_type - */ -static char dsi_dsc_rc_range_min_qp_1_1[][15] = { - {0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 13}, - {0, 4, 5, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 11, 17}, - {0, 4, 9, 9, 11, 11, 11, 11, 11, 11, 13, 13, 13, 15, 21}, - }; - -/* - * DSC 1.1 SCR - * Rate control - Min QP values for each ratio type in dsi_dsc_ratio_type - */ -static char dsi_dsc_rc_range_min_qp_1_1_scr1[][15] = { - {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, 9, 9, 11, 11, 11, 11, 11, 11, 13, 13, 13, 17, 20}, - }; - -/* - * DSC 1.1 - * Rate control - Max QP values for each ratio type in dsi_dsc_ratio_type - */ -static char dsi_dsc_rc_range_max_qp_1_1[][15] = { - {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, 15, 16, 17, 17, 19}, - {12, 12, 13, 14, 15, 15, 15, 16, 17, 18, 19, 20, 21, 21, 23}, - }; - -/* - * DSC 1.1 SCR - * Rate control - Max QP values for each ratio type in dsi_dsc_ratio_type - */ -static char dsi_dsc_rc_range_max_qp_1_1_scr1[][15] = { - {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}, - {12, 12, 13, 14, 15, 15, 15, 16, 17, 18, 18, 19, 19, 20, 21}, - }; - -/* - * DSC 1.1 and DSC 1.1 SCR - * Rate control - bpg offset values - */ -static char dsi_dsc_rc_range_bpg_offset[] = {2, 0, 0, -2, -4, -6, -8, -8, - -8, -10, -10, -12, -12, -12, -12}; - -int dsi_dsc_create_pps_buf_cmd(struct msm_display_dsc_info *dsc, char *buf, - int pps_id) -{ - char *bp; - char data; - int i, bpp; - char *dbgbp; - - dbgbp = buf; - bp = buf; - /* First 7 bytes are cmd header */ - *bp++ = 0x0A; - *bp++ = 1; - *bp++ = 0; - *bp++ = 0; - *bp++ = 10; - *bp++ = 0; - *bp++ = 128; - - *bp++ = (dsc->version & 0xff); /* pps0 */ - *bp++ = (pps_id & 0xff); /* pps1 */ - bp++; /* pps2, reserved */ - - data = dsc->line_buf_depth & 0x0f; - data |= ((dsc->bpc & 0xf) << 4); - *bp++ = data; /* pps3 */ - - bpp = dsc->bpp; - bpp <<= 4; /* 4 fraction bits */ - data = (bpp >> 8); - data &= 0x03; /* upper two bits */ - data |= ((dsc->block_pred_enable & 0x1) << 5); - data |= ((dsc->convert_rgb & 0x1) << 4); - data |= ((dsc->enable_422 & 0x1) << 3); - data |= ((dsc->vbr_enable & 0x1) << 2); - *bp++ = data; /* pps4 */ - *bp++ = (bpp & 0xff); /* pps5 */ - - *bp++ = ((dsc->pic_height >> 8) & 0xff); /* pps6 */ - *bp++ = (dsc->pic_height & 0x0ff); /* pps7 */ - *bp++ = ((dsc->pic_width >> 8) & 0xff); /* pps8 */ - *bp++ = (dsc->pic_width & 0x0ff); /* pps9 */ - - *bp++ = ((dsc->slice_height >> 8) & 0xff);/* pps10 */ - *bp++ = (dsc->slice_height & 0x0ff); /* pps11 */ - *bp++ = ((dsc->slice_width >> 8) & 0xff); /* pps12 */ - *bp++ = (dsc->slice_width & 0x0ff); /* pps13 */ - - *bp++ = ((dsc->chunk_size >> 8) & 0xff);/* pps14 */ - *bp++ = (dsc->chunk_size & 0x0ff); /* pps15 */ - - *bp++ = (dsc->initial_xmit_delay >> 8) & 0x3; /* pps16, bit 0, 1 */ - *bp++ = (dsc->initial_xmit_delay & 0xff);/* pps17 */ - - *bp++ = ((dsc->initial_dec_delay >> 8) & 0xff); /* pps18 */ - *bp++ = (dsc->initial_dec_delay & 0xff);/* pps19 */ - - bp++; /* pps20, reserved */ - - *bp++ = (dsc->initial_scale_value & 0x3f); /* pps21 */ - - *bp++ = ((dsc->scale_increment_interval >> 8) & 0xff); /* pps22 */ - *bp++ = (dsc->scale_increment_interval & 0xff); /* pps23 */ - - *bp++ = ((dsc->scale_decrement_interval >> 8) & 0xf); /* pps24 */ - *bp++ = (dsc->scale_decrement_interval & 0x0ff);/* pps25 */ - - bp++; /* pps26, reserved */ - - *bp++ = (dsc->first_line_bpg_offset & 0x1f);/* pps27 */ - - *bp++ = ((dsc->nfl_bpg_offset >> 8) & 0xff);/* pps28 */ - *bp++ = (dsc->nfl_bpg_offset & 0x0ff); /* pps29 */ - *bp++ = ((dsc->slice_bpg_offset >> 8) & 0xff);/* pps30 */ - *bp++ = (dsc->slice_bpg_offset & 0x0ff);/* pps31 */ - - *bp++ = ((dsc->initial_offset >> 8) & 0xff);/* pps32 */ - *bp++ = (dsc->initial_offset & 0x0ff); /* pps33 */ - - *bp++ = ((dsc->final_offset >> 8) & 0xff);/* pps34 */ - *bp++ = (dsc->final_offset & 0x0ff); /* pps35 */ - - *bp++ = (dsc->min_qp_flatness & 0x1f); /* pps36 */ - *bp++ = (dsc->max_qp_flatness & 0x1f); /* pps37 */ - - *bp++ = ((dsc->rc_model_size >> 8) & 0xff);/* pps38 */ - *bp++ = (dsc->rc_model_size & 0x0ff); /* pps39 */ - - *bp++ = (dsc->edge_factor & 0x0f); /* pps40 */ - - *bp++ = (dsc->quant_incr_limit0 & 0x1f); /* pps41 */ - *bp++ = (dsc->quant_incr_limit1 & 0x1f); /* pps42 */ - - data = ((dsc->tgt_offset_hi & 0xf) << 4); - data |= (dsc->tgt_offset_lo & 0x0f); - *bp++ = data; /* pps43 */ - - for (i = 0; i < 14; i++) - *bp++ = (dsc->buf_thresh[i] & 0xff); /* pps44 - pps57 */ - - for (i = 0; i < 15; i++) { /* pps58 - pps87 */ - data = (dsc->range_min_qp[i] & 0x1f); - data <<= 3; - data |= ((dsc->range_max_qp[i] >> 2) & 0x07); - *bp++ = data; - data = (dsc->range_max_qp[i] & 0x03); - data <<= 6; - data |= (dsc->range_bpg_offset[i] & 0x3f); - *bp++ = data; - } - - return 128; -} - -static int dsi_panel_vreg_get(struct dsi_panel *panel) -{ - int rc = 0; - int i; - struct regulator *vreg = NULL; - - for (i = 0; i < panel->power_info.count; i++) { - vreg = devm_regulator_get(panel->parent, - panel->power_info.vregs[i].vreg_name); - rc = PTR_RET(vreg); - if (rc) { - pr_err("failed to get %s regulator\n", - panel->power_info.vregs[i].vreg_name); - goto error_put; - } - panel->power_info.vregs[i].vreg = vreg; - } - - return rc; -error_put: - for (i = i - 1; i >= 0; i--) { - devm_regulator_put(panel->power_info.vregs[i].vreg); - panel->power_info.vregs[i].vreg = NULL; - } - return -EPROBE_DEFER; -} - -static int dsi_panel_vreg_put(struct dsi_panel *panel) -{ - int rc = 0; - int i; - - for (i = panel->power_info.count - 1; i >= 0; i--) - devm_regulator_put(panel->power_info.vregs[i].vreg); - - return rc; -} - -static int dsi_panel_gpio_request(struct dsi_panel *panel) -{ - int rc = 0; - struct dsi_panel_reset_config *r_config = &panel->reset_config; - - if (gpio_is_valid(r_config->reset_gpio)) { - rc = gpio_request(r_config->reset_gpio, "reset_gpio"); - if (rc) { - pr_err("request for reset_gpio failed, rc=%d\n", rc); - goto error; - } - } - - if (gpio_is_valid(r_config->disp_en_gpio)) { - rc = gpio_request(r_config->disp_en_gpio, "disp_en_gpio"); - if (rc) { - pr_err("request for disp_en_gpio failed, rc=%d\n", rc); - goto error_release_reset; - } - } - - if (gpio_is_valid(panel->bl_config.en_gpio)) { - rc = gpio_request(panel->bl_config.en_gpio, "bklt_en_gpio"); - if (rc) { - pr_err("request for bklt_en_gpio failed, rc=%d\n", rc); - goto error_release_disp_en; - } - } - - if (gpio_is_valid(r_config->lcd_mode_sel_gpio)) { - rc = gpio_request(r_config->lcd_mode_sel_gpio, "mode_gpio"); - if (rc) { - pr_err("request for mode_gpio failed, rc=%d\n", rc); - goto error_release_mode_sel; - } - } - - goto error; -error_release_mode_sel: - if (gpio_is_valid(panel->bl_config.en_gpio)) - gpio_free(panel->bl_config.en_gpio); -error_release_disp_en: - if (gpio_is_valid(r_config->disp_en_gpio)) - gpio_free(r_config->disp_en_gpio); -error_release_reset: - if (gpio_is_valid(r_config->reset_gpio)) - gpio_free(r_config->reset_gpio); -error: - return rc; -} - -static int dsi_panel_gpio_release(struct dsi_panel *panel) -{ - int rc = 0; - struct dsi_panel_reset_config *r_config = &panel->reset_config; - - if (gpio_is_valid(r_config->reset_gpio)) - gpio_free(r_config->reset_gpio); - - if (gpio_is_valid(r_config->disp_en_gpio)) - gpio_free(r_config->disp_en_gpio); - - if (gpio_is_valid(panel->bl_config.en_gpio)) - gpio_free(panel->bl_config.en_gpio); - - if (gpio_is_valid(panel->reset_config.lcd_mode_sel_gpio)) - gpio_free(panel->reset_config.lcd_mode_sel_gpio); - - return rc; -} - -static int dsi_panel_reset(struct dsi_panel *panel) -{ - int rc = 0; - struct dsi_panel_reset_config *r_config = &panel->reset_config; - int i; - - if (gpio_is_valid(panel->reset_config.disp_en_gpio)) { - rc = gpio_direction_output(panel->reset_config.disp_en_gpio, 1); - if (rc) { - pr_err("unable to set dir for disp gpio rc=%d\n", rc); - goto exit; - } - } - - if (r_config->count) { - rc = gpio_direction_output(r_config->reset_gpio, - r_config->sequence[0].level); - if (rc) { - pr_err("unable to set dir for rst gpio rc=%d\n", rc); - goto exit; - } - } - - for (i = 0; i < r_config->count; i++) { - gpio_set_value(r_config->reset_gpio, - r_config->sequence[i].level); - - - if (r_config->sequence[i].sleep_ms) - usleep_range(r_config->sequence[i].sleep_ms * 1000, - r_config->sequence[i].sleep_ms * 1000); - } - - if (gpio_is_valid(panel->bl_config.en_gpio)) { - rc = gpio_direction_output(panel->bl_config.en_gpio, 1); - if (rc) - pr_err("unable to set dir for bklt gpio rc=%d\n", rc); - } - - if (gpio_is_valid(panel->reset_config.lcd_mode_sel_gpio)) { - bool out = true; - - if ((panel->reset_config.mode_sel_state == MODE_SEL_DUAL_PORT) - || (panel->reset_config.mode_sel_state - == MODE_GPIO_LOW)) - out = false; - else if ((panel->reset_config.mode_sel_state - == MODE_SEL_SINGLE_PORT) || - (panel->reset_config.mode_sel_state - == MODE_GPIO_HIGH)) - out = true; - - rc = gpio_direction_output( - panel->reset_config.lcd_mode_sel_gpio, out); - if (rc) - pr_err("unable to set dir for mode gpio rc=%d\n", rc); - } -exit: - return rc; -} - -static int dsi_panel_set_pinctrl_state(struct dsi_panel *panel, bool enable) -{ - int rc = 0; - struct pinctrl_state *state; - - if (enable) - state = panel->pinctrl.active; - else - state = panel->pinctrl.suspend; - - rc = pinctrl_select_state(panel->pinctrl.pinctrl, state); - if (rc) - pr_err("[%s] failed to set pin state, rc=%d\n", panel->name, - rc); - - return rc; -} - - -static int dsi_panel_power_on(struct dsi_panel *panel) -{ - int rc = 0; - - rc = dsi_pwr_enable_regulator(&panel->power_info, true); - if (rc) { - pr_err("[%s] failed to enable vregs, rc=%d\n", panel->name, rc); - goto exit; - } - - rc = dsi_panel_set_pinctrl_state(panel, true); - if (rc) { - pr_err("[%s] failed to set pinctrl, rc=%d\n", panel->name, rc); - goto error_disable_vregs; - } - - rc = dsi_panel_reset(panel); - if (rc) { - pr_err("[%s] failed to reset panel, rc=%d\n", panel->name, rc); - goto error_disable_gpio; - } - - goto exit; - -error_disable_gpio: - if (gpio_is_valid(panel->reset_config.disp_en_gpio)) - gpio_set_value(panel->reset_config.disp_en_gpio, 0); - - if (gpio_is_valid(panel->bl_config.en_gpio)) - gpio_set_value(panel->bl_config.en_gpio, 0); - - (void)dsi_panel_set_pinctrl_state(panel, false); - -error_disable_vregs: - (void)dsi_pwr_enable_regulator(&panel->power_info, false); - -exit: - return rc; -} - -static int dsi_panel_power_off(struct dsi_panel *panel) -{ - int rc = 0; - - if (gpio_is_valid(panel->reset_config.disp_en_gpio)) - gpio_set_value(panel->reset_config.disp_en_gpio, 0); - - if (gpio_is_valid(panel->reset_config.reset_gpio)) - gpio_set_value(panel->reset_config.reset_gpio, 0); - - if (gpio_is_valid(panel->reset_config.lcd_mode_sel_gpio)) - gpio_set_value(panel->reset_config.lcd_mode_sel_gpio, 0); - - rc = dsi_panel_set_pinctrl_state(panel, false); - if (rc) { - pr_err("[%s] failed set pinctrl state, rc=%d\n", panel->name, - rc); - } - - rc = dsi_pwr_enable_regulator(&panel->power_info, false); - if (rc) - pr_err("[%s] failed to enable vregs, rc=%d\n", panel->name, rc); - - return rc; -} -static int dsi_panel_tx_cmd_set(struct dsi_panel *panel, - enum dsi_cmd_set_type type) -{ - int rc = 0, i = 0; - ssize_t len; - struct dsi_cmd_desc *cmds; - u32 count; - enum dsi_cmd_set_state state; - struct dsi_display_mode *mode; - const struct mipi_dsi_host_ops *ops = panel->host->ops; - - if (!panel || !panel->cur_mode) - return -EINVAL; - - mode = panel->cur_mode; - - cmds = mode->priv_info->cmd_sets[type].cmds; - count = mode->priv_info->cmd_sets[type].count; - state = mode->priv_info->cmd_sets[type].state; - - if (count == 0) { - pr_debug("[%s] No commands to be sent for state(%d)\n", - panel->name, type); - goto error; - } - - for (i = 0; i < count; i++) { - /* TODO: handle last command */ - if (state == DSI_CMD_SET_STATE_LP) - cmds->msg.flags |= MIPI_DSI_MSG_USE_LPM; - - len = ops->transfer(panel->host, &cmds->msg); - if (len < 0) { - rc = len; - pr_err("failed to set cmds(%d), rc=%d\n", type, rc); - goto error; - } - if (cmds->post_wait_ms) - msleep(cmds->post_wait_ms); - cmds++; - } -error: - return rc; -} - -static int dsi_panel_pinctrl_deinit(struct dsi_panel *panel) -{ - int rc = 0; - - devm_pinctrl_put(panel->pinctrl.pinctrl); - - return rc; -} - -static int dsi_panel_pinctrl_init(struct dsi_panel *panel) -{ - int rc = 0; - - /* TODO: pinctrl is defined in dsi dt node */ - panel->pinctrl.pinctrl = devm_pinctrl_get(panel->parent); - if (IS_ERR_OR_NULL(panel->pinctrl.pinctrl)) { - rc = PTR_ERR(panel->pinctrl.pinctrl); - pr_err("failed to get pinctrl, rc=%d\n", rc); - goto error; - } - - panel->pinctrl.active = pinctrl_lookup_state(panel->pinctrl.pinctrl, - "panel_active"); - if (IS_ERR_OR_NULL(panel->pinctrl.active)) { - rc = PTR_ERR(panel->pinctrl.active); - pr_err("failed to get pinctrl active state, rc=%d\n", rc); - goto error; - } - - panel->pinctrl.suspend = - pinctrl_lookup_state(panel->pinctrl.pinctrl, "panel_suspend"); - - if (IS_ERR_OR_NULL(panel->pinctrl.suspend)) { - rc = PTR_ERR(panel->pinctrl.suspend); - pr_err("failed to get pinctrl suspend state, rc=%d\n", rc); - goto error; - } - -error: - return rc; -} - -#ifdef CONFIG_LEDS_TRIGGERS -static int dsi_panel_led_bl_register(struct dsi_panel *panel, - struct dsi_backlight_config *bl) -{ - int rc = 0; - - led_trigger_register_simple("bkl-trigger", &bl->wled); - - /* LED APIs don't tell us directly whether a clasdpuv has yet - * been registered to service this trigger. Until clasdpuv is - * registered, calling led_trigger has no effect, and doesn't - * fail. Clasdpuvs are associated with any registered triggers - * when they do register, but that is too late for FBCon. - * Check the cdev list directly and defer if appropriate. - */ - if (!bl->wled) { - pr_err("[%s] backlight registration failed\n", panel->name); - rc = -EINVAL; - } else { - read_lock(&bl->wled->leddev_list_lock); - if (list_empty(&bl->wled->led_cdevs)) - rc = -EPROBE_DEFER; - read_unlock(&bl->wled->leddev_list_lock); - - if (rc) { - pr_info("[%s] backlight %s not ready, defer probe\n", - panel->name, bl->wled->name); - led_trigger_unregister_simple(bl->wled); - } - } - - return rc; -} -#else -static int dsi_panel_led_bl_register(struct dsi_panel *panel, - struct dsi_backlight_config *bl) -{ - return 0; -} -#endif - -static int dsi_panel_update_backlight(struct dsi_panel *panel, - u32 bl_lvl) -{ - int rc = 0; - struct mipi_dsi_device *dsi; - - if (!panel || (bl_lvl > 0xffff)) { - pr_err("invalid params\n"); - return -EINVAL; - } - - dsi = &panel->mipi_device; - - mutex_lock(&panel->panel_lock); - - rc = mipi_dsi_dcs_set_display_brightness(dsi, bl_lvl); - if (rc < 0) - pr_err("failed to update dcs backlight:%d\n", bl_lvl); - - mutex_unlock(&panel->panel_lock); - return rc; -} - -int dsi_panel_set_backlight(struct dsi_panel *panel, u32 bl_lvl) -{ - int rc = 0; - struct dsi_backlight_config *bl = &panel->bl_config; - - pr_debug("backlight type:%d lvl:%d\n", bl->type, bl_lvl); - switch (bl->type) { - case DSI_BACKLIGHT_WLED: - led_trigger_event(bl->wled, bl_lvl); - break; - case DSI_BACKLIGHT_DCS: - dsi_panel_update_backlight(panel, bl_lvl); - break; - default: - pr_err("Backlight type(%d) not supported\n", bl->type); - rc = -ENOTSUPP; - } - - return rc; -} - -static int dsi_panel_bl_register(struct dsi_panel *panel) -{ - int rc = 0; - struct dsi_backlight_config *bl = &panel->bl_config; - - switch (bl->type) { - case DSI_BACKLIGHT_WLED: - rc = dsi_panel_led_bl_register(panel, bl); - break; - case DSI_BACKLIGHT_DCS: - break; - default: - pr_err("Backlight type(%d) not supported\n", bl->type); - rc = -ENOTSUPP; - goto error; - } - -error: - return rc; -} - -static int dsi_panel_bl_unregister(struct dsi_panel *panel) -{ - int rc = 0; - struct dsi_backlight_config *bl = &panel->bl_config; - - switch (bl->type) { - case DSI_BACKLIGHT_WLED: - led_trigger_unregister_simple(bl->wled); - break; - case DSI_BACKLIGHT_DCS: - break; - default: - pr_err("Backlight type(%d) not supported\n", bl->type); - rc = -ENOTSUPP; - goto error; - } - -error: - return rc; -} -static int dsi_panel_parse_timing(struct dsi_mode_info *mode, - struct device_node *of_node) -{ - int rc = 0; - - rc = of_property_read_u32(of_node, "qcom,mdss-dsi-panel-framerate", - &mode->refresh_rate); - if (rc) { - pr_err("failed to read qcom,mdss-dsi-panel-framerate, rc=%d\n", - rc); - goto error; - } - - rc = of_property_read_u32(of_node, "qcom,mdss-dsi-panel-width", - &mode->h_active); - if (rc) { - pr_err("failed to read qcom,mdss-dsi-panel-width, rc=%d\n", rc); - goto error; - } - - rc = of_property_read_u32(of_node, "qcom,mdss-dsi-h-front-porch", - &mode->h_front_porch); - if (rc) { - pr_err("failed to read qcom,mdss-dsi-h-front-porch, rc=%d\n", - rc); - goto error; - } - - rc = of_property_read_u32(of_node, "qcom,mdss-dsi-h-back-porch", - &mode->h_back_porch); - if (rc) { - pr_err("failed to read qcom,mdss-dsi-h-back-porch, rc=%d\n", - rc); - goto error; - } - - rc = of_property_read_u32(of_node, "qcom,mdss-dsi-h-pulse-width", - &mode->h_sync_width); - if (rc) { - pr_err("failed to read qcom,mdss-dsi-h-pulse-width, rc=%d\n", - rc); - goto error; - } - - rc = of_property_read_u32(of_node, "qcom,mdss-dsi-h-sync-skew", - &mode->h_skew); - if (rc) - pr_err("qcom,mdss-dsi-h-sync-skew is not defined, rc=%d\n", rc); - - rc = of_property_read_u32(of_node, "qcom,mdss-dsi-panel-height", - &mode->v_active); - if (rc) { - pr_err("failed to read qcom,mdss-dsi-panel-height, rc=%d\n", - rc); - goto error; - } - - rc = of_property_read_u32(of_node, "qcom,mdss-dsi-v-back-porch", - &mode->v_back_porch); - if (rc) { - pr_err("failed to read qcom,mdss-dsi-v-back-porch, rc=%d\n", - rc); - goto error; - } - - rc = of_property_read_u32(of_node, "qcom,mdss-dsi-v-front-porch", - &mode->v_front_porch); - if (rc) { - pr_err("failed to read qcom,mdss-dsi-v-back-porch, rc=%d\n", - rc); - goto error; - } - - rc = of_property_read_u32(of_node, "qcom,mdss-dsi-v-pulse-width", - &mode->v_sync_width); - if (rc) { - pr_err("failed to read qcom,mdss-dsi-v-pulse-width, rc=%d\n", - rc); - goto error; - } - -error: - return rc; -} - -static int dsi_panel_parse_pixel_format(struct dsi_host_common_cfg *host, - struct device_node *of_node, - const char *name) -{ - int rc = 0; - u32 bpp = 0; - enum dsi_pixel_format fmt; - const char *packing; - - rc = of_property_read_u32(of_node, "qcom,mdss-dsi-bpp", &bpp); - if (rc) { - pr_err("[%s] failed to read qcom,mdss-dsi-bpp, rc=%d\n", - name, rc); - return rc; - } - - switch (bpp) { - case 3: - fmt = DSI_PIXEL_FORMAT_RGB111; - break; - case 8: - fmt = DSI_PIXEL_FORMAT_RGB332; - break; - case 12: - fmt = DSI_PIXEL_FORMAT_RGB444; - break; - case 16: - fmt = DSI_PIXEL_FORMAT_RGB565; - break; - case 18: - fmt = DSI_PIXEL_FORMAT_RGB666; - break; - case 24: - default: - fmt = DSI_PIXEL_FORMAT_RGB888; - break; - } - - if (fmt == DSI_PIXEL_FORMAT_RGB666) { - packing = of_get_property(of_node, - "qcom,mdss-dsi-pixel-packing", - NULL); - if (packing && !strcmp(packing, "loose")) - fmt = DSI_PIXEL_FORMAT_RGB666_LOOSE; - } - - host->dst_format = fmt; - return rc; -} - -static int dsi_panel_parse_lane_states(struct dsi_host_common_cfg *host, - struct device_node *of_node, - const char *name) -{ - int rc = 0; - bool lane_enabled; - - lane_enabled = of_property_read_bool(of_node, - "qcom,mdss-dsi-lane-0-state"); - host->data_lanes |= (lane_enabled ? DSI_DATA_LANE_0 : 0); - - lane_enabled = of_property_read_bool(of_node, - "qcom,mdss-dsi-lane-1-state"); - host->data_lanes |= (lane_enabled ? DSI_DATA_LANE_1 : 0); - - lane_enabled = of_property_read_bool(of_node, - "qcom,mdss-dsi-lane-2-state"); - host->data_lanes |= (lane_enabled ? DSI_DATA_LANE_2 : 0); - - lane_enabled = of_property_read_bool(of_node, - "qcom,mdss-dsi-lane-3-state"); - host->data_lanes |= (lane_enabled ? DSI_DATA_LANE_3 : 0); - - if (host->data_lanes == 0) { - pr_err("[%s] No data lanes are enabled, rc=%d\n", name, rc); - rc = -EINVAL; - } - - return rc; -} - -static int dsi_panel_parse_color_swap(struct dsi_host_common_cfg *host, - struct device_node *of_node, - const char *name) -{ - int rc = 0; - const char *swap_mode; - - swap_mode = of_get_property(of_node, "qcom,mdss-dsi-color-order", NULL); - if (swap_mode) { - if (!strcmp(swap_mode, "rgb_swap_rgb")) { - host->swap_mode = DSI_COLOR_SWAP_RGB; - } else if (!strcmp(swap_mode, "rgb_swap_rbg")) { - host->swap_mode = DSI_COLOR_SWAP_RBG; - } else if (!strcmp(swap_mode, "rgb_swap_brg")) { - host->swap_mode = DSI_COLOR_SWAP_BRG; - } else if (!strcmp(swap_mode, "rgb_swap_grb")) { - host->swap_mode = DSI_COLOR_SWAP_GRB; - } else if (!strcmp(swap_mode, "rgb_swap_gbr")) { - host->swap_mode = DSI_COLOR_SWAP_GBR; - } else { - pr_err("[%s] Unrecognized color order-%s\n", - name, swap_mode); - rc = -EINVAL; - } - } else { - pr_debug("[%s] Falling back to default color order\n", name); - host->swap_mode = DSI_COLOR_SWAP_RGB; - } - - /* bit swap on color channel is not defined in dt */ - host->bit_swap_red = false; - host->bit_swap_green = false; - host->bit_swap_blue = false; - return rc; -} - -static int dsi_panel_parse_triggers(struct dsi_host_common_cfg *host, - struct device_node *of_node, - const char *name) -{ - const char *trig; - int rc = 0; - - trig = of_get_property(of_node, "qcom,mdss-dsi-mdp-trigger", NULL); - if (trig) { - if (!strcmp(trig, "none")) { - host->mdp_cmd_trigger = DSI_TRIGGER_NONE; - } else if (!strcmp(trig, "trigger_te")) { - host->mdp_cmd_trigger = DSI_TRIGGER_TE; - } else if (!strcmp(trig, "trigger_sw")) { - host->mdp_cmd_trigger = DSI_TRIGGER_SW; - } else if (!strcmp(trig, "trigger_sw_te")) { - host->mdp_cmd_trigger = DSI_TRIGGER_SW_TE; - } else { - pr_err("[%s] Unrecognized mdp trigger type (%s)\n", - name, trig); - rc = -EINVAL; - } - - } else { - pr_debug("[%s] Falling back to default MDP trigger\n", - name); - host->mdp_cmd_trigger = DSI_TRIGGER_SW; - } - - trig = of_get_property(of_node, "qcom,mdss-dsi-dma-trigger", NULL); - if (trig) { - if (!strcmp(trig, "none")) { - host->dma_cmd_trigger = DSI_TRIGGER_NONE; - } else if (!strcmp(trig, "trigger_te")) { - host->dma_cmd_trigger = DSI_TRIGGER_TE; - } else if (!strcmp(trig, "trigger_sw")) { - host->dma_cmd_trigger = DSI_TRIGGER_SW; - } else if (!strcmp(trig, "trigger_sw_seof")) { - host->dma_cmd_trigger = DSI_TRIGGER_SW_SEOF; - } else if (!strcmp(trig, "trigger_sw_te")) { - host->dma_cmd_trigger = DSI_TRIGGER_SW_TE; - } else { - pr_err("[%s] Unrecognized mdp trigger type (%s)\n", - name, trig); - rc = -EINVAL; - } - - } else { - pr_debug("[%s] Falling back to default MDP trigger\n", name); - host->dma_cmd_trigger = DSI_TRIGGER_SW; - } - - rc = of_property_read_u32(of_node, "qcom,mdss-dsi-te-pin-select", - &host->te_mode); - if (rc) { - pr_warn("[%s] fallback to default te-pin-select\n", name); - host->te_mode = 1; - rc = 0; - } - - return rc; -} - -static int dsi_panel_parse_misc_host_config(struct dsi_host_common_cfg *host, - struct device_node *of_node, - const char *name) -{ - u32 val = 0; - int rc = 0; - - rc = of_property_read_u32(of_node, "qcom,mdss-dsi-t-clk-post", &val); - if (rc) { - pr_debug("[%s] Fallback to default t_clk_post value\n", name); - host->t_clk_post = 0x03; - } else { - host->t_clk_post = val; - pr_debug("[%s] t_clk_post = %d\n", name, val); - } - - val = 0; - rc = of_property_read_u32(of_node, "qcom,mdss-dsi-t-clk-pre", &val); - if (rc) { - pr_debug("[%s] Fallback to default t_clk_pre value\n", name); - host->t_clk_pre = 0x24; - } else { - host->t_clk_pre = val; - pr_debug("[%s] t_clk_pre = %d\n", name, val); - } - - host->ignore_rx_eot = of_property_read_bool(of_node, - "qcom,mdss-dsi-rx-eot-ignore"); - - host->append_tx_eot = of_property_read_bool(of_node, - "qcom,mdss-dsi-tx-eot-append"); - - return 0; -} - -static int dsi_panel_parse_host_config(struct dsi_panel *panel, - struct device_node *of_node) -{ - int rc = 0; - - rc = dsi_panel_parse_pixel_format(&panel->host_config, of_node, - panel->name); - if (rc) { - pr_err("[%s] failed to get pixel format, rc=%d\n", - panel->name, rc); - goto error; - } - - rc = dsi_panel_parse_lane_states(&panel->host_config, of_node, - panel->name); - if (rc) { - pr_err("[%s] failed to parse lane states, rc=%d\n", - panel->name, rc); - goto error; - } - - rc = dsi_panel_parse_color_swap(&panel->host_config, of_node, - panel->name); - if (rc) { - pr_err("[%s] failed to parse color swap config, rc=%d\n", - panel->name, rc); - goto error; - } - - rc = dsi_panel_parse_triggers(&panel->host_config, of_node, - panel->name); - if (rc) { - pr_err("[%s] failed to parse triggers, rc=%d\n", - panel->name, rc); - goto error; - } - - rc = dsi_panel_parse_misc_host_config(&panel->host_config, of_node, - panel->name); - if (rc) { - pr_err("[%s] failed to parse misc host config, rc=%d\n", - panel->name, rc); - goto error; - } - -error: - return rc; -} - -static int dsi_panel_parse_dfps_caps(struct dsi_dfps_capabilities *dfps_caps, - struct device_node *of_node, - const char *name) -{ - int rc = 0; - bool supported = false; - const char *type; - u32 val = 0; - - supported = of_property_read_bool(of_node, - "qcom,mdss-dsi-pan-enable-dynamic-fps"); - - if (!supported) { - pr_debug("[%s] DFPS is not supported\n", name); - dfps_caps->dfps_support = false; - } else { - - type = of_get_property(of_node, - "qcom,mdss-dsi-pan-fps-update", - NULL); - if (!type) { - pr_err("[%s] dfps type not defined\n", name); - rc = -EINVAL; - goto error; - } else if (!strcmp(type, "dfps_suspend_resume_mode")) { - dfps_caps->type = DSI_DFPS_SUSPEND_RESUME; - } else if (!strcmp(type, "dfps_immediate_clk_mode")) { - dfps_caps->type = DSI_DFPS_IMMEDIATE_CLK; - } else if (!strcmp(type, "dfps_immediate_porch_mode_hfp")) { - dfps_caps->type = DSI_DFPS_IMMEDIATE_HFP; - } else if (!strcmp(type, "dfps_immediate_porch_mode_vfp")) { - dfps_caps->type = DSI_DFPS_IMMEDIATE_VFP; - } else { - pr_err("[%s] dfps type is not recognized\n", name); - rc = -EINVAL; - goto error; - } - - rc = of_property_read_u32(of_node, - "qcom,mdss-dsi-min-refresh-rate", - &val); - if (rc) { - pr_err("[%s] Min refresh rate is not defined\n", name); - rc = -EINVAL; - goto error; - } - dfps_caps->min_refresh_rate = val; - - rc = of_property_read_u32(of_node, - "qcom,mdss-dsi-max-refresh-rate", - &val); - if (rc) { - pr_debug("[%s] Using default refresh rate\n", name); - rc = of_property_read_u32(of_node, - "qcom,mdss-dsi-panel-framerate", - &val); - if (rc) { - pr_err("[%s] max refresh rate is not defined\n", - name); - rc = -EINVAL; - goto error; - } - } - dfps_caps->max_refresh_rate = val; - - if (dfps_caps->min_refresh_rate > dfps_caps->max_refresh_rate) { - pr_err("[%s] min rate > max rate\n", name); - rc = -EINVAL; - } - - pr_debug("[%s] DFPS is supported %d-%d, mode %d\n", name, - dfps_caps->min_refresh_rate, - dfps_caps->max_refresh_rate, - dfps_caps->type); - dfps_caps->dfps_support = true; - } - -error: - return rc; -} - -static int dsi_panel_parse_video_host_config(struct dsi_video_engine_cfg *cfg, - struct device_node *of_node, - const char *name) -{ - int rc = 0; - const char *traffic_mode; - u32 vc_id = 0; - u32 val = 0; - - rc = of_property_read_u32(of_node, "qcom,mdss-dsi-h-sync-pulse", &val); - if (rc) { - pr_debug("[%s] fallback to default h-sync-pulse\n", name); - cfg->pulse_mode_hsa_he = false; - } else if (val == 1) { - cfg->pulse_mode_hsa_he = true; - } else if (val == 0) { - cfg->pulse_mode_hsa_he = false; - } else { - pr_err("[%s] Unrecognized value for mdss-dsi-h-sync-pulse\n", - name); - rc = -EINVAL; - goto error; - } - - cfg->hfp_lp11_en = of_property_read_bool(of_node, - "qcom,mdss-dsi-hfp-power-mode"); - - cfg->hbp_lp11_en = of_property_read_bool(of_node, - "qcom,mdss-dsi-hbp-power-mode"); - - cfg->hsa_lp11_en = of_property_read_bool(of_node, - "qcom,mdss-dsi-hsa-power-mode"); - - cfg->last_line_interleave_en = of_property_read_bool(of_node, - "qcom,mdss-dsi-last-line-interleave"); - - cfg->eof_bllp_lp11_en = of_property_read_bool(of_node, - "qcom,mdss-dsi-bllp-eof-power-mode"); - - cfg->bllp_lp11_en = of_property_read_bool(of_node, - "qcom,mdss-dsi-bllp-power-mode"); - - traffic_mode = of_get_property(of_node, - "qcom,mdss-dsi-traffic-mode", - NULL); - if (!traffic_mode) { - pr_debug("[%s] Falling back to default traffic mode\n", name); - cfg->traffic_mode = DSI_VIDEO_TRAFFIC_SYNC_PULSES; - } else if (!strcmp(traffic_mode, "non_burst_sync_pulse")) { - cfg->traffic_mode = DSI_VIDEO_TRAFFIC_SYNC_PULSES; - } else if (!strcmp(traffic_mode, "non_burst_sync_event")) { - cfg->traffic_mode = DSI_VIDEO_TRAFFIC_SYNC_START_EVENTS; - } else if (!strcmp(traffic_mode, "burst_mode")) { - cfg->traffic_mode = DSI_VIDEO_TRAFFIC_BURST_MODE; - } else { - pr_err("[%s] Unrecognized traffic mode-%s\n", name, - traffic_mode); - rc = -EINVAL; - goto error; - } - - rc = of_property_read_u32(of_node, "qcom,mdss-dsi-virtual-channel-id", - &vc_id); - if (rc) { - pr_debug("[%s] Fallback to default vc id\n", name); - cfg->vc_id = 0; - } else { - cfg->vc_id = vc_id; - } - -error: - return rc; -} - -static int dsi_panel_parse_cmd_host_config(struct dsi_cmd_engine_cfg *cfg, - struct device_node *of_node, - const char *name) -{ - u32 val = 0; - int rc = 0; - - rc = of_property_read_u32(of_node, "qcom,mdss-dsi-wr-mem-start", &val); - if (rc) { - pr_debug("[%s] Fallback to default wr-mem-start\n", name); - cfg->wr_mem_start = 0x2C; - } else { - cfg->wr_mem_start = val; - } - - val = 0; - rc = of_property_read_u32(of_node, "qcom,mdss-dsi-wr-mem-continue", - &val); - if (rc) { - pr_debug("[%s] Fallback to default wr-mem-continue\n", name); - cfg->wr_mem_continue = 0x3C; - } else { - cfg->wr_mem_continue = val; - } - - /* TODO: fix following */ - cfg->max_cmd_packets_interleave = 0; - - val = 0; - rc = of_property_read_u32(of_node, "qcom,mdss-dsi-te-dcs-command", - &val); - if (rc) { - pr_debug("[%s] fallback to default te-dcs-cmd\n", name); - cfg->insert_dcs_command = true; - } else if (val == 1) { - cfg->insert_dcs_command = true; - } else if (val == 0) { - cfg->insert_dcs_command = false; - } else { - pr_err("[%s] Unrecognized value for mdss-dsi-te-dcs-command\n", - name); - rc = -EINVAL; - goto error; - } - - if (of_property_read_u32(of_node, "qcom,mdss-mdp-transfer-time-us", - &val)) { - pr_debug("[%s] Fallback to default transfer-time-us\n", name); - cfg->mdp_transfer_time_us = DEFAULT_MDP_TRANSFER_TIME; - } else { - cfg->mdp_transfer_time_us = val; - } - -error: - return rc; -} - -static int dsi_panel_parse_panel_mode(struct dsi_panel *panel, - struct device_node *of_node) -{ - int rc = 0; - enum dsi_op_mode panel_mode; - const char *mode; - - mode = of_get_property(of_node, "qcom,mdss-dsi-panel-type", NULL); - if (!mode) { - pr_debug("[%s] Fallback to default panel mode\n", panel->name); - panel_mode = DSI_OP_VIDEO_MODE; - } else if (!strcmp(mode, "dsi_video_mode")) { - panel_mode = DSI_OP_VIDEO_MODE; - } else if (!strcmp(mode, "dsi_cmd_mode")) { - panel_mode = DSI_OP_CMD_MODE; - } else { - pr_err("[%s] Unrecognized panel type-%s\n", panel->name, mode); - rc = -EINVAL; - goto error; - } - - if (panel_mode == DSI_OP_VIDEO_MODE) { - rc = dsi_panel_parse_video_host_config(&panel->video_config, - of_node, - panel->name); - if (rc) { - pr_err("[%s] Failed to parse video host cfg, rc=%d\n", - panel->name, rc); - goto error; - } - } - - if (panel_mode == DSI_OP_CMD_MODE) { - rc = dsi_panel_parse_cmd_host_config(&panel->cmd_config, - of_node, - panel->name); - if (rc) { - pr_err("[%s] Failed to parse cmd host config, rc=%d\n", - panel->name, rc); - goto error; - } - } - - panel->panel_mode = panel_mode; -error: - return rc; -} - -static int dsi_panel_parse_phy_props(struct dsi_panel_phy_props *props, - struct device_node *of_node, - const char *name) -{ - int rc = 0; - u32 val = 0; - const char *str; - - rc = of_property_read_u32(of_node, - "qcom,mdss-pan-physical-width-dimension", - &val); - if (rc) { - pr_debug("[%s] Physical panel width is not defined\n", name); - props->panel_width_mm = 0; - rc = 0; - } else { - props->panel_width_mm = val; - } - - rc = of_property_read_u32(of_node, - "qcom,mdss-pan-physical-height-dimension", - &val); - if (rc) { - pr_debug("[%s] Physical panel height is not defined\n", name); - props->panel_height_mm = 0; - rc = 0; - } else { - props->panel_height_mm = val; - } - - str = of_get_property(of_node, "qcom,mdss-dsi-panel-orientation", NULL); - if (!str) { - props->rotation = DSI_PANEL_ROTATE_NONE; - } else if (!strcmp(str, "180")) { - props->rotation = DSI_PANEL_ROTATE_HV_FLIP; - } else if (!strcmp(str, "hflip")) { - props->rotation = DSI_PANEL_ROTATE_H_FLIP; - } else if (!strcmp(str, "vflip")) { - props->rotation = DSI_PANEL_ROTATE_V_FLIP; - } else { - pr_err("[%s] Unrecognized panel rotation-%s\n", name, str); - rc = -EINVAL; - goto error; - } -error: - return rc; -} -const char *cmd_set_prop_map[DSI_CMD_SET_MAX] = { - "qcom,mdss-dsi-pre-on-command", - "qcom,mdss-dsi-on-command", - "qcom,mdss-dsi-post-panel-on-command", - "qcom,mdss-dsi-pre-off-command", - "qcom,mdss-dsi-off-command", - "qcom,mdss-dsi-post-off-command", - "qcom,mdss-dsi-pre-res-switch", - "qcom,mdss-dsi-res-switch", - "qcom,mdss-dsi-post-res-switch", - "qcom,cmd-to-video-mode-switch-commands", - "qcom,cmd-to-video-mode-post-switch-commands", - "qcom,video-to-cmd-mode-switch-commands", - "qcom,video-to-cmd-mode-post-switch-commands", - "qcom,mdss-dsi-panel-status-command", - "qcom,mdss-dsi-lp1-command", - "qcom,mdss-dsi-lp2-command", - "qcom,mdss-dsi-nolp-command", - "PPS not parsed from DTSI, generated dynamically", - "qcom,mdss-dsi-timing-switch-command", - "qcom,mdss-dsi-post-mode-switch-on-command", -}; - -const char *cmd_set_state_map[DSI_CMD_SET_MAX] = { - "qcom,mdss-dsi-pre-on-command-state", - "qcom,mdss-dsi-on-command-state", - "qcom,mdss-dsi-post-on-command-state", - "qcom,mdss-dsi-pre-off-command-state", - "qcom,mdss-dsi-off-command-state", - "qcom,mdss-dsi-post-off-command-state", - "qcom,mdss-dsi-pre-res-switch-state", - "qcom,mdss-dsi-res-switch-state", - "qcom,mdss-dsi-post-res-switch-state", - "qcom,cmd-to-video-mode-switch-commands-state", - "qcom,cmd-to-video-mode-post-switch-commands-state", - "qcom,video-to-cmd-mode-switch-commands-state", - "qcom,video-to-cmd-mode-post-switch-commands-state", - "qcom,mdss-dsi-panel-status-command-state", - "qcom,mdss-dsi-lp1-command-state", - "qcom,mdss-dsi-lp2-command-state", - "qcom,mdss-dsi-nolp-command-state", - "PPS not parsed from DTSI, generated dynamically", - "qcom,mdss-dsi-timing-switch-command-state", - "qcom,mdss-dsi-post-mode-switch-on-command-state", -}; - -static int dsi_panel_get_cmd_pkt_count(const char *data, u32 length, u32 *cnt) -{ - const u32 cmd_set_min_size = 7; - u32 count = 0; - u32 packet_length; - u32 tmp; - - while (length >= cmd_set_min_size) { - packet_length = cmd_set_min_size; - tmp = ((data[5] << 8) | (data[6])); - packet_length += tmp; - if (packet_length > length) { - pr_err("format error\n"); - return -EINVAL; - } - length -= packet_length; - data += packet_length; - count++; - }; - - *cnt = count; - return 0; -} - -static int dsi_panel_create_cmd_packets(const char *data, - u32 length, - u32 count, - struct dsi_cmd_desc *cmd) -{ - int rc = 0; - int i, j; - u8 *payload; - - for (i = 0; i < count; i++) { - u32 size; - - cmd[i].msg.type = data[0]; - cmd[i].last_command = (data[1] == 1 ? true : false); - cmd[i].msg.channel = data[2]; - cmd[i].msg.flags |= (data[3] == 1 ? MIPI_DSI_MSG_REQ_ACK : 0); - cmd[i].msg.ctrl = 0; - cmd[i].post_wait_ms = data[4]; - cmd[i].msg.tx_len = ((data[5] << 8) | (data[6])); - - size = cmd[i].msg.tx_len * sizeof(u8); - - payload = kzalloc(size, GFP_KERNEL); - if (!payload) { - rc = -ENOMEM; - goto error_free_payloads; - } - - for (j = 0; j < cmd[i].msg.tx_len; j++) - payload[j] = data[7 + j]; - - cmd[i].msg.tx_buf = payload; - data += (7 + cmd[i].msg.tx_len); - } - - return rc; -error_free_payloads: - for (i = i - 1; i >= 0; i--) { - cmd--; - kfree(cmd->msg.tx_buf); - } - - return rc; -} - -void dsi_panel_destroy_cmd_packets(struct dsi_panel_cmd_set *set) -{ - u32 i = 0; - struct dsi_cmd_desc *cmd; - - for (i = 0; i < set->count; i++) { - cmd = &set->cmds[i]; - kfree(cmd->msg.tx_buf); - } - - kfree(set->cmds); -} - -static int dsi_panel_alloc_cmd_packets(struct dsi_panel_cmd_set *cmd, - u32 packet_count) -{ - u32 size; - - size = packet_count * sizeof(*cmd->cmds); - cmd->cmds = kzalloc(size, GFP_KERNEL); - if (!cmd->cmds) - return -ENOMEM; - - cmd->count = packet_count; - return 0; -} - -static int dsi_panel_parse_cmd_sets_sub(struct dsi_panel_cmd_set *cmd, - enum dsi_cmd_set_type type, - struct device_node *of_node) -{ - int rc = 0; - u32 length = 0; - const char *data; - const char *state; - u32 packet_count = 0; - - data = of_get_property(of_node, cmd_set_prop_map[type], &length); - if (!data) { - pr_debug("%s commands not defined\n", cmd_set_prop_map[type]); - rc = -ENOTSUPP; - goto error; - } - - rc = dsi_panel_get_cmd_pkt_count(data, length, &packet_count); - if (rc) { - pr_err("commands failed, rc=%d\n", rc); - goto error; - } - pr_debug("[%s] packet-count=%d, %d\n", cmd_set_prop_map[type], - packet_count, length); - - rc = dsi_panel_alloc_cmd_packets(cmd, packet_count); - if (rc) { - pr_err("failed to allocate cmd packets, rc=%d\n", rc); - goto error; - } - - rc = dsi_panel_create_cmd_packets(data, length, packet_count, - cmd->cmds); - if (rc) { - pr_err("failed to create cmd packets, rc=%d\n", rc); - goto error_free_mem; - } - - state = of_get_property(of_node, cmd_set_state_map[type], NULL); - if (!state || !strcmp(state, "dsi_lp_mode")) { - cmd->state = DSI_CMD_SET_STATE_LP; - } else if (!strcmp(state, "dsi_hs_mode")) { - cmd->state = DSI_CMD_SET_STATE_HS; - } else { - pr_err("[%s] command state unrecognized-%s\n", - cmd_set_state_map[type], state); - goto error_free_mem; - } - - return rc; -error_free_mem: - kfree(cmd->cmds); - cmd->cmds = NULL; -error: - return rc; - -} - -static int dsi_panel_parse_cmd_sets( - struct dsi_display_mode_priv_info *priv_info, - struct device_node *of_node) -{ - int rc = 0; - struct dsi_panel_cmd_set *set; - u32 i; - - if (!priv_info) { - pr_err("invalid mode priv info\n"); - return -EINVAL; - } - - for (i = DSI_CMD_SET_PRE_ON; i < DSI_CMD_SET_MAX; i++) { - set = &priv_info->cmd_sets[i]; - set->type = i; - set->count = 0; - - if (i == DSI_CMD_SET_PPS) { - rc = dsi_panel_alloc_cmd_packets(set, 1); - if (rc) - pr_err("failed to allocate cmd set %d, rc = %d\n", - i, rc); - set->state = DSI_CMD_SET_STATE_LP; - } else { - rc = dsi_panel_parse_cmd_sets_sub(set, i, of_node); - if (rc) - pr_debug("failed to parse set %d\n", i); - } - } - - rc = 0; - return rc; -} - -static int dsi_panel_parse_reset_sequence(struct dsi_panel *panel, - struct device_node *of_node) -{ - int rc = 0; - int i; - u32 length = 0; - u32 count = 0; - u32 size = 0; - u32 *arr_32 = NULL; - const u32 *arr; - struct dsi_reset_seq *seq; - - arr = of_get_property(of_node, "qcom,mdss-dsi-reset-sequence", &length); - if (!arr) { - pr_err("[%s] dsi-reset-sequence not found\n", panel->name); - rc = -EINVAL; - goto error; - } - if (length & 0x1) { - pr_err("[%s] syntax error for dsi-reset-sequence\n", - panel->name); - rc = -EINVAL; - goto error; - } - - pr_err("RESET SEQ LENGTH = %d\n", length); - length = length / sizeof(u32); - - size = length * sizeof(u32); - - arr_32 = kzalloc(size, GFP_KERNEL); - if (!arr_32) { - rc = -ENOMEM; - goto error; - } - - rc = of_property_read_u32_array(of_node, "qcom,mdss-dsi-reset-sequence", - arr_32, length); - if (rc) { - pr_err("[%s] cannot read dso-reset-seqience\n", panel->name); - goto error_free_arr_32; - } - - count = length / 2; - size = count * sizeof(*seq); - seq = kzalloc(size, GFP_KERNEL); - if (!seq) { - rc = -ENOMEM; - goto error_free_arr_32; - } - - panel->reset_config.sequence = seq; - panel->reset_config.count = count; - - for (i = 0; i < length; i += 2) { - seq->level = arr_32[i]; - seq->sleep_ms = arr_32[i + 1]; - seq++; - } - - -error_free_arr_32: - kfree(arr_32); -error: - return rc; -} - -static int dsi_panel_parse_misc_features(struct dsi_panel *panel, - struct device_node *of_node) -{ - panel->ulps_enabled = - of_property_read_bool(of_node, "qcom,ulps-enabled"); - - if (panel->ulps_enabled) - pr_debug("ulps_enabled:%d\n", panel->ulps_enabled); - - panel->te_using_watchdog_timer = of_property_read_bool(of_node, - "qcom,mdss-dsi-te-using-wd"); - - panel->sync_broadcast_en = of_property_read_bool(of_node, - "qcom,cmd-sync-wait-broadcast"); - return 0; -} - -static int dsi_panel_parse_jitter_config( - struct dsi_display_mode *mode, - struct device_node *of_node) -{ - int rc; - struct dsi_display_mode_priv_info *priv_info; - u32 jitter[DEFAULT_PANEL_JITTER_ARRAY_SIZE] = {0, 0}; - u64 jitter_val = 0; - - priv_info = mode->priv_info; - - rc = of_property_read_u32_array(of_node, "qcom,mdss-dsi-panel-jitter", - jitter, DEFAULT_PANEL_JITTER_ARRAY_SIZE); - if (rc) { - pr_debug("panel jitter not defined rc=%d\n", rc); - } else { - jitter_val = jitter[0]; - jitter_val = div_u64(jitter_val, jitter[1]); - } - - if (rc || !jitter_val || (jitter_val > MAX_PANEL_JITTER)) { - priv_info->panel_jitter_numer = DEFAULT_PANEL_JITTER_NUMERATOR; - priv_info->panel_jitter_denom = - DEFAULT_PANEL_JITTER_DENOMINATOR; - } else { - priv_info->panel_jitter_numer = jitter[0]; - priv_info->panel_jitter_denom = jitter[1]; - } - - rc = of_property_read_u32(of_node, "qcom,mdss-dsi-panel-prefill-lines", - &priv_info->panel_prefill_lines); - if (rc) { - pr_debug("panel prefill lines are not defined rc=%d\n", rc); - priv_info->panel_prefill_lines = DEFAULT_PANEL_PREFILL_LINES; - } else if (priv_info->panel_prefill_lines >= - DSI_V_TOTAL(&mode->timing)) { - pr_debug("invalid prefill lines config=%d setting to:%d\n", - priv_info->panel_prefill_lines, DEFAULT_PANEL_PREFILL_LINES); - - priv_info->panel_prefill_lines = DEFAULT_PANEL_PREFILL_LINES; - } - - return 0; -} - -static int dsi_panel_parse_power_cfg(struct device *parent, - struct dsi_panel *panel, - struct device_node *of_node) -{ - int rc = 0; - - rc = dsi_pwr_of_get_vreg_data(of_node, - &panel->power_info, - "qcom,panel-supply-entries"); - if (rc) { - pr_err("[%s] failed to parse vregs\n", panel->name); - goto error; - } - -error: - return rc; -} - -static int dsi_panel_parse_gpios(struct dsi_panel *panel, - struct device_node *of_node) -{ - int rc = 0; - const char *data; - - panel->reset_config.reset_gpio = of_get_named_gpio(of_node, - "qcom,platform-reset-gpio", - 0); - if (!gpio_is_valid(panel->reset_config.reset_gpio)) { - pr_err("[%s] failed get reset gpio, rc=%d\n", panel->name, rc); - rc = -EINVAL; - goto error; - } - - panel->reset_config.disp_en_gpio = of_get_named_gpio(of_node, - "qcom,5v-boost-gpio", - 0); - if (!gpio_is_valid(panel->reset_config.disp_en_gpio)) { - pr_debug("[%s] 5v-boot-gpio is not set, rc=%d\n", - panel->name, rc); - panel->reset_config.disp_en_gpio = of_get_named_gpio(of_node, - "qcom,platform-en-gpio", - 0); - if (!gpio_is_valid(panel->reset_config.disp_en_gpio)) { - pr_debug("[%s] platform-en-gpio is not set, rc=%d\n", - panel->name, rc); - } - } - - panel->reset_config.lcd_mode_sel_gpio = of_get_named_gpio(of_node, - "qcom,panel-mode-gpio", 0); - if (!gpio_is_valid(panel->reset_config.lcd_mode_sel_gpio)) - pr_debug("%s:%d mode gpio not specified\n", __func__, __LINE__); - - data = of_get_property(of_node, - "qcom,mdss-dsi-mode-sel-gpio-state", NULL); - if (data) { - if (!strcmp(data, "single_port")) - panel->reset_config.mode_sel_state = - MODE_SEL_SINGLE_PORT; - else if (!strcmp(data, "dual_port")) - panel->reset_config.mode_sel_state = - MODE_SEL_DUAL_PORT; - else if (!strcmp(data, "high")) - panel->reset_config.mode_sel_state = - MODE_GPIO_HIGH; - else if (!strcmp(data, "low")) - panel->reset_config.mode_sel_state = - MODE_GPIO_LOW; - } else { - /* Set default mode as SPLIT mode */ - panel->reset_config.mode_sel_state = MODE_SEL_DUAL_PORT; - } - - /* TODO: release memory */ - rc = dsi_panel_parse_reset_sequence(panel, of_node); - if (rc) { - pr_err("[%s] failed to parse reset sequence, rc=%d\n", - panel->name, rc); - goto error; - } - -error: - return rc; -} - -static int dsi_panel_parse_bl_pwm_config(struct dsi_backlight_config *config, - struct device_node *of_node) -{ - int rc = 0; - u32 val; - - rc = of_property_read_u32(of_node, "qcom,dsi-bl-pmic-bank-select", - &val); - if (rc) { - pr_err("bl-pmic-bank-select is not defined, rc=%d\n", rc); - goto error; - } - config->pwm_pmic_bank = val; - - rc = of_property_read_u32(of_node, "qcom,dsi-bl-pmic-pwm-frequency", - &val); - if (rc) { - pr_err("bl-pmic-bank-select is not defined, rc=%d\n", rc); - goto error; - } - config->pwm_period_usecs = val; - - config->pwm_pmi_control = of_property_read_bool(of_node, - "qcom,mdss-dsi-bl-pwm-pmi"); - - config->pwm_gpio = of_get_named_gpio(of_node, - "qcom,mdss-dsi-pwm-gpio", - 0); - if (!gpio_is_valid(config->pwm_gpio)) { - pr_err("pwm gpio is invalid\n"); - rc = -EINVAL; - goto error; - } - -error: - return rc; -} - -static int dsi_panel_parse_bl_config(struct dsi_panel *panel, - struct device_node *of_node) -{ - int rc = 0; - const char *bl_type; - u32 val = 0; - - bl_type = of_get_property(of_node, - "qcom,mdss-dsi-bl-pmic-control-type", - NULL); - if (!bl_type) { - panel->bl_config.type = DSI_BACKLIGHT_UNKNOWN; - } else if (!strcmp(bl_type, "bl_ctrl_pwm")) { - panel->bl_config.type = DSI_BACKLIGHT_PWM; - } else if (!strcmp(bl_type, "bl_ctrl_wled")) { - panel->bl_config.type = DSI_BACKLIGHT_WLED; - } else if (!strcmp(bl_type, "bl_ctrl_dcs")) { - panel->bl_config.type = DSI_BACKLIGHT_DCS; - } else { - pr_debug("[%s] bl-pmic-control-type unknown-%s\n", - panel->name, bl_type); - panel->bl_config.type = DSI_BACKLIGHT_UNKNOWN; - } - - panel->bl_config.bl_scale = MAX_BL_SCALE_LEVEL; - panel->bl_config.bl_scale_ad = MAX_AD_BL_SCALE_LEVEL; - - rc = of_property_read_u32(of_node, "qcom,mdss-dsi-bl-min-level", &val); - if (rc) { - pr_debug("[%s] bl-min-level unspecified, defaulting to zero\n", - panel->name); - panel->bl_config.bl_min_level = 0; - } else { - panel->bl_config.bl_min_level = val; - } - - rc = of_property_read_u32(of_node, "qcom,mdss-dsi-bl-max-level", &val); - if (rc) { - pr_debug("[%s] bl-max-level unspecified, defaulting to max level\n", - panel->name); - panel->bl_config.bl_max_level = MAX_BL_LEVEL; - } else { - panel->bl_config.bl_max_level = val; - } - - rc = of_property_read_u32(of_node, "qcom,mdss-brightness-max-level", - &val); - if (rc) { - pr_debug("[%s] brigheness-max-level unspecified, defaulting to 255\n", - panel->name); - panel->bl_config.brightness_max_level = 255; - } else { - panel->bl_config.brightness_max_level = val; - } - - if (panel->bl_config.type == DSI_BACKLIGHT_PWM) { - rc = dsi_panel_parse_bl_pwm_config(&panel->bl_config, of_node); - if (rc) { - pr_err("[%s] failed to parse pwm config, rc=%d\n", - panel->name, rc); - goto error; - } - } - - panel->bl_config.en_gpio = of_get_named_gpio(of_node, - "qcom,platform-bklight-en-gpio", - 0); - if (!gpio_is_valid(panel->bl_config.en_gpio)) { - pr_debug("[%s] failed get bklt gpio, rc=%d\n", panel->name, rc); - rc = 0; - goto error; - } - -error: - return rc; -} - -void dsi_dsc_pclk_param_calc(struct msm_display_dsc_info *dsc, int intf_width) -{ - int slice_per_pkt, slice_per_intf; - int bytes_in_slice, total_bytes_per_intf; - - if (!dsc || !dsc->slice_width || !dsc->slice_per_pkt || - (intf_width < dsc->slice_width)) { - pr_err("invalid input, intf_width=%d slice_width=%d\n", - intf_width, dsc ? dsc->slice_width : -1); - return; - } - - slice_per_pkt = dsc->slice_per_pkt; - slice_per_intf = DIV_ROUND_UP(intf_width, dsc->slice_width); - - /* - * If slice_per_pkt is greater than slice_per_intf then default to 1. - * This can happen during partial update. - */ - if (slice_per_pkt > slice_per_intf) - slice_per_pkt = 1; - - bytes_in_slice = DIV_ROUND_UP(dsc->slice_width * dsc->bpp, 8); - total_bytes_per_intf = bytes_in_slice * slice_per_intf; - - dsc->eol_byte_num = total_bytes_per_intf % 3; - dsc->pclk_per_line = DIV_ROUND_UP(total_bytes_per_intf, 3); - dsc->bytes_in_slice = bytes_in_slice; - dsc->bytes_per_pkt = bytes_in_slice * slice_per_pkt; - dsc->pkt_per_line = slice_per_intf / slice_per_pkt; -} - - -int dsi_dsc_populate_static_param(struct msm_display_dsc_info *dsc) -{ - int bpp, bpc; - int mux_words_size; - 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 target_bpp_x16; - int data; - int final_value, final_scale; - int ratio_index; - - dsc->version = 0x11; - dsc->scr_rev = 0; - dsc->rc_model_size = 8192; - if (dsc->version == 0x11 && dsc->scr_rev == 0x1) - dsc->first_line_bpg_offset = 15; - else - dsc->first_line_bpg_offset = 12; - - dsc->edge_factor = 6; - dsc->tgt_offset_hi = 3; - dsc->tgt_offset_lo = 3; - dsc->enable_422 = 0; - dsc->convert_rgb = 1; - dsc->vbr_enable = 0; - - dsc->buf_thresh = dsi_dsc_rc_buf_thresh; - - bpp = dsc->bpp; - bpc = dsc->bpc; - - if (bpc == 12) - ratio_index = DSC_12BPC_8BPP; - else if (bpc == 10) - ratio_index = DSC_10BPC_8BPP; - else - ratio_index = DSC_8BPC_8BPP; - - if (dsc->version == 0x11 && dsc->scr_rev == 0x1) { - dsc->range_min_qp = - dsi_dsc_rc_range_min_qp_1_1_scr1[ratio_index]; - dsc->range_max_qp = - dsi_dsc_rc_range_max_qp_1_1_scr1[ratio_index]; - } else { - dsc->range_min_qp = dsi_dsc_rc_range_min_qp_1_1[ratio_index]; - dsc->range_max_qp = dsi_dsc_rc_range_max_qp_1_1[ratio_index]; - } - dsc->range_bpg_offset = dsi_dsc_rc_range_bpg_offset; - - if (bpp == 8) - dsc->initial_offset = 6144; - else - dsc->initial_offset = 2048; /* bpp = 12 */ - - if (bpc == 12) - mux_words_size = 64; - else - mux_words_size = 48; /* bpc == 8/10 */ - - if (bpc == 8) { - dsc->line_buf_depth = 9; - dsc->input_10_bits = 0; - dsc->min_qp_flatness = 3; - dsc->max_qp_flatness = 12; - dsc->quant_incr_limit0 = 11; - dsc->quant_incr_limit1 = 11; - } else if (bpc == 10) { /* 10bpc */ - dsc->line_buf_depth = 11; - dsc->input_10_bits = 1; - dsc->min_qp_flatness = 7; - dsc->max_qp_flatness = 16; - dsc->quant_incr_limit0 = 15; - dsc->quant_incr_limit1 = 15; - } else { /* 12 bpc */ - dsc->line_buf_depth = 9; - dsc->input_10_bits = 0; - dsc->min_qp_flatness = 11; - dsc->max_qp_flatness = 20; - dsc->quant_incr_limit0 = 19; - dsc->quant_incr_limit1 = 19; - } - - dsc->slice_last_group_size = 3 - (dsc->slice_width % 3); - - dsc->det_thresh_flatness = 7 + 2*(bpc - 8); - - dsc->initial_xmit_delay = dsc->rc_model_size / (2 * bpp); - - groups_per_line = DIV_ROUND_UP(dsc->slice_width, 3); - - dsc->chunk_size = dsc->slice_width * bpp / 8; - if ((dsc->slice_width * bpp) % 8) - dsc->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->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 * (mux_words_size + (4 * bpc + 4) - 2); - - num_extra_mux_bits = pre_num_extra_mux_bits - (mux_words_size - - ((slice_bits - pre_num_extra_mux_bits) % mux_words_size)); - - data = 2048 * (dsc->rc_model_size - dsc->initial_offset - + num_extra_mux_bits); - dsc->slice_bpg_offset = DIV_ROUND_UP(data, groups_total); - - /* bpp * 16 + 0.5 */ - data = bpp * 16; - data *= 2; - data++; - data /= 2; - target_bpp_x16 = data; - - data = (dsc->initial_xmit_delay * target_bpp_x16) / 16; - 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; -} - - -static int dsi_panel_parse_phy_timing(struct dsi_display_mode *mode, - struct device_node *of_node) -{ - const char *data; - u32 len, i; - int rc = 0; - struct dsi_display_mode_priv_info *priv_info; - - priv_info = mode->priv_info; - - data = of_get_property(of_node, - "qcom,mdss-dsi-panel-phy-timings", &len); - if (!data) { - pr_debug("Unable to read Phy timing settings"); - } else { - priv_info->phy_timing_val = - kzalloc((sizeof(u32) * len), GFP_KERNEL); - if (!priv_info->phy_timing_val) - return -EINVAL; - - for (i = 0; i < len; i++) - priv_info->phy_timing_val[i] = data[i]; - - priv_info->phy_timing_len = len; - }; - - mode->pixel_clk_khz = (DSI_H_TOTAL(&mode->timing) * - DSI_V_TOTAL(&mode->timing) * - mode->timing.refresh_rate) / 1000; - return rc; -} - -static int dsi_panel_parse_dsc_params(struct dsi_display_mode *mode, - struct device_node *of_node) -{ - u32 data; - int rc = -EINVAL; - int intf_width; - const char *compression; - struct dsi_display_mode_priv_info *priv_info; - - if (!mode || !mode->priv_info) - return -EINVAL; - - priv_info = mode->priv_info; - - priv_info->dsc_enabled = false; - compression = of_get_property(of_node, "qcom,compression-mode", NULL); - if (compression && !strcmp(compression, "dsc")) - priv_info->dsc_enabled = true; - - if (!priv_info->dsc_enabled) { - pr_debug("dsc compression is not enabled for the mode"); - return 0; - } - - rc = of_property_read_u32(of_node, "qcom,mdss-dsc-slice-height", &data); - if (rc) { - pr_err("failed to parse qcom,mdss-dsc-slice-height\n"); - goto error; - } - priv_info->dsc.slice_height = data; - - rc = of_property_read_u32(of_node, "qcom,mdss-dsc-slice-width", &data); - if (rc) { - pr_err("failed to parse qcom,mdss-dsc-slice-width\n"); - goto error; - } - priv_info->dsc.slice_width = data; - - intf_width = mode->timing.h_active; - if (intf_width % priv_info->dsc.slice_width) { - pr_err("invalid slice width for the panel\n"); - goto error; - } - - priv_info->dsc.pic_width = mode->timing.h_active; - priv_info->dsc.pic_height = mode->timing.v_active; - - rc = of_property_read_u32(of_node, "qcom,mdss-dsc-slice-per-pkt", - &data); - if (rc) { - pr_err("failed to parse qcom,mdss-dsc-slice-per-pkt\n"); - goto error; - } - priv_info->dsc.slice_per_pkt = data; - - rc = of_property_read_u32(of_node, "qcom,mdss-dsc-bit-per-component", - &data); - if (rc) { - pr_err("failed to parse qcom,mdss-dsc-bit-per-component\n"); - goto error; - } - priv_info->dsc.bpc = data; - - rc = of_property_read_u32(of_node, "qcom,mdss-dsc-bit-per-pixel", - &data); - if (rc) { - pr_err("failed to parse qcom,mdss-dsc-bit-per-pixel\n"); - goto error; - } - priv_info->dsc.bpp = data; - - priv_info->dsc.block_pred_enable = of_property_read_bool(of_node, - "qcom,mdss-dsc-block-prediction-enable"); - - priv_info->dsc.full_frame_slices = DIV_ROUND_UP(intf_width, - priv_info->dsc.slice_width); - - dsi_dsc_populate_static_param(&priv_info->dsc); - dsi_dsc_pclk_param_calc(&priv_info->dsc, intf_width); - -error: - return rc; -} - -static int dsi_panel_parse_hdr_config(struct dsi_panel *panel, - struct device_node *of_node) -{ - - int rc = 0; - struct drm_panel_hdr_properties *hdr_prop; - - hdr_prop = &panel->hdr_props; - hdr_prop->hdr_enabled = of_property_read_bool(of_node, - "qcom,mdss-dsi-panel-hdr-enabled"); - - if (hdr_prop->hdr_enabled) { - rc = of_property_read_u32_array(of_node, - "qcom,mdss-dsi-panel-hdr-color-primaries", - hdr_prop->display_primaries, - DISPLAY_PRIMARIES_MAX); - if (rc) { - pr_err("%s:%d, Unable to read color primaries,rc:%u", - __func__, __LINE__, rc); - hdr_prop->hdr_enabled = false; - return rc; - } - - rc = of_property_read_u32(of_node, - "qcom,mdss-dsi-panel-peak-brightness", - &(hdr_prop->peak_brightness)); - if (rc) { - pr_err("%s:%d, Unable to read hdr brightness, rc:%u", - __func__, __LINE__, rc); - hdr_prop->hdr_enabled = false; - return rc; - } - - rc = of_property_read_u32(of_node, - "qcom,mdss-dsi-panel-blackness-level", - &(hdr_prop->blackness_level)); - if (rc) { - pr_err("%s:%d, Unable to read hdr brightness, rc:%u", - __func__, __LINE__, rc); - hdr_prop->hdr_enabled = false; - return rc; - } - } - return 0; -} - -static int dsi_panel_parse_topology( - struct dsi_display_mode_priv_info *priv_info, - struct device_node *of_node, int topology_override) -{ - struct msm_display_topology *topology; - u32 top_count, top_sel, *array = NULL; - int i, len = 0; - int rc = -EINVAL; - - len = of_property_count_u32_elems(of_node, "qcom,display-topology"); - if (len <= 0 || len % TOPOLOGY_SET_LEN || - len > (TOPOLOGY_SET_LEN * MAX_TOPOLOGY)) { - pr_err("invalid topology list for the panel, rc = %d\n", rc); - return rc; - } - - top_count = len / TOPOLOGY_SET_LEN; - - array = kcalloc(len, sizeof(u32), GFP_KERNEL); - if (!array) - return -ENOMEM; - - rc = of_property_read_u32_array(of_node, - "qcom,display-topology", array, len); - if (rc) { - pr_err("unable to read the display topologies, rc = %d\n", rc); - goto read_fail; - } - - topology = kcalloc(top_count, sizeof(*topology), GFP_KERNEL); - if (!topology) { - rc = -ENOMEM; - goto read_fail; - } - - for (i = 0; i < top_count; i++) { - struct msm_display_topology *top = &topology[i]; - - top->num_lm = array[i * TOPOLOGY_SET_LEN]; - top->num_enc = array[i * TOPOLOGY_SET_LEN + 1]; - top->num_intf = array[i * TOPOLOGY_SET_LEN + 2]; - }; - - if (topology_override >= 0 && topology_override < top_count) { - pr_debug("override topology: cfg:%d lm:%d comp_enc:%d intf:%d\n", - topology_override, - topology[topology_override].num_lm, - topology[topology_override].num_enc, - topology[topology_override].num_intf); - top_sel = topology_override; - goto parse_done; - } - - rc = of_property_read_u32(of_node, - "qcom,default-topology-index", &top_sel); - if (rc) { - pr_err("no default topology selected, rc = %d\n", rc); - goto parse_fail; - } - - if (top_sel >= top_count) { - rc = -EINVAL; - pr_err("default topology is specified is not valid, rc = %d\n", - rc); - goto parse_fail; - } - - pr_debug("default topology: lm: %d comp_enc:%d intf: %d\n", - topology[top_sel].num_lm, - topology[top_sel].num_enc, - topology[top_sel].num_intf); - -parse_done: - memcpy(&priv_info->topology, &topology[top_sel], - sizeof(struct msm_display_topology)); -parse_fail: - kfree(topology); -read_fail: - kfree(array); - - return rc; -} - -static int dsi_panel_parse_dms_info(struct dsi_panel *panel, - struct device_node *of_node) -{ - int dms_enabled; - const char *data; - - if (!of_node || !panel) { - pr_err("invalid params\n"); - return -EINVAL; - } - - panel->dms_mode = DSI_DMS_MODE_DISABLED; - dms_enabled = of_property_read_bool(of_node, - "qcom,dynamic-mode-switch-enabled"); - if (!dms_enabled) - return 0; - - data = of_get_property(of_node, "qcom,dynamic-mode-switch-type", NULL); - if (data && !strcmp(data, "dynamic-resolution-switch-immediate")) { - panel->dms_mode = DSI_DMS_MODE_RES_SWITCH_IMMEDIATE; - } else { - pr_err("[%s] unsupported dynamic switch mode: %s\n", - panel->name, data); - return -EINVAL; - } - - return 0; -}; - -/* - * The length of all the valid values to be checked should not be greater - * than the length of returned data from read command. - */ -static bool -dsi_panel_parse_esd_check_valid_params(struct dsi_panel *panel, u32 count) -{ - int i; - struct drm_panel_esd_config *config = &panel->esd_config; - - for (i = 0; i < count; ++i) { - if (config->status_valid_params[i] > - config->status_cmds_rlen[i]) { - pr_debug("ignore valid params\n"); - return false; - } - } - - return true; -} - -static bool dsi_panel_parse_esd_status_len(struct device_node *np, - char *prop_key, u32 **target, u32 cmd_cnt) -{ - int tmp; - - if (!of_find_property(np, prop_key, &tmp)) - return false; - - tmp /= sizeof(u32); - if (tmp != cmd_cnt) { - pr_err("request property(%d) do not match cmd count(%d)\n", - tmp, cmd_cnt); - return false; - } - - *target = kcalloc(tmp, sizeof(u32), GFP_KERNEL); - if (IS_ERR_OR_NULL(*target)) { - pr_err("Error allocating memory for property\n"); - return false; - } - - if (of_property_read_u32_array(np, prop_key, *target, tmp)) { - pr_err("cannot get values from dts\n"); - kfree(*target); - *target = NULL; - return false; - } - - return true; -} - -static void dsi_panel_esd_config_deinit(struct drm_panel_esd_config *esd_config) -{ - kfree(esd_config->return_buf); - kfree(esd_config->status_value); - kfree(esd_config->status_valid_params); - kfree(esd_config->status_cmds_rlen); - kfree(esd_config->status_cmd.cmds); -} - -static int dsi_panel_parse_esd_config(struct dsi_panel *panel, - struct device_node *of_node) -{ - int rc = 0; - u32 tmp; - u32 i, status_len, *lenp; - struct property *data; - const char *string; - struct drm_panel_esd_config *esd_config; - - esd_config = &panel->esd_config; - esd_config->esd_enabled = of_property_read_bool(of_node, - "qcom,esd-check-enabled"); - - if (!esd_config->esd_enabled) - return 0; - - rc = of_property_read_string(of_node, - "qcom,mdss-dsi-panel-status-check-mode", &string); - if (!rc) { - if (!strcmp(string, "bta_check")) { - esd_config->status_mode = ESD_MODE_SW_BTA; - } else if (!strcmp(string, "reg_read")) { - esd_config->status_mode = ESD_MODE_REG_READ; - } else if (!strcmp(string, "te_signal_check")) { - if (panel->panel_mode == DSI_OP_CMD_MODE) { - esd_config->status_mode = ESD_MODE_PANEL_TE; - } else { - pr_err("TE-ESD not valid for video mode\n"); - rc = -EINVAL; - goto error; - } - } else { - pr_err("No valid panel-status-check-mode string\n"); - rc = -EINVAL; - goto error; - } - } else { - pr_debug("status check method not defined!\n"); - rc = -EINVAL; - goto error; - } - - if ((esd_config->status_mode == ESD_MODE_SW_BTA) || - (esd_config->status_mode == ESD_MODE_PANEL_TE)) - return 0; - - dsi_panel_parse_cmd_sets_sub(&esd_config->status_cmd, - DSI_CMD_SET_PANEL_STATUS, of_node); - if (!esd_config->status_cmd.count) { - pr_err("panel status command parsing failed\n"); - rc = -EINVAL; - goto error; - } - - if (!dsi_panel_parse_esd_status_len(of_node, - "qcom,mdss-dsi-panel-status-read-length", - &panel->esd_config.status_cmds_rlen, - esd_config->status_cmd.count)) { - pr_err("Invalid status read length\n"); - rc = -EINVAL; - goto error1; - } - - if (dsi_panel_parse_esd_status_len(of_node, - "qcom,mdss-dsi-panel-status-valid-params", - &panel->esd_config.status_valid_params, - esd_config->status_cmd.count)) { - if (!dsi_panel_parse_esd_check_valid_params(panel, - esd_config->status_cmd.count)) { - rc = -EINVAL; - goto error2; - } - } - - status_len = 0; - lenp = esd_config->status_valid_params ?: esd_config->status_cmds_rlen; - for (i = 0; i < esd_config->status_cmd.count; ++i) - status_len += lenp[i]; - - if (!status_len) { - rc = -EINVAL; - goto error2; - } - - /* - * Some panel may need multiple read commands to properly - * check panel status. Do a sanity check for proper status - * value which will be compared with the value read by dsi - * controller during ESD check. Also check if multiple read - * commands are there then, there should be corresponding - * status check values for each read command. - */ - data = of_find_property(of_node, - "qcom,mdss-dsi-panel-status-value", &tmp); - tmp /= sizeof(u32); - if (!IS_ERR_OR_NULL(data) && tmp != 0 && (tmp % status_len) == 0) { - esd_config->groups = tmp / status_len; - } else { - pr_err("error parse panel-status-value\n"); - rc = -EINVAL; - goto error2; - } - - esd_config->status_value = - kzalloc(sizeof(u32) * status_len * esd_config->groups, - GFP_KERNEL); - if (!esd_config->status_value) { - rc = -ENOMEM; - goto error2; - } - - esd_config->return_buf = kcalloc(status_len * esd_config->groups, - sizeof(unsigned char), GFP_KERNEL); - if (!esd_config->return_buf) { - rc = -ENOMEM; - goto error3; - } - - rc = of_property_read_u32_array(of_node, - "qcom,mdss-dsi-panel-status-value", - esd_config->status_value, esd_config->groups * status_len); - if (rc) { - pr_debug("error reading panel status values\n"); - memset(esd_config->status_value, 0, - esd_config->groups * status_len); - } - - return 0; - -error3: - kfree(esd_config->status_value); -error2: - kfree(esd_config->status_valid_params); - kfree(esd_config->status_cmds_rlen); -error1: - kfree(esd_config->status_cmd.cmds); -error: - panel->esd_config.esd_enabled = false; - return rc; -} - -struct dsi_panel *dsi_panel_get(struct device *parent, - struct device_node *of_node, - int topology_override) -{ - struct dsi_panel *panel; - int rc = 0; - - panel = kzalloc(sizeof(*panel), GFP_KERNEL); - if (!panel) - return ERR_PTR(-ENOMEM); - - panel->name = of_get_property(of_node, "qcom,mdss-dsi-panel-name", - NULL); - if (!panel->name) - panel->name = DSI_PANEL_DEFAULT_LABEL; - - rc = dsi_panel_parse_host_config(panel, of_node); - if (rc) { - pr_err("failed to parse host configuration, rc=%d\n", rc); - goto error; - } - - rc = dsi_panel_parse_panel_mode(panel, of_node); - if (rc) { - pr_err("failed to parse panel mode configuration, rc=%d\n", rc); - goto error; - } - - rc = dsi_panel_parse_dfps_caps(&panel->dfps_caps, of_node, panel->name); - if (rc) - pr_err("failed to parse dfps configuration, rc=%d\n", rc); - - rc = dsi_panel_parse_phy_props(&panel->phy_props, of_node, panel->name); - if (rc) { - pr_err("failed to parse panel physical dimension, rc=%d\n", rc); - goto error; - } - - rc = dsi_panel_parse_power_cfg(parent, panel, of_node); - if (rc) - pr_err("failed to parse power config, rc=%d\n", rc); - - rc = dsi_panel_parse_gpios(panel, of_node); - if (rc) - pr_err("failed to parse panel gpios, rc=%d\n", rc); - - rc = dsi_panel_parse_bl_config(panel, of_node); - if (rc) - pr_err("failed to parse backlight config, rc=%d\n", rc); - - - rc = dsi_panel_parse_misc_features(panel, of_node); - if (rc) - pr_err("failed to parse misc features, rc=%d\n", rc); - - rc = dsi_panel_parse_hdr_config(panel, of_node); - if (rc) - pr_err("failed to parse hdr config, rc=%d\n", rc); - - rc = dsi_panel_get_mode_count(panel, of_node); - if (rc) { - pr_err("failed to get mode count, rc=%d\n", rc); - goto error; - } - - rc = dsi_panel_parse_dms_info(panel, of_node); - if (rc) - pr_debug("failed to get dms info, rc=%d\n", rc); - - rc = dsi_panel_parse_esd_config(panel, of_node); - if (rc) { - pr_debug("failed to parse esd config, rc=%d\n", rc); - } else { - u8 *esd_mode = NULL; - - if (panel->esd_config.status_mode == ESD_MODE_REG_READ) - esd_mode = "register_read"; - else if (panel->esd_config.status_mode == ESD_MODE_SW_BTA) - esd_mode = "bta_trigger"; - else if (panel->esd_config.status_mode == ESD_MODE_PANEL_TE) - esd_mode = "te_check"; - - pr_info("ESD enabled with mode: %s\n", esd_mode); - } - - panel->panel_of_node = of_node; - drm_panel_init(&panel->drm_panel); - mutex_init(&panel->panel_lock); - panel->parent = parent; - return panel; -error: - kfree(panel); - return ERR_PTR(rc); -} - -void dsi_panel_put(struct dsi_panel *panel) -{ - /* free resources allocated for ESD check */ - dsi_panel_esd_config_deinit(&panel->esd_config); - - kfree(panel); -} - -int dsi_panel_drv_init(struct dsi_panel *panel, - struct mipi_dsi_host *host) -{ - int rc = 0; - struct mipi_dsi_device *dev; - - if (!panel || !host) { - pr_err("invalid params\n"); - return -EINVAL; - } - - mutex_lock(&panel->panel_lock); - - dev = &panel->mipi_device; - - dev->host = host; - /* - * We dont have device structure since panel is not a device node. - * When using drm panel framework, the device is probed when the host is - * create. - */ - dev->channel = 0; - dev->lanes = 4; - - panel->host = host; - rc = dsi_panel_vreg_get(panel); - if (rc) { - pr_err("[%s] failed to get panel regulators, rc=%d\n", - panel->name, rc); - goto exit; - } - - rc = dsi_panel_pinctrl_init(panel); - if (rc) { - pr_err("[%s] failed to init pinctrl, rc=%d\n", panel->name, rc); - goto error_vreg_put; - } - - rc = dsi_panel_gpio_request(panel); - if (rc) { - pr_err("[%s] failed to request gpios, rc=%d\n", panel->name, - rc); - goto error_pinctrl_deinit; - } - - rc = dsi_panel_bl_register(panel); - if (rc) { - if (rc != -EPROBE_DEFER) - pr_err("[%s] failed to register backlight, rc=%d\n", - panel->name, rc); - goto error_gpio_release; - } - - goto exit; - -error_gpio_release: - (void)dsi_panel_gpio_release(panel); -error_pinctrl_deinit: - (void)dsi_panel_pinctrl_deinit(panel); -error_vreg_put: - (void)dsi_panel_vreg_put(panel); -exit: - mutex_unlock(&panel->panel_lock); - return rc; -} - -int dsi_panel_drv_deinit(struct dsi_panel *panel) -{ - int rc = 0; - - if (!panel) { - pr_err("invalid params\n"); - return -EINVAL; - } - - mutex_lock(&panel->panel_lock); - - rc = dsi_panel_bl_unregister(panel); - if (rc) - pr_err("[%s] failed to unregister backlight, rc=%d\n", - panel->name, rc); - - rc = dsi_panel_gpio_release(panel); - if (rc) - pr_err("[%s] failed to release gpios, rc=%d\n", panel->name, - rc); - - rc = dsi_panel_pinctrl_deinit(panel); - if (rc) - pr_err("[%s] failed to deinit gpios, rc=%d\n", panel->name, - rc); - - rc = dsi_panel_vreg_put(panel); - if (rc) - pr_err("[%s] failed to put regs, rc=%d\n", panel->name, rc); - - panel->host = NULL; - memset(&panel->mipi_device, 0x0, sizeof(panel->mipi_device)); - - mutex_unlock(&panel->panel_lock); - return rc; -} - -int dsi_panel_validate_mode(struct dsi_panel *panel, - struct dsi_display_mode *mode) -{ - return 0; -} - -int dsi_panel_get_mode_count(struct dsi_panel *panel, - struct device_node *of_node) -{ - const u32 SINGLE_MODE_SUPPORT = 1; - struct device_node *timings_np; - int count, rc = 0; - - if (!of_node || !panel) { - pr_err("invalid params\n"); - return -EINVAL; - } - - panel->num_timing_nodes = 0; - - timings_np = of_get_child_by_name(of_node, - "qcom,mdss-dsi-display-timings"); - if (!timings_np) { - pr_err("no display timing nodes defined\n"); - rc = -EINVAL; - goto error; - } - - count = of_get_child_count(timings_np); - if (!count || count > DSI_MODE_MAX) { - pr_err("invalid count of timing nodes: %d\n", count); - rc = -EINVAL; - goto error; - } - - /* No multiresolution support is available for video mode panels */ - if (panel->panel_mode != DSI_OP_CMD_MODE) - count = SINGLE_MODE_SUPPORT; - - panel->num_timing_nodes = count; - -error: - return rc; -} - -int dsi_panel_get_phy_props(struct dsi_panel *panel, - struct dsi_panel_phy_props *phy_props) -{ - int rc = 0; - - if (!panel || !phy_props) { - pr_err("invalid params\n"); - return -EINVAL; - } - - mutex_lock(&panel->panel_lock); - - memcpy(phy_props, &panel->phy_props, sizeof(*phy_props)); - - mutex_unlock(&panel->panel_lock); - return rc; -} - -int dsi_panel_get_dfps_caps(struct dsi_panel *panel, - struct dsi_dfps_capabilities *dfps_caps) -{ - int rc = 0; - - if (!panel || !dfps_caps) { - pr_err("invalid params\n"); - return -EINVAL; - } - - mutex_lock(&panel->panel_lock); - - memcpy(dfps_caps, &panel->dfps_caps, sizeof(*dfps_caps)); - - mutex_unlock(&panel->panel_lock); - return rc; -} - -void dsi_panel_put_mode(struct dsi_display_mode *mode) -{ - int i; - - if (!mode->priv_info) - return; - - for (i = 0; i < DSI_CMD_SET_MAX; i++) - dsi_panel_destroy_cmd_packets(&mode->priv_info->cmd_sets[i]); - - kfree(mode->priv_info); -} - -int dsi_panel_get_mode(struct dsi_panel *panel, - u32 index, struct dsi_display_mode *mode, - int topology_override) -{ - struct device_node *timings_np, *child_np; - struct dsi_display_mode_priv_info *prv_info; - u32 child_idx = 0; - int rc = 0, num_timings; - - if (!panel || !mode) { - pr_err("invalid params\n"); - return -EINVAL; - } - - mutex_lock(&panel->panel_lock); - - mode->priv_info = kzalloc(sizeof(*mode->priv_info), GFP_KERNEL); - if (!mode->priv_info) { - rc = -ENOMEM; - goto done; - } - - prv_info = mode->priv_info; - - timings_np = of_get_child_by_name(panel->panel_of_node, - "qcom,mdss-dsi-display-timings"); - if (!timings_np) { - pr_err("no display timing nodes defined\n"); - rc = -EINVAL; - goto parse_fail; - } - - num_timings = of_get_child_count(timings_np); - if (!num_timings || num_timings > DSI_MODE_MAX) { - pr_err("invalid count of timing nodes: %d\n", num_timings); - rc = -EINVAL; - goto parse_fail; - } - - for_each_child_of_node(timings_np, child_np) { - if (index != child_idx++) - continue; - - rc = dsi_panel_parse_timing(&mode->timing, child_np); - if (rc) { - pr_err("failed to parse panel timing, rc=%d\n", rc); - goto parse_fail; - } - - rc = dsi_panel_parse_dsc_params(mode, child_np); - if (rc) { - pr_err("failed to parse dsc params, rc=%d\n", rc); - goto parse_fail; - } - - rc = dsi_panel_parse_topology(prv_info, child_np, - topology_override); - if (rc) { - pr_err("failed to parse panel topology, rc=%d\n", rc); - goto parse_fail; - } - - rc = dsi_panel_parse_cmd_sets(prv_info, child_np); - if (rc) { - pr_err("failed to parse command sets, rc=%d\n", rc); - goto parse_fail; - } - - rc = dsi_panel_parse_jitter_config(mode, child_np); - if (rc) - pr_err( - "failed to parse panel jitter config, rc=%d\n", rc); - - rc = dsi_panel_parse_phy_timing(mode, child_np); - if (rc) { - pr_err( - "failed to parse panel phy timings, rc=%d\n", rc); - goto parse_fail; - } - } - goto done; - -parse_fail: - kfree(mode->priv_info); - mode->priv_info = NULL; -done: - mutex_unlock(&panel->panel_lock); - return rc; -} - -int dsi_panel_get_host_cfg_for_mode(struct dsi_panel *panel, - struct dsi_display_mode *mode, - struct dsi_host_config *config) -{ - int rc = 0; - - if (!panel || !mode || !config) { - pr_err("invalid params\n"); - return -EINVAL; - } - - mutex_lock(&panel->panel_lock); - - config->panel_mode = panel->panel_mode; - memcpy(&config->common_config, &panel->host_config, - sizeof(config->common_config)); - - if (panel->panel_mode == DSI_OP_VIDEO_MODE) { - memcpy(&config->u.video_engine, &panel->video_config, - sizeof(config->u.video_engine)); - } else { - memcpy(&config->u.cmd_engine, &panel->cmd_config, - sizeof(config->u.cmd_engine)); - } - - memcpy(&config->video_timing, &mode->timing, - sizeof(config->video_timing)); - config->video_timing.dsc_enabled = mode->priv_info->dsc_enabled; - config->video_timing.dsc = &mode->priv_info->dsc; - - config->esc_clk_rate_hz = 19200000; - mutex_unlock(&panel->panel_lock); - return rc; -} - -int dsi_panel_pre_prepare(struct dsi_panel *panel) -{ - int rc = 0; - - if (!panel) { - pr_err("invalid params\n"); - return -EINVAL; - } - - mutex_lock(&panel->panel_lock); - - /* If LP11_INIT is set, panel will be powered up during prepare() */ - if (panel->lp11_init) - goto error; - - rc = dsi_panel_power_on(panel); - if (rc) { - pr_err("[%s] panel power on failed, rc=%d\n", panel->name, rc); - goto error; - } - -error: - mutex_unlock(&panel->panel_lock); - return rc; -} - -int dsi_panel_update_pps(struct dsi_panel *panel) -{ - int rc = 0; - struct dsi_panel_cmd_set *set = NULL; - struct dsi_display_mode_priv_info *priv_info = NULL; - - if (!panel || !panel->cur_mode) { - pr_err("invalid params\n"); - return -EINVAL; - } - - mutex_lock(&panel->panel_lock); - - priv_info = panel->cur_mode->priv_info; - - set = &priv_info->cmd_sets[DSI_CMD_SET_PPS]; - - dsi_dsc_create_pps_buf_cmd(&priv_info->dsc, panel->dsc_pps_cmd, 0); - rc = dsi_panel_create_cmd_packets(panel->dsc_pps_cmd, - DSI_CMD_PPS_SIZE, 1, set->cmds); - if (rc) { - pr_err("failed to create cmd packets, rc=%d\n", rc); - goto error; - } - - rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_PPS); - if (rc) { - pr_err("[%s] failed to send DSI_CMD_SET_PPS cmds, rc=%d\n", - panel->name, rc); - goto error; - } - -error: - mutex_unlock(&panel->panel_lock); - return rc; -} - -int dsi_panel_set_lp1(struct dsi_panel *panel) -{ - int rc = 0; - - if (!panel) { - pr_err("invalid params\n"); - return -EINVAL; - } - - mutex_lock(&panel->panel_lock); - rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_LP1); - if (rc) - pr_err("[%s] failed to send DSI_CMD_SET_LP1 cmd, rc=%d\n", - panel->name, rc); - mutex_unlock(&panel->panel_lock); - return rc; -} - -int dsi_panel_set_lp2(struct dsi_panel *panel) -{ - int rc = 0; - - if (!panel) { - pr_err("invalid params\n"); - return -EINVAL; - } - - mutex_lock(&panel->panel_lock); - rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_LP2); - if (rc) - pr_err("[%s] failed to send DSI_CMD_SET_LP2 cmd, rc=%d\n", - panel->name, rc); - mutex_unlock(&panel->panel_lock); - return rc; -} - -int dsi_panel_set_nolp(struct dsi_panel *panel) -{ - int rc = 0; - - if (!panel) { - pr_err("invalid params\n"); - return -EINVAL; - } - - mutex_lock(&panel->panel_lock); - rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_NOLP); - if (rc) - pr_err("[%s] failed to send DSI_CMD_SET_NOLP cmd, rc=%d\n", - panel->name, rc); - mutex_unlock(&panel->panel_lock); - return rc; -} - -int dsi_panel_prepare(struct dsi_panel *panel) -{ - int rc = 0; - - if (!panel) { - pr_err("invalid params\n"); - return -EINVAL; - } - - mutex_lock(&panel->panel_lock); - - if (panel->lp11_init) { - rc = dsi_panel_power_on(panel); - if (rc) { - pr_err("[%s] panel power on failed, rc=%d\n", - panel->name, rc); - goto error; - } - } - - rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_PRE_ON); - if (rc) { - pr_err("[%s] failed to send DSI_CMD_SET_PRE_ON cmds, rc=%d\n", - panel->name, rc); - goto error; - } - -error: - mutex_unlock(&panel->panel_lock); - return rc; -} - -int dsi_panel_switch(struct dsi_panel *panel) -{ - int rc = 0; - - if (!panel) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - mutex_lock(&panel->panel_lock); - - rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_TIMING_SWITCH); - if (rc) - pr_err("[%s] failed to send DSI_CMD_SET_TIMING_SWITCH cmds, rc=%d\n", - panel->name, rc); - - mutex_unlock(&panel->panel_lock); - return rc; -} - -int dsi_panel_post_switch(struct dsi_panel *panel) -{ - int rc = 0; - - if (!panel) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - mutex_lock(&panel->panel_lock); - - rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_POST_TIMING_SWITCH); - if (rc) - pr_err("[%s] failed to send DSI_CMD_SET_POST_TIMING_SWITCH cmds, rc=%d\n", - panel->name, rc); - - mutex_unlock(&panel->panel_lock); - return rc; -} - -int dsi_panel_enable(struct dsi_panel *panel) -{ - int rc = 0; - - if (!panel) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - mutex_lock(&panel->panel_lock); - - rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_ON); - if (rc) { - pr_err("[%s] failed to send DSI_CMD_SET_ON cmds, rc=%d\n", - panel->name, rc); - } - panel->panel_initialized = true; - mutex_unlock(&panel->panel_lock); - return rc; -} - -int dsi_panel_post_enable(struct dsi_panel *panel) -{ - int rc = 0; - - if (!panel) { - pr_err("invalid params\n"); - return -EINVAL; - } - - mutex_lock(&panel->panel_lock); - - rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_POST_ON); - if (rc) { - pr_err("[%s] failed to send DSI_CMD_SET_POST_ON cmds, rc=%d\n", - panel->name, rc); - goto error; - } -error: - mutex_unlock(&panel->panel_lock); - return rc; -} - -int dsi_panel_pre_disable(struct dsi_panel *panel) -{ - int rc = 0; - - if (!panel) { - pr_err("invalid params\n"); - return -EINVAL; - } - - mutex_lock(&panel->panel_lock); - - rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_PRE_OFF); - if (rc) { - pr_err("[%s] failed to send DSI_CMD_SET_PRE_OFF cmds, rc=%d\n", - panel->name, rc); - goto error; - } - -error: - mutex_unlock(&panel->panel_lock); - return rc; -} - -int dsi_panel_disable(struct dsi_panel *panel) -{ - int rc = 0; - - if (!panel) { - pr_err("invalid params\n"); - return -EINVAL; - } - - mutex_lock(&panel->panel_lock); - - rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_OFF); - if (rc) { - pr_err("[%s] failed to send DSI_CMD_SET_OFF cmds, rc=%d\n", - panel->name, rc); - goto error; - } - panel->panel_initialized = false; - -error: - mutex_unlock(&panel->panel_lock); - return rc; -} - -int dsi_panel_unprepare(struct dsi_panel *panel) -{ - int rc = 0; - - if (!panel) { - pr_err("invalid params\n"); - return -EINVAL; - } - - mutex_lock(&panel->panel_lock); - - rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_POST_OFF); - if (rc) { - pr_err("[%s] failed to send DSI_CMD_SET_POST_OFF cmds, rc=%d\n", - panel->name, rc); - goto error; - } - - if (panel->lp11_init) { - rc = dsi_panel_power_off(panel); - if (rc) { - pr_err("[%s] panel power_Off failed, rc=%d\n", - panel->name, rc); - goto error; - } - } -error: - mutex_unlock(&panel->panel_lock); - return rc; -} - -int dsi_panel_post_unprepare(struct dsi_panel *panel) -{ - int rc = 0; - - if (!panel) { - pr_err("invalid params\n"); - return -EINVAL; - } - - mutex_lock(&panel->panel_lock); - - if (!panel->lp11_init) { - rc = dsi_panel_power_off(panel); - if (rc) { - pr_err("[%s] panel power_Off failed, rc=%d\n", - panel->name, rc); - goto error; - } - } -error: - mutex_unlock(&panel->panel_lock); - return rc; -} diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h deleted file mode 100644 index 2ef3220..0000000 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * 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 _DSI_PANEL_H_ -#define _DSI_PANEL_H_ - -#include <linux/of_device.h> -#include <linux/types.h> -#include <linux/bitops.h> -#include <linux/errno.h> -#include <linux/leds.h> -#include <drm/drm_panel.h> -#include <drm/msm_drm.h> - -#include "dsi_defs.h" -#include "dsi_ctrl_hw.h" -#include "dsi_clk.h" -#include "dsi_pwr.h" -#include "msm_drv.h" - -#define MAX_BL_LEVEL 4096 -#define MAX_BL_SCALE_LEVEL 1024 -#define MAX_AD_BL_SCALE_LEVEL 65535 -#define DSI_CMD_PPS_SIZE 135 - -#define DSI_MODE_MAX 5 - -enum dsi_panel_rotation { - DSI_PANEL_ROTATE_NONE = 0, - DSI_PANEL_ROTATE_HV_FLIP, - DSI_PANEL_ROTATE_H_FLIP, - DSI_PANEL_ROTATE_V_FLIP -}; - -enum dsi_backlight_type { - DSI_BACKLIGHT_PWM = 0, - DSI_BACKLIGHT_WLED, - DSI_BACKLIGHT_DCS, - DSI_BACKLIGHT_UNKNOWN, - DSI_BACKLIGHT_MAX, -}; - -enum { - MODE_GPIO_NOT_VALID = 0, - MODE_SEL_DUAL_PORT, - MODE_SEL_SINGLE_PORT, - MODE_GPIO_HIGH, - MODE_GPIO_LOW, -}; - -enum dsi_dms_mode { - DSI_DMS_MODE_DISABLED = 0, - DSI_DMS_MODE_RES_SWITCH_IMMEDIATE, -}; - -struct dsi_dfps_capabilities { - bool dfps_support; - enum dsi_dfps_type type; - u32 min_refresh_rate; - u32 max_refresh_rate; -}; - -struct dsi_pinctrl_info { - struct pinctrl *pinctrl; - struct pinctrl_state *active; - struct pinctrl_state *suspend; -}; - -struct dsi_panel_phy_props { - u32 panel_width_mm; - u32 panel_height_mm; - enum dsi_panel_rotation rotation; -}; - -struct dsi_backlight_config { - enum dsi_backlight_type type; - - u32 bl_min_level; - u32 bl_max_level; - u32 brightness_max_level; - u32 bl_level; - u32 bl_scale; - u32 bl_scale_ad; - - int en_gpio; - /* PWM params */ - bool pwm_pmi_control; - u32 pwm_pmic_bank; - u32 pwm_period_usecs; - int pwm_gpio; - - /* WLED params */ - struct led_trigger *wled; - struct backlight_device *bd; -}; - -struct dsi_reset_seq { - u32 level; - u32 sleep_ms; -}; - -struct dsi_panel_reset_config { - struct dsi_reset_seq *sequence; - u32 count; - - int reset_gpio; - int disp_en_gpio; - int lcd_mode_sel_gpio; - u32 mode_sel_state; -}; - -enum esd_check_status_mode { - ESD_MODE_REG_READ, - ESD_MODE_SW_BTA, - ESD_MODE_PANEL_TE, - ESD_MODE_MAX -}; - -struct drm_panel_esd_config { - bool esd_enabled; - - enum esd_check_status_mode status_mode; - struct dsi_panel_cmd_set status_cmd; - u32 *status_cmds_rlen; - u32 *status_valid_params; - u32 *status_value; - unsigned char *return_buf; - u32 groups; -}; - -struct dsi_panel { - const char *name; - struct device_node *panel_of_node; - struct mipi_dsi_device mipi_device; - - struct mutex panel_lock; - struct drm_panel drm_panel; - struct mipi_dsi_host *host; - struct device *parent; - - struct dsi_host_common_cfg host_config; - struct dsi_video_engine_cfg video_config; - struct dsi_cmd_engine_cfg cmd_config; - enum dsi_op_mode panel_mode; - - struct dsi_dfps_capabilities dfps_caps; - struct dsi_panel_phy_props phy_props; - - struct dsi_display_mode *cur_mode; - u32 num_timing_nodes; - - struct dsi_regulator_info power_info; - struct dsi_backlight_config bl_config; - struct dsi_panel_reset_config reset_config; - struct dsi_pinctrl_info pinctrl; - struct drm_panel_hdr_properties hdr_props; - struct drm_panel_esd_config esd_config; - - bool lp11_init; - bool ulps_enabled; - bool allow_phy_power_off; - - bool panel_initialized; - bool te_using_watchdog_timer; - - char dsc_pps_cmd[DSI_CMD_PPS_SIZE]; - enum dsi_dms_mode dms_mode; - - bool sync_broadcast_en; -}; - -static inline bool dsi_panel_ulps_feature_enabled(struct dsi_panel *panel) -{ - return panel->ulps_enabled; -} - -static inline bool dsi_panel_initialized(struct dsi_panel *panel) -{ - return panel->panel_initialized; -} - -struct dsi_panel *dsi_panel_get(struct device *parent, - struct device_node *of_node, - int topology_override); - -void dsi_panel_put(struct dsi_panel *panel); - -int dsi_panel_drv_init(struct dsi_panel *panel, struct mipi_dsi_host *host); - -int dsi_panel_drv_deinit(struct dsi_panel *panel); - -int dsi_panel_get_mode_count(struct dsi_panel *panel, - struct device_node *of_node); - -void dsi_panel_put_mode(struct dsi_display_mode *mode); - -int dsi_panel_get_mode(struct dsi_panel *panel, - u32 index, - struct dsi_display_mode *mode, - int topology_override); - -int dsi_panel_validate_mode(struct dsi_panel *panel, - struct dsi_display_mode *mode); - -int dsi_panel_get_host_cfg_for_mode(struct dsi_panel *panel, - struct dsi_display_mode *mode, - struct dsi_host_config *config); - -int dsi_panel_get_phy_props(struct dsi_panel *panel, - struct dsi_panel_phy_props *phy_props); -int dsi_panel_get_dfps_caps(struct dsi_panel *panel, - struct dsi_dfps_capabilities *dfps_caps); - -int dsi_panel_pre_prepare(struct dsi_panel *panel); - -int dsi_panel_set_lp1(struct dsi_panel *panel); - -int dsi_panel_set_lp2(struct dsi_panel *panel); - -int dsi_panel_set_nolp(struct dsi_panel *panel); - -int dsi_panel_prepare(struct dsi_panel *panel); - -int dsi_panel_enable(struct dsi_panel *panel); - -int dsi_panel_post_enable(struct dsi_panel *panel); - -int dsi_panel_pre_disable(struct dsi_panel *panel); - -int dsi_panel_disable(struct dsi_panel *panel); - -int dsi_panel_unprepare(struct dsi_panel *panel); - -int dsi_panel_post_unprepare(struct dsi_panel *panel); - -int dsi_panel_set_backlight(struct dsi_panel *panel, u32 bl_lvl); - -int dsi_panel_update_pps(struct dsi_panel *panel); - -int dsi_panel_switch(struct dsi_panel *panel); - -int dsi_panel_post_switch(struct dsi_panel *panel); - -void dsi_dsc_pclk_param_calc(struct msm_display_dsc_info *dsc, int intf_width); - -#endif /* _DSI_PANEL_H_ */ diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c deleted file mode 100644 index e712c61..0000000 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c +++ /dev/null @@ -1,937 +0,0 @@ -/* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * 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) "msm-dsi-phy:[%s] " fmt, __func__ - -#include <linux/of_device.h> -#include <linux/err.h> -#include <linux/regulator/consumer.h> -#include <linux/clk.h> -#ifdef CONFIG_QCOM_BUS_SCALING -#include <linux/msm-bus.h> -#endif -#include <linux/list.h> - -#include "msm_drv.h" -#include "msm_kms.h" -#include "msm_gpu.h" -#include "dsi_phy.h" -#include "dsi_phy_hw.h" -#include "dsi_clk.h" -#include "dsi_pwr.h" -#include "dsi_catalog.h" - -#include "dpu_dbg.h" - -#define DSI_PHY_DEFAULT_LABEL "MDSS PHY CTRL" - -struct dsi_phy_list_item { - struct msm_dsi_phy *phy; - struct list_head list; -}; - -static LIST_HEAD(dsi_phy_list); -static DEFINE_MUTEX(dsi_phy_list_lock); - -static const struct dsi_ver_spec_info dsi_phy_v0_0_hpm = { - .version = DSI_PHY_VERSION_0_0_HPM, - .lane_cfg_count = 4, - .strength_cfg_count = 2, - .regulator_cfg_count = 1, - .timing_cfg_count = 8, -}; -static const struct dsi_ver_spec_info dsi_phy_v0_0_lpm = { - .version = DSI_PHY_VERSION_0_0_LPM, - .lane_cfg_count = 4, - .strength_cfg_count = 2, - .regulator_cfg_count = 1, - .timing_cfg_count = 8, -}; -static const struct dsi_ver_spec_info dsi_phy_v1_0 = { - .version = DSI_PHY_VERSION_1_0, - .lane_cfg_count = 4, - .strength_cfg_count = 2, - .regulator_cfg_count = 1, - .timing_cfg_count = 8, -}; -static const struct dsi_ver_spec_info dsi_phy_v2_0 = { - .version = DSI_PHY_VERSION_2_0, - .lane_cfg_count = 4, - .strength_cfg_count = 2, - .regulator_cfg_count = 1, - .timing_cfg_count = 8, -}; -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, - .regulator_cfg_count = 0, - .timing_cfg_count = 12, -}; - -static const struct of_device_id msm_dsi_phy_of_match[] = { - { .compatible = "qcom,dsi-phy-v0.0-hpm", - .data = &dsi_phy_v0_0_hpm,}, - { .compatible = "qcom,dsi-phy-v0.0-lpm", - .data = &dsi_phy_v0_0_lpm,}, - { .compatible = "qcom,dsi-phy-v1.0", - .data = &dsi_phy_v1_0,}, - { .compatible = "qcom,dsi-phy-v2.0", - .data = &dsi_phy_v2_0,}, - { .compatible = "qcom,dsi-phy-v3.0", - .data = &dsi_phy_v3_0,}, - {} -}; - -static int dsi_phy_regmap_init(struct platform_device *pdev, - struct msm_dsi_phy *phy) -{ - int rc = 0; - void __iomem *ptr; - - ptr = msm_ioremap(pdev, "dsi_phy", phy->name); - if (IS_ERR(ptr)) { - rc = PTR_ERR(ptr); - return rc; - } - - phy->hw.base = ptr; - - pr_debug("[%s] map dsi_phy registers to %p\n", phy->name, phy->hw.base); - - return rc; -} - -static int dsi_phy_regmap_deinit(struct msm_dsi_phy *phy) -{ - pr_debug("[%s] unmap registers\n", phy->name); - return 0; -} - -static int dsi_phy_supplies_init(struct platform_device *pdev, - struct msm_dsi_phy *phy) -{ - int rc = 0; - int i = 0; - struct dsi_regulator_info *regs; - struct regulator *vreg = NULL; - - regs = &phy->pwr_info.digital; - regs->vregs = devm_kzalloc(&pdev->dev, sizeof(struct dsi_vreg), - GFP_KERNEL); - if (!regs->vregs) - goto error; - - regs->count = 1; - snprintf(regs->vregs->vreg_name, - ARRAY_SIZE(regs->vregs[i].vreg_name), - "%s", "gdsc"); - - rc = dsi_pwr_get_dt_vreg_data(&pdev->dev, - &phy->pwr_info.phy_pwr, - "qcom,phy-supply-entries"); - if (rc) { - pr_err("failed to get host power supplies, rc = %d\n", rc); - goto error_digital; - } - - regs = &phy->pwr_info.digital; - for (i = 0; i < regs->count; i++) { - vreg = devm_regulator_get(&pdev->dev, regs->vregs[i].vreg_name); - rc = PTR_RET(vreg); - if (rc) { - pr_err("failed to get %s regulator\n", - regs->vregs[i].vreg_name); - goto error_host_pwr; - } - regs->vregs[i].vreg = vreg; - } - - regs = &phy->pwr_info.phy_pwr; - for (i = 0; i < regs->count; i++) { - vreg = devm_regulator_get(&pdev->dev, regs->vregs[i].vreg_name); - rc = PTR_RET(vreg); - if (rc) { - pr_err("failed to get %s regulator\n", - regs->vregs[i].vreg_name); - for (--i; i >= 0; i--) - devm_regulator_put(regs->vregs[i].vreg); - goto error_digital_put; - } - regs->vregs[i].vreg = vreg; - } - - return rc; - -error_digital_put: - regs = &phy->pwr_info.digital; - for (i = 0; i < regs->count; i++) - devm_regulator_put(regs->vregs[i].vreg); -error_host_pwr: - devm_kfree(&pdev->dev, phy->pwr_info.phy_pwr.vregs); - phy->pwr_info.phy_pwr.vregs = NULL; - phy->pwr_info.phy_pwr.count = 0; -error_digital: - devm_kfree(&pdev->dev, phy->pwr_info.digital.vregs); - phy->pwr_info.digital.vregs = NULL; - phy->pwr_info.digital.count = 0; -error: - return rc; -} - -static int dsi_phy_supplies_deinit(struct msm_dsi_phy *phy) -{ - int i = 0; - int rc = 0; - struct dsi_regulator_info *regs; - - regs = &phy->pwr_info.digital; - for (i = 0; i < regs->count; i++) { - if (!regs->vregs[i].vreg) - pr_err("vreg is NULL, should not reach here\n"); - else - devm_regulator_put(regs->vregs[i].vreg); - } - - regs = &phy->pwr_info.phy_pwr; - for (i = 0; i < regs->count; i++) { - if (!regs->vregs[i].vreg) - pr_err("vreg is NULL, should not reach here\n"); - else - devm_regulator_put(regs->vregs[i].vreg); - } - - if (phy->pwr_info.phy_pwr.vregs) { - devm_kfree(&phy->pdev->dev, phy->pwr_info.phy_pwr.vregs); - phy->pwr_info.phy_pwr.vregs = NULL; - phy->pwr_info.phy_pwr.count = 0; - } - if (phy->pwr_info.digital.vregs) { - devm_kfree(&phy->pdev->dev, phy->pwr_info.digital.vregs); - phy->pwr_info.digital.vregs = NULL; - phy->pwr_info.digital.count = 0; - } - - return rc; -} - -static int dsi_phy_parse_dt_per_lane_cfgs(struct platform_device *pdev, - struct dsi_phy_per_lane_cfgs *cfg, - char *property) -{ - int rc = 0, i = 0, j = 0; - const u8 *data; - u32 len = 0; - - data = of_get_property(pdev->dev.of_node, property, &len); - if (!data) { - pr_err("Unable to read Phy %s settings\n", property); - return -EINVAL; - } - - if (len != DSI_LANE_MAX * cfg->count_per_lane) { - pr_err("incorrect phy %s settings, exp=%d, act=%d\n", - property, (DSI_LANE_MAX * cfg->count_per_lane), len); - return -EINVAL; - } - - for (i = DSI_LOGICAL_LANE_0; i < DSI_LANE_MAX; i++) { - for (j = 0; j < cfg->count_per_lane; j++) { - cfg->lane[i][j] = *data; - data++; - } - } - - return rc; -} - -static int dsi_phy_settings_init(struct platform_device *pdev, - struct msm_dsi_phy *phy) -{ - int rc = 0; - struct dsi_phy_per_lane_cfgs *lane = &phy->cfg.lanecfg; - struct dsi_phy_per_lane_cfgs *strength = &phy->cfg.strength; - struct dsi_phy_per_lane_cfgs *timing = &phy->cfg.timing; - struct dsi_phy_per_lane_cfgs *regs = &phy->cfg.regulators; - - lane->count_per_lane = phy->ver_info->lane_cfg_count; - rc = dsi_phy_parse_dt_per_lane_cfgs(pdev, lane, - "qcom,platform-lane-config"); - if (rc) { - pr_err("failed to parse lane cfgs, rc=%d\n", rc); - goto err; - } - - strength->count_per_lane = phy->ver_info->strength_cfg_count; - rc = dsi_phy_parse_dt_per_lane_cfgs(pdev, strength, - "qcom,platform-strength-ctrl"); - if (rc) { - pr_err("failed to parse lane cfgs, rc=%d\n", rc); - goto err; - } - - regs->count_per_lane = phy->ver_info->regulator_cfg_count; - if (regs->count_per_lane > 0) { - rc = dsi_phy_parse_dt_per_lane_cfgs(pdev, regs, - "qcom,platform-regulator-settings"); - if (rc) { - pr_err("failed to parse lane cfgs, rc=%d\n", rc); - goto err; - } - } - - /* Actual timing values are dependent on panel */ - timing->count_per_lane = phy->ver_info->timing_cfg_count; - return 0; -err: - lane->count_per_lane = 0; - strength->count_per_lane = 0; - regs->count_per_lane = 0; - timing->count_per_lane = 0; - return rc; -} - -static int dsi_phy_settings_deinit(struct msm_dsi_phy *phy) -{ - memset(&phy->cfg.lanecfg, 0x0, sizeof(phy->cfg.lanecfg)); - memset(&phy->cfg.strength, 0x0, sizeof(phy->cfg.strength)); - memset(&phy->cfg.timing, 0x0, sizeof(phy->cfg.timing)); - memset(&phy->cfg.regulators, 0x0, sizeof(phy->cfg.regulators)); - return 0; -} - -static int dsi_phy_driver_probe(struct platform_device *pdev) -{ - struct msm_dsi_phy *dsi_phy; - struct dsi_phy_list_item *item; - const struct of_device_id *id; - const struct dsi_ver_spec_info *ver_info; - int rc = 0; - u32 index = 0; - - if (!pdev || !pdev->dev.of_node) { - pr_err("pdev not found\n"); - return -ENODEV; - } - - id = of_match_node(msm_dsi_phy_of_match, pdev->dev.of_node); - if (!id) - return -ENODEV; - - ver_info = id->data; - - item = devm_kzalloc(&pdev->dev, sizeof(*item), GFP_KERNEL); - if (!item) - return -ENOMEM; - - - dsi_phy = devm_kzalloc(&pdev->dev, sizeof(*dsi_phy), GFP_KERNEL); - if (!dsi_phy) { - devm_kfree(&pdev->dev, item); - return -ENOMEM; - } - - rc = of_property_read_u32(pdev->dev.of_node, "cell-index", &index); - if (rc) { - pr_debug("cell index not set, default to 0\n"); - index = 0; - } - - dsi_phy->index = index; - - dsi_phy->name = of_get_property(pdev->dev.of_node, "label", NULL); - if (!dsi_phy->name) - dsi_phy->name = DSI_PHY_DEFAULT_LABEL; - - pr_debug("Probing %s device\n", dsi_phy->name); - - rc = dsi_phy_regmap_init(pdev, dsi_phy); - if (rc) { - pr_err("Failed to parse register information, rc=%d\n", rc); - goto fail; - } - - rc = dsi_phy_supplies_init(pdev, dsi_phy); - if (rc) { - pr_err("failed to parse voltage supplies, rc = %d\n", rc); - goto fail_regmap; - } - - rc = dsi_catalog_phy_setup(&dsi_phy->hw, ver_info->version, - dsi_phy->index); - if (rc) { - pr_err("Catalog does not support version (%d)\n", - ver_info->version); - goto fail_supplies; - } - - dsi_phy->ver_info = ver_info; - rc = dsi_phy_settings_init(pdev, dsi_phy); - if (rc) { - pr_err("Failed to parse phy setting, rc=%d\n", rc); - goto fail_supplies; - } - - item->phy = dsi_phy; - - mutex_lock(&dsi_phy_list_lock); - list_add(&item->list, &dsi_phy_list); - mutex_unlock(&dsi_phy_list_lock); - - mutex_init(&dsi_phy->phy_lock); - /** TODO: initialize debugfs */ - dsi_phy->pdev = pdev; - platform_set_drvdata(pdev, dsi_phy); - pr_info("Probe successful for %s\n", dsi_phy->name); - return 0; - -fail_supplies: - (void)dsi_phy_supplies_deinit(dsi_phy); -fail_regmap: - (void)dsi_phy_regmap_deinit(dsi_phy); -fail: - devm_kfree(&pdev->dev, dsi_phy); - devm_kfree(&pdev->dev, item); - return rc; -} - -static int dsi_phy_driver_remove(struct platform_device *pdev) -{ - int rc = 0; - struct msm_dsi_phy *phy = platform_get_drvdata(pdev); - struct list_head *pos, *tmp; - - if (!pdev || !phy) { - pr_err("Invalid device\n"); - return -EINVAL; - } - - mutex_lock(&dsi_phy_list_lock); - list_for_each_safe(pos, tmp, &dsi_phy_list) { - struct dsi_phy_list_item *n; - - n = list_entry(pos, struct dsi_phy_list_item, list); - if (n->phy == phy) { - list_del(&n->list); - devm_kfree(&pdev->dev, n); - break; - } - } - mutex_unlock(&dsi_phy_list_lock); - - mutex_lock(&phy->phy_lock); - rc = dsi_phy_settings_deinit(phy); - if (rc) - pr_err("failed to deinitialize phy settings, rc=%d\n", rc); - - rc = dsi_phy_supplies_deinit(phy); - if (rc) - pr_err("failed to deinitialize voltage supplies, rc=%d\n", rc); - - rc = dsi_phy_regmap_deinit(phy); - if (rc) - pr_err("failed to deinitialize regmap, rc=%d\n", rc); - mutex_unlock(&phy->phy_lock); - - mutex_destroy(&phy->phy_lock); - devm_kfree(&pdev->dev, phy); - - platform_set_drvdata(pdev, NULL); - - return 0; -} - -static struct platform_driver dsi_phy_platform_driver = { - .probe = dsi_phy_driver_probe, - .remove = dsi_phy_driver_remove, - .driver = { - .name = "dsi_phy", - .of_match_table = msm_dsi_phy_of_match, - }, -}; - -static void dsi_phy_enable_hw(struct msm_dsi_phy *phy) -{ - if (phy->hw.ops.regulator_enable) - phy->hw.ops.regulator_enable(&phy->hw, &phy->cfg.regulators); - - if (phy->hw.ops.enable) - phy->hw.ops.enable(&phy->hw, &phy->cfg); -} - -static void dsi_phy_disable_hw(struct msm_dsi_phy *phy) -{ - if (phy->hw.ops.disable) - phy->hw.ops.disable(&phy->hw, &phy->cfg); - - if (phy->hw.ops.regulator_disable) - phy->hw.ops.regulator_disable(&phy->hw); -} - -/** - * dsi_phy_get() - get a dsi phy handle from device node - * @of_node: device node for dsi phy controller - * - * Gets the DSI PHY handle for the corresponding of_node. The ref count is - * incremented to one all subsequents get will fail until the original client - * calls a put. - * - * Return: DSI PHY handle or an error code. - */ -struct msm_dsi_phy *dsi_phy_get(struct device_node *of_node) -{ - struct list_head *pos, *tmp; - struct msm_dsi_phy *phy = NULL; - - mutex_lock(&dsi_phy_list_lock); - list_for_each_safe(pos, tmp, &dsi_phy_list) { - struct dsi_phy_list_item *n; - - n = list_entry(pos, struct dsi_phy_list_item, list); - if (n->phy->pdev->dev.of_node == of_node) { - phy = n->phy; - break; - } - } - mutex_unlock(&dsi_phy_list_lock); - - if (!phy) { - pr_err("Device with of node not found\n"); - phy = ERR_PTR(-EPROBE_DEFER); - return phy; - } - - mutex_lock(&phy->phy_lock); - if (phy->refcount > 0) { - pr_err("[PHY_%d] Device under use\n", phy->index); - phy = ERR_PTR(-EINVAL); - } else { - phy->refcount++; - } - mutex_unlock(&phy->phy_lock); - return phy; -} - -/** - * dsi_phy_put() - release dsi phy handle - * @dsi_phy: DSI PHY handle. - * - * Release the DSI PHY hardware. Driver will clean up all resources and puts - * back the DSI PHY into reset state. - */ -void dsi_phy_put(struct msm_dsi_phy *dsi_phy) -{ - mutex_lock(&dsi_phy->phy_lock); - - if (dsi_phy->refcount == 0) - pr_err("Unbalanced %s call\n", __func__); - else - dsi_phy->refcount--; - - mutex_unlock(&dsi_phy->phy_lock); -} - -/** - * dsi_phy_drv_init() - initialize dsi phy driver - * @dsi_phy: DSI PHY handle. - * - * Initializes DSI PHY driver. Should be called after dsi_phy_get(). - * - * Return: error code. - */ -int dsi_phy_drv_init(struct msm_dsi_phy *dsi_phy) -{ - char dbg_name[DSI_DEBUG_NAME_LEN]; - - snprintf(dbg_name, DSI_DEBUG_NAME_LEN, "dsi%d_phy", dsi_phy->index); - dpu_dbg_reg_register_base(dbg_name, dsi_phy->hw.base, - msm_iomap_size(dsi_phy->pdev, "dsi_phy")); - return 0; -} - -/** - * dsi_phy_drv_deinit() - de-initialize dsi phy driver - * @dsi_phy: DSI PHY handle. - * - * Release all resources acquired by dsi_phy_drv_init(). - * - * Return: error code. - */ -int dsi_phy_drv_deinit(struct msm_dsi_phy *dsi_phy) -{ - return 0; -} - -int dsi_phy_clk_cb_register(struct msm_dsi_phy *dsi_phy, - struct clk_ctrl_cb *clk_cb) -{ - if (!dsi_phy || !clk_cb) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - dsi_phy->clk_cb.priv = clk_cb->priv; - dsi_phy->clk_cb.dsi_clk_cb = clk_cb->dsi_clk_cb; - return 0; -} - -/** - * dsi_phy_validate_mode() - validate a display mode - * @dsi_phy: DSI PHY handle. - * @mode: Mode information. - * - * Validation will fail if the mode cannot be supported by the PHY driver or - * hardware. - * - * Return: error code. - */ -int dsi_phy_validate_mode(struct msm_dsi_phy *dsi_phy, - struct dsi_mode_info *mode) -{ - int rc = 0; - - if (!dsi_phy || !mode) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - mutex_lock(&dsi_phy->phy_lock); - - pr_debug("[PHY_%d] Skipping validation\n", dsi_phy->index); - - mutex_unlock(&dsi_phy->phy_lock); - return rc; -} - -/** - * dsi_phy_set_power_state() - enable/disable dsi phy power supplies - * @dsi_phy: DSI PHY handle. - * @enable: Boolean flag to enable/disable. - * - * Return: error code. - */ -int dsi_phy_set_power_state(struct msm_dsi_phy *dsi_phy, bool enable) -{ - int rc = 0; - - if (!dsi_phy) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - mutex_lock(&dsi_phy->phy_lock); - - if (enable == dsi_phy->power_state) { - pr_err("[PHY_%d] No state change\n", dsi_phy->index); - goto error; - } - - if (enable) { - rc = dsi_pwr_enable_regulator(&dsi_phy->pwr_info.digital, true); - if (rc) { - pr_err("failed to enable digital regulator\n"); - goto error; - } - - if (dsi_phy->dsi_phy_state == DSI_PHY_ENGINE_OFF) { - rc = dsi_pwr_enable_regulator( - &dsi_phy->pwr_info.phy_pwr, true); - if (rc) { - pr_err("failed to enable phy power\n"); - (void)dsi_pwr_enable_regulator( - &dsi_phy->pwr_info.digital, false); - goto error; - } - } - } else { - if (dsi_phy->dsi_phy_state == DSI_PHY_ENGINE_OFF) { - rc = dsi_pwr_enable_regulator( - &dsi_phy->pwr_info.phy_pwr, false); - if (rc) { - pr_err("failed to enable digital regulator\n"); - goto error; - } - } - - rc = dsi_pwr_enable_regulator(&dsi_phy->pwr_info.digital, - false); - if (rc) { - pr_err("failed to enable phy power\n"); - goto error; - } - } - - dsi_phy->power_state = enable; -error: - mutex_unlock(&dsi_phy->phy_lock); - return rc; -} - -static int dsi_phy_enable_ulps(struct msm_dsi_phy *phy, - struct dsi_host_config *config, bool clamp_enabled) -{ - int rc = 0; - u32 lanes = 0; - u32 ulps_lanes; - - if (config->panel_mode == DSI_OP_CMD_MODE) - lanes = config->common_config.data_lanes; - lanes |= DSI_CLOCK_LANE; - - /* - * If DSI clamps are enabled, it means that the DSI lanes are - * already in idle state. Checking for lanes to be in idle state - * should be skipped during ULPS entry programming while coming - * out of idle screen. - */ - if (!clamp_enabled) { - rc = phy->hw.ops.ulps_ops.wait_for_lane_idle(&phy->hw, lanes); - if (rc) { - pr_err("lanes not entering idle, skip ULPS\n"); - return rc; - } - } - - phy->hw.ops.ulps_ops.ulps_request(&phy->hw, &phy->cfg, lanes); - - ulps_lanes = phy->hw.ops.ulps_ops.get_lanes_in_ulps(&phy->hw); - - if (!phy->hw.ops.ulps_ops.is_lanes_in_ulps(lanes, ulps_lanes)) { - pr_err("Failed to enter ULPS, request=0x%x, actual=0x%x\n", - lanes, ulps_lanes); - rc = -EIO; - } - - return rc; -} - -static int dsi_phy_disable_ulps(struct msm_dsi_phy *phy, - struct dsi_host_config *config) -{ - u32 ulps_lanes, lanes = 0; - - if (config->panel_mode == DSI_OP_CMD_MODE) - lanes = config->common_config.data_lanes; - lanes |= DSI_CLOCK_LANE; - - ulps_lanes = phy->hw.ops.ulps_ops.get_lanes_in_ulps(&phy->hw); - - if (!phy->hw.ops.ulps_ops.is_lanes_in_ulps(lanes, ulps_lanes)) { - pr_err("Mismatch in ULPS: lanes:%d, ulps_lanes:%d\n", - lanes, ulps_lanes); - return -EIO; - } - - phy->hw.ops.ulps_ops.ulps_exit(&phy->hw, &phy->cfg, lanes); - - ulps_lanes = phy->hw.ops.ulps_ops.get_lanes_in_ulps(&phy->hw); - - if (phy->hw.ops.ulps_ops.is_lanes_in_ulps(lanes, ulps_lanes)) { - pr_err("Lanes (0x%x) stuck in ULPS\n", ulps_lanes); - return -EIO; - } - - return 0; -} - - -int dsi_phy_set_ulps(struct msm_dsi_phy *phy, struct dsi_host_config *config, - bool enable, bool clamp_enabled) -{ - int rc = 0; - - if (!phy) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - if (!phy->hw.ops.ulps_ops.ulps_request || - !phy->hw.ops.ulps_ops.ulps_exit || - !phy->hw.ops.ulps_ops.get_lanes_in_ulps || - !phy->hw.ops.ulps_ops.is_lanes_in_ulps || - !phy->hw.ops.ulps_ops.wait_for_lane_idle) { - pr_debug("DSI PHY ULPS ops not present\n"); - return 0; - } - - mutex_lock(&phy->phy_lock); - - if (enable) - rc = dsi_phy_enable_ulps(phy, config, clamp_enabled); - else - rc = dsi_phy_disable_ulps(phy, config); - - if (rc) { - pr_err("[DSI_PHY%d] Ulps state change(%d) failed, rc=%d\n", - phy->index, enable, rc); - goto error; - } - pr_debug("[DSI_PHY%d] ULPS state = %d\n", phy->index, enable); - -error: - mutex_unlock(&phy->phy_lock); - return rc; -} - -/** - * dsi_phy_enable() - enable DSI PHY hardware - * @dsi_phy: DSI PHY handle. - * @config: DSI host configuration. - * @pll_source: Source PLL for PHY clock. - * @skip_validation: Validation will not be performed on parameters. - * - * Validates and enables DSI PHY. - * - * Return: error code. - */ -int dsi_phy_enable(struct msm_dsi_phy *phy, - struct dsi_host_config *config, - enum dsi_phy_pll_source pll_source, - bool skip_validation) -{ - int rc = 0; - - if (!phy || !config) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - mutex_lock(&phy->phy_lock); - - if (!skip_validation) - pr_debug("[PHY_%d] TODO: perform validation\n", phy->index); - - memcpy(&phy->mode, &config->video_timing, sizeof(phy->mode)); - memcpy(&phy->cfg.lane_map, &config->lane_map, sizeof(config->lane_map)); - phy->data_lanes = config->common_config.data_lanes; - phy->dst_format = config->common_config.dst_format; - phy->cfg.pll_source = pll_source; - - /** - * If PHY timing parameters are not present in panel dtsi file, - * then calculate them in the driver - */ - if (!phy->cfg.is_phy_timing_present) - rc = phy->hw.ops.calculate_timing_params(&phy->hw, - &phy->mode, - &config->common_config, - &phy->cfg.timing); - if (rc) { - pr_err("[%s] failed to set timing, rc=%d\n", phy->name, rc); - goto error; - } - - dsi_phy_enable_hw(phy); - phy->dsi_phy_state = DSI_PHY_ENGINE_ON; - -error: - mutex_unlock(&phy->phy_lock); - - return rc; -} - -/** - * dsi_phy_disable() - disable DSI PHY hardware. - * @phy: DSI PHY handle. - * - * Return: error code. - */ -int dsi_phy_disable(struct msm_dsi_phy *phy) -{ - int rc = 0; - - if (!phy) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - mutex_lock(&phy->phy_lock); - dsi_phy_disable_hw(phy); - phy->dsi_phy_state = DSI_PHY_ENGINE_OFF; - mutex_unlock(&phy->phy_lock); - - return rc; -} - -/** - * dsi_phy_idle_ctrl() - enable/disable DSI PHY during idle screen - * @phy: DSI PHY handle - * @enable: boolean to specify PHY enable/disable. - * - * Return: error code. - */ - -int dsi_phy_idle_ctrl(struct msm_dsi_phy *phy, bool enable) -{ - if (!phy) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - mutex_lock(&phy->phy_lock); - if (enable) { - if (phy->hw.ops.phy_idle_on) - phy->hw.ops.phy_idle_on(&phy->hw, &phy->cfg); - - if (phy->hw.ops.regulator_enable) - phy->hw.ops.regulator_enable(&phy->hw, - &phy->cfg.regulators); - } else { - if (phy->hw.ops.phy_idle_off) - phy->hw.ops.phy_idle_off(&phy->hw); - } - mutex_unlock(&phy->phy_lock); - - return 0; -} - -/** - * dsi_phy_set_timing_params() - timing parameters for the panel - * @phy: DSI PHY handle - * @timing: array holding timing params. - * @size: size of the array. - * - * When PHY timing calculator is not implemented, this array will be used to - * pass PHY timing information. - * - * Return: error code. - */ -int dsi_phy_set_timing_params(struct msm_dsi_phy *phy, - u32 *timing, u32 size) -{ - int rc = 0; - - if (!phy || !timing || !size) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - mutex_lock(&phy->phy_lock); - - if (phy->hw.ops.phy_timing_val) - rc = phy->hw.ops.phy_timing_val(&phy->cfg.timing, timing, size); - if (!rc) - phy->cfg.is_phy_timing_present = true; - mutex_unlock(&phy->phy_lock); - return rc; -} - -void dsi_phy_drv_register(void) -{ - platform_driver_register(&dsi_phy_platform_driver); -} - -void dsi_phy_drv_unregister(void) -{ - platform_driver_unregister(&dsi_phy_platform_driver); -} diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.h b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.h deleted file mode 100644 index 92307e9..0000000 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.h +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * 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 _DSI_PHY_H_ -#define _DSI_PHY_H_ - -#include "dsi_defs.h" -#include "dsi_clk.h" -#include "dsi_pwr.h" -#include "dsi_phy_hw.h" - -struct dsi_ver_spec_info { - enum dsi_phy_version version; - u32 lane_cfg_count; - u32 strength_cfg_count; - u32 regulator_cfg_count; - u32 timing_cfg_count; -}; - -/** - * struct dsi_phy_power_info - digital and analog power supplies for DSI PHY - * @digital: Digital power supply for DSI PHY. - * @phy_pwr: Analog power supplies for DSI PHY to work. - */ -struct dsi_phy_power_info { - struct dsi_regulator_info digital; - struct dsi_regulator_info phy_pwr; -}; - -/** - * enum phy_engine_state - define engine status for dsi phy. - * @DSI_PHY_ENGINE_OFF: Engine is turned off. - * @DSI_PHY_ENGINE_ON: Engine is turned on. - * @DSI_PHY_ENGINE_MAX: Maximum value. - */ -enum phy_engine_state { - DSI_PHY_ENGINE_OFF = 0, - DSI_PHY_ENGINE_ON, - DSI_PHY_ENGINE_MAX, -}; - - -/** - * struct msm_dsi_phy - DSI PHY object - * @pdev: Pointer to platform device. - * @index: Instance id. - * @name: Name of the PHY instance. - * @refcount: Reference count. - * @phy_lock: Mutex for hardware and object access. - * @ver_info: Version specific phy parameters. - * @hw: DSI PHY hardware object. - * @pwr_info: Power information. - * @cfg: DSI phy configuration. - * @clk_cb: structure containing call backs for clock control - * @power_state: True if PHY is powered on. - * @dsi_phy_state: PHY state information. - * @mode: Current mode. - * @data_lanes: Number of data lanes used. - * @dst_format: Destination format. - */ -struct msm_dsi_phy { - struct platform_device *pdev; - int index; - const char *name; - u32 refcount; - struct mutex phy_lock; - - const struct dsi_ver_spec_info *ver_info; - struct dsi_phy_hw hw; - - struct dsi_phy_power_info pwr_info; - - struct dsi_phy_cfg cfg; - struct clk_ctrl_cb clk_cb; - - enum phy_engine_state dsi_phy_state; - bool power_state; - struct dsi_mode_info mode; - enum dsi_data_lanes data_lanes; - enum dsi_pixel_format dst_format; -}; - -/** - * dsi_phy_get() - get a dsi phy handle from device node - * @of_node: device node for dsi phy controller - * - * Gets the DSI PHY handle for the corresponding of_node. The ref count is - * incremented to one all subsequents get will fail until the original client - * calls a put. - * - * Return: DSI PHY handle or an error code. - */ -struct msm_dsi_phy *dsi_phy_get(struct device_node *of_node); - -/** - * dsi_phy_put() - release dsi phy handle - * @dsi_phy: DSI PHY handle. - * - * Release the DSI PHY hardware. Driver will clean up all resources and puts - * back the DSI PHY into reset state. - */ -void dsi_phy_put(struct msm_dsi_phy *dsi_phy); - -/** - * dsi_phy_drv_init() - initialize dsi phy driver - * @dsi_phy: DSI PHY handle. - * - * Initializes DSI PHY driver. Should be called after dsi_phy_get(). - * - * Return: error code. - */ -int dsi_phy_drv_init(struct msm_dsi_phy *dsi_phy); - -/** - * dsi_phy_drv_deinit() - de-initialize dsi phy driver - * @dsi_phy: DSI PHY handle. - * - * Release all resources acquired by dsi_phy_drv_init(). - * - * Return: error code. - */ -int dsi_phy_drv_deinit(struct msm_dsi_phy *dsi_phy); - -/** - * dsi_phy_validate_mode() - validate a display mode - * @dsi_phy: DSI PHY handle. - * @mode: Mode information. - * - * Validation will fail if the mode cannot be supported by the PHY driver or - * hardware. - * - * Return: error code. - */ -int dsi_phy_validate_mode(struct msm_dsi_phy *dsi_phy, - struct dsi_mode_info *mode); - -/** - * dsi_phy_set_power_state() - enable/disable dsi phy power supplies - * @dsi_phy: DSI PHY handle. - * @enable: Boolean flag to enable/disable. - * - * Return: error code. - */ -int dsi_phy_set_power_state(struct msm_dsi_phy *dsi_phy, bool enable); - -/** - * dsi_phy_enable() - enable DSI PHY hardware - * @dsi_phy: DSI PHY handle. - * @config: DSI host configuration. - * @pll_source: Source PLL for PHY clock. - * @skip_validation: Validation will not be performed on parameters. - * - * Validates and enables DSI PHY. - * - * Return: error code. - */ -int dsi_phy_enable(struct msm_dsi_phy *dsi_phy, - struct dsi_host_config *config, - enum dsi_phy_pll_source pll_source, - bool skip_validation); - -/** - * dsi_phy_disable() - disable DSI PHY hardware. - * @phy: DSI PHY handle. - * - * Return: error code. - */ -int dsi_phy_disable(struct msm_dsi_phy *phy); - -/** - * dsi_phy_set_ulps() - set ulps state for DSI pHY - * @phy: DSI PHY handle - * @config: DSi host configuration information. - * @enable: Enable/Disable - * @clamp_enabled: mmss_clamp enabled/disabled - * - * Return: error code. - */ -int dsi_phy_set_ulps(struct msm_dsi_phy *phy, struct dsi_host_config *config, - bool enable, bool clamp_enabled); - -/** - * dsi_phy_clk_cb_register() - Register PHY clock control callback - * @phy: DSI PHY handle - * @clk_cb: Structure containing call back for clock control - * - * Return: error code. - */ -int dsi_phy_clk_cb_register(struct msm_dsi_phy *phy, - struct clk_ctrl_cb *clk_cb); - -/** - * dsi_phy_idle_ctrl() - enable/disable DSI PHY during idle screen - * @phy: DSI PHY handle - * @enable: boolean to specify PHY enable/disable. - * - * Return: error code. - */ -int dsi_phy_idle_ctrl(struct msm_dsi_phy *phy, bool enable); - -/** - * dsi_phy_set_timing_params() - timing parameters for the panel - * @phy: DSI PHY handle - * @timing: array holding timing params. - * @size: size of the array. - * - * When PHY timing calculator is not implemented, this array will be used to - * pass PHY timing information. - * - * Return: error code. - */ -int dsi_phy_set_timing_params(struct msm_dsi_phy *phy, - u32 *timing, u32 size); - -/** - * dsi_phy_drv_register() - register platform driver for dsi phy - */ -void dsi_phy_drv_register(void); - -/** - * dsi_phy_drv_unregister() - unregister platform driver - */ -void dsi_phy_drv_unregister(void); - -#endif /* _DSI_PHY_H_ */ diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h deleted file mode 100644 index b71a458..0000000 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * 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 _DSI_PHY_HW_H_ -#define _DSI_PHY_HW_H_ - -#include "dsi_defs.h" - -#define DSI_MAX_SETTINGS 8 -#define DSI_PHY_TIMING_V3_SIZE 12 - -/** - * enum dsi_phy_version - DSI PHY version enumeration - * @DSI_PHY_VERSION_UNKNOWN: Unknown version. - * @DSI_PHY_VERSION_0_0_HPM: 28nm-HPM. - * @DSI_PHY_VERSION_0_0_LPM: 28nm-HPM. - * @DSI_PHY_VERSION_1_0: 20nm - * @DSI_PHY_VERSION_2_0: 14nm - * @DSI_PHY_VERSION_3_0: 10nm - * @DSI_PHY_VERSION_MAX: - */ -enum dsi_phy_version { - DSI_PHY_VERSION_UNKNOWN, - DSI_PHY_VERSION_0_0_HPM, /* 28nm-HPM */ - DSI_PHY_VERSION_0_0_LPM, /* 28nm-LPM */ - DSI_PHY_VERSION_1_0, /* 20nm */ - DSI_PHY_VERSION_2_0, /* 14nm */ - DSI_PHY_VERSION_3_0, /* 10nm */ - DSI_PHY_VERSION_MAX -}; - -/** - * enum dsi_phy_hw_features - features supported by DSI PHY hardware - * @DSI_PHY_DPHY: Supports DPHY - * @DSI_PHY_CPHY: Supports CPHY - * @DSI_PHY_MAX_FEATURES: - */ -enum dsi_phy_hw_features { - DSI_PHY_DPHY, - DSI_PHY_CPHY, - DSI_PHY_MAX_FEATURES -}; - -/** - * enum dsi_phy_pll_source - pll clock source for PHY. - * @DSI_PLL_SOURCE_STANDALONE: Clock is sourced from native PLL and is not - * shared by other PHYs. - * @DSI_PLL_SOURCE_NATIVE: Clock is sourced from native PLL and is - * shared by other PHYs. - * @DSI_PLL_SOURCE_NON_NATIVE: Clock is sourced from other PHYs. - * @DSI_PLL_SOURCE_MAX: - */ -enum dsi_phy_pll_source { - DSI_PLL_SOURCE_STANDALONE = 0, - DSI_PLL_SOURCE_NATIVE, - DSI_PLL_SOURCE_NON_NATIVE, - DSI_PLL_SOURCE_MAX -}; - -/** - * struct dsi_phy_per_lane_cfgs - Holds register values for PHY parameters - * @lane: A set of maximum 8 values for each lane. - * @lane_v3: A set of maximum 12 values for each lane. - * @count_per_lane: Number of values per each lane. - */ -struct dsi_phy_per_lane_cfgs { - u8 lane[DSI_LANE_MAX][DSI_MAX_SETTINGS]; - u8 lane_v3[DSI_PHY_TIMING_V3_SIZE]; - u32 count_per_lane; -}; - -/** - * struct dsi_phy_cfg - DSI PHY configuration - * @lanecfg: Lane configuration settings. - * @strength: Strength settings for lanes. - * @timing: Timing parameters for lanes. - * @is_phy_timing_present: Boolean whether phy timings are defined. - * @regulators: Regulator settings for lanes. - * @pll_source: PLL source. - * @lane_map: DSI logical to PHY lane mapping. - */ -struct dsi_phy_cfg { - struct dsi_phy_per_lane_cfgs lanecfg; - struct dsi_phy_per_lane_cfgs strength; - struct dsi_phy_per_lane_cfgs timing; - bool is_phy_timing_present; - struct dsi_phy_per_lane_cfgs regulators; - enum dsi_phy_pll_source pll_source; - struct dsi_lane_map lane_map; -}; - -struct dsi_phy_hw; - -struct phy_ulps_config_ops { - /** - * wait_for_lane_idle() - wait for DSI lanes to go to idle state - * @phy: Pointer to DSI PHY hardware instance. - * @lanes: ORed list of lanes (enum dsi_data_lanes) which need - * to be checked to be in idle state. - */ - int (*wait_for_lane_idle)(struct dsi_phy_hw *phy, u32 lanes); - - /** - * ulps_request() - request ulps entry for specified lanes - * @phy: Pointer to DSI PHY hardware instance. - * @cfg: Per lane configurations for timing, strength and lane - * configurations. - * @lanes: ORed list of lanes (enum dsi_data_lanes) which need - * to enter ULPS. - * - * Caller should check if lanes are in ULPS mode by calling - * get_lanes_in_ulps() operation. - */ - void (*ulps_request)(struct dsi_phy_hw *phy, - struct dsi_phy_cfg *cfg, u32 lanes); - - /** - * ulps_exit() - exit ULPS on specified lanes - * @phy: Pointer to DSI PHY hardware instance. - * @cfg: Per lane configurations for timing, strength and lane - * configurations. - * @lanes: ORed list of lanes (enum dsi_data_lanes) which need - * to exit ULPS. - * - * Caller should check if lanes are in active mode by calling - * get_lanes_in_ulps() operation. - */ - void (*ulps_exit)(struct dsi_phy_hw *phy, - struct dsi_phy_cfg *cfg, u32 lanes); - - /** - * get_lanes_in_ulps() - returns the list of lanes in ULPS mode - * @phy: Pointer to DSI PHY hardware instance. - * - * Returns an ORed list of lanes (enum dsi_data_lanes) that are in ULPS - * state. - * - * Return: List of lanes in ULPS state. - */ - u32 (*get_lanes_in_ulps)(struct dsi_phy_hw *phy); - - /** - * is_lanes_in_ulps() - checks if the given lanes are in ulps - * @lanes: lanes to be checked. - * @ulps_lanes: lanes in ulps currenly. - * - * Return: true if all the given lanes are in ulps; false otherwise. - */ - bool (*is_lanes_in_ulps)(u32 ulps, u32 ulps_lanes); -}; - -/** - * struct dsi_phy_hw_ops - Operations for DSI PHY hardware. - * @regulator_enable: Enable PHY regulators. - * @regulator_disable: Disable PHY regulators. - * @enable: Enable PHY. - * @disable: Disable PHY. - * @calculate_timing_params: Calculate PHY timing params from mode information - */ -struct dsi_phy_hw_ops { - /** - * regulator_enable() - enable regulators for DSI PHY - * @phy: Pointer to DSI PHY hardware object. - * @reg_cfg: Regulator configuration for all DSI lanes. - */ - void (*regulator_enable)(struct dsi_phy_hw *phy, - struct dsi_phy_per_lane_cfgs *reg_cfg); - - /** - * regulator_disable() - disable regulators - * @phy: Pointer to DSI PHY hardware object. - */ - void (*regulator_disable)(struct dsi_phy_hw *phy); - - /** - * enable() - Enable PHY hardware - * @phy: Pointer to DSI PHY hardware object. - * @cfg: Per lane configurations for timing, strength and lane - * configurations. - */ - void (*enable)(struct dsi_phy_hw *phy, struct dsi_phy_cfg *cfg); - - /** - * disable() - Disable PHY hardware - * @phy: Pointer to DSI PHY hardware object. - * @cfg: Per lane configurations for timing, strength and lane - * configurations. - */ - void (*disable)(struct dsi_phy_hw *phy, struct dsi_phy_cfg *cfg); - - /** - * phy_idle_on() - Enable PHY hardware when entering idle screen - * @phy: Pointer to DSI PHY hardware object. - * @cfg: Per lane configurations for timing, strength and lane - * configurations. - */ - void (*phy_idle_on)(struct dsi_phy_hw *phy, struct dsi_phy_cfg *cfg); - - /** - * phy_idle_off() - Disable PHY hardware when exiting idle screen - * @phy: Pointer to DSI PHY hardware object. - */ - void (*phy_idle_off)(struct dsi_phy_hw *phy); - - /** - * calculate_timing_params() - calculates timing parameters. - * @phy: Pointer to DSI PHY hardware object. - * @mode: Mode information for which timing has to be calculated. - * @config: DSI host configuration for this mode. - * @timing: Timing parameters for each lane which will be returned. - */ - int (*calculate_timing_params)(struct dsi_phy_hw *phy, - struct dsi_mode_info *mode, - struct dsi_host_common_cfg *config, - struct dsi_phy_per_lane_cfgs *timing); - - /** - * phy_timing_val() - Gets PHY timing values. - * @timing_val: Timing parameters for each lane which will be returned. - * @timing: Array containing PHY timing values - * @size: Size of the array - */ - int (*phy_timing_val)(struct dsi_phy_per_lane_cfgs *timing_val, - u32 *timing, u32 size); - - void *timing_ops; - struct phy_ulps_config_ops ulps_ops; -}; - -/** - * struct dsi_phy_hw - DSI phy hardware object specific to an instance - * @base: VA for the DSI PHY base address. - * @length: Length of the DSI PHY register base map. - * @index: Instance ID of the controller. - * @version: DSI PHY version. - * @feature_map: Features supported by DSI PHY. - * @ops: Function pointer to PHY operations. - */ -struct dsi_phy_hw { - void __iomem *base; - u32 length; - u32 index; - - enum dsi_phy_version version; - - DECLARE_BITMAP(feature_map, DSI_PHY_MAX_FEATURES); - struct dsi_phy_hw_ops ops; -}; - -#endif /* _DSI_PHY_HW_H_ */ diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v2_0.c b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v2_0.c deleted file mode 100644 index cd54581..0000000 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v2_0.c +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * 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) "dsi-phy-hw:" fmt -#include <linux/math64.h> -#include <linux/delay.h> -#include "dsi_hw.h" -#include "dsi_phy_hw.h" - -#define DSIPHY_CMN_REVISION_ID0 0x0000 -#define DSIPHY_CMN_REVISION_ID1 0x0004 -#define DSIPHY_CMN_REVISION_ID2 0x0008 -#define DSIPHY_CMN_REVISION_ID3 0x000C -#define DSIPHY_CMN_CLK_CFG0 0x0010 -#define DSIPHY_CMN_CLK_CFG1 0x0014 -#define DSIPHY_CMN_GLBL_TEST_CTRL 0x0018 -#define DSIPHY_CMN_CTRL_0 0x001C -#define DSIPHY_CMN_CTRL_1 0x0020 -#define DSIPHY_CMN_CAL_HW_TRIGGER 0x0024 -#define DSIPHY_CMN_CAL_SW_CFG0 0x0028 -#define DSIPHY_CMN_CAL_SW_CFG1 0x002C -#define DSIPHY_CMN_CAL_SW_CFG2 0x0030 -#define DSIPHY_CMN_CAL_HW_CFG0 0x0034 -#define DSIPHY_CMN_CAL_HW_CFG1 0x0038 -#define DSIPHY_CMN_CAL_HW_CFG2 0x003C -#define DSIPHY_CMN_CAL_HW_CFG3 0x0040 -#define DSIPHY_CMN_CAL_HW_CFG4 0x0044 -#define DSIPHY_CMN_PLL_CNTRL 0x0048 -#define DSIPHY_CMN_LDO_CNTRL 0x004C - -#define DSIPHY_CMN_REGULATOR_CAL_STATUS0 0x0064 -#define DSIPHY_CMN_REGULATOR_CAL_STATUS1 0x0068 - -/* n = 0..3 for data lanes and n = 4 for clock lane */ -#define DSIPHY_DLNX_CFG0(n) (0x100 + ((n) * 0x80)) -#define DSIPHY_DLNX_CFG1(n) (0x104 + ((n) * 0x80)) -#define DSIPHY_DLNX_CFG2(n) (0x108 + ((n) * 0x80)) -#define DSIPHY_DLNX_CFG3(n) (0x10C + ((n) * 0x80)) -#define DSIPHY_DLNX_TEST_DATAPATH(n) (0x110 + ((n) * 0x80)) -#define DSIPHY_DLNX_TEST_STR(n) (0x114 + ((n) * 0x80)) -#define DSIPHY_DLNX_TIMING_CTRL_4(n) (0x118 + ((n) * 0x80)) -#define DSIPHY_DLNX_TIMING_CTRL_5(n) (0x11C + ((n) * 0x80)) -#define DSIPHY_DLNX_TIMING_CTRL_6(n) (0x120 + ((n) * 0x80)) -#define DSIPHY_DLNX_TIMING_CTRL_7(n) (0x124 + ((n) * 0x80)) -#define DSIPHY_DLNX_TIMING_CTRL_8(n) (0x128 + ((n) * 0x80)) -#define DSIPHY_DLNX_TIMING_CTRL_9(n) (0x12C + ((n) * 0x80)) -#define DSIPHY_DLNX_TIMING_CTRL_10(n) (0x130 + ((n) * 0x80)) -#define DSIPHY_DLNX_TIMING_CTRL_11(n) (0x134 + ((n) * 0x80)) -#define DSIPHY_DLNX_STRENGTH_CTRL_0(n) (0x138 + ((n) * 0x80)) -#define DSIPHY_DLNX_STRENGTH_CTRL_1(n) (0x13C + ((n) * 0x80)) -#define DSIPHY_DLNX_BIST_POLY(n) (0x140 + ((n) * 0x80)) -#define DSIPHY_DLNX_BIST_SEED0(n) (0x144 + ((n) * 0x80)) -#define DSIPHY_DLNX_BIST_SEED1(n) (0x148 + ((n) * 0x80)) -#define DSIPHY_DLNX_BIST_HEAD(n) (0x14C + ((n) * 0x80)) -#define DSIPHY_DLNX_BIST_SOT(n) (0x150 + ((n) * 0x80)) -#define DSIPHY_DLNX_BIST_CTRL0(n) (0x154 + ((n) * 0x80)) -#define DSIPHY_DLNX_BIST_CTRL1(n) (0x158 + ((n) * 0x80)) -#define DSIPHY_DLNX_BIST_CTRL2(n) (0x15C + ((n) * 0x80)) -#define DSIPHY_DLNX_BIST_CTRL3(n) (0x160 + ((n) * 0x80)) -#define DSIPHY_DLNX_VREG_CNTRL(n) (0x164 + ((n) * 0x80)) -#define DSIPHY_DLNX_HSTX_STR_STATUS(n) (0x168 + ((n) * 0x80)) -#define DSIPHY_DLNX_BIST_STATUS0(n) (0x16C + ((n) * 0x80)) -#define DSIPHY_DLNX_BIST_STATUS1(n) (0x170 + ((n) * 0x80)) -#define DSIPHY_DLNX_BIST_STATUS2(n) (0x174 + ((n) * 0x80)) -#define DSIPHY_DLNX_BIST_STATUS3(n) (0x178 + ((n) * 0x80)) -#define DSIPHY_DLNX_MISR_STATUS(n) (0x17C + ((n) * 0x80)) - -#define DSIPHY_PLL_CLKBUFLR_EN 0x041C -#define DSIPHY_PLL_PLL_BANDGAP 0x0508 - -/** - * regulator_enable() - enable regulators for DSI PHY - * @phy: Pointer to DSI PHY hardware object. - * @reg_cfg: Regulator configuration for all DSI lanes. - */ -void dsi_phy_hw_v2_0_regulator_enable(struct dsi_phy_hw *phy, - struct dsi_phy_per_lane_cfgs *reg_cfg) -{ - int i; - - for (i = DSI_LOGICAL_LANE_0; i < DSI_LANE_MAX; i++) - DSI_W32(phy, DSIPHY_DLNX_VREG_CNTRL(i), reg_cfg->lane[i][0]); - - /* make sure all values are written to hardware */ - wmb(); - - pr_debug("[DSI_%d] Phy regulators enabled\n", phy->index); -} - -/** - * regulator_disable() - disable regulators - * @phy: Pointer to DSI PHY hardware object. - */ -void dsi_phy_hw_v2_0_regulator_disable(struct dsi_phy_hw *phy) -{ - pr_debug("[DSI_%d] Phy regulators disabled\n", phy->index); -} - -/** - * enable() - Enable PHY hardware - * @phy: Pointer to DSI PHY hardware object. - * @cfg: Per lane configurations for timing, strength and lane - * configurations. - */ -void dsi_phy_hw_v2_0_enable(struct dsi_phy_hw *phy, - struct dsi_phy_cfg *cfg) -{ - int i; - struct dsi_phy_per_lane_cfgs *timing = &cfg->timing; - u32 data; - - DSI_W32(phy, DSIPHY_CMN_LDO_CNTRL, 0x1C); - - DSI_W32(phy, DSIPHY_CMN_GLBL_TEST_CTRL, 0x1); - for (i = DSI_LOGICAL_LANE_0; i < DSI_LANE_MAX; i++) { - - DSI_W32(phy, DSIPHY_DLNX_CFG0(i), cfg->lanecfg.lane[i][0]); - DSI_W32(phy, DSIPHY_DLNX_CFG1(i), cfg->lanecfg.lane[i][1]); - DSI_W32(phy, DSIPHY_DLNX_CFG2(i), cfg->lanecfg.lane[i][2]); - DSI_W32(phy, DSIPHY_DLNX_CFG3(i), cfg->lanecfg.lane[i][3]); - - DSI_W32(phy, DSIPHY_DLNX_TEST_STR(i), 0x88); - - DSI_W32(phy, DSIPHY_DLNX_TIMING_CTRL_4(i), timing->lane[i][0]); - DSI_W32(phy, DSIPHY_DLNX_TIMING_CTRL_5(i), timing->lane[i][1]); - DSI_W32(phy, DSIPHY_DLNX_TIMING_CTRL_6(i), timing->lane[i][2]); - DSI_W32(phy, DSIPHY_DLNX_TIMING_CTRL_7(i), timing->lane[i][3]); - DSI_W32(phy, DSIPHY_DLNX_TIMING_CTRL_8(i), timing->lane[i][4]); - DSI_W32(phy, DSIPHY_DLNX_TIMING_CTRL_9(i), timing->lane[i][5]); - DSI_W32(phy, DSIPHY_DLNX_TIMING_CTRL_10(i), timing->lane[i][6]); - DSI_W32(phy, DSIPHY_DLNX_TIMING_CTRL_11(i), timing->lane[i][7]); - - DSI_W32(phy, DSIPHY_DLNX_STRENGTH_CTRL_0(i), - cfg->strength.lane[i][0]); - DSI_W32(phy, DSIPHY_DLNX_STRENGTH_CTRL_1(i), - cfg->strength.lane[i][1]); - } - - /* make sure all values are written to hardware before enabling phy */ - wmb(); - - DSI_W32(phy, DSIPHY_CMN_CTRL_1, 0x80); - udelay(100); - DSI_W32(phy, DSIPHY_CMN_CTRL_1, 0x00); - - data = DSI_R32(phy, DSIPHY_CMN_GLBL_TEST_CTRL); - - switch (cfg->pll_source) { - case DSI_PLL_SOURCE_STANDALONE: - DSI_W32(phy, DSIPHY_PLL_CLKBUFLR_EN, 0x01); - data &= ~BIT(2); - break; - case DSI_PLL_SOURCE_NATIVE: - DSI_W32(phy, DSIPHY_PLL_CLKBUFLR_EN, 0x03); - data &= ~BIT(2); - break; - case DSI_PLL_SOURCE_NON_NATIVE: - DSI_W32(phy, DSIPHY_PLL_CLKBUFLR_EN, 0x00); - data |= BIT(2); - break; - default: - break; - } - - DSI_W32(phy, DSIPHY_CMN_GLBL_TEST_CTRL, data); - - /* Enable bias current for pll1 during split display case */ - if (cfg->pll_source == DSI_PLL_SOURCE_NON_NATIVE) - DSI_W32(phy, DSIPHY_PLL_PLL_BANDGAP, 0x3); - - pr_debug("[DSI_%d]Phy enabled ", phy->index); -} - -/** - * disable() - Disable PHY hardware - * @phy: Pointer to DSI PHY hardware object. - */ -void dsi_phy_hw_v2_0_disable(struct dsi_phy_hw *phy, - struct dsi_phy_cfg *cfg) -{ - DSI_W32(phy, DSIPHY_PLL_CLKBUFLR_EN, 0); - DSI_W32(phy, DSIPHY_CMN_GLBL_TEST_CTRL, 0); - DSI_W32(phy, DSIPHY_CMN_CTRL_0, 0); - pr_debug("[DSI_%d]Phy disabled ", phy->index); -} - -/** - * dsi_phy_hw_v2_0_idle_on() - Enable DSI PHY hardware during idle screen - * @phy: Pointer to DSI PHY hardware object. - */ -void dsi_phy_hw_v2_0_idle_on(struct dsi_phy_hw *phy, struct dsi_phy_cfg *cfg) -{ - int i = 0; - - for (i = DSI_LOGICAL_LANE_0; i < DSI_LANE_MAX; i++) { - DSI_W32(phy, DSIPHY_DLNX_STRENGTH_CTRL_0(i), - cfg->strength.lane[i][0]); - DSI_W32(phy, DSIPHY_DLNX_STRENGTH_CTRL_1(i), - cfg->strength.lane[i][1]); - } - wmb(); /* make sure write happens */ - pr_debug("[DSI_%d]Phy enabled out of idle screen\n", phy->index); -} - - -/** - * dsi_phy_hw_v2_0_idle_off() - Disable DSI PHY hardware during idle screen - * @phy: Pointer to DSI PHY hardware object. - */ -void dsi_phy_hw_v2_0_idle_off(struct dsi_phy_hw *phy) -{ - int i = 0; - - DSI_W32(phy, DSIPHY_CMN_CTRL_0, 0x7f); - for (i = DSI_LOGICAL_LANE_0; i < DSI_LANE_MAX; i++) - DSI_W32(phy, DSIPHY_DLNX_VREG_CNTRL(i), 0x1c); - DSI_W32(phy, DSIPHY_CMN_LDO_CNTRL, 0x1C); - - for (i = DSI_LOGICAL_LANE_0; i < DSI_LANE_MAX; i++) - DSI_W32(phy, DSIPHY_DLNX_STRENGTH_CTRL_1(i), 0x0); - wmb(); /* make sure write happens */ - pr_debug("[DSI_%d]Phy disabled during idle screen\n", phy->index); -} - -int dsi_phy_hw_timing_val_v2_0(struct dsi_phy_per_lane_cfgs *timing_cfg, - u32 *timing_val, u32 size) -{ - int i = 0, j = 0; - - if (size != (DSI_LANE_MAX * DSI_MAX_SETTINGS)) { - pr_err("Unexpected timing array size %d\n", size); - return -EINVAL; - } - - for (i = DSI_LOGICAL_LANE_0; i < DSI_LANE_MAX; i++) { - for (j = 0; j < DSI_MAX_SETTINGS; j++) { - timing_cfg->lane[i][j] = *timing_val; - timing_val++; - } - } - return 0; -} diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v3_0.c b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v3_0.c deleted file mode 100644 index c1eae68..0000000 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v3_0.c +++ /dev/null @@ -1,447 +0,0 @@ -/* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * 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) "dsi-phy-hw:" fmt -#include <linux/math64.h> -#include <linux/delay.h> -#include <linux/iopoll.h> -#include "dsi_hw.h" -#include "dsi_phy_hw.h" - -#define DSIPHY_CMN_CLK_CFG0 0x010 -#define DSIPHY_CMN_CLK_CFG1 0x014 -#define DSIPHY_CMN_GLBL_CTRL 0x018 -#define DSIPHY_CMN_RBUF_CTRL 0x01C -#define DSIPHY_CMN_VREG_CTRL 0x020 -#define DSIPHY_CMN_CTRL_0 0x024 -#define DSIPHY_CMN_CTRL_1 0x028 -#define DSIPHY_CMN_CTRL_2 0x02C -#define DSIPHY_CMN_LANE_CFG0 0x030 -#define DSIPHY_CMN_LANE_CFG1 0x034 -#define DSIPHY_CMN_PLL_CNTRL 0x038 -#define DSIPHY_CMN_LANE_CTRL0 0x098 -#define DSIPHY_CMN_LANE_CTRL1 0x09C -#define DSIPHY_CMN_LANE_CTRL2 0x0A0 -#define DSIPHY_CMN_LANE_CTRL3 0x0A4 -#define DSIPHY_CMN_LANE_CTRL4 0x0A8 -#define DSIPHY_CMN_TIMING_CTRL_0 0x0AC -#define DSIPHY_CMN_TIMING_CTRL_1 0x0B0 -#define DSIPHY_CMN_TIMING_CTRL_2 0x0B4 -#define DSIPHY_CMN_TIMING_CTRL_3 0x0B8 -#define DSIPHY_CMN_TIMING_CTRL_4 0x0BC -#define DSIPHY_CMN_TIMING_CTRL_5 0x0C0 -#define DSIPHY_CMN_TIMING_CTRL_6 0x0C4 -#define DSIPHY_CMN_TIMING_CTRL_7 0x0C8 -#define DSIPHY_CMN_TIMING_CTRL_8 0x0CC -#define DSIPHY_CMN_TIMING_CTRL_9 0x0D0 -#define DSIPHY_CMN_TIMING_CTRL_10 0x0D4 -#define DSIPHY_CMN_TIMING_CTRL_11 0x0D8 -#define DSIPHY_CMN_PHY_STATUS 0x0EC -#define DSIPHY_CMN_LANE_STATUS0 0x0F4 -#define DSIPHY_CMN_LANE_STATUS1 0x0F8 - - -/* n = 0..3 for data lanes and n = 4 for clock lane */ -#define DSIPHY_LNX_CFG0(n) (0x200 + (0x80 * (n))) -#define DSIPHY_LNX_CFG1(n) (0x204 + (0x80 * (n))) -#define DSIPHY_LNX_CFG2(n) (0x208 + (0x80 * (n))) -#define DSIPHY_LNX_CFG3(n) (0x20C + (0x80 * (n))) -#define DSIPHY_LNX_TEST_DATAPATH(n) (0x210 + (0x80 * (n))) -#define DSIPHY_LNX_PIN_SWAP(n) (0x214 + (0x80 * (n))) -#define DSIPHY_LNX_HSTX_STR_CTRL(n) (0x218 + (0x80 * (n))) -#define DSIPHY_LNX_OFFSET_TOP_CTRL(n) (0x21C + (0x80 * (n))) -#define DSIPHY_LNX_OFFSET_BOT_CTRL(n) (0x220 + (0x80 * (n))) -#define DSIPHY_LNX_LPTX_STR_CTRL(n) (0x224 + (0x80 * (n))) -#define DSIPHY_LNX_LPRX_CTRL(n) (0x228 + (0x80 * (n))) -#define DSIPHY_LNX_TX_DCTRL(n) (0x22C + (0x80 * (n))) - -static inline int dsi_conv_phy_to_logical_lane( - struct dsi_lane_map *lane_map, enum dsi_phy_data_lanes phy_lane) -{ - int i = 0; - - if (phy_lane > DSI_PHYSICAL_LANE_3) - return -EINVAL; - - for (i = DSI_LOGICAL_LANE_0; i < (DSI_LANE_MAX - 1); i++) { - if (lane_map->lane_map_v2[i] == phy_lane) - break; - } - return i; -} - -static inline int dsi_conv_logical_to_phy_lane( - struct dsi_lane_map *lane_map, enum dsi_logical_lane lane) -{ - int i = 0; - - if (lane > (DSI_LANE_MAX - 1)) - return -EINVAL; - - for (i = DSI_LOGICAL_LANE_0; i < (DSI_LANE_MAX - 1); i++) { - if (BIT(i) == lane_map->lane_map_v2[lane]) - break; - } - return i; -} - -/** - * regulator_enable() - enable regulators for DSI PHY - * @phy: Pointer to DSI PHY hardware object. - * @reg_cfg: Regulator configuration for all DSI lanes. - */ -void dsi_phy_hw_v3_0_regulator_enable(struct dsi_phy_hw *phy, - struct dsi_phy_per_lane_cfgs *reg_cfg) -{ - pr_debug("[DSI_%d] Phy regulators enabled\n", phy->index); - /* Nothing to be done for DSI PHY regulator enable */ -} - -/** - * regulator_disable() - disable regulators - * @phy: Pointer to DSI PHY hardware object. - */ -void dsi_phy_hw_v3_0_regulator_disable(struct dsi_phy_hw *phy) -{ - pr_debug("[DSI_%d] Phy regulators disabled\n", phy->index); - /* Nothing to be done for DSI PHY regulator disable */ -} - - -static int dsi_phy_hw_v3_0_is_pll_on(struct dsi_phy_hw *phy) -{ - u32 data = 0; - - data = DSI_R32(phy, DSIPHY_CMN_PLL_CNTRL); - mb(); /*make sure read happened */ - return (data & BIT(0)); -} - -static void dsi_phy_hw_v3_0_config_lpcdrx(struct dsi_phy_hw *phy, - struct dsi_phy_cfg *cfg, bool enable) -{ - int phy_lane_0 = dsi_conv_logical_to_phy_lane(&cfg->lane_map, - DSI_LOGICAL_LANE_0); - /* - * LPRX and CDRX need to enabled only for physical data lane - * corresponding to the logical data lane 0 - */ - - if (enable) - DSI_W32(phy, DSIPHY_LNX_LPRX_CTRL(phy_lane_0), - cfg->strength.lane[phy_lane_0][1]); - else - DSI_W32(phy, DSIPHY_LNX_LPRX_CTRL(phy_lane_0), 0); -} - -static void dsi_phy_hw_v3_0_lane_swap_config(struct dsi_phy_hw *phy, - struct dsi_lane_map *lane_map) -{ - DSI_W32(phy, DSIPHY_CMN_LANE_CFG0, - (lane_map->lane_map_v2[DSI_LOGICAL_LANE_0] | - (lane_map->lane_map_v2[DSI_LOGICAL_LANE_1] << 4))); - DSI_W32(phy, DSIPHY_CMN_LANE_CFG1, - (lane_map->lane_map_v2[DSI_LOGICAL_LANE_2] | - (lane_map->lane_map_v2[DSI_LOGICAL_LANE_3] << 4))); -} - -static void dsi_phy_hw_v3_0_lane_settings(struct dsi_phy_hw *phy, - struct dsi_phy_cfg *cfg) -{ - int i; - u8 tx_dctrl[] = {0x00, 0x00, 0x00, 0x04, 0x01}; - - /* Strength ctrl settings */ - for (i = DSI_LOGICAL_LANE_0; i < DSI_LANE_MAX; i++) { - DSI_W32(phy, DSIPHY_LNX_LPTX_STR_CTRL(i), - cfg->strength.lane[i][0]); - /* - * Disable LPRX and CDRX for all lanes. And later on, it will - * be only enabled for the physical data lane corresponding - * to the logical data lane 0 - */ - 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); - } - dsi_phy_hw_v3_0_config_lpcdrx(phy, cfg, true); - - /* other settings */ - for (i = DSI_LOGICAL_LANE_0; i < DSI_LANE_MAX; i++) { - DSI_W32(phy, DSIPHY_LNX_CFG0(i), cfg->lanecfg.lane[i][0]); - 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_TX_DCTRL(i), tx_dctrl[i]); - } - - /* Toggle BIT 0 to release freeze I/0 */ - DSI_W32(phy, DSIPHY_LNX_TX_DCTRL(3), 0x05); - DSI_W32(phy, DSIPHY_LNX_TX_DCTRL(3), 0x04); -} - -/** - * enable() - Enable PHY hardware - * @phy: Pointer to DSI PHY hardware object. - * @cfg: Per lane configurations for timing, strength and lane - * configurations. - */ -void dsi_phy_hw_v3_0_enable(struct dsi_phy_hw *phy, - struct dsi_phy_cfg *cfg) -{ - int rc = 0; - u32 status; - u32 const delay_us = 5; - u32 const timeout_us = 1000; - struct dsi_phy_per_lane_cfgs *timing = &cfg->timing; - u32 data; - - if (dsi_phy_hw_v3_0_is_pll_on(phy)) - pr_warn("PLL turned on before configuring PHY\n"); - - /* wait for REFGEN READY */ - rc = readl_poll_timeout_atomic(phy->base + DSIPHY_CMN_PHY_STATUS, - status, (status & BIT(0)), delay_us, timeout_us); - if (rc) { - pr_err("Ref gen not ready. Aborting\n"); - return; - } - - /* de-assert digital and pll power down */ - data = BIT(6) | BIT(5); - DSI_W32(phy, DSIPHY_CMN_CTRL_0, data); - - /* Assert PLL core reset */ - DSI_W32(phy, DSIPHY_CMN_PLL_CNTRL, 0x00); - - /* turn off resync FIFO */ - DSI_W32(phy, DSIPHY_CMN_RBUF_CTRL, 0x00); - - /* Select MS1 byte-clk */ - DSI_W32(phy, DSIPHY_CMN_GLBL_CTRL, 0x10); - - /* Enable LDO */ - DSI_W32(phy, DSIPHY_CMN_VREG_CTRL, 0x59); - - /* Configure PHY lane swap */ - dsi_phy_hw_v3_0_lane_swap_config(phy, &cfg->lane_map); - - /* DSI PHY timings */ - DSI_W32(phy, DSIPHY_CMN_TIMING_CTRL_0, timing->lane_v3[0]); - DSI_W32(phy, DSIPHY_CMN_TIMING_CTRL_1, timing->lane_v3[1]); - DSI_W32(phy, DSIPHY_CMN_TIMING_CTRL_2, timing->lane_v3[2]); - DSI_W32(phy, DSIPHY_CMN_TIMING_CTRL_3, timing->lane_v3[3]); - DSI_W32(phy, DSIPHY_CMN_TIMING_CTRL_4, timing->lane_v3[4]); - DSI_W32(phy, DSIPHY_CMN_TIMING_CTRL_5, timing->lane_v3[5]); - DSI_W32(phy, DSIPHY_CMN_TIMING_CTRL_6, timing->lane_v3[6]); - DSI_W32(phy, DSIPHY_CMN_TIMING_CTRL_7, timing->lane_v3[7]); - DSI_W32(phy, DSIPHY_CMN_TIMING_CTRL_8, timing->lane_v3[8]); - DSI_W32(phy, DSIPHY_CMN_TIMING_CTRL_9, timing->lane_v3[9]); - DSI_W32(phy, DSIPHY_CMN_TIMING_CTRL_10, timing->lane_v3[10]); - DSI_W32(phy, DSIPHY_CMN_TIMING_CTRL_11, timing->lane_v3[11]); - - /* Remove power down from all blocks */ - DSI_W32(phy, DSIPHY_CMN_CTRL_0, 0x7f); - - /*power up lanes */ - data = DSI_R32(phy, DSIPHY_CMN_CTRL_0); - /* TODO: only power up lanes that are used */ - data |= 0x1F; - DSI_W32(phy, DSIPHY_CMN_CTRL_0, data); - DSI_W32(phy, DSIPHY_CMN_LANE_CTRL0, 0x1F); - - /* Select full-rate mode */ - DSI_W32(phy, DSIPHY_CMN_CTRL_2, 0x40); - - switch (cfg->pll_source) { - case DSI_PLL_SOURCE_STANDALONE: - case DSI_PLL_SOURCE_NATIVE: - data = 0x0; /* internal PLL */ - break; - case DSI_PLL_SOURCE_NON_NATIVE: - data = 0x1; /* external PLL */ - break; - default: - break; - } - DSI_W32(phy, DSIPHY_CMN_CLK_CFG1, (data << 2)); /* set PLL src */ - - /* DSI lane settings */ - dsi_phy_hw_v3_0_lane_settings(phy, cfg); - - pr_debug("[DSI_%d]Phy enabled ", phy->index); -} - -/** - * disable() - Disable PHY hardware - * @phy: Pointer to DSI PHY hardware object. - */ -void dsi_phy_hw_v3_0_disable(struct dsi_phy_hw *phy, - struct dsi_phy_cfg *cfg) -{ - u32 data = 0; - - if (dsi_phy_hw_v3_0_is_pll_on(phy)) - pr_warn("Turning OFF PHY while PLL is on\n"); - - dsi_phy_hw_v3_0_config_lpcdrx(phy, cfg, false); - - data = DSI_R32(phy, DSIPHY_CMN_CTRL_0); - /* disable all lanes */ - data &= ~0x1F; - DSI_W32(phy, DSIPHY_CMN_CTRL_0, data); - DSI_W32(phy, DSIPHY_CMN_LANE_CTRL0, 0); - - /* Turn off all PHY blocks */ - DSI_W32(phy, DSIPHY_CMN_CTRL_0, 0x00); - /* make sure phy is turned off */ - wmb(); - pr_debug("[DSI_%d]Phy disabled ", phy->index); -} - -int dsi_phy_hw_v3_0_wait_for_lane_idle( - struct dsi_phy_hw *phy, u32 lanes) -{ - int rc = 0, val = 0; - u32 stop_state_mask = 0; - u32 const sleep_us = 10; - u32 const timeout_us = 100; - - stop_state_mask = BIT(4); /* clock lane */ - if (lanes & DSI_DATA_LANE_0) - stop_state_mask |= BIT(0); - if (lanes & DSI_DATA_LANE_1) - stop_state_mask |= BIT(1); - if (lanes & DSI_DATA_LANE_2) - stop_state_mask |= BIT(2); - if (lanes & DSI_DATA_LANE_3) - stop_state_mask |= BIT(3); - - pr_debug("%s: polling for lanes to be in stop state, mask=0x%08x\n", - __func__, stop_state_mask); - rc = readl_poll_timeout(phy->base + DSIPHY_CMN_LANE_STATUS1, val, - (val == stop_state_mask), sleep_us, timeout_us); - if (rc) { - pr_err("%s: lanes not in stop state, LANE_STATUS=0x%08x\n", - __func__, val); - return rc; - } - - return 0; -} - -void dsi_phy_hw_v3_0_ulps_request(struct dsi_phy_hw *phy, - struct dsi_phy_cfg *cfg, u32 lanes) -{ - u32 reg = 0; - - if (lanes & DSI_CLOCK_LANE) - reg = BIT(4); - if (lanes & DSI_DATA_LANE_0) - reg |= BIT(0); - if (lanes & DSI_DATA_LANE_1) - reg |= BIT(1); - if (lanes & DSI_DATA_LANE_2) - reg |= BIT(2); - if (lanes & DSI_DATA_LANE_3) - reg |= BIT(3); - - /* - * ULPS entry request. Wait for short time to make sure - * that the lanes enter ULPS. Recommended as per HPG. - */ - DSI_W32(phy, DSIPHY_CMN_LANE_CTRL1, reg); - usleep_range(100, 110); - - /* disable LPRX and CDRX */ - dsi_phy_hw_v3_0_config_lpcdrx(phy, cfg, false); - /* disable lane LDOs */ - DSI_W32(phy, DSIPHY_CMN_VREG_CTRL, 0x19); - pr_debug("[DSI_PHY%d] ULPS requested for lanes 0x%x\n", phy->index, - lanes); -} - -void dsi_phy_hw_v3_0_ulps_exit(struct dsi_phy_hw *phy, - struct dsi_phy_cfg *cfg, u32 lanes) -{ - u32 reg = 0; - - if (lanes & DSI_CLOCK_LANE) - reg = BIT(4); - if (lanes & DSI_DATA_LANE_0) - reg |= BIT(0); - if (lanes & DSI_DATA_LANE_1) - reg |= BIT(1); - if (lanes & DSI_DATA_LANE_2) - reg |= BIT(2); - if (lanes & DSI_DATA_LANE_3) - reg |= BIT(3); - - /* enable lane LDOs */ - DSI_W32(phy, DSIPHY_CMN_VREG_CTRL, 0x59); - /* enable LPRX and CDRX */ - dsi_phy_hw_v3_0_config_lpcdrx(phy, cfg, true); - - /* ULPS exit request */ - DSI_W32(phy, DSIPHY_CMN_LANE_CTRL2, reg); - usleep_range(1000, 1010); - - /* Clear ULPS request flags on all lanes */ - DSI_W32(phy, DSIPHY_CMN_LANE_CTRL1, 0); - /* Clear ULPS exit flags on all lanes */ - DSI_W32(phy, DSIPHY_CMN_LANE_CTRL2, 0); - - /* - * Sometimes when exiting ULPS, it is possible that some DSI - * lanes are not in the stop state which could lead to DSI - * commands not going through. To avoid this, force the lanes - * to be in stop state. - */ - DSI_W32(phy, DSIPHY_CMN_LANE_CTRL3, reg); - DSI_W32(phy, DSIPHY_CMN_LANE_CTRL3, 0); - usleep_range(100, 110); -} - -u32 dsi_phy_hw_v3_0_get_lanes_in_ulps(struct dsi_phy_hw *phy) -{ - u32 lanes = 0; - - lanes = DSI_R32(phy, DSIPHY_CMN_LANE_STATUS0); - pr_debug("[DSI_PHY%d] lanes in ulps = 0x%x\n", phy->index, lanes); - return lanes; -} - -bool dsi_phy_hw_v3_0_is_lanes_in_ulps(u32 lanes, u32 ulps_lanes) -{ - if (lanes & ulps_lanes) - return false; - - return true; -} - -int dsi_phy_hw_timing_val_v3_0(struct dsi_phy_per_lane_cfgs *timing_cfg, - u32 *timing_val, u32 size) -{ - int i = 0; - - if (size != DSI_PHY_TIMING_V3_SIZE) { - pr_err("Unexpected timing array size %d\n", size); - return -EINVAL; - } - - for (i = 0; i < size; i++) - timing_cfg->lane_v3[i] = timing_val[i]; - return 0; -} diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_calc.c b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_calc.c deleted file mode 100644 index 13fe6ec..0000000 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_calc.c +++ /dev/null @@ -1,676 +0,0 @@ -/* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * 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) "dsi-phy-timing:" fmt - -#include "dsi_phy_timing_calc.h" - -static const u32 bits_per_pixel[DSI_PIXEL_FORMAT_MAX] = { - 16, 18, 18, 24, 3, 8, 12 }; - -static int dsi_phy_cmn_validate_and_set(struct timing_entry *t, - char const *t_name) -{ - if (t->rec & 0xffffff00) { - /* Output value can only be 8 bits */ - pr_err("Incorrect %s rec value - %d\n", t_name, t->rec); - return -EINVAL; - } - t->reg_value = t->rec; - return 0; -} - -/** - * calc_clk_prepare - calculates prepare timing params for clk lane. - */ -static int calc_clk_prepare(struct dsi_phy_hw *phy, - struct phy_clk_params *clk_params, - struct phy_timing_desc *desc, - s32 *actual_frac, - s64 *actual_intermediate) -{ - u64 multiplier = BIT(20); - struct timing_entry *t = &desc->clk_prepare; - int rc = 0; - u64 dividend, temp, temp_multiple; - s32 frac = 0; - s64 intermediate; - s64 clk_prep_actual; - - dividend = ((t->rec_max - t->rec_min) * - clk_params->clk_prep_buf * multiplier); - temp = roundup(div_s64(dividend, 100), multiplier); - temp += (t->rec_min * multiplier); - t->rec = div_s64(temp, multiplier); - - rc = dsi_phy_cmn_validate_and_set(t, "clk_prepare"); - if (rc) - goto error; - - /* calculate theoretical value */ - temp_multiple = 8 * t->reg_value * clk_params->tlpx_numer_ns - * multiplier; - intermediate = div_s64(temp_multiple, clk_params->bitclk_mbps); - div_s64_rem(temp_multiple, clk_params->bitclk_mbps, &frac); - clk_prep_actual = div_s64((intermediate + frac), multiplier); - - pr_debug("CLK_PREPARE:mipi_min=%d, mipi_max=%d, rec_min=%d, rec_max=%d", - t->mipi_min, t->mipi_max, t->rec_min, t->rec_max); - pr_debug(" reg_value=%d, actual=%lld\n", t->reg_value, clk_prep_actual); - - *actual_frac = frac; - *actual_intermediate = intermediate; - -error: - return rc; -} - -/** - * calc_clk_zero - calculates zero timing params for clk lane. - */ -static int calc_clk_zero(struct dsi_phy_hw *phy, - struct phy_clk_params *clk_params, - struct phy_timing_desc *desc, - s32 actual_frac, s64 actual_intermediate) -{ - u64 const multiplier = BIT(20); - int rc = 0; - struct timing_entry *t = &desc->clk_zero; - s64 mipi_min, rec_temp1; - struct phy_timing_ops *ops = phy->ops.timing_ops; - - mipi_min = ((300 * multiplier) - (actual_intermediate + actual_frac)); - t->mipi_min = div_s64(mipi_min, multiplier); - - rec_temp1 = div_s64((mipi_min * clk_params->bitclk_mbps), - clk_params->tlpx_numer_ns); - - if (ops->calc_clk_zero) { - t->rec_min = ops->calc_clk_zero(rec_temp1, multiplier); - } else { - rc = -EINVAL; - goto error; - } - t->rec_max = ((t->rec_min > 255) ? 511 : 255); - - t->rec = DIV_ROUND_UP((((t->rec_max - t->rec_min) * - clk_params->clk_zero_buf) + (t->rec_min * 100)), 100); - - rc = dsi_phy_cmn_validate_and_set(t, "clk_zero"); - if (rc) - goto error; - - - pr_debug("CLK_ZERO:mipi_min=%d, mipi_max=%d, rec_min=%d, rec_max=%d, reg_val=%d\n", - t->mipi_min, t->mipi_max, t->rec_min, t->rec_max, - t->reg_value); -error: - return rc; -} - -/** - * calc_clk_trail - calculates prepare trail params for clk lane. - */ -static int calc_clk_trail(struct dsi_phy_hw *phy, - struct phy_clk_params *clk_params, - struct phy_timing_desc *desc, - s64 *teot_clk_lane) -{ - u64 const multiplier = BIT(20); - int rc = 0; - struct timing_entry *t = &desc->clk_trail; - u64 temp_multiple; - s32 frac; - s64 mipi_max_tr, rec_temp1, mipi_max; - s64 teot_clk_lane1; - struct phy_timing_ops *ops = phy->ops.timing_ops; - - temp_multiple = div_s64( - (12 * multiplier * clk_params->tlpx_numer_ns), - clk_params->bitclk_mbps); - div_s64_rem(temp_multiple, multiplier, &frac); - - mipi_max_tr = ((105 * multiplier) + - (temp_multiple + frac)); - teot_clk_lane1 = div_s64(mipi_max_tr, multiplier); - - mipi_max = (mipi_max_tr - (clk_params->treot_ns * multiplier)); - t->mipi_max = div_s64(mipi_max, multiplier); - - temp_multiple = div_s64( - (t->mipi_min * multiplier * clk_params->bitclk_mbps), - clk_params->tlpx_numer_ns); - - div_s64_rem(temp_multiple, multiplier, &frac); - if (ops->calc_clk_trail_rec_min) { - t->rec_min = ops->calc_clk_trail_rec_min(temp_multiple, - frac, multiplier); - } else { - rc = -EINVAL; - goto error; - } - - /* recommended max */ - rec_temp1 = div_s64((mipi_max * clk_params->bitclk_mbps), - clk_params->tlpx_numer_ns); - if (ops->calc_clk_trail_rec_max) { - t->rec_max = ops->calc_clk_trail_rec_max(rec_temp1, multiplier); - } else { - rc = -EINVAL; - goto error; - } - - t->rec = DIV_ROUND_UP( - (((t->rec_max - t->rec_min) * clk_params->clk_trail_buf) + - (t->rec_min * 100)), 100); - - rc = dsi_phy_cmn_validate_and_set(t, "clk_trail"); - if (rc) - goto error; - - *teot_clk_lane = teot_clk_lane1; - pr_debug("CLK_TRAIL:mipi_min=%d, mipi_max=%d, rec_min=%d, rec_max=%d, reg_val=%d\n", - t->mipi_min, t->mipi_max, t->rec_min, t->rec_max, - t->reg_value); - -error: - return rc; - -} - -/** - * calc_hs_prepare - calculates prepare timing params for data lanes in HS. - */ -static int calc_hs_prepare(struct dsi_phy_hw *phy, - struct phy_clk_params *clk_params, - struct phy_timing_desc *desc, - u64 *temp_mul) -{ - u64 multiplier = BIT(20); - int rc = 0; - struct timing_entry *t = &desc->hs_prepare; - u64 temp_multiple, dividend, temp; - s32 frac; - s64 rec_temp1, rec_temp2, mipi_max, mipi_min; - u32 low_clk_multiplier = 0; - - if (clk_params->bitclk_mbps <= 120) - low_clk_multiplier = 2; - /* mipi min */ - temp_multiple = div_s64((4 * multiplier * clk_params->tlpx_numer_ns), - clk_params->bitclk_mbps); - div_s64_rem(temp_multiple, multiplier, &frac); - mipi_min = (40 * multiplier) + (temp_multiple + frac); - t->mipi_min = div_s64(mipi_min, multiplier); - - /* mipi_max */ - temp_multiple = div_s64( - (6 * multiplier * clk_params->tlpx_numer_ns), - clk_params->bitclk_mbps); - div_s64_rem(temp_multiple, multiplier, &frac); - mipi_max = (85 * multiplier) + temp_multiple; - t->mipi_max = div_s64(mipi_max, multiplier); - - /* recommended min */ - temp_multiple = div_s64((mipi_min * clk_params->bitclk_mbps), - clk_params->tlpx_numer_ns); - temp_multiple -= (low_clk_multiplier * multiplier); - div_s64_rem(temp_multiple, multiplier, &frac); - rec_temp1 = roundup(((temp_multiple + frac) / 8), multiplier); - t->rec_min = div_s64(rec_temp1, multiplier); - - /* recommended max */ - temp_multiple = div_s64((mipi_max * clk_params->bitclk_mbps), - clk_params->tlpx_numer_ns); - temp_multiple -= (low_clk_multiplier * multiplier); - div_s64_rem(temp_multiple, multiplier, &frac); - rec_temp2 = rounddown((temp_multiple / 8), multiplier); - t->rec_max = div_s64(rec_temp2, multiplier); - - /* register value */ - dividend = ((rec_temp2 - rec_temp1) * clk_params->hs_prep_buf); - temp = roundup(div_u64(dividend, 100), multiplier); - t->rec = div_s64((temp + rec_temp1), multiplier); - - rc = dsi_phy_cmn_validate_and_set(t, "hs_prepare"); - if (rc) - goto error; - - temp_multiple = div_s64( - (8 * (temp + rec_temp1) * clk_params->tlpx_numer_ns), - clk_params->bitclk_mbps); - - *temp_mul = temp_multiple; - pr_debug("HS_PREP:mipi_min=%d, mipi_max=%d, rec_min=%d, rec_max=%d, reg_val=%d\n", - t->mipi_min, t->mipi_max, t->rec_min, t->rec_max, - t->reg_value); -error: - return rc; -} - -/** - * calc_hs_zero - calculates zero timing params for data lanes in HS. - */ -static int calc_hs_zero(struct dsi_phy_hw *phy, - struct phy_clk_params *clk_params, - struct phy_timing_desc *desc, - u64 temp_multiple) -{ - u64 const multiplier = BIT(20); - int rc = 0; - struct timing_entry *t = &desc->hs_zero; - s64 rec_temp1, mipi_min; - struct phy_timing_ops *ops = phy->ops.timing_ops; - - mipi_min = div_s64((10 * clk_params->tlpx_numer_ns * multiplier), - clk_params->bitclk_mbps); - rec_temp1 = (145 * multiplier) + mipi_min - temp_multiple; - t->mipi_min = div_s64(rec_temp1, multiplier); - - /* recommended min */ - rec_temp1 = div_s64((rec_temp1 * clk_params->bitclk_mbps), - clk_params->tlpx_numer_ns); - - if (ops->calc_hs_zero) { - t->rec_min = ops->calc_hs_zero(rec_temp1, multiplier); - } else { - rc = -EINVAL; - goto error; - } - - t->rec_max = ((t->rec_min > 255) ? 511 : 255); - t->rec = DIV_ROUND_UP( - (((t->rec_max - t->rec_min) * clk_params->hs_zero_buf) + - (t->rec_min * 100)), - 100); - - rc = dsi_phy_cmn_validate_and_set(t, "hs_zero"); - if (rc) - goto error; - - pr_debug("HS_ZERO:mipi_min=%d, mipi_max=%d, rec_min=%d, rec_max=%d, reg_val=%d\n", - t->mipi_min, t->mipi_max, t->rec_min, t->rec_max, - t->reg_value); - -error: - return rc; -} - -/** - * calc_hs_trail - calculates trail timing params for data lanes in HS. - */ -static int calc_hs_trail(struct dsi_phy_hw *phy, - struct phy_clk_params *clk_params, - struct phy_timing_desc *desc, - u64 teot_clk_lane) -{ - int rc = 0; - struct timing_entry *t = &desc->hs_trail; - s64 rec_temp1; - struct phy_timing_ops *ops = phy->ops.timing_ops; - - t->mipi_min = 60 + - mult_frac(clk_params->tlpx_numer_ns, 4, - clk_params->bitclk_mbps); - - t->mipi_max = teot_clk_lane - clk_params->treot_ns; - - if (ops->calc_hs_trail) { - ops->calc_hs_trail(clk_params, desc); - } else { - rc = -EINVAL; - goto error; - } - - rec_temp1 = DIV_ROUND_UP( - ((t->rec_max - t->rec_min) * clk_params->hs_trail_buf), - 100); - t->rec = rec_temp1 + t->rec_min; - - rc = dsi_phy_cmn_validate_and_set(t, "hs_trail"); - if (rc) - goto error; - - pr_debug("HS_TRAIL:mipi_min=%d, mipi_max=%d, rec_min=%d, rec_max=%d, reg_val=%d\n", - t->mipi_min, t->mipi_max, t->rec_min, t->rec_max, - t->reg_value); - -error: - return rc; -} - -/** - * calc_hs_rqst - calculates rqst timing params for data lanes in HS. - */ -static int calc_hs_rqst(struct dsi_phy_hw *phy, - struct phy_clk_params *clk_params, - struct phy_timing_desc *desc) -{ - int rc = 0; - struct timing_entry *t = &desc->hs_rqst; - - t->rec = DIV_ROUND_UP( - ((t->mipi_min * clk_params->bitclk_mbps) - - (8 * clk_params->tlpx_numer_ns)), - (8 * clk_params->tlpx_numer_ns)); - - rc = dsi_phy_cmn_validate_and_set(t, "hs_rqst"); - if (rc) - goto error; - - pr_debug("HS_RQST:mipi_min=%d, mipi_max=%d, rec_min=%d, rec_max=%d, reg_val=%d\n", - t->mipi_min, t->mipi_max, t->rec_min, t->rec_max, - t->reg_value); - -error: - return rc; -} - -/** - * calc_hs_exit - calculates exit timing params for data lanes in HS. - */ -static int calc_hs_exit(struct dsi_phy_hw *phy, - struct phy_clk_params *clk_params, - struct phy_timing_desc *desc) -{ - int rc = 0; - struct timing_entry *t = &desc->hs_exit; - - t->rec_min = (DIV_ROUND_UP( - (t->mipi_min * clk_params->bitclk_mbps), - (8 * clk_params->tlpx_numer_ns)) - 1); - - t->rec = DIV_ROUND_UP( - (((t->rec_max - t->rec_min) * clk_params->hs_exit_buf) + - (t->rec_min * 100)), 100); - - rc = dsi_phy_cmn_validate_and_set(t, "hs_exit"); - if (rc) - goto error; - - - pr_debug("HS_EXIT:mipi_min=%d, mipi_max=%d, rec_min=%d, rec_max=%d, reg_val=%d\n", - t->mipi_min, t->mipi_max, t->rec_min, t->rec_max, - t->reg_value); - -error: - return rc; -} - -/** - * calc_hs_rqst_clk - calculates rqst timing params for clock lane.. - */ -static int calc_hs_rqst_clk(struct dsi_phy_hw *phy, - struct phy_clk_params *clk_params, - struct phy_timing_desc *desc) -{ - int rc = 0; - struct timing_entry *t = &desc->hs_rqst_clk; - - t->rec = DIV_ROUND_UP( - ((t->mipi_min * clk_params->bitclk_mbps) - - (8 * clk_params->tlpx_numer_ns)), - (8 * clk_params->tlpx_numer_ns)); - - rc = dsi_phy_cmn_validate_and_set(t, "hs_rqst_clk"); - if (rc) - goto error; - - pr_debug("HS_RQST_CLK:mipi_min=%d, mipi_max=%d, rec_min=%d, rec_max=%d, reg_val=%d\n", - t->mipi_min, t->mipi_max, t->rec_min, t->rec_max, - t->reg_value); - -error: - return rc; -} - -/** - * dsi_phy_calc_timing_params - calculates timing paramets for a given bit clock - */ -static int dsi_phy_cmn_calc_timing_params(struct dsi_phy_hw *phy, - struct phy_clk_params *clk_params, struct phy_timing_desc *desc) -{ - int rc = 0; - s32 actual_frac = 0; - s64 actual_intermediate = 0; - u64 temp_multiple; - s64 teot_clk_lane; - - rc = calc_clk_prepare(phy, clk_params, desc, &actual_frac, - &actual_intermediate); - if (rc) { - pr_err("clk_prepare calculations failed, rc=%d\n", rc); - goto error; - } - - rc = calc_clk_zero(phy, clk_params, desc, - actual_frac, actual_intermediate); - if (rc) { - pr_err("clk_zero calculations failed, rc=%d\n", rc); - goto error; - } - - rc = calc_clk_trail(phy, clk_params, desc, &teot_clk_lane); - if (rc) { - pr_err("clk_trail calculations failed, rc=%d\n", rc); - goto error; - } - - rc = calc_hs_prepare(phy, clk_params, desc, &temp_multiple); - if (rc) { - pr_err("hs_prepare calculations failed, rc=%d\n", rc); - goto error; - } - - rc = calc_hs_zero(phy, clk_params, desc, temp_multiple); - if (rc) { - pr_err("hs_zero calculations failed, rc=%d\n", rc); - goto error; - } - - rc = calc_hs_trail(phy, clk_params, desc, teot_clk_lane); - if (rc) { - pr_err("hs_trail calculations failed, rc=%d\n", rc); - goto error; - } - - rc = calc_hs_rqst(phy, clk_params, desc); - if (rc) { - pr_err("hs_rqst calculations failed, rc=%d\n", rc); - goto error; - } - - rc = calc_hs_exit(phy, clk_params, desc); - if (rc) { - pr_err("hs_exit calculations failed, rc=%d\n", rc); - goto error; - } - - rc = calc_hs_rqst_clk(phy, clk_params, desc); - if (rc) { - pr_err("hs_rqst_clk calculations failed, rc=%d\n", rc); - goto error; - } -error: - return rc; -} - -/** - * calculate_timing_params() - calculates timing parameters. - * @phy: Pointer to DSI PHY hardware object. - * @mode: Mode information for which timing has to be calculated. - * @config: DSI host configuration for this mode. - * @timing: Timing parameters for each lane which will be returned. - */ -int dsi_phy_hw_calculate_timing_params(struct dsi_phy_hw *phy, - struct dsi_mode_info *mode, - struct dsi_host_common_cfg *host, - struct dsi_phy_per_lane_cfgs *timing) -{ - /* constants */ - u32 const esc_clk_mhz = 192; /* TODO: esc clock is hardcoded */ - u32 const esc_clk_mmss_cc_prediv = 10; - u32 const tlpx_numer = 1000; - u32 const tr_eot = 20; - u32 const clk_prepare_spec_min = 38; - u32 const clk_prepare_spec_max = 95; - u32 const clk_trail_spec_min = 60; - u32 const hs_exit_spec_min = 100; - u32 const hs_exit_reco_max = 255; - u32 const hs_rqst_spec_min = 50; - - /* local vars */ - int rc = 0; - u32 h_total, v_total; - u64 inter_num; - u32 num_of_lanes = 0; - u32 bpp; - u64 x, y; - struct phy_timing_desc desc; - struct phy_clk_params clk_params = {0}; - struct phy_timing_ops *ops = phy->ops.timing_ops; - - memset(&desc, 0x0, sizeof(desc)); - h_total = DSI_H_TOTAL(mode); - v_total = DSI_V_TOTAL(mode); - - bpp = bits_per_pixel[host->dst_format]; - - inter_num = bpp * mode->refresh_rate; - - if (host->data_lanes & DSI_DATA_LANE_0) - num_of_lanes++; - if (host->data_lanes & DSI_DATA_LANE_1) - num_of_lanes++; - if (host->data_lanes & DSI_DATA_LANE_2) - num_of_lanes++; - if (host->data_lanes & DSI_DATA_LANE_3) - num_of_lanes++; - - - x = mult_frac(v_total * h_total, inter_num, num_of_lanes); - y = rounddown(x, 1); - - clk_params.bitclk_mbps = rounddown(mult_frac(y, 1, 1000000), 1); - clk_params.escclk_numer = esc_clk_mhz; - clk_params.escclk_denom = esc_clk_mmss_cc_prediv; - clk_params.tlpx_numer_ns = tlpx_numer; - clk_params.treot_ns = tr_eot; - - - /* Setup default parameters */ - desc.clk_prepare.mipi_min = clk_prepare_spec_min; - desc.clk_prepare.mipi_max = clk_prepare_spec_max; - desc.clk_trail.mipi_min = clk_trail_spec_min; - desc.hs_exit.mipi_min = hs_exit_spec_min; - desc.hs_exit.rec_max = hs_exit_reco_max; - desc.hs_rqst.mipi_min = hs_rqst_spec_min; - desc.hs_rqst_clk.mipi_min = hs_rqst_spec_min; - - if (ops->get_default_phy_params) { - ops->get_default_phy_params(&clk_params); - } else { - rc = -EINVAL; - goto error; - } - - desc.clk_prepare.rec_min = DIV_ROUND_UP( - (desc.clk_prepare.mipi_min * clk_params.bitclk_mbps), - (8 * clk_params.tlpx_numer_ns) - ); - - desc.clk_prepare.rec_max = rounddown( - mult_frac((desc.clk_prepare.mipi_max * clk_params.bitclk_mbps), - 1, (8 * clk_params.tlpx_numer_ns)), - 1); - - pr_debug("BIT CLOCK = %d, tlpx_numer_ns=%d, treot_ns=%d\n", - clk_params.bitclk_mbps, clk_params.tlpx_numer_ns, - clk_params.treot_ns); - rc = dsi_phy_cmn_calc_timing_params(phy, &clk_params, &desc); - if (rc) { - pr_err("Timing calc failed, rc=%d\n", rc); - goto error; - } - - if (ops->update_timing_params) { - ops->update_timing_params(timing, &desc); - } else { - rc = -EINVAL; - goto error; - } - -error: - return rc; -} - -int dsi_phy_timing_calc_init(struct dsi_phy_hw *phy, - enum dsi_phy_version version) -{ - struct phy_timing_ops *ops = NULL; - - if (version == DSI_PHY_VERSION_UNKNOWN || - version >= DSI_PHY_VERSION_MAX || !phy) { - pr_err("Unsupported version: %d\n", version); - return -ENOTSUPP; - } - - ops = kzalloc(sizeof(struct phy_timing_ops), GFP_KERNEL); - if (!ops) - return -EINVAL; - phy->ops.timing_ops = ops; - - switch (version) { - case DSI_PHY_VERSION_2_0: - ops->get_default_phy_params = - dsi_phy_hw_v2_0_get_default_phy_params; - ops->calc_clk_zero = - dsi_phy_hw_v2_0_calc_clk_zero; - ops->calc_clk_trail_rec_min = - dsi_phy_hw_v2_0_calc_clk_trail_rec_min; - ops->calc_clk_trail_rec_max = - dsi_phy_hw_v2_0_calc_clk_trail_rec_max; - ops->calc_hs_zero = - dsi_phy_hw_v2_0_calc_hs_zero; - ops->calc_hs_trail = - dsi_phy_hw_v2_0_calc_hs_trail; - ops->update_timing_params = - dsi_phy_hw_v2_0_update_timing_params; - break; - case DSI_PHY_VERSION_3_0: - ops->get_default_phy_params = - dsi_phy_hw_v3_0_get_default_phy_params; - ops->calc_clk_zero = - dsi_phy_hw_v3_0_calc_clk_zero; - ops->calc_clk_trail_rec_min = - dsi_phy_hw_v3_0_calc_clk_trail_rec_min; - ops->calc_clk_trail_rec_max = - dsi_phy_hw_v3_0_calc_clk_trail_rec_max; - ops->calc_hs_zero = - dsi_phy_hw_v3_0_calc_hs_zero; - ops->calc_hs_trail = - dsi_phy_hw_v3_0_calc_hs_trail; - ops->update_timing_params = - dsi_phy_hw_v3_0_update_timing_params; - break; - case DSI_PHY_VERSION_0_0_HPM: - case DSI_PHY_VERSION_0_0_LPM: - case DSI_PHY_VERSION_1_0: - default: - kfree(ops); - return -ENOTSUPP; - } - - return 0; -} - diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_calc.h b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_calc.h deleted file mode 100644 index 99224fa..0000000 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_calc.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * 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 _DSI_PHY_TIMING_CALC_H_ -#define _DSI_PHY_TIMING_CALC_H_ - -#include <linux/math64.h> -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/slab.h> -#include <linux/bitops.h> -#include <linux/bitmap.h> -#include <linux/errno.h> - -#include "dsi_defs.h" -#include "dsi_phy_hw.h" -#include "dsi_catalog.h" - -/** - * struct timing_entry - Calculated values for each timing parameter. - * @mipi_min: - * @mipi_max: - * @rec_min: - * @rec_max: - * @rec: - * @reg_value: Value to be programmed in register. - */ -struct timing_entry { - s32 mipi_min; - s32 mipi_max; - s32 rec_min; - s32 rec_max; - s32 rec; - u8 reg_value; -}; - -/** - * struct phy_timing_desc - Timing parameters for DSI PHY. - */ -struct phy_timing_desc { - struct timing_entry clk_prepare; - struct timing_entry clk_zero; - struct timing_entry clk_trail; - struct timing_entry hs_prepare; - struct timing_entry hs_zero; - struct timing_entry hs_trail; - struct timing_entry hs_rqst; - struct timing_entry hs_rqst_clk; - struct timing_entry hs_exit; - struct timing_entry ta_go; - struct timing_entry ta_sure; - struct timing_entry ta_set; - struct timing_entry clk_post; - struct timing_entry clk_pre; -}; - -/** - * struct phy_clk_params - Clock parameters for PHY timing calculations. - */ -struct phy_clk_params { - u32 bitclk_mbps; - u32 escclk_numer; - u32 escclk_denom; - u32 tlpx_numer_ns; - u32 treot_ns; - u32 clk_prep_buf; - u32 clk_zero_buf; - u32 clk_trail_buf; - u32 hs_prep_buf; - u32 hs_zero_buf; - u32 hs_trail_buf; - u32 hs_rqst_buf; - u32 hs_exit_buf; -}; - -/** - * Various Ops needed for auto-calculation of DSI PHY timing parameters. - */ -struct phy_timing_ops { - void (*get_default_phy_params)(struct phy_clk_params *params); - - int32_t (*calc_clk_zero)(s64 rec_temp1, s64 mult); - - int32_t (*calc_clk_trail_rec_min)(s64 temp_mul, - s64 frac, s64 mult); - - int32_t (*calc_clk_trail_rec_max)(s64 temp1, s64 mult); - - int32_t (*calc_hs_zero)(s64 temp1, s64 mult); - - void (*calc_hs_trail)(struct phy_clk_params *clk_params, - struct phy_timing_desc *desc); - - void (*update_timing_params)(struct dsi_phy_per_lane_cfgs *timing, - struct phy_timing_desc *desc); -}; - -/* DSI PHY timing functions for 14nm */ -void dsi_phy_hw_v2_0_get_default_phy_params(struct phy_clk_params *params); - -int32_t dsi_phy_hw_v2_0_calc_clk_zero(s64 rec_temp1, s64 mult); - -int32_t dsi_phy_hw_v2_0_calc_clk_trail_rec_min(s64 temp_mul, - s64 frac, s64 mult); - -int32_t dsi_phy_hw_v2_0_calc_clk_trail_rec_max(s64 temp1, s64 mult); - -int32_t dsi_phy_hw_v2_0_calc_hs_zero(s64 temp1, s64 mult); - -void dsi_phy_hw_v2_0_calc_hs_trail(struct phy_clk_params *clk_params, - struct phy_timing_desc *desc); - -void dsi_phy_hw_v2_0_update_timing_params(struct dsi_phy_per_lane_cfgs *timing, - struct phy_timing_desc *desc); - -/* DSI PHY timing functions for 10nm */ -void dsi_phy_hw_v3_0_get_default_phy_params(struct phy_clk_params *params); - -int32_t dsi_phy_hw_v3_0_calc_clk_zero(s64 rec_temp1, s64 mult); - -int32_t dsi_phy_hw_v3_0_calc_clk_trail_rec_min(s64 temp_mul, - s64 frac, s64 mult); - -int32_t dsi_phy_hw_v3_0_calc_clk_trail_rec_max(s64 temp1, s64 mult); - -int32_t dsi_phy_hw_v3_0_calc_hs_zero(s64 temp1, s64 mult); - -void dsi_phy_hw_v3_0_calc_hs_trail(struct phy_clk_params *clk_params, - struct phy_timing_desc *desc); - -void dsi_phy_hw_v3_0_update_timing_params(struct dsi_phy_per_lane_cfgs *timing, - struct phy_timing_desc *desc); - -#endif /* _DSI_PHY_TIMING_CALC_H_ */ diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_v2_0.c b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_v2_0.c deleted file mode 100644 index a8139e3..0000000 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_v2_0.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * 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) "dsi-phy-timing:" fmt -#include "dsi_phy_timing_calc.h" - -void dsi_phy_hw_v2_0_get_default_phy_params(struct phy_clk_params *params) -{ - params->clk_prep_buf = 50; - params->clk_zero_buf = 2; - params->clk_trail_buf = 30; - params->hs_prep_buf = 50; - params->hs_zero_buf = 10; - params->hs_trail_buf = 30; - params->hs_rqst_buf = 0; - params->hs_exit_buf = 10; -} - -int32_t dsi_phy_hw_v2_0_calc_clk_zero(s64 rec_temp1, s64 mult) -{ - s64 rec_temp2, rec_temp3; - - rec_temp2 = (rec_temp1 - (11 * mult)); - rec_temp3 = roundup(div_s64(rec_temp2, 8), mult); - return (div_s64(rec_temp3, mult) - 3); -} - -int32_t dsi_phy_hw_v2_0_calc_clk_trail_rec_min(s64 temp_mul, - s64 frac, s64 mult) -{ - s64 rec_temp1, rec_temp2, rec_temp3; - - rec_temp1 = temp_mul + frac + (3 * mult); - rec_temp2 = div_s64(rec_temp1, 8); - rec_temp3 = roundup(rec_temp2, mult); - - return div_s64(rec_temp3, mult); -} - -int32_t dsi_phy_hw_v2_0_calc_clk_trail_rec_max(s64 temp1, s64 mult) -{ - s64 rec_temp2, rec_temp3; - - rec_temp2 = temp1 + (3 * mult); - rec_temp3 = rec_temp2 / 8; - return div_s64(rec_temp3, mult); - -} - -int32_t dsi_phy_hw_v2_0_calc_hs_zero(s64 temp1, s64 mult) -{ - s64 rec_temp2, rec_temp3, rec_min; - - rec_temp2 = temp1 - (11 * mult); - rec_temp3 = roundup((rec_temp2 / 8), mult); - rec_min = rec_temp3 - (3 * mult); - return div_s64(rec_min, mult); -} - -void dsi_phy_hw_v2_0_calc_hs_trail(struct phy_clk_params *clk_params, - struct phy_timing_desc *desc) -{ - s64 rec_temp1; - struct timing_entry *t = &desc->hs_trail; - - t->rec_min = DIV_ROUND_UP( - ((t->mipi_min * clk_params->bitclk_mbps) + - (3 * clk_params->tlpx_numer_ns)), - (8 * clk_params->tlpx_numer_ns)); - - rec_temp1 = ((t->mipi_max * clk_params->bitclk_mbps) + - (3 * clk_params->tlpx_numer_ns)); - t->rec_max = (rec_temp1 / (8 * clk_params->tlpx_numer_ns)); -} - -void dsi_phy_hw_v2_0_update_timing_params( - struct dsi_phy_per_lane_cfgs *timing, - struct phy_timing_desc *desc) -{ - int i = 0; - - for (i = DSI_LOGICAL_LANE_0; i < DSI_LANE_MAX; i++) { - timing->lane[i][0] = desc->hs_exit.reg_value; - - if (i == DSI_LOGICAL_CLOCK_LANE) - timing->lane[i][1] = desc->clk_zero.reg_value; - else - timing->lane[i][1] = desc->hs_zero.reg_value; - - if (i == DSI_LOGICAL_CLOCK_LANE) - timing->lane[i][2] = desc->clk_prepare.reg_value; - else - timing->lane[i][2] = desc->hs_prepare.reg_value; - - if (i == DSI_LOGICAL_CLOCK_LANE) - timing->lane[i][3] = desc->clk_trail.reg_value; - else - timing->lane[i][3] = desc->hs_trail.reg_value; - - if (i == DSI_LOGICAL_CLOCK_LANE) - timing->lane[i][4] = desc->hs_rqst_clk.reg_value; - else - timing->lane[i][4] = desc->hs_rqst.reg_value; - - timing->lane[i][5] = 0x3; - timing->lane[i][6] = 0x4; - timing->lane[i][7] = 0xA0; - pr_debug("[%d][%d %d %d %d %d]\n", i, timing->lane[i][0], - timing->lane[i][1], - timing->lane[i][2], - timing->lane[i][3], - timing->lane[i][4]); - } - timing->count_per_lane = 8; -} - diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_v3_0.c b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_v3_0.c deleted file mode 100644 index 1d6b3cd..0000000 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_v3_0.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * 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) "dsi-phy-timing:" fmt -#include "dsi_phy_timing_calc.h" - -void dsi_phy_hw_v3_0_get_default_phy_params( - struct phy_clk_params *params) -{ - params->clk_prep_buf = 0; - params->clk_zero_buf = 0; - params->clk_trail_buf = 0; - params->hs_prep_buf = 0; - params->hs_zero_buf = 0; - params->hs_trail_buf = 0; - params->hs_rqst_buf = 0; - params->hs_exit_buf = 0; -} - -int32_t dsi_phy_hw_v3_0_calc_clk_zero(s64 rec_temp1, s64 mult) -{ - s64 rec_temp2, rec_temp3; - - rec_temp2 = (rec_temp1 - mult); - rec_temp3 = roundup(div_s64(rec_temp2, 8), mult); - return (div_s64(rec_temp3, mult) - 1); -} - -int32_t dsi_phy_hw_v3_0_calc_clk_trail_rec_min(s64 temp_mul, - s64 frac, s64 mult) -{ - s64 rec_temp1, rec_temp2, rec_temp3; - - rec_temp1 = temp_mul + frac; - rec_temp2 = div_s64(rec_temp1, 8); - rec_temp3 = roundup(rec_temp2, mult); - return (div_s64(rec_temp3, mult) - 1); -} - -int32_t dsi_phy_hw_v3_0_calc_clk_trail_rec_max(s64 temp1, s64 mult) -{ - s64 rec_temp2; - - rec_temp2 = temp1 / 8; - return (div_s64(rec_temp2, mult) - 1); -} - -int32_t dsi_phy_hw_v3_0_calc_hs_zero(s64 temp1, s64 mult) -{ - s64 rec_temp2, rec_min; - - rec_temp2 = roundup((temp1 / 8), mult); - rec_min = rec_temp2 - (1 * mult); - return div_s64(rec_min, mult); -} - -void dsi_phy_hw_v3_0_calc_hs_trail(struct phy_clk_params *clk_params, - struct phy_timing_desc *desc) -{ - s64 rec_temp1; - struct timing_entry *t = &desc->hs_trail; - - t->rec_min = DIV_ROUND_UP( - (t->mipi_min * clk_params->bitclk_mbps), - (8 * clk_params->tlpx_numer_ns)) - 1; - - rec_temp1 = (t->mipi_max * clk_params->bitclk_mbps); - t->rec_max = - (div_s64(rec_temp1, (8 * clk_params->tlpx_numer_ns))) - 1; -} - -void dsi_phy_hw_v3_0_update_timing_params( - struct dsi_phy_per_lane_cfgs *timing, - struct phy_timing_desc *desc) -{ - timing->lane_v3[0] = 0x00; - timing->lane_v3[1] = desc->clk_zero.reg_value; - timing->lane_v3[2] = desc->clk_prepare.reg_value; - timing->lane_v3[3] = desc->clk_trail.reg_value; - timing->lane_v3[4] = desc->hs_exit.reg_value; - timing->lane_v3[5] = desc->hs_zero.reg_value; - timing->lane_v3[6] = desc->hs_prepare.reg_value; - timing->lane_v3[7] = desc->hs_trail.reg_value; - timing->lane_v3[8] = desc->hs_rqst.reg_value; - timing->lane_v3[9] = 0x03; - timing->lane_v3[10] = 0x04; - timing->lane_v3[11] = 0x00; - - pr_debug("[%d %d %d %d]\n", timing->lane_v3[0], - timing->lane_v3[1], timing->lane_v3[2], timing->lane_v3[3]); - pr_debug("[%d %d %d %d]\n", timing->lane_v3[4], - timing->lane_v3[5], timing->lane_v3[6], timing->lane_v3[7]); - pr_debug("[%d %d %d %d]\n", timing->lane_v3[8], - timing->lane_v3[9], timing->lane_v3[10], timing->lane_v3[11]); - timing->count_per_lane = 12; -} - diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_pwr.c b/drivers/gpu/drm/msm/dsi-staging/dsi_pwr.c deleted file mode 100644 index ca2eb3f..0000000 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_pwr.c +++ /dev/null @@ -1,365 +0,0 @@ -/* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * 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/of.h> -#include <linux/delay.h> -#include <linux/slab.h> - -#include "dsi_pwr.h" - -/* - * dsi_pwr_parse_supply_node() - parse power supply node from root device node - */ -static int dsi_pwr_parse_supply_node(struct device_node *root, - struct dsi_regulator_info *regs) -{ - int rc = 0; - int i = 0; - u32 tmp = 0; - struct device_node *node = NULL; - - for_each_child_of_node(root, node) { - const char *st = NULL; - - rc = of_property_read_string(node, "qcom,supply-name", &st); - if (rc) { - pr_err("failed to read name, rc = %d\n", rc); - goto error; - } - - snprintf(regs->vregs[i].vreg_name, - ARRAY_SIZE(regs->vregs[i].vreg_name), - "%s", st); - - rc = of_property_read_u32(node, "qcom,supply-min-voltage", - &tmp); - if (rc) { - pr_err("failed to read min voltage, rc = %d\n", rc); - goto error; - } - regs->vregs[i].min_voltage = tmp; - - rc = of_property_read_u32(node, "qcom,supply-max-voltage", - &tmp); - if (rc) { - pr_err("failed to read max voltage, rc = %d\n", rc); - goto error; - } - regs->vregs[i].max_voltage = tmp; - - rc = of_property_read_u32(node, "qcom,supply-enable-load", - &tmp); - if (rc) { - pr_err("failed to read enable load, rc = %d\n", rc); - goto error; - } - regs->vregs[i].enable_load = tmp; - - rc = of_property_read_u32(node, "qcom,supply-disable-load", - &tmp); - if (rc) { - pr_err("failed to read disable load, rc = %d\n", rc); - goto error; - } - regs->vregs[i].disable_load = tmp; - - /* Optional values */ - rc = of_property_read_u32(node, "qcom,supply-pre-on-sleep", - &tmp); - if (rc) { - pr_debug("pre-on-sleep not specified\n"); - rc = 0; - } else { - regs->vregs[i].pre_on_sleep = tmp; - } - - rc = of_property_read_u32(node, "qcom,supply-pre-off-sleep", - &tmp); - if (rc) { - pr_debug("pre-off-sleep not specified\n"); - rc = 0; - } else { - regs->vregs[i].pre_off_sleep = tmp; - } - - rc = of_property_read_u32(node, "qcom,supply-post-on-sleep", - &tmp); - if (rc) { - pr_debug("post-on-sleep not specified\n"); - rc = 0; - } else { - regs->vregs[i].post_on_sleep = tmp; - } - - rc = of_property_read_u32(node, "qcom,supply-post-off-sleep", - &tmp); - if (rc) { - pr_debug("post-off-sleep not specified\n"); - rc = 0; - } else { - regs->vregs[i].post_off_sleep = tmp; - } - - ++i; - pr_debug("[%s] minv=%d maxv=%d, en_load=%d, dis_load=%d\n", - regs->vregs[i].vreg_name, - regs->vregs[i].min_voltage, - regs->vregs[i].max_voltage, - regs->vregs[i].enable_load, - regs->vregs[i].disable_load); - } - -error: - return rc; -} - -/** - * dsi_pwr_enable_vregs() - enable/disable regulators - */ -static int dsi_pwr_enable_vregs(struct dsi_regulator_info *regs, bool enable) -{ - int rc = 0, i = 0; - struct dsi_vreg *vreg; - int num_of_v = 0; - - if (enable) { - for (i = 0; i < regs->count; i++) { - vreg = ®s->vregs[i]; - if (vreg->pre_on_sleep) - msleep(vreg->pre_on_sleep); - - rc = regulator_set_load(vreg->vreg, - vreg->enable_load); - if (rc < 0) { - pr_err("Setting optimum mode failed for %s\n", - vreg->vreg_name); - goto error; - } - num_of_v = regulator_count_voltages(vreg->vreg); - if (num_of_v > 0) { - rc = regulator_set_voltage(vreg->vreg, - vreg->min_voltage, - vreg->max_voltage); - if (rc) { - pr_err("Set voltage(%s) fail, rc=%d\n", - vreg->vreg_name, rc); - goto error_disable_opt_mode; - } - } - - rc = regulator_enable(vreg->vreg); - if (rc) { - pr_err("enable failed for %s, rc=%d\n", - vreg->vreg_name, rc); - goto error_disable_voltage; - } - - if (vreg->post_on_sleep) - msleep(vreg->post_on_sleep); - } - } else { - for (i = (regs->count - 1); i >= 0; i--) { - if (regs->vregs[i].pre_off_sleep) - msleep(regs->vregs[i].pre_off_sleep); - - (void)regulator_set_load(regs->vregs[i].vreg, - regs->vregs[i].disable_load); - (void)regulator_disable(regs->vregs[i].vreg); - - if (regs->vregs[i].post_off_sleep) - msleep(regs->vregs[i].post_off_sleep); - } - } - - return 0; -error_disable_opt_mode: - (void)regulator_set_load(regs->vregs[i].vreg, - regs->vregs[i].disable_load); - -error_disable_voltage: - if (num_of_v > 0) - (void)regulator_set_voltage(regs->vregs[i].vreg, - 0, regs->vregs[i].max_voltage); -error: - for (i--; i >= 0; i--) { - if (regs->vregs[i].pre_off_sleep) - msleep(regs->vregs[i].pre_off_sleep); - - (void)regulator_set_load(regs->vregs[i].vreg, - regs->vregs[i].disable_load); - - num_of_v = regulator_count_voltages(regs->vregs[i].vreg); - if (num_of_v > 0) - (void)regulator_set_voltage(regs->vregs[i].vreg, - 0, regs->vregs[i].max_voltage); - - (void)regulator_disable(regs->vregs[i].vreg); - - if (regs->vregs[i].post_off_sleep) - msleep(regs->vregs[i].post_off_sleep); - } - - return rc; -} - -/** - * dsi_pwr_of_get_vreg_data - Parse regulator supply information - * @of_node: Device of node to parse for supply information. - * @regs: Pointer where regulator information will be copied to. - * @supply_name: Name of the supply node. - * - * return: error code in case of failure or 0 for success. - */ -int dsi_pwr_of_get_vreg_data(struct device_node *of_node, - struct dsi_regulator_info *regs, - char *supply_name) -{ - int rc = 0; - struct device_node *supply_root_node = NULL; - - if (!of_node || !regs) { - pr_err("Bad params\n"); - return -EINVAL; - } - - regs->count = 0; - supply_root_node = of_get_child_by_name(of_node, supply_name); - if (!supply_root_node) { - supply_root_node = of_parse_phandle(of_node, supply_name, 0); - if (!supply_root_node) { - pr_debug("No supply entry present for %s\n", - supply_name); - return -EINVAL; - } - } - - regs->count = of_get_available_child_count(supply_root_node); - if (regs->count == 0) { - pr_err("No vregs defined for %s\n", supply_name); - return -EINVAL; - } - - regs->vregs = kcalloc(regs->count, sizeof(*regs->vregs), GFP_KERNEL); - if (!regs->vregs) { - regs->count = 0; - return -ENOMEM; - } - - rc = dsi_pwr_parse_supply_node(supply_root_node, regs); - if (rc) { - pr_err("failed to parse supply node for %s, rc = %d\n", - supply_name, rc); - - kfree(regs->vregs); - regs->vregs = NULL; - regs->count = 0; - } - - return rc; -} - -/** - * dsi_pwr_get_dt_vreg_data - parse regulator supply information - * @dev: Device whose of_node needs to be parsed. - * @regs: Pointer where regulator information will be copied to. - * @supply_name: Name of the supply node. - * - * return: error code in case of failure or 0 for success. - */ -int dsi_pwr_get_dt_vreg_data(struct device *dev, - struct dsi_regulator_info *regs, - char *supply_name) -{ - int rc = 0; - struct device_node *of_node = NULL; - struct device_node *supply_node = NULL; - struct device_node *supply_root_node = NULL; - - if (!dev || !regs) { - pr_err("Bad params\n"); - return -EINVAL; - } - - of_node = dev->of_node; - regs->count = 0; - supply_root_node = of_get_child_by_name(of_node, supply_name); - if (!supply_root_node) { - supply_root_node = of_parse_phandle(of_node, supply_name, 0); - if (!supply_root_node) { - pr_debug("No supply entry present for %s\n", - supply_name); - return -EINVAL; - } - } - - for_each_child_of_node(supply_root_node, supply_node) - regs->count++; - - if (regs->count == 0) { - pr_err("No vregs defined for %s\n", supply_name); - return -EINVAL; - } - - regs->vregs = devm_kcalloc(dev, regs->count, sizeof(*regs->vregs), - GFP_KERNEL); - if (!regs->vregs) { - regs->count = 0; - return -ENOMEM; - } - - rc = dsi_pwr_parse_supply_node(supply_root_node, regs); - if (rc) { - pr_err("failed to parse supply node for %s, rc = %d\n", - supply_name, rc); - devm_kfree(dev, regs->vregs); - regs->vregs = NULL; - regs->count = 0; - } - - return rc; -} - -/** - * dsi_pwr_enable_regulator() - enable a set of regulators - * @regs: Pointer to set of regulators to enable or disable. - * @enable: Enable/Disable regulators. - * - * return: error code in case of failure or 0 for success. - */ -int dsi_pwr_enable_regulator(struct dsi_regulator_info *regs, bool enable) -{ - int rc = 0; - - if (enable) { - if (regs->refcount == 0) { - rc = dsi_pwr_enable_vregs(regs, true); - if (rc) - pr_err("failed to enable regulators\n"); - } - regs->refcount++; - } else { - if (regs->refcount == 0) { - pr_err("Unbalanced regulator off\n"); - } else { - regs->refcount--; - if (regs->refcount == 0) { - rc = dsi_pwr_enable_vregs(regs, false); - if (rc) - pr_err("failed to disable vregs\n"); - } - } - } - - return rc; -} diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_pwr.h b/drivers/gpu/drm/msm/dsi-staging/dsi_pwr.h deleted file mode 100644 index 0ee5c66..0000000 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_pwr.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * 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 _DSI_PWR_H_ -#define _DSI_PWR_H_ - -#include <linux/device.h> -#include <linux/platform_device.h> -#include <linux/types.h> -#include <linux/regulator/consumer.h> - -/** - * struct dsi_vreg - regulator information for DSI regulators - * @vreg: Handle to the regulator. - * @vreg_name: Regulator name. - * @min_voltage: Minimum voltage in uV. - * @max_voltage: Maximum voltage in uV. - * @enable_load: Load, in uA, when enabled. - * @disable_load: Load, in uA, when disabled. - * @pre_on_sleep: Sleep, in ms, before enabling the regulator. - * @post_on_sleep: Sleep, in ms, after enabling the regulator. - * @pre_off_sleep: Sleep, in ms, before disabling the regulator. - * @post_off_sleep: Sleep, in ms, after disabling the regulator. - */ -struct dsi_vreg { - struct regulator *vreg; - char vreg_name[32]; - u32 min_voltage; - u32 max_voltage; - u32 enable_load; - u32 disable_load; - u32 pre_on_sleep; - u32 post_on_sleep; - u32 pre_off_sleep; - u32 post_off_sleep; -}; - -/** - * struct dsi_regulator_info - set of vregs that are turned on/off together. - * @vregs: Array of dsi_vreg structures. - * @count: Number of vregs. - * @refcount: Reference counting for enabling. - */ -struct dsi_regulator_info { - struct dsi_vreg *vregs; - u32 count; - u32 refcount; -}; - -/** - * dsi_pwr_of_get_vreg_data - parse regulator supply information - * @of_node: Device of node to parse for supply information. - * @regs: Pointer where regulator information will be copied to. - * @supply_name: Name of the supply node. - * - * return: error code in case of failure or 0 for success. - */ -int dsi_pwr_of_get_vreg_data(struct device_node *of_node, - struct dsi_regulator_info *regs, - char *supply_name); - -/** - * dsi_pwr_get_dt_vreg_data - parse regulator supply information - * @dev: Device whose of_node needs to be parsed. - * @regs: Pointer where regulator information will be copied to. - * @supply_name: Name of the supply node. - * - * return: error code in case of failure or 0 for success. - */ -int dsi_pwr_get_dt_vreg_data(struct device *dev, - struct dsi_regulator_info *regs, - char *supply_name); - -/** - * dsi_pwr_enable_regulator() - enable a set of regulators - * @regs: Pointer to set of regulators to enable or disable. - * @enable: Enable/Disable regulators. - * - * return: error code in case of failure or 0 for success. - */ -int dsi_pwr_enable_regulator(struct dsi_regulator_info *regs, bool enable); -#endif /* _DSI_PWR_H_ */ -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel