Hello again, Well, here's the driver for QC SDM845 DPU support that I sent out in February, this time without the RFC safety net. We've been busy since then, here's what we've been up to!
We've seen 184 unique patches from 8 people sent to the list to prepare the driver, here are the diffstat diffs:
Diffstat from February: 236 files changed, 110234 insertions(+), 159 deletions(-)
Diffstat from present day: 81 files changed, 32900 insertions(+), 237 deletions(-)
So now you're wondering what was removed to get here, the breakdown of patches is listed below. The highlights are: - Remove dsi-staging driver, use upstream msm/dsi - Remove dp driver, will introduce soon - Remove writeback support, will re-introduce using upstream UAPI - Remove dpu_connector abstraction layer - Remove color processing/adaptive display features - Remove hdcp support, will re-introduce using upstream UAPI - Remove custom dpu ioctls and properties - A _bunch_ of other stuff that really adds up
We've also de-duplicated a bunch of functionality: - dpu EDID parsing vs. drm_edid - dpu_rect vs. drm_rect - DPU_TRACE vs. tracepoints
Finally, we've improved upstream msm in the following ways: - Converted to atomic helpers - Added dual-dsi support to msm/dsi - Added a few kms callbacks to allow finer grained control - Added mdss subclassing to share infrastructure between dpu/mdp5
The work is obviously not done, in addition to the re-introduction of features above, we still have a fair amount of clean up and polishing to do. All of that clean up (aside from the disp/event kthreads) are isolated to the dpu portion of the msm driver. We're also getting to the point where we want to add functionality back to the driver. For these reasons, I think now is a good time to land dpu in msm-next and work on the rest there.
One note: "dt-bindings: clock: Introduce QCOM Display clock bindings" is included here since the DPU bindings depend on it. It has been posted and reviewed elsewhere, so it is simply here for completion.
If you would like this in the form of a git tree, it is hosted at https://gitlab.freedesktop.org/seanpaul/dpu-staging/tree/for-next
Finally, huge thanks to the display team at Qualcomm for diving into this headfirst, they've been awesome to work with. We've still got a long road ahead, but we've come far in little time. I'm looking forward to their continued contributions.
Thanks for your consideration,
Sean
------- Breakdown of patches squashed into the "Add SDM845 DPU Support" patch:
Abhinav Kumar abhinavk@codeaurora.org (12): drm/msm/dsi: add only dsi nodes with a valid device to list drm/msm/dsi: check return value for video done waits drm/msm/dsi: check video mode engine status before waiting drm/msm/dsi: configure VCO rate for 10nm PLL driver drm/msm/dsi: implement auto PHY timing calculator for 10nm PHY drm/msm/dsi: set encoder mode for DRM bridge explicitly drm/msm: higher values of pclk can exceed 32 bits when multiplied by a factor drm/msm: make pclk_rate u64 to avoid truncation drm/msm: remove support for seamless modes drm/panel: Add support for Truly NT35597 panel drm/panel: add backlight control support for truly panel dt-bindings: Add Truly NT35597 panel bindings
Archit Taneja architt@codeaurora.org (5): drm/msm/mdp5: Add global state as a private atomic object drm/msm/mdp5: Use the new private_obj state drm/msm: Don't subclass drm_atomic_state anymore drm/panel: Add Truly Dual DSI video mode panel drm/panel: Add Truly NT35597 panel
Chandan Uddaraju chandanu@codeaurora.org (6): ARM: dts: msm: Add DPU node as a child of MDSS for SDM845 ARM: dts: msm: disable MDP/DSI driver present in "SDM845-dpu" ARM: dts: msm: fix panel gpio/regulator settings for SDM845 Fix GPIO/Regulator settings in DT for truly panel drm/msm/dsi: Use one connector for dual DSI mode drm/msm/dsi: adjust dsi timing for dual dsi mode
Jeykumar Sankaran jsanka@codeaurora.org (35): Remove dpu crtc custom properties and its handlers drm/fourcc: add msm compressed format modifiers drm/msm/dpu: Fix writeback compile macros drm/msm/dpu: add atomic private object to dpu kms drm/msm/dpu: avoid querying for hw intf before assignment drm/msm/dpu: clean up dpu crtc custom properties drm/msm/dpu: clean up dpu plane custom properties drm/msm/dpu: iterate for assigned hw ctl in virtual encoder drm/msm/dpu: move hw resource tracking to crtc state drm/msm/dpu: program master-slave encoders explicitly drm/msm/dpu: remove display H_TILE from encoder drm/msm/dpu: remove ping pong split topology variables drm/msm/dpu: remove resource pool manager drm/msm/dpu: remove scalar config definitions drm/msm/dpu: remove stale encoder code drm/msm/dpu: remove topology name drm/msm/dpu: rename hw_ctl to lm_ctl drm/msm/dpu: switch to drm zpos property drm/msm/dpu: use kms stored hw mdp block drm/msm/dpu: use private obj to track hw resources drm/msm/dsi-staging: compile out partial update path drm/msm/dsi-staging: remove support for partial update drm/msm: enable zpos normalization drm/msm: hook up DPU with upstream DSI drm/msm: populate aspace in msm_kms drm/msm: remove connector custom properties drm/msm: remove display stream compression(DSC) support for SM845 drm/msm: remove dpu specific uapi header drm/msm: remove dsi-staging driver drm/msm: remove hw rotation support drm/msm: remove msm_prop files drm/msm: remove panel autorefresh support for SDM845 drm/msm: remove partial update support drm/msm: remove support for ping pong split topology drm/msm: strip down custom event ioctl's
Jordan Crouse jcrouse@codeaurora.org (1): drm/msm/dpu: Remove unused code and move the header
Rajesh Yadav ryadav@codeaurora.org (29): Revert "drm/msm: Add DisplayPort support" drm/msm/dp: remove dpu_power_handle calls from dp driver drm/msm/dpu: add MDSS top level driver for dpu drm/msm/dpu: add error handling in dpu_core_perf_crtc_update drm/msm/dpu: correct dpu_io_util.h include path drm/msm/dpu: create new platform driver for dpu device drm/msm/dpu: move dpu_io_util to dpu folder drm/msm/dpu: move dpu_power_handle to dpu folder drm/msm/dpu: remove clock management code from dpu_power_handle drm/msm/dpu: remove dt parsing logic for bus_scale config drm/msm/dpu: remove hdcp support drm/msm/dpu: remove msm_prop entry from Makefile drm/msm/dpu: remove power management code from dpu_power_handle drm/msm/dpu: remove writeback support drm/msm/dpu: update dpu sub-block offsets wrt dpu base address drm/msm/dpu: use runtime_pm calls in dpu_dbg drm/msm/dpu: use runtime_pm calls on dpu device drm/msm/dsi-staging: Gate bus scale code drm/msm/dsi: initialize postdiv_lock before use for 10nm pll drm/msm/mdp5: subclass msm_mdss for mdp5 drm/msm: Fix return type mismatch for dpu_kms_init drm/msm: Remove RSC support from DPU driver drm/msm: Remove unused variables drm/msm: remove redundant pm_runtime_enable call from msm_drv dt-bindings: msm/disp: Remove DPU RSC device bindings dt-bindings: msm/disp: cleanup bindings for Snapdragon 845 DPU dt-bindings: msm/disp: remove unused display port bindings dt-bindings: msm/disp: remove unused dsi & panel bindings dt-bindings: msm/disp: remove unused writeback bindings
Sean Paul seanpaul@chromium.org (85): arm64: dts: qcom: Remove obsolete dpu dts files arm64: dts: qcom: sdm845: Add dpu to sdm845 dts file drm/bridge: adv7511: Reset registers on hotplug drm/mipi: Remove Qualcomm-specific dsi packet header format drm/mipi: Remove unused mipi/dsi packet types drm/msm: Add displayport files to Makefile drm/msm: Add pm_runtime_get/put calls to dpu drm/msm: Alphabetize dpu files in Makefile drm/msm: Change driver name back to msm drm/msm: Defer probe if display component not found drm/msm: Disable mdp5 crtc when there are no active planes drm/msm: Don't duplicate modeset_enables atomic helper drm/msm: Fix NULL deref on bind/probe deferral drm/msm: Fix deadlock calling msm_gem_new() drm/msm: Fix dpu build warnings drm/msm: Fix dpu compile when CONFIG_DEBUG_FS !defined drm/msm: Fix uninitialized use of prefill_lines drm/msm: Include the dpu_dbg header in msm_drv.c drm/msm: Issue queued events when disabling crtc drm/msm: Mark the crtc->state->event consumed drm/msm: More cleanup in msm_drv drm/msm: Move debugfs root tracking to dpu drm/msm: Move dpu_dbg init/destroy into dpu_kms drm/msm: Move implicit sync fence handling to prepare_fb drm/msm: Move implicit sync handling to prepare_fb drm/msm: Populate kms->irq for dpu drm/msm: Properly cast return with ERR_PTR drm/msm: Reduce dpu_crtc_atomic_check frame size drm/msm: Refactor complete_commit() to look more the helpers drm/msm: Remove DPU_DBG->pr_err ifdef gate drm/msm: Remove _dpu_format_calc_offset_linear() drm/msm: Remove atomic_check() from msm_kms drm/msm: Remove dpu bus scaling code drm/msm: Remove dpu input fences drm/msm: Remove dpu module parameters drm/msm: Remove dpu_edid_parser drm/msm: Remove dpu_kms_fbo and associated functions drm/msm: Remove dpu_plane_state->defer_prepare_fb drm/msm: Remove get_address_space msm_kms hook drm/msm: Remove hand-rolled out fences drm/msm: Remove ion from dpu drm/msm: Remove more dpu changes from msm core drm/msm: Remove more dpu-related code from msm_drv drm/msm: Remove msm_commit/kthread, use atomic helper commit drm/msm: Remove msm_commit/worker, use atomic helper commit drm/msm: Remove msm_hdcp devicetree bindings drm/msm: Remove prepare_fence kms_function drm/msm: Remove remnants of dsi-staging drm/msm: Remove secure fb/plane support from dpu drm/msm: Remove smmu driver init/cleanup from msm_drv drm/msm: Remove unused backpointers from dpu_crtc drm/msm: Remove wait_for_tx_complete() from msm_kms drm/msm: Skip seamless disables in crtc/encoder drm/msm: Sprinkle pm_runtime calls around drm/msm: Switch to atomic_helper_commit() drm/msm: Use atomic private_obj instead of subclassing drm/msm: Use drm_private_obj/state instead of subclassing drm/msm: dpu: Do debugfs init in the debugfs_init() hook drm/msm: dpu: Fix build warnings drm/msm: dpu: Move dpu_dbg into dpu1 directory drm/msm: dpu: Remove arbitrary register dumps drm/msm: dpu: Remove dpu evtlog drm/msm: dpu: Remove dpu_format_populate_layout_with_roi() drm/msm: dpu: Remove dpu_rect drm/msm: dpu: Remove dsi debug block name drm/msm: dpu: Remove panic from dpu debug dump drm/msm: dpu_core_irq: Replace DPU_EVT with tracepoints drm/msm: dpu_core_perf: Replace DPU_EVT with tracepoints drm/msm: dpu_crtc: Replace DPU_EVT with tracepoints drm/msm: dpu_dbg: Remove dump_all option for dumping registers drm/msm: dpu_dbg: Remove string parsing from DBG_DUMP drm/msm: dpu_encoder: Replace DPU_EVT with tracepoints drm/msm: dpu_encoder_phys_cmd: Replace DPU_EVT with tracepoints drm/msm: dpu_encoder_phys_vid: Replace DPU_EVT with tracepoints drm/msm: dpu_kms: Replace DPU_EVT with tracepoints drm/msm: dpu_mdss: Replace DPU_EVT with DRM_ERROR drm/msm: dpu_pingpong: Replace DPU_EVT with tracepoints drm/msm: dpu_plane: Replace DPU_EVT with tracepoints drm/msm: dpu_rm: Replace DPU_EVT with tracepoints drm/msm: dpu_vbif: Replace DPU_EVT with tracepoints drm: Remove duplicate ycbcr420 parsing drm: Remove unused drm_connector fields dt-bindings: dpu: Fixup dt-bindings discrepencies msm/hdcp: Remove redundant stubs/CONFIG video: Remove LF copyright in mipi_display.h
Sravanthi Kollukuduru skolluku@codeaurora.org (11): arm64: dts: Remove hw block offset DT entries for SDM845 arm64: dts: Remove inline rotator DT entry for SDM845 drm/msm/dpu: dynamic assignment of hw pipe to plane drm/msm/dpu: enable cursor plane for primary crtc drm/msm/dpu: introduce state based plane resource management drm/msm/dpu: remove smart dma support drm/msm/dpu: remove static binding of hw pipe to plane drm/msm: Add hardware catalog data in driver source for SDM845 drm/msm: Add hardware catalog file for SDM845 drm/msm: fix compilation warnings in display driver dt-bindings: msm/disp: Remove hw block offset DT entries for SDM845
END Breakdown of squashed patches -------
Abhinav Kumar (1): drm/msm: higher values of pclk can exceed 32 bits when multiplied by a factor
Chandan Uddaraju (2): drm/msm/dsi: adjust dsi timing for dual dsi mode drm/msm/dsi: Use one connector for dual DSI mode
Jeykumar Sankaran (11): dt-bindings: msm/dsi: Add mdp transfer time to msm dsi binding drm: add msm compressed format modifiers drm/msm: enable zpos normalization drm/msm: #define MDP version numbers drm/msm: Use labels for unwinding in the error path drm/msm: #define MAX_<OBJECT> in msm_drv.h drm/msm: Add .commit() callback to msm_kms functions drm/msm: Add preclose kms hook drm/msm: Add pm_suspend/resume callbacks to msm_kms dt-bindings: msm/disp: Add bindings for Snapdragon 845 DPU drm/msm: Add SDM845 DPU support
Rajesh Yadav (2): drm/msm/dsi: initialize postdiv_lock before use for 10nm pll drm/msm/mdp5: subclass msm_mdss for mdp5
Sean Paul (3): drm/msm: Move wait_for_vblanks into mdp complete_commit() hooks drm/msm: Clean up dangling atomic_wq arm64: dts: qcom: sdm845: Add dpu to sdm845 dts file
Taniya Das (1): dt-bindings: clock: Introduce QCOM Display clock bindings
vkorjani (1): drm: Add support for pps and compression mode command packet
.../devicetree/bindings/clock/qcom,dispcc.txt | 19 + .../devicetree/bindings/display/msm/dpu.txt | 128 + .../devicetree/bindings/display/msm/dsi.txt | 16 + arch/arm64/boot/dts/qcom/sdm845.dtsi | 194 ++ drivers/gpu/drm/drm_mipi_dsi.c | 2 + drivers/gpu/drm/msm/Makefile | 32 +- drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c | 532 ++++ drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h | 178 ++ drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c | 637 ++++ drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h | 133 + drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 2523 ++++++++++++++++ drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h | 491 ++++ drivers/gpu/drm/msm/disp/dpu1/dpu_dbg.c | 2393 +++++++++++++++ drivers/gpu/drm/msm/disp/dpu1/dpu_dbg.h | 103 + drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 2574 +++++++++++++++++ drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 191 ++ .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 453 +++ .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 905 ++++++ .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 922 ++++++ drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c | 1276 ++++++++ drivers/gpu/drm/msm/disp/dpu1/dpu_formats.h | 136 + drivers/gpu/drm/msm/disp/dpu1/dpu_hw_blk.c | 155 + drivers/gpu/drm/msm/disp/dpu1/dpu_hw_blk.h | 53 + .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 511 ++++ .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 804 +++++ .../drm/msm/disp/dpu1/dpu_hw_catalog_format.h | 182 ++ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c | 323 +++ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h | 139 + drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 540 ++++ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h | 218 ++ .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 1213 ++++++++ .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h | 278 ++ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 349 +++ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h | 128 + drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c | 261 ++ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h | 122 + drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 465 +++ .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c | 250 ++ .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h | 136 + drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c | 753 +++++ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h | 424 +++ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c | 398 +++ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h | 202 ++ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c | 452 +++ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h | 358 +++ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c | 275 ++ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h | 128 + drivers/gpu/drm/msm/disp/dpu1/dpu_hwio.h | 56 + drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c | 186 ++ drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h | 57 + drivers/gpu/drm/msm/disp/dpu1/dpu_irq.c | 66 + drivers/gpu/drm/msm/disp/dpu1/dpu_irq.h | 59 + drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 1380 +++++++++ drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 402 +++ drivers/gpu/drm/msm/disp/dpu1/dpu_kms_utils.c | 153 + drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c | 259 ++ drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 1963 +++++++++++++ drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h | 175 ++ .../gpu/drm/msm/disp/dpu1/dpu_power_handle.c | 249 ++ .../gpu/drm/msm/disp/dpu1/dpu_power_handle.h | 225 ++ drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 1079 +++++++ drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 199 ++ drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h | 1011 +++++++ drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c | 384 +++ drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.h | 94 + drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c | 2 + drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 2 + drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c | 154 +- drivers/gpu/drm/msm/dsi/dsi.c | 3 + drivers/gpu/drm/msm/dsi/dsi.h | 7 +- drivers/gpu/drm/msm/dsi/dsi_host.c | 64 +- drivers/gpu/drm/msm/dsi/dsi_manager.c | 119 +- drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c | 2 + drivers/gpu/drm/msm/msm_atomic.c | 7 +- drivers/gpu/drm/msm/msm_drv.c | 230 +- drivers/gpu/drm/msm/msm_drv.h | 96 +- drivers/gpu/drm/msm/msm_kms.h | 30 +- .../dt-bindings/clock/qcom,dispcc-sdm845.h | 45 + include/uapi/drm/drm_fourcc.h | 45 + include/uapi/media/msm_media_info.h | 1376 +++++++++ include/video/mipi_display.h | 3 + 81 files changed, 32900 insertions(+), 237 deletions(-) create mode 100644 Documentation/devicetree/bindings/clock/qcom,dispcc.txt create mode 100644 Documentation/devicetree/bindings/display/msm/dpu.txt create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_dbg.c create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_dbg.h create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_formats.h create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_blk.c create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_blk.h create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog_format.h create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hwio.h create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.h create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_irq.c create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_irq.h create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_kms_utils.c create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_power_handle.c create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_power_handle.h create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.h create mode 100644 include/dt-bindings/clock/qcom,dispcc-sdm845.h create mode 100644 include/uapi/media/msm_media_info.h
From: Jeykumar Sankaran jsanka@codeaurora.org
Adds mdp transfer time to msm dsi binding
Signed-off-by: Jeykumar Sankaran jsanka@codeaurora.org Signed-off-by: Rajesh Yadav ryadav@codeaurora.org Signed-off-by: Sean Paul seanpaul@chromium.org --- .../devicetree/bindings/display/msm/dsi.txt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
diff --git a/Documentation/devicetree/bindings/display/msm/dsi.txt b/Documentation/devicetree/bindings/display/msm/dsi.txt index 518e9cdf0d4b..d22237a88eae 100644 --- a/Documentation/devicetree/bindings/display/msm/dsi.txt +++ b/Documentation/devicetree/bindings/display/msm/dsi.txt @@ -121,6 +121,20 @@ Required properties: Optional properties: - qcom,dsi-phy-regulator-ldo-mode: Boolean value indicating if the LDO mode PHY regulator is wanted. +- qcom,mdss-mdp-transfer-time-us: Specifies the dsi transfer time for command mode + panels in microseconds. Driver uses this number to adjust + the clock rate according to the expected transfer time. + Increasing this value would slow down the mdp processing + and can result in slower performance. + Decreasing this value can speed up the mdp processing, + but this can also impact power consumption. + As a rule this time should not be higher than the time + that would be expected with the processing at the + dsi link rate since anyways this would be the maximum + transfer time that could be achieved. + If ping pong split is enabled, this time should not be higher + than two times the dsi link rate time. + If the property is not specified, then the default value is 14000 us.
[1] Documentation/devicetree/bindings/clock/clock-bindings.txt [2] Documentation/devicetree/bindings/graph.txt @@ -171,6 +185,8 @@ Example: qcom,master-dsi; qcom,sync-dual-dsi;
+ qcom,mdss-mdp-transfer-time-us = <12000>; + pinctrl-names = "default", "sleep"; pinctrl-0 = <&dsi_active>; pinctrl-1 = <&dsi_suspend>;
On Mon, Jul 09, 2018 at 01:31:37PM -0400, Sean Paul wrote:
From: Jeykumar Sankaran jsanka@codeaurora.org
Adds mdp transfer time to msm dsi binding
Signed-off-by: Jeykumar Sankaran jsanka@codeaurora.org Signed-off-by: Rajesh Yadav ryadav@codeaurora.org Signed-off-by: Sean Paul seanpaul@chromium.org
.../devicetree/bindings/display/msm/dsi.txt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
Reviewed-by: Rob Herring robh@kernel.org
From: Taniya Das tdas@codeaurora.org
Add device tree bindings for display clock controller for Qualcomm Technology Inc's SDM845 SoCs.
Signed-off-by: Taniya Das tdas@codeaurora.org Reviewed-by: Rob Herring robh@kernel.org Signed-off-by: Sean Paul seanpaul@chromium.org --- .../devicetree/bindings/clock/qcom,dispcc.txt | 19 ++++++++ .../dt-bindings/clock/qcom,dispcc-sdm845.h | 45 +++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/qcom,dispcc.txt create mode 100644 include/dt-bindings/clock/qcom,dispcc-sdm845.h
diff --git a/Documentation/devicetree/bindings/clock/qcom,dispcc.txt b/Documentation/devicetree/bindings/clock/qcom,dispcc.txt new file mode 100644 index 000000000000..d639e18d0b85 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,dispcc.txt @@ -0,0 +1,19 @@ +Qualcomm Technologies, Inc. Display Clock Controller Binding +------------------------------------------------------------ + +Required properties : + +- compatible : shall contain "qcom,sdm845-dispcc" +- reg : shall contain base register location and length. +- #clock-cells : from common clock binding, shall contain 1. +- #reset-cells : from common reset binding, shall contain 1. +- #power-domain-cells : from generic power domain binding, shall contain 1. + +Example: + dispcc: clock-controller@af00000 { + compatible = "qcom,sdm845-dispcc"; + reg = <0xaf00000 0x100000>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; diff --git a/include/dt-bindings/clock/qcom,dispcc-sdm845.h b/include/dt-bindings/clock/qcom,dispcc-sdm845.h new file mode 100644 index 000000000000..11eed4bc9646 --- /dev/null +++ b/include/dt-bindings/clock/qcom,dispcc-sdm845.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _DT_BINDINGS_CLK_SDM_DISP_CC_SDM845_H +#define _DT_BINDINGS_CLK_SDM_DISP_CC_SDM845_H + +/* DISP_CC clock registers */ +#define DISP_CC_MDSS_AHB_CLK 0 +#define DISP_CC_MDSS_AXI_CLK 1 +#define DISP_CC_MDSS_BYTE0_CLK 2 +#define DISP_CC_MDSS_BYTE0_CLK_SRC 3 +#define DISP_CC_MDSS_BYTE0_INTF_CLK 4 +#define DISP_CC_MDSS_BYTE1_CLK 5 +#define DISP_CC_MDSS_BYTE1_CLK_SRC 6 +#define DISP_CC_MDSS_BYTE1_INTF_CLK 7 +#define DISP_CC_MDSS_ESC0_CLK 8 +#define DISP_CC_MDSS_ESC0_CLK_SRC 9 +#define DISP_CC_MDSS_ESC1_CLK 10 +#define DISP_CC_MDSS_ESC1_CLK_SRC 11 +#define DISP_CC_MDSS_MDP_CLK 12 +#define DISP_CC_MDSS_MDP_CLK_SRC 13 +#define DISP_CC_MDSS_MDP_LUT_CLK 14 +#define DISP_CC_MDSS_PCLK0_CLK 15 +#define DISP_CC_MDSS_PCLK0_CLK_SRC 16 +#define DISP_CC_MDSS_PCLK1_CLK 17 +#define DISP_CC_MDSS_PCLK1_CLK_SRC 18 +#define DISP_CC_MDSS_ROT_CLK 19 +#define DISP_CC_MDSS_ROT_CLK_SRC 20 +#define DISP_CC_MDSS_RSCC_AHB_CLK 21 +#define DISP_CC_MDSS_RSCC_VSYNC_CLK 22 +#define DISP_CC_MDSS_VSYNC_CLK 23 +#define DISP_CC_MDSS_VSYNC_CLK_SRC 24 +#define DISP_CC_PLL0 25 +#define DISP_CC_MDSS_BYTE0_DIV_CLK_SRC 26 +#define DISP_CC_MDSS_BYTE1_DIV_CLK_SRC 27 + +/* DISP_CC Reset */ +#define DISP_CC_MDSS_RSCC_BCR 0 + +/* DISP_CC GDSCR */ +#define MDSS_GDSC 0 + +#endif
From: vkorjani vikas.korjani@intel.com
After enabling DSC we need to send compression mode command packet and pps data packet, for which 2 new data types are added 07h Compression Mode Data Type Write , short write, 2 parameters 0Ah PPS Long Write (word count determines number of bytes) This patch adds support to send these packets.
Cc: David Airlie airlied@linux.ie Cc: Jean-Christophe Plagniol-Villard plagnioj@jcrosoft.com Cc: Tomi Valkeinen tomi.valkeinen@ti.com Cc: dri-devel@lists.freedesktop.org Cc: linux-kernel@vger.kernel.org Cc: linux-fbdev@vger.kernel.org
Signed-off-by: vkorjani vikas.korjani@intel.com [seanpaul removed pps_write_buffer fn, added types to packet_format helpers] Signed-off-by: Sean Paul seanpaul@chromium.org --- drivers/gpu/drm/drm_mipi_dsi.c | 2 ++ include/video/mipi_display.h | 3 +++ 2 files changed, 5 insertions(+)
diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c index bc73b7f5b9fc..80b75501f5c6 100644 --- a/drivers/gpu/drm/drm_mipi_dsi.c +++ b/drivers/gpu/drm/drm_mipi_dsi.c @@ -392,6 +392,7 @@ bool mipi_dsi_packet_format_is_short(u8 type) case MIPI_DSI_DCS_SHORT_WRITE: case MIPI_DSI_DCS_SHORT_WRITE_PARAM: case MIPI_DSI_DCS_READ: + case MIPI_DSI_DCS_COMPRESSION_MODE: case MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE: return true; } @@ -410,6 +411,7 @@ EXPORT_SYMBOL(mipi_dsi_packet_format_is_short); bool mipi_dsi_packet_format_is_long(u8 type) { switch (type) { + case MIPI_DSI_PPS_LONG_WRITE: case MIPI_DSI_NULL_PACKET: case MIPI_DSI_BLANKING_PACKET: case MIPI_DSI_GENERIC_LONG_WRITE: diff --git a/include/video/mipi_display.h b/include/video/mipi_display.h index 19aa65a35546..49a53ef8da96 100644 --- a/include/video/mipi_display.h +++ b/include/video/mipi_display.h @@ -38,6 +38,9 @@ enum {
MIPI_DSI_DCS_READ = 0x06,
+ MIPI_DSI_DCS_COMPRESSION_MODE = 0x07, + MIPI_DSI_PPS_LONG_WRITE = 0x0A, + MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE = 0x37,
MIPI_DSI_END_OF_TRANSMISSION = 0x08,
From: Jeykumar Sankaran jsanka@codeaurora.org
Qualcomm Snapdragon chipsets uses compressed format to optimize BW across multiple IP's. This change adds needed modifier support in drm for a simple 4x4 tile based compressed variants of base formats.
Signed-off-by: Jeykumar Sankaran jsanka@codeaurora.org Signed-off-by: Sean Paul seanpaul@chromium.org --- include/uapi/drm/drm_fourcc.h | 45 +++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+)
diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h index e04613d30a13..9a97405a3d2a 100644 --- a/include/uapi/drm/drm_fourcc.h +++ b/include/uapi/drm/drm_fourcc.h @@ -298,6 +298,38 @@ extern "C" { */ #define DRM_FORMAT_MOD_SAMSUNG_64_32_TILE fourcc_mod_code(SAMSUNG, 1)
+/* + * Qualcomm Compressed Format + * + * Refers to a compressed variant of the base format that is compressed. + * Implementation may be platform and base-format specific. + */ +#define DRM_FORMAT_MOD_QCOM_COMPRESSED fourcc_mod_code(QCOM, 1) + +/* + * QTI DX Format + * + * Refers to a DX variant of the base format. + * Implementation may be platform and base-format specific. + */ +#define DRM_FORMAT_MOD_QCOM_DX fourcc_mod_code(QCOM, 0x2) + +/* + * QTI Tight Format + * + * Refers to a tightly packed variant of the base format. + * Implementation may be platform and base-format specific. + */ +#define DRM_FORMAT_MOD_QCOM_TIGHT fourcc_mod_code(QCOM, 0x4) + +/* + * QTI Tile Format + * + * Refers to a tile variant of the base format. + * Implementation may be platform and base-format specific. + */ +#define DRM_FORMAT_MOD_QCOM_TILE fourcc_mod_code(QCOM, 0x8) + /* Vivante framebuffer modifiers */
/* @@ -405,6 +437,19 @@ extern "C" { */ #define DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED fourcc_mod_code(BROADCOM, 1)
+/* + * MSM compressed format + * + * Refers to the compressed variant of a base format. + * Implementation may be platform and base-format specific. + * + * Each macrotile consists of m x n (mostly 4 x 4) tiles. + * Pixel data pitch/stride is aligned with macrotile width. + * Pixel data height is aligned with macrotile height. + * Entire pixel data buffer is aligned with 4k(bytes). + */ +#define DRM_FORMAT_MOD_QCOM_COMPRESSED fourcc_mod_code(QCOM, 1) + #if defined(__cplusplus) } #endif
On Mon, Jul 9, 2018 at 1:31 PM, Sean Paul seanpaul@chromium.org wrote:
From: Jeykumar Sankaran jsanka@codeaurora.org
Qualcomm Snapdragon chipsets uses compressed format to optimize BW across multiple IP's. This change adds needed modifier support in drm for a simple 4x4 tile based compressed variants of base formats.
Signed-off-by: Jeykumar Sankaran jsanka@codeaurora.org Signed-off-by: Sean Paul seanpaul@chromium.org
include/uapi/drm/drm_fourcc.h | 45 +++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+)
diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h index e04613d30a13..9a97405a3d2a 100644 --- a/include/uapi/drm/drm_fourcc.h +++ b/include/uapi/drm/drm_fourcc.h @@ -298,6 +298,38 @@ extern "C" { */ #define DRM_FORMAT_MOD_SAMSUNG_64_32_TILE fourcc_mod_code(SAMSUNG, 1)
+/*
- Qualcomm Compressed Format
- Refers to a compressed variant of the base format that is compressed.
- Implementation may be platform and base-format specific.
- */
+#define DRM_FORMAT_MOD_QCOM_COMPRESSED fourcc_mod_code(QCOM, 1)
hmm, somehow (I guess rebasing gone wrong?) we end up with DRM_FORMAT_MOD_QCOM_COMPRESSED.. I'll drop the 2nd hunk
BR, -R
+/*
- QTI DX Format
- Refers to a DX variant of the base format.
- Implementation may be platform and base-format specific.
- */
+#define DRM_FORMAT_MOD_QCOM_DX fourcc_mod_code(QCOM, 0x2)
+/*
- QTI Tight Format
- Refers to a tightly packed variant of the base format.
- Implementation may be platform and base-format specific.
- */
+#define DRM_FORMAT_MOD_QCOM_TIGHT fourcc_mod_code(QCOM, 0x4)
+/*
- QTI Tile Format
- Refers to a tile variant of the base format.
- Implementation may be platform and base-format specific.
- */
+#define DRM_FORMAT_MOD_QCOM_TILE fourcc_mod_code(QCOM, 0x8)
/* Vivante framebuffer modifiers */
/* @@ -405,6 +437,19 @@ extern "C" { */ #define DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED fourcc_mod_code(BROADCOM, 1)
+/*
- MSM compressed format
- Refers to the compressed variant of a base format.
- Implementation may be platform and base-format specific.
- Each macrotile consists of m x n (mostly 4 x 4) tiles.
- Pixel data pitch/stride is aligned with macrotile width.
- Pixel data height is aligned with macrotile height.
- Entire pixel data buffer is aligned with 4k(bytes).
- */
+#define DRM_FORMAT_MOD_QCOM_COMPRESSED fourcc_mod_code(QCOM, 1)
#if defined(__cplusplus) }
#endif
Sean Paul, Software Engineer, Google / Chromium OS
From: Chandan Uddaraju chandanu@codeaurora.org
For dual dsi mode, the horizontal timing needs to be divided by half since both the dsi controllers will be driving this panel. Adjust the pixel clock and DSI timing accordingly.
Changes in V2: --Removed Change-Id from the commit text tags.
Changes in V3: --Instead of adjusting the DRM mode structure, divide the clocks and horizontal timings in DSI host just before configuring the values.
Signed-off-by: Chandan Uddaraju chandanu@codeaurora.org Signed-off-by: Sean Paul seanpaul@chromium.org --- drivers/gpu/drm/msm/dsi/dsi.h | 6 ++- drivers/gpu/drm/msm/dsi/dsi_host.c | 55 +++++++++++++++++++++------ drivers/gpu/drm/msm/dsi/dsi_manager.c | 7 ++-- 3 files changed, 52 insertions(+), 16 deletions(-)
diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index 70d9a9a47acd..01c38f67d699 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -162,7 +162,8 @@ void msm_dsi_host_cmd_xfer_commit(struct mipi_dsi_host *host, int msm_dsi_host_enable(struct mipi_dsi_host *host); int msm_dsi_host_disable(struct mipi_dsi_host *host); int msm_dsi_host_power_on(struct mipi_dsi_host *host, - struct msm_dsi_phy_shared_timings *phy_shared_timings); + struct msm_dsi_phy_shared_timings *phy_shared_timings, + bool is_dual_dsi); int msm_dsi_host_power_off(struct mipi_dsi_host *host); int msm_dsi_host_set_display_mode(struct mipi_dsi_host *host, struct drm_display_mode *mode); @@ -175,7 +176,8 @@ int msm_dsi_host_set_src_pll(struct mipi_dsi_host *host, struct msm_dsi_pll *src_pll); void msm_dsi_host_reset_phy(struct mipi_dsi_host *host); void msm_dsi_host_get_phy_clk_req(struct mipi_dsi_host *host, - struct msm_dsi_phy_clk_request *clk_req); + struct msm_dsi_phy_clk_request *clk_req, + bool is_dual_dsi); void msm_dsi_host_destroy(struct mipi_dsi_host *host); int msm_dsi_host_modeset_init(struct mipi_dsi_host *host, struct drm_device *dev); diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index 2f1a2780658a..671039b7b75b 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -118,6 +118,7 @@ struct msm_dsi_host { struct clk *byte_intf_clk;
u32 byte_clk_rate; + u32 pixel_clk_rate; u32 esc_clk_rate;
/* DSI v2 specific clocks */ @@ -511,7 +512,7 @@ static int dsi_link_clk_enable_6g(struct msm_dsi_host *msm_host) goto error; }
- ret = clk_set_rate(msm_host->pixel_clk, msm_host->mode->clock * 1000); + ret = clk_set_rate(msm_host->pixel_clk, msm_host->pixel_clk_rate); if (ret) { pr_err("%s: Failed to set rate pixel clk, %d\n", __func__, ret); goto error; @@ -592,7 +593,7 @@ static int dsi_link_clk_enable_v2(struct msm_dsi_host *msm_host) goto error; }
- ret = clk_set_rate(msm_host->pixel_clk, msm_host->mode->clock * 1000); + ret = clk_set_rate(msm_host->pixel_clk, msm_host->pixel_clk_rate); if (ret) { pr_err("%s: Failed to set rate pixel clk, %d\n", __func__, ret); goto error; @@ -662,7 +663,7 @@ static void dsi_link_clk_disable(struct msm_dsi_host *msm_host) } }
-static int dsi_calc_clk_rate(struct msm_dsi_host *msm_host) +static int dsi_calc_clk_rate(struct msm_dsi_host *msm_host, bool is_dual_dsi) { struct drm_display_mode *mode = msm_host->mode; const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd; @@ -676,14 +677,28 @@ static int dsi_calc_clk_rate(struct msm_dsi_host *msm_host) }
pclk_rate = mode->clock * 1000; + + /* + * For dual DSI mode, the current DRM mode has + * the complete width of the panel. Since, the complete + * panel is driven by two DSI controllers, the + * the clock rates have to be split between + * the two dsi controllers. Adjust the byte and + * pixel clock rates for each dsi host accordingly. + */ + if (is_dual_dsi) + pclk_rate /= 2; + if (lanes > 0) { msm_host->byte_clk_rate = (pclk_rate * bpp) / (8 * lanes); } else { pr_err("%s: forcing mdss_dsi lanes to 1\n", __func__); msm_host->byte_clk_rate = (pclk_rate * bpp) / 8; } + msm_host->pixel_clk_rate = pclk_rate;
- DBG("pclk=%d, bclk=%d", pclk_rate, msm_host->byte_clk_rate); + DBG("pclk=%d, bclk=%d", msm_host->pixel_clk_rate, + msm_host->byte_clk_rate);
msm_host->esc_clk_rate = clk_get_rate(msm_host->esc_clk);
@@ -885,7 +900,7 @@ static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable, dsi_write(msm_host, REG_DSI_CTRL, data); }
-static void dsi_timing_setup(struct msm_dsi_host *msm_host) +static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_dual_dsi) { struct drm_display_mode *mode = msm_host->mode; u32 hs_start = 0, vs_start = 0; /* take sync start as 0 */ @@ -897,10 +912,26 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host) u32 ha_end = ha_start + mode->hdisplay; u32 va_start = v_total - mode->vsync_start; u32 va_end = va_start + mode->vdisplay; + u32 hdisplay = mode->hdisplay; u32 wc;
DBG("");
+ /* + * For dual DSI mode, the current DRM mode has + * the complete width of the panel. Since, the complete + * panel is driven by two DSI controllers, the horizontal + * timings have to be split between the two dsi controllers. + * Adjust the DSI host timing values accordingly. + */ + if (is_dual_dsi) { + h_total /= 2; + hs_end /= 2; + ha_start /= 2; + ha_end /= 2; + hdisplay /= 2; + } + if (msm_host->mode_flags & MIPI_DSI_MODE_VIDEO) { dsi_write(msm_host, REG_DSI_ACTIVE_H, DSI_ACTIVE_H_START(ha_start) | @@ -921,7 +952,7 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host) DSI_ACTIVE_VSYNC_VPOS_END(vs_end)); } else { /* command mode */ /* image data and 1 byte write_memory_start cmd */ - wc = mode->hdisplay * dsi_get_bpp(msm_host->format) / 8 + 1; + wc = hdisplay * dsi_get_bpp(msm_host->format) / 8 + 1;
dsi_write(msm_host, REG_DSI_CMD_MDP_STREAM_CTRL, DSI_CMD_MDP_STREAM_CTRL_WORD_COUNT(wc) | @@ -931,7 +962,7 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host) MIPI_DSI_DCS_LONG_WRITE));
dsi_write(msm_host, REG_DSI_CMD_MDP_STREAM_TOTAL, - DSI_CMD_MDP_STREAM_TOTAL_H_TOTAL(mode->hdisplay) | + DSI_CMD_MDP_STREAM_TOTAL_H_TOTAL(hdisplay) | DSI_CMD_MDP_STREAM_TOTAL_V_TOTAL(mode->vdisplay)); } } @@ -2189,12 +2220,13 @@ void msm_dsi_host_reset_phy(struct mipi_dsi_host *host) }
void msm_dsi_host_get_phy_clk_req(struct mipi_dsi_host *host, - struct msm_dsi_phy_clk_request *clk_req) + struct msm_dsi_phy_clk_request *clk_req, + bool is_dual_dsi) { struct msm_dsi_host *msm_host = to_msm_dsi_host(host); int ret;
- ret = dsi_calc_clk_rate(msm_host); + ret = dsi_calc_clk_rate(msm_host, is_dual_dsi); if (ret) { pr_err("%s: unable to calc clk rate, %d\n", __func__, ret); return; @@ -2256,7 +2288,8 @@ static void msm_dsi_sfpb_config(struct msm_dsi_host *msm_host, bool enable) }
int msm_dsi_host_power_on(struct mipi_dsi_host *host, - struct msm_dsi_phy_shared_timings *phy_shared_timings) + struct msm_dsi_phy_shared_timings *phy_shared_timings, + bool is_dual_dsi) { struct msm_dsi_host *msm_host = to_msm_dsi_host(host); int ret = 0; @@ -2291,7 +2324,7 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host, goto fail_disable_clk; }
- dsi_timing_setup(msm_host); + dsi_timing_setup(msm_host, is_dual_dsi); dsi_sw_reset(msm_host); dsi_ctrl_config(msm_host, true, phy_shared_timings);
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index 4cb1cb68878b..3bb506b44a4b 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -134,8 +134,9 @@ static int enable_phy(struct msm_dsi *msm_dsi, int src_pll_id, { struct msm_dsi_phy_clk_request clk_req; int ret; + bool is_dual_dsi = IS_DUAL_DSI();
- msm_dsi_host_get_phy_clk_req(msm_dsi->host, &clk_req); + msm_dsi_host_get_phy_clk_req(msm_dsi->host, &clk_req, is_dual_dsi);
ret = msm_dsi_phy_enable(msm_dsi->phy, src_pll_id, &clk_req); msm_dsi_phy_get_shared_timings(msm_dsi->phy, shared_timings); @@ -458,7 +459,7 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge) if (is_dual_dsi && (DSI_1 == id)) return;
- ret = msm_dsi_host_power_on(host, &phy_shared_timings[id]); + ret = msm_dsi_host_power_on(host, &phy_shared_timings[id], is_dual_dsi); if (ret) { pr_err("%s: power on host %d failed, %d\n", __func__, id, ret); goto host_on_fail; @@ -466,7 +467,7 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
if (is_dual_dsi && msm_dsi1) { ret = msm_dsi_host_power_on(msm_dsi1->host, - &phy_shared_timings[DSI_1]); + &phy_shared_timings[DSI_1], is_dual_dsi); if (ret) { pr_err("%s: power on host1 failed, %d\n", __func__, ret);
On Monday 09 July 2018 11:01 PM, Sean Paul wrote:
From: Chandan Uddaraju chandanu@codeaurora.org
For dual dsi mode, the horizontal timing needs to be divided by half since both the dsi controllers will be driving this panel. Adjust the pixel clock and DSI timing accordingly.
Reviewed-by: Archit Taneja architt@codeaurora.org
Changes in V2: --Removed Change-Id from the commit text tags.
Changes in V3: --Instead of adjusting the DRM mode structure, divide the clocks and horizontal timings in DSI host just before configuring the values.
Signed-off-by: Chandan Uddaraju chandanu@codeaurora.org Signed-off-by: Sean Paul seanpaul@chromium.org
drivers/gpu/drm/msm/dsi/dsi.h | 6 ++- drivers/gpu/drm/msm/dsi/dsi_host.c | 55 +++++++++++++++++++++------ drivers/gpu/drm/msm/dsi/dsi_manager.c | 7 ++-- 3 files changed, 52 insertions(+), 16 deletions(-)
diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index 70d9a9a47acd..01c38f67d699 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -162,7 +162,8 @@ void msm_dsi_host_cmd_xfer_commit(struct mipi_dsi_host *host, int msm_dsi_host_enable(struct mipi_dsi_host *host); int msm_dsi_host_disable(struct mipi_dsi_host *host); int msm_dsi_host_power_on(struct mipi_dsi_host *host,
struct msm_dsi_phy_shared_timings *phy_shared_timings);
struct msm_dsi_phy_shared_timings *phy_shared_timings,
int msm_dsi_host_power_off(struct mipi_dsi_host *host); int msm_dsi_host_set_display_mode(struct mipi_dsi_host *host, struct drm_display_mode *mode);bool is_dual_dsi);
@@ -175,7 +176,8 @@ int msm_dsi_host_set_src_pll(struct mipi_dsi_host *host, struct msm_dsi_pll *src_pll); void msm_dsi_host_reset_phy(struct mipi_dsi_host *host); void msm_dsi_host_get_phy_clk_req(struct mipi_dsi_host *host,
- struct msm_dsi_phy_clk_request *clk_req);
- struct msm_dsi_phy_clk_request *clk_req,
- bool is_dual_dsi); void msm_dsi_host_destroy(struct mipi_dsi_host *host); int msm_dsi_host_modeset_init(struct mipi_dsi_host *host, struct drm_device *dev);
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index 2f1a2780658a..671039b7b75b 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -118,6 +118,7 @@ struct msm_dsi_host { struct clk *byte_intf_clk;
u32 byte_clk_rate;
u32 pixel_clk_rate; u32 esc_clk_rate;
/* DSI v2 specific clocks */
@@ -511,7 +512,7 @@ static int dsi_link_clk_enable_6g(struct msm_dsi_host *msm_host) goto error; }
- ret = clk_set_rate(msm_host->pixel_clk, msm_host->mode->clock * 1000);
- ret = clk_set_rate(msm_host->pixel_clk, msm_host->pixel_clk_rate); if (ret) { pr_err("%s: Failed to set rate pixel clk, %d\n", __func__, ret); goto error;
@@ -592,7 +593,7 @@ static int dsi_link_clk_enable_v2(struct msm_dsi_host *msm_host) goto error; }
- ret = clk_set_rate(msm_host->pixel_clk, msm_host->mode->clock * 1000);
- ret = clk_set_rate(msm_host->pixel_clk, msm_host->pixel_clk_rate); if (ret) { pr_err("%s: Failed to set rate pixel clk, %d\n", __func__, ret); goto error;
@@ -662,7 +663,7 @@ static void dsi_link_clk_disable(struct msm_dsi_host *msm_host) } }
-static int dsi_calc_clk_rate(struct msm_dsi_host *msm_host) +static int dsi_calc_clk_rate(struct msm_dsi_host *msm_host, bool is_dual_dsi) { struct drm_display_mode *mode = msm_host->mode; const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd; @@ -676,14 +677,28 @@ static int dsi_calc_clk_rate(struct msm_dsi_host *msm_host) }
pclk_rate = mode->clock * 1000;
- /*
* For dual DSI mode, the current DRM mode has
* the complete width of the panel. Since, the complete
* panel is driven by two DSI controllers, the
* the clock rates have to be split between
* the two dsi controllers. Adjust the byte and
* pixel clock rates for each dsi host accordingly.
*/
- if (is_dual_dsi)
pclk_rate /= 2;
- if (lanes > 0) { msm_host->byte_clk_rate = (pclk_rate * bpp) / (8 * lanes); } else { pr_err("%s: forcing mdss_dsi lanes to 1\n", __func__); msm_host->byte_clk_rate = (pclk_rate * bpp) / 8; }
- msm_host->pixel_clk_rate = pclk_rate;
- DBG("pclk=%d, bclk=%d", pclk_rate, msm_host->byte_clk_rate);
DBG("pclk=%d, bclk=%d", msm_host->pixel_clk_rate,
msm_host->byte_clk_rate);
msm_host->esc_clk_rate = clk_get_rate(msm_host->esc_clk);
@@ -885,7 +900,7 @@ static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable, dsi_write(msm_host, REG_DSI_CTRL, data); }
-static void dsi_timing_setup(struct msm_dsi_host *msm_host) +static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_dual_dsi) { struct drm_display_mode *mode = msm_host->mode; u32 hs_start = 0, vs_start = 0; /* take sync start as 0 */ @@ -897,10 +912,26 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host) u32 ha_end = ha_start + mode->hdisplay; u32 va_start = v_total - mode->vsync_start; u32 va_end = va_start + mode->vdisplay;
u32 hdisplay = mode->hdisplay; u32 wc;
DBG("");
/*
* For dual DSI mode, the current DRM mode has
* the complete width of the panel. Since, the complete
* panel is driven by two DSI controllers, the horizontal
* timings have to be split between the two dsi controllers.
* Adjust the DSI host timing values accordingly.
*/
if (is_dual_dsi) {
h_total /= 2;
hs_end /= 2;
ha_start /= 2;
ha_end /= 2;
hdisplay /= 2;
}
if (msm_host->mode_flags & MIPI_DSI_MODE_VIDEO) { dsi_write(msm_host, REG_DSI_ACTIVE_H, DSI_ACTIVE_H_START(ha_start) |
@@ -921,7 +952,7 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host) DSI_ACTIVE_VSYNC_VPOS_END(vs_end)); } else { /* command mode */ /* image data and 1 byte write_memory_start cmd */
wc = mode->hdisplay * dsi_get_bpp(msm_host->format) / 8 + 1;
wc = hdisplay * dsi_get_bpp(msm_host->format) / 8 + 1;
dsi_write(msm_host, REG_DSI_CMD_MDP_STREAM_CTRL, DSI_CMD_MDP_STREAM_CTRL_WORD_COUNT(wc) |
@@ -931,7 +962,7 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host) MIPI_DSI_DCS_LONG_WRITE));
dsi_write(msm_host, REG_DSI_CMD_MDP_STREAM_TOTAL,
DSI_CMD_MDP_STREAM_TOTAL_H_TOTAL(mode->hdisplay) |
} }DSI_CMD_MDP_STREAM_TOTAL_H_TOTAL(hdisplay) | DSI_CMD_MDP_STREAM_TOTAL_V_TOTAL(mode->vdisplay));
@@ -2189,12 +2220,13 @@ void msm_dsi_host_reset_phy(struct mipi_dsi_host *host) }
void msm_dsi_host_get_phy_clk_req(struct mipi_dsi_host *host,
- struct msm_dsi_phy_clk_request *clk_req)
struct msm_dsi_phy_clk_request *clk_req,
{ struct msm_dsi_host *msm_host = to_msm_dsi_host(host); int ret;bool is_dual_dsi)
- ret = dsi_calc_clk_rate(msm_host);
- ret = dsi_calc_clk_rate(msm_host, is_dual_dsi); if (ret) { pr_err("%s: unable to calc clk rate, %d\n", __func__, ret); return;
@@ -2256,7 +2288,8 @@ static void msm_dsi_sfpb_config(struct msm_dsi_host *msm_host, bool enable) }
int msm_dsi_host_power_on(struct mipi_dsi_host *host,
struct msm_dsi_phy_shared_timings *phy_shared_timings)
struct msm_dsi_phy_shared_timings *phy_shared_timings,
{ struct msm_dsi_host *msm_host = to_msm_dsi_host(host); int ret = 0;bool is_dual_dsi)
@@ -2291,7 +2324,7 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host, goto fail_disable_clk; }
- dsi_timing_setup(msm_host);
- dsi_timing_setup(msm_host, is_dual_dsi); dsi_sw_reset(msm_host); dsi_ctrl_config(msm_host, true, phy_shared_timings);
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index 4cb1cb68878b..3bb506b44a4b 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -134,8 +134,9 @@ static int enable_phy(struct msm_dsi *msm_dsi, int src_pll_id, { struct msm_dsi_phy_clk_request clk_req; int ret;
- bool is_dual_dsi = IS_DUAL_DSI();
- msm_dsi_host_get_phy_clk_req(msm_dsi->host, &clk_req);
msm_dsi_host_get_phy_clk_req(msm_dsi->host, &clk_req, is_dual_dsi);
ret = msm_dsi_phy_enable(msm_dsi->phy, src_pll_id, &clk_req); msm_dsi_phy_get_shared_timings(msm_dsi->phy, shared_timings);
@@ -458,7 +459,7 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge) if (is_dual_dsi && (DSI_1 == id)) return;
- ret = msm_dsi_host_power_on(host, &phy_shared_timings[id]);
- ret = msm_dsi_host_power_on(host, &phy_shared_timings[id], is_dual_dsi); if (ret) { pr_err("%s: power on host %d failed, %d\n", __func__, id, ret); goto host_on_fail;
@@ -466,7 +467,7 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
if (is_dual_dsi && msm_dsi1) { ret = msm_dsi_host_power_on(msm_dsi1->host,
&phy_shared_timings[DSI_1]);
if (ret) { pr_err("%s: power on host1 failed, %d\n", __func__, ret);&phy_shared_timings[DSI_1], is_dual_dsi);
From: Chandan Uddaraju chandanu@codeaurora.org
Current DSI driver uses two connectors for dual DSI case even though we only have one panel. Fix this by implementing one connector/bridge for dual DSI use case. Use master DSI controllers to register one connector/bridge.
Changes in V2: -Removed Change-Id from the commit text tags. -Remove extra parentheses
Changes in V3: -None
Reviewed-by: Archit Taneja architt@codeaurora.org Signed-off-by: Chandan Uddaraju chandanu@codeaurora.org [seanpaul removed unused local var causing a build warning] Signed-off-by: Sean Paul seanpaul@chromium.org --- drivers/gpu/drm/msm/dsi/dsi.c | 3 + drivers/gpu/drm/msm/dsi/dsi.h | 1 + drivers/gpu/drm/msm/dsi/dsi_manager.c | 112 ++++++-------------------- 3 files changed, 30 insertions(+), 86 deletions(-)
diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c index b744bcc7d8ad..ff8164cc6738 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.c +++ b/drivers/gpu/drm/msm/dsi/dsi.c @@ -208,6 +208,9 @@ int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev, goto fail; }
+ if (!msm_dsi_manager_validate_current_config(msm_dsi->id)) + goto fail; + msm_dsi->encoder = encoder;
msm_dsi->bridge = msm_dsi_manager_bridge_init(msm_dsi->id); diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index 01c38f67d699..c858e8e1a5bd 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -100,6 +100,7 @@ bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 dma_base, u32 len); void msm_dsi_manager_attach_dsi_device(int id, u32 device_flags); int msm_dsi_manager_register(struct msm_dsi *msm_dsi); void msm_dsi_manager_unregister(struct msm_dsi *msm_dsi); +bool msm_dsi_manager_validate_current_config(u8 id);
/* msm dsi */ static inline bool msm_dsi_device_connected(struct msm_dsi *msm_dsi) diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index 3bb506b44a4b..000721fe5ab4 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -306,102 +306,25 @@ static void dsi_mgr_connector_destroy(struct drm_connector *connector) kfree(dsi_connector); }
-static void dsi_dual_connector_fix_modes(struct drm_connector *connector) -{ - struct drm_display_mode *mode, *m; - - /* Only support left-right mode */ - list_for_each_entry_safe(mode, m, &connector->probed_modes, head) { - mode->clock >>= 1; - mode->hdisplay >>= 1; - mode->hsync_start >>= 1; - mode->hsync_end >>= 1; - mode->htotal >>= 1; - drm_mode_set_name(mode); - } -} - -static int dsi_dual_connector_tile_init( - struct drm_connector *connector, int id) -{ - struct drm_display_mode *mode; - /* Fake topology id */ - char topo_id[8] = {'M', 'S', 'M', 'D', 'U', 'D', 'S', 'I'}; - - if (connector->tile_group) { - DBG("Tile property has been initialized"); - return 0; - } - - /* Use the first mode only for now */ - mode = list_first_entry(&connector->probed_modes, - struct drm_display_mode, - head); - if (!mode) - return -EINVAL; - - connector->tile_group = drm_mode_get_tile_group( - connector->dev, topo_id); - if (!connector->tile_group) - connector->tile_group = drm_mode_create_tile_group( - connector->dev, topo_id); - if (!connector->tile_group) { - pr_err("%s: failed to create tile group\n", __func__); - return -ENOMEM; - } - - connector->has_tile = true; - connector->tile_is_single_monitor = true; - - /* mode has been fixed */ - connector->tile_h_size = mode->hdisplay; - connector->tile_v_size = mode->vdisplay; - - /* Only support left-right mode */ - connector->num_h_tile = 2; - connector->num_v_tile = 1; - - connector->tile_v_loc = 0; - connector->tile_h_loc = (id == DSI_RIGHT) ? 1 : 0; - - return 0; -} - static int dsi_mgr_connector_get_modes(struct drm_connector *connector) { int id = dsi_mgr_connector_get_id(connector); struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); struct drm_panel *panel = msm_dsi->panel; - int ret, num; + int num;
if (!panel) return 0;
- /* Since we have 2 connectors, but only 1 drm_panel in dual DSI mode, - * panel should not attach to any connector. - * Only temporarily attach panel to the current connector here, - * to let panel set mode to this connector. + /* + * In dual DSI mode, we have one connector that can be + * attached to the drm_panel. */ drm_panel_attach(panel, connector); num = drm_panel_get_modes(panel); - drm_panel_detach(panel); if (!num) return 0;
- if (IS_DUAL_DSI()) { - /* report half resolution to user */ - dsi_dual_connector_fix_modes(connector); - ret = dsi_dual_connector_tile_init(connector, id); - if (ret) - return ret; - ret = drm_mode_connector_set_tile_property(connector); - if (ret) { - pr_err("%s: set tile property failed, %d\n", - __func__, ret); - return ret; - } - } - return num; }
@@ -455,8 +378,8 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge) if (ret) goto phy_en_fail;
- /* Do nothing with the host if it is DSI 1 in case of dual DSI */ - if (is_dual_dsi && (DSI_1 == id)) + /* Do nothing with the host if it is slave-DSI in case of dual DSI */ + if (is_dual_dsi && !IS_MASTER_DSI_LINK(id)) return;
ret = msm_dsi_host_power_on(host, &phy_shared_timings[id], is_dual_dsi); @@ -557,11 +480,11 @@ static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge) return;
/* - * Do nothing with the host if it is DSI 1 in case of dual DSI. + * Do nothing with the host if it is slave-DSI in case of dual DSI. * It is safe to call dsi_mgr_phy_disable() here because a single PHY * won't be diabled until both PHYs request disable. */ - if (is_dual_dsi && (DSI_1 == id)) + if (is_dual_dsi && !IS_MASTER_DSI_LINK(id)) goto disable_phy;
if (panel) { @@ -622,7 +545,7 @@ static void dsi_mgr_bridge_mode_set(struct drm_bridge *bridge, mode->vsync_end, mode->vtotal, mode->type, mode->flags);
- if (is_dual_dsi && (DSI_1 == id)) + if (is_dual_dsi && !IS_MASTER_DSI_LINK(id)) return;
msm_dsi_host_set_display_mode(host, adjusted_mode); @@ -690,6 +613,23 @@ struct drm_connector *msm_dsi_manager_connector_init(u8 id) return connector; }
+bool msm_dsi_manager_validate_current_config(u8 id) +{ + bool is_dual_dsi = IS_DUAL_DSI(); + + /* + * For dual DSI, we only have one drm panel. For this + * use case, we register only one bridge/connector. + * Skip bridge/connector initialisation if it is + * slave-DSI for dual DSI configuration. + */ + if (is_dual_dsi && !IS_MASTER_DSI_LINK(id)) { + DBG("Skip bridge registration for slave DSI->id: %d\n", id); + return false; + } + return true; +} + /* initialize bridge */ struct drm_bridge *msm_dsi_manager_bridge_init(u8 id) {
From: Rajesh Yadav ryadav@codeaurora.org
postdiv_lock spinlock was used before initialization for 10nm pll. It causes following spin_bug: "BUG: spinlock bad magic on CPU#0". Initialize spinlock before its usage.
Signed-off-by: Rajesh Yadav ryadav@codeaurora.org Signed-off-by: Sean Paul seanpaul@chromium.org --- drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c b/drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c index c4c37a7df637..4c03f0b7343e 100644 --- a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c +++ b/drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c @@ -798,6 +798,8 @@ struct msm_dsi_pll *msm_dsi_pll_10nm_init(struct platform_device *pdev, int id) return ERR_PTR(-ENOMEM); }
+ spin_lock_init(&pll_10nm->postdiv_lock); + pll = &pll_10nm->base; pll->min_rate = 1000000000UL; pll->max_rate = 3500000000UL;
On Monday 09 July 2018 11:01 PM, Sean Paul wrote:
From: Rajesh Yadav ryadav@codeaurora.org
postdiv_lock spinlock was used before initialization for 10nm pll. It causes following spin_bug: "BUG: spinlock bad magic on CPU#0". Initialize spinlock before its usage.
Reviewed-by: Archit Taneja architt@codeaurora.org
Signed-off-by: Rajesh Yadav ryadav@codeaurora.org Signed-off-by: Sean Paul seanpaul@chromium.org
drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c b/drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c index c4c37a7df637..4c03f0b7343e 100644 --- a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c +++ b/drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c @@ -798,6 +798,8 @@ struct msm_dsi_pll *msm_dsi_pll_10nm_init(struct platform_device *pdev, int id) return ERR_PTR(-ENOMEM); }
- spin_lock_init(&pll_10nm->postdiv_lock);
- pll = &pll_10nm->base; pll->min_rate = 1000000000UL; pll->max_rate = 3500000000UL;
DPU doesn't use this, so push it into the mdp drivers.
Signed-off-by: Sean Paul seanpaul@chromium.org Signed-off-by: Rajesh Yadav ryadav@codeaurora.org --- drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c | 2 ++ drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 2 ++ drivers/gpu/drm/msm/msm_atomic.c | 2 -- 3 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c index 4b646bf9c214..44d1cda56974 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c @@ -125,6 +125,8 @@ static void mdp4_complete_commit(struct msm_kms *kms, struct drm_atomic_state *s struct drm_crtc *crtc; struct drm_crtc_state *crtc_state;
+ drm_atomic_helper_wait_for_vblanks(mdp4_kms->dev, state); + /* see 119ecb7fd */ for_each_new_crtc_in_state(state, crtc, crtc_state, i) drm_crtc_vblank_put(crtc); diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c index 6e12e275deba..bddd625ab91b 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c @@ -170,6 +170,8 @@ static void mdp5_complete_commit(struct msm_kms *kms, struct drm_atomic_state *s struct device *dev = &mdp5_kms->pdev->dev; struct mdp5_global_state *global_state;
+ drm_atomic_helper_wait_for_vblanks(mdp5_kms->dev, state); + global_state = mdp5_get_existing_global_state(mdp5_kms);
if (mdp5_kms->smp) diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c index f0635c3da7f4..e6f1e25c60af 100644 --- a/drivers/gpu/drm/msm/msm_atomic.c +++ b/drivers/gpu/drm/msm/msm_atomic.c @@ -75,8 +75,6 @@ void msm_atomic_commit_tail(struct drm_atomic_state *state)
kms->funcs->complete_commit(kms, state);
- drm_atomic_helper_wait_for_vblanks(dev, state); - drm_atomic_helper_commit_hw_done(state);
drm_atomic_helper_cleanup_planes(dev, state);
From: Rajesh Yadav ryadav@codeaurora.org
SoCs having mdp5 or dpu have identical tree like device hierarchy where MDSS top level wrapper manages common power resources for all child devices.
Subclass msm_mdss so that msm_mdss includes common defines and mdp5/dpu mdss derivations to include any extensions.
Add mdss helper interface (msm_mdss_funcs) to msm_mdss base for mdp5/dpu mdss specific implementation calls.
This change subclasses msm_mdss for mdp5, dpu specific changes will be done separately.
Changes in v3: - none
Changes in v2: - fixed indentation for irq_domain_add_linear call (Sean Paul)
Signed-off-by: Rajesh Yadav ryadav@codeaurora.org Reviewed-by: Sean Paul seanpaul@chromium.org [seanpaul rebased on msm-next and resolved conflicts] Signed-off-by: Sean Paul seanpaul@chromium.org --- drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c | 154 ++++++++++++---------- drivers/gpu/drm/msm/msm_drv.c | 22 +++- drivers/gpu/drm/msm/msm_kms.h | 17 ++- 3 files changed, 109 insertions(+), 84 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c index f2a0db7a8a03..1cc4e57f0226 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c @@ -20,12 +20,10 @@ #include "msm_drv.h" #include "mdp5_kms.h"
-/* - * If needed, this can become more specific: something like struct mdp5_mdss, - * which contains a 'struct msm_mdss base' member. - */ -struct msm_mdss { - struct drm_device *dev; +#define to_mdp5_mdss(x) container_of(x, struct mdp5_mdss, base) + +struct mdp5_mdss { + struct msm_mdss base;
void __iomem *mmio, *vbif;
@@ -41,22 +39,22 @@ struct msm_mdss { } irqcontroller; };
-static inline void mdss_write(struct msm_mdss *mdss, u32 reg, u32 data) +static inline void mdss_write(struct mdp5_mdss *mdp5_mdss, u32 reg, u32 data) { - msm_writel(data, mdss->mmio + reg); + msm_writel(data, mdp5_mdss->mmio + reg); }
-static inline u32 mdss_read(struct msm_mdss *mdss, u32 reg) +static inline u32 mdss_read(struct mdp5_mdss *mdp5_mdss, u32 reg) { - return msm_readl(mdss->mmio + reg); + return msm_readl(mdp5_mdss->mmio + reg); }
static irqreturn_t mdss_irq(int irq, void *arg) { - struct msm_mdss *mdss = arg; + struct mdp5_mdss *mdp5_mdss = arg; u32 intr;
- intr = mdss_read(mdss, REG_MDSS_HW_INTR_STATUS); + intr = mdss_read(mdp5_mdss, REG_MDSS_HW_INTR_STATUS);
VERB("intr=%08x", intr);
@@ -64,7 +62,7 @@ static irqreturn_t mdss_irq(int irq, void *arg) irq_hw_number_t hwirq = fls(intr) - 1;
generic_handle_irq(irq_find_mapping( - mdss->irqcontroller.domain, hwirq)); + mdp5_mdss->irqcontroller.domain, hwirq)); intr &= ~(1 << hwirq); }
@@ -84,19 +82,19 @@ static irqreturn_t mdss_irq(int irq, void *arg)
static void mdss_hw_mask_irq(struct irq_data *irqd) { - struct msm_mdss *mdss = irq_data_get_irq_chip_data(irqd); + struct mdp5_mdss *mdp5_mdss = irq_data_get_irq_chip_data(irqd);
smp_mb__before_atomic(); - clear_bit(irqd->hwirq, &mdss->irqcontroller.enabled_mask); + clear_bit(irqd->hwirq, &mdp5_mdss->irqcontroller.enabled_mask); smp_mb__after_atomic(); }
static void mdss_hw_unmask_irq(struct irq_data *irqd) { - struct msm_mdss *mdss = irq_data_get_irq_chip_data(irqd); + struct mdp5_mdss *mdp5_mdss = irq_data_get_irq_chip_data(irqd);
smp_mb__before_atomic(); - set_bit(irqd->hwirq, &mdss->irqcontroller.enabled_mask); + set_bit(irqd->hwirq, &mdp5_mdss->irqcontroller.enabled_mask); smp_mb__after_atomic(); }
@@ -109,13 +107,13 @@ static struct irq_chip mdss_hw_irq_chip = { static int mdss_hw_irqdomain_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hwirq) { - struct msm_mdss *mdss = d->host_data; + struct mdp5_mdss *mdp5_mdss = d->host_data;
if (!(VALID_IRQS & (1 << hwirq))) return -EPERM;
irq_set_chip_and_handler(irq, &mdss_hw_irq_chip, handle_level_irq); - irq_set_chip_data(irq, mdss); + irq_set_chip_data(irq, mdp5_mdss);
return 0; } @@ -126,90 +124,99 @@ static const struct irq_domain_ops mdss_hw_irqdomain_ops = { };
-static int mdss_irq_domain_init(struct msm_mdss *mdss) +static int mdss_irq_domain_init(struct mdp5_mdss *mdp5_mdss) { - struct device *dev = mdss->dev->dev; + struct device *dev = mdp5_mdss->base.dev->dev; struct irq_domain *d;
d = irq_domain_add_linear(dev->of_node, 32, &mdss_hw_irqdomain_ops, - mdss); + mdp5_mdss); if (!d) { dev_err(dev, "mdss irq domain add failed\n"); return -ENXIO; }
- mdss->irqcontroller.enabled_mask = 0; - mdss->irqcontroller.domain = d; + mdp5_mdss->irqcontroller.enabled_mask = 0; + mdp5_mdss->irqcontroller.domain = d;
return 0; }
-int msm_mdss_enable(struct msm_mdss *mdss) +static int mdp5_mdss_enable(struct msm_mdss *mdss) { + struct mdp5_mdss *mdp5_mdss = to_mdp5_mdss(mdss); DBG("");
- clk_prepare_enable(mdss->ahb_clk); - if (mdss->axi_clk) - clk_prepare_enable(mdss->axi_clk); - if (mdss->vsync_clk) - clk_prepare_enable(mdss->vsync_clk); + clk_prepare_enable(mdp5_mdss->ahb_clk); + if (mdp5_mdss->axi_clk) + clk_prepare_enable(mdp5_mdss->axi_clk); + if (mdp5_mdss->vsync_clk) + clk_prepare_enable(mdp5_mdss->vsync_clk);
return 0; }
-int msm_mdss_disable(struct msm_mdss *mdss) +static int mdp5_mdss_disable(struct msm_mdss *mdss) { + struct mdp5_mdss *mdp5_mdss = to_mdp5_mdss(mdss); DBG("");
- if (mdss->vsync_clk) - clk_disable_unprepare(mdss->vsync_clk); - if (mdss->axi_clk) - clk_disable_unprepare(mdss->axi_clk); - clk_disable_unprepare(mdss->ahb_clk); + if (mdp5_mdss->vsync_clk) + clk_disable_unprepare(mdp5_mdss->vsync_clk); + if (mdp5_mdss->axi_clk) + clk_disable_unprepare(mdp5_mdss->axi_clk); + clk_disable_unprepare(mdp5_mdss->ahb_clk);
return 0; }
-static int msm_mdss_get_clocks(struct msm_mdss *mdss) +static int msm_mdss_get_clocks(struct mdp5_mdss *mdp5_mdss) { - struct platform_device *pdev = to_platform_device(mdss->dev->dev); + struct platform_device *pdev = + to_platform_device(mdp5_mdss->base.dev->dev);
- mdss->ahb_clk = msm_clk_get(pdev, "iface"); - if (IS_ERR(mdss->ahb_clk)) - mdss->ahb_clk = NULL; + mdp5_mdss->ahb_clk = msm_clk_get(pdev, "iface"); + if (IS_ERR(mdp5_mdss->ahb_clk)) + mdp5_mdss->ahb_clk = NULL;
- mdss->axi_clk = msm_clk_get(pdev, "bus"); - if (IS_ERR(mdss->axi_clk)) - mdss->axi_clk = NULL; + mdp5_mdss->axi_clk = msm_clk_get(pdev, "bus"); + if (IS_ERR(mdp5_mdss->axi_clk)) + mdp5_mdss->axi_clk = NULL;
- mdss->vsync_clk = msm_clk_get(pdev, "vsync"); - if (IS_ERR(mdss->vsync_clk)) - mdss->vsync_clk = NULL; + mdp5_mdss->vsync_clk = msm_clk_get(pdev, "vsync"); + if (IS_ERR(mdp5_mdss->vsync_clk)) + mdp5_mdss->vsync_clk = NULL;
return 0; }
-void msm_mdss_destroy(struct drm_device *dev) +static void mdp5_mdss_destroy(struct drm_device *dev) { struct msm_drm_private *priv = dev->dev_private; - struct msm_mdss *mdss = priv->mdss; + struct mdp5_mdss *mdp5_mdss = to_mdp5_mdss(priv->mdss);
- if (!mdss) + if (!mdp5_mdss) return;
- irq_domain_remove(mdss->irqcontroller.domain); - mdss->irqcontroller.domain = NULL; + irq_domain_remove(mdp5_mdss->irqcontroller.domain); + mdp5_mdss->irqcontroller.domain = NULL;
- regulator_disable(mdss->vdd); + regulator_disable(mdp5_mdss->vdd);
pm_runtime_disable(dev->dev); }
-int msm_mdss_init(struct drm_device *dev) +static const struct msm_mdss_funcs mdss_funcs = { + .enable = mdp5_mdss_enable, + .disable = mdp5_mdss_disable, + .destroy = mdp5_mdss_destroy, +}; + +int mdp5_mdss_init(struct drm_device *dev) { struct platform_device *pdev = to_platform_device(dev->dev); struct msm_drm_private *priv = dev->dev_private; - struct msm_mdss *mdss; + struct mdp5_mdss *mdp5_mdss; int ret;
DBG(""); @@ -217,40 +224,40 @@ int msm_mdss_init(struct drm_device *dev) if (!of_device_is_compatible(dev->dev->of_node, "qcom,mdss")) return 0;
- mdss = devm_kzalloc(dev->dev, sizeof(*mdss), GFP_KERNEL); - if (!mdss) { + mdp5_mdss = devm_kzalloc(dev->dev, sizeof(*mdp5_mdss), GFP_KERNEL); + if (!mdp5_mdss) { ret = -ENOMEM; goto fail; }
- mdss->dev = dev; + mdp5_mdss->base.dev = dev;
- mdss->mmio = msm_ioremap(pdev, "mdss_phys", "MDSS"); - if (IS_ERR(mdss->mmio)) { - ret = PTR_ERR(mdss->mmio); + mdp5_mdss->mmio = msm_ioremap(pdev, "mdss_phys", "MDSS"); + if (IS_ERR(mdp5_mdss->mmio)) { + ret = PTR_ERR(mdp5_mdss->mmio); goto fail; }
- mdss->vbif = msm_ioremap(pdev, "vbif_phys", "VBIF"); - if (IS_ERR(mdss->vbif)) { - ret = PTR_ERR(mdss->vbif); + mdp5_mdss->vbif = msm_ioremap(pdev, "vbif_phys", "VBIF"); + if (IS_ERR(mdp5_mdss->vbif)) { + ret = PTR_ERR(mdp5_mdss->vbif); goto fail; }
- ret = msm_mdss_get_clocks(mdss); + ret = msm_mdss_get_clocks(mdp5_mdss); if (ret) { dev_err(dev->dev, "failed to get clocks: %d\n", ret); goto fail; }
/* Regulator to enable GDSCs in downstream kernels */ - mdss->vdd = devm_regulator_get(dev->dev, "vdd"); - if (IS_ERR(mdss->vdd)) { - ret = PTR_ERR(mdss->vdd); + mdp5_mdss->vdd = devm_regulator_get(dev->dev, "vdd"); + if (IS_ERR(mdp5_mdss->vdd)) { + ret = PTR_ERR(mdp5_mdss->vdd); goto fail; }
- ret = regulator_enable(mdss->vdd); + ret = regulator_enable(mdp5_mdss->vdd); if (ret) { dev_err(dev->dev, "failed to enable regulator vdd: %d\n", ret); @@ -258,25 +265,26 @@ int msm_mdss_init(struct drm_device *dev) }
ret = devm_request_irq(dev->dev, platform_get_irq(pdev, 0), - mdss_irq, 0, "mdss_isr", mdss); + mdss_irq, 0, "mdss_isr", mdp5_mdss); if (ret) { dev_err(dev->dev, "failed to init irq: %d\n", ret); goto fail_irq; }
- ret = mdss_irq_domain_init(mdss); + ret = mdss_irq_domain_init(mdp5_mdss); if (ret) { dev_err(dev->dev, "failed to init sub-block irqs: %d\n", ret); goto fail_irq; }
- priv->mdss = mdss; + mdp5_mdss->base.funcs = &mdss_funcs; + priv->mdss = &mdp5_mdss->base;
pm_runtime_enable(dev->dev);
return 0; fail_irq: - regulator_disable(mdss->vdd); + regulator_disable(mdp5_mdss->vdd); fail: return ret; } diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 7f7321eb5312..2608d3f77956 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -208,6 +208,7 @@ static int msm_drm_uninit(struct device *dev) struct drm_device *ddev = platform_get_drvdata(pdev); struct msm_drm_private *priv = ddev->dev_private; struct msm_kms *kms = priv->kms; + struct msm_mdss *mdss = priv->mdss; struct msm_vblank_ctrl *vbl_ctrl = &priv->vblank_ctrl; struct vblank_event *vbl_ev, *tmp;
@@ -258,7 +259,8 @@ static int msm_drm_uninit(struct device *dev)
component_unbind_all(dev, ddev);
- msm_mdss_destroy(ddev); + if (mdss && mdss->funcs) + mdss->funcs->destroy(ddev);
ddev->dev_private = NULL; drm_dev_unref(ddev); @@ -357,6 +359,7 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv) struct drm_device *ddev; struct msm_drm_private *priv; struct msm_kms *kms; + struct msm_mdss *mdss; int ret;
ddev = drm_dev_alloc(drv, dev); @@ -376,13 +379,15 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv) ddev->dev_private = priv; priv->dev = ddev;
- ret = msm_mdss_init(ddev); + ret = mdp5_mdss_init(ddev); if (ret) { kfree(priv); drm_dev_unref(ddev); return ret; }
+ mdss = priv->mdss; + priv->wq = alloc_ordered_workqueue("msm", 0); priv->atomic_wq = alloc_ordered_workqueue("msm:atomic", 0);
@@ -396,7 +401,8 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv) /* Bind all our sub-components: */ ret = component_bind_all(dev, ddev); if (ret) { - msm_mdss_destroy(ddev); + if (mdss && mdss->funcs) + mdss->funcs->destroy(ddev); kfree(priv); drm_dev_unref(ddev); return ret; @@ -924,11 +930,12 @@ static int msm_runtime_suspend(struct device *dev) { struct drm_device *ddev = dev_get_drvdata(dev); struct msm_drm_private *priv = ddev->dev_private; + struct msm_mdss *mdss = priv->mdss;
DBG("");
- if (priv->mdss) - return msm_mdss_disable(priv->mdss); + if (mdss && mdss->funcs) + return mdss->funcs->disable(mdss);
return 0; } @@ -937,11 +944,12 @@ static int msm_runtime_resume(struct device *dev) { struct drm_device *ddev = dev_get_drvdata(dev); struct msm_drm_private *priv = ddev->dev_private; + struct msm_mdss *mdss = priv->mdss;
DBG("");
- if (priv->mdss) - return msm_mdss_enable(priv->mdss); + if (mdss && mdss->funcs) + return mdss->funcs->enable(mdss);
return 0; } diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h index dfd92947de2c..76c14221ffdf 100644 --- a/drivers/gpu/drm/msm/msm_kms.h +++ b/drivers/gpu/drm/msm/msm_kms.h @@ -86,9 +86,18 @@ static inline void msm_kms_init(struct msm_kms *kms,
struct msm_kms *mdp4_kms_init(struct drm_device *dev); struct msm_kms *mdp5_kms_init(struct drm_device *dev); -int msm_mdss_init(struct drm_device *dev); -void msm_mdss_destroy(struct drm_device *dev); -int msm_mdss_enable(struct msm_mdss *mdss); -int msm_mdss_disable(struct msm_mdss *mdss); + +struct msm_mdss_funcs { + int (*enable)(struct msm_mdss *mdss); + int (*disable)(struct msm_mdss *mdss); + void (*destroy)(struct drm_device *dev); +}; + +struct msm_mdss { + struct drm_device *dev; + const struct msm_mdss_funcs *funcs; +}; + +int mdp5_mdss_init(struct drm_device *dev);
#endif /* __MSM_KMS_H__ */
On Monday 09 July 2018 11:01 PM, Sean Paul wrote:
From: Rajesh Yadav ryadav@codeaurora.org
SoCs having mdp5 or dpu have identical tree like device hierarchy where MDSS top level wrapper manages common power resources for all child devices.
Subclass msm_mdss so that msm_mdss includes common defines and mdp5/dpu mdss derivations to include any extensions.
Add mdss helper interface (msm_mdss_funcs) to msm_mdss base for mdp5/dpu mdss specific implementation calls.
This change subclasses msm_mdss for mdp5, dpu specific changes will be done separately.
Reviewed-by: Archit Taneja architt@codeaurora.org
Changes in v3:
- none
Changes in v2:
- fixed indentation for irq_domain_add_linear call (Sean Paul)
Signed-off-by: Rajesh Yadav ryadav@codeaurora.org Reviewed-by: Sean Paul seanpaul@chromium.org [seanpaul rebased on msm-next and resolved conflicts] Signed-off-by: Sean Paul seanpaul@chromium.org
drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c | 154 ++++++++++++---------- drivers/gpu/drm/msm/msm_drv.c | 22 +++- drivers/gpu/drm/msm/msm_kms.h | 17 ++- 3 files changed, 109 insertions(+), 84 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c index f2a0db7a8a03..1cc4e57f0226 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c @@ -20,12 +20,10 @@ #include "msm_drv.h" #include "mdp5_kms.h"
-/*
- If needed, this can become more specific: something like struct mdp5_mdss,
- which contains a 'struct msm_mdss base' member.
- */
-struct msm_mdss {
- struct drm_device *dev;
+#define to_mdp5_mdss(x) container_of(x, struct mdp5_mdss, base)
+struct mdp5_mdss {
struct msm_mdss base;
void __iomem *mmio, *vbif;
@@ -41,22 +39,22 @@ struct msm_mdss { } irqcontroller; };
-static inline void mdss_write(struct msm_mdss *mdss, u32 reg, u32 data) +static inline void mdss_write(struct mdp5_mdss *mdp5_mdss, u32 reg, u32 data) {
- msm_writel(data, mdss->mmio + reg);
- msm_writel(data, mdp5_mdss->mmio + reg); }
-static inline u32 mdss_read(struct msm_mdss *mdss, u32 reg) +static inline u32 mdss_read(struct mdp5_mdss *mdp5_mdss, u32 reg) {
- return msm_readl(mdss->mmio + reg);
return msm_readl(mdp5_mdss->mmio + reg); }
static irqreturn_t mdss_irq(int irq, void *arg) {
- struct msm_mdss *mdss = arg;
- struct mdp5_mdss *mdp5_mdss = arg; u32 intr;
- intr = mdss_read(mdss, REG_MDSS_HW_INTR_STATUS);
intr = mdss_read(mdp5_mdss, REG_MDSS_HW_INTR_STATUS);
VERB("intr=%08x", intr);
@@ -64,7 +62,7 @@ static irqreturn_t mdss_irq(int irq, void *arg) irq_hw_number_t hwirq = fls(intr) - 1;
generic_handle_irq(irq_find_mapping(
mdss->irqcontroller.domain, hwirq));
intr &= ~(1 << hwirq); }mdp5_mdss->irqcontroller.domain, hwirq));
@@ -84,19 +82,19 @@ static irqreturn_t mdss_irq(int irq, void *arg)
static void mdss_hw_mask_irq(struct irq_data *irqd) {
- struct msm_mdss *mdss = irq_data_get_irq_chip_data(irqd);
struct mdp5_mdss *mdp5_mdss = irq_data_get_irq_chip_data(irqd);
smp_mb__before_atomic();
- clear_bit(irqd->hwirq, &mdss->irqcontroller.enabled_mask);
clear_bit(irqd->hwirq, &mdp5_mdss->irqcontroller.enabled_mask); smp_mb__after_atomic(); }
static void mdss_hw_unmask_irq(struct irq_data *irqd) {
- struct msm_mdss *mdss = irq_data_get_irq_chip_data(irqd);
struct mdp5_mdss *mdp5_mdss = irq_data_get_irq_chip_data(irqd);
smp_mb__before_atomic();
- set_bit(irqd->hwirq, &mdss->irqcontroller.enabled_mask);
- set_bit(irqd->hwirq, &mdp5_mdss->irqcontroller.enabled_mask); smp_mb__after_atomic(); }
@@ -109,13 +107,13 @@ static struct irq_chip mdss_hw_irq_chip = { static int mdss_hw_irqdomain_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hwirq) {
- struct msm_mdss *mdss = d->host_data;
struct mdp5_mdss *mdp5_mdss = d->host_data;
if (!(VALID_IRQS & (1 << hwirq))) return -EPERM;
irq_set_chip_and_handler(irq, &mdss_hw_irq_chip, handle_level_irq);
- irq_set_chip_data(irq, mdss);
irq_set_chip_data(irq, mdp5_mdss);
return 0; }
@@ -126,90 +124,99 @@ static const struct irq_domain_ops mdss_hw_irqdomain_ops = { };
-static int mdss_irq_domain_init(struct msm_mdss *mdss) +static int mdss_irq_domain_init(struct mdp5_mdss *mdp5_mdss) {
- struct device *dev = mdss->dev->dev;
struct device *dev = mdp5_mdss->base.dev->dev; struct irq_domain *d;
d = irq_domain_add_linear(dev->of_node, 32, &mdss_hw_irqdomain_ops,
mdss);
if (!d) { dev_err(dev, "mdss irq domain add failed\n"); return -ENXIO; }mdp5_mdss);
- mdss->irqcontroller.enabled_mask = 0;
- mdss->irqcontroller.domain = d;
mdp5_mdss->irqcontroller.enabled_mask = 0;
mdp5_mdss->irqcontroller.domain = d;
return 0; }
-int msm_mdss_enable(struct msm_mdss *mdss) +static int mdp5_mdss_enable(struct msm_mdss *mdss) {
- struct mdp5_mdss *mdp5_mdss = to_mdp5_mdss(mdss); DBG("");
- clk_prepare_enable(mdss->ahb_clk);
- if (mdss->axi_clk)
clk_prepare_enable(mdss->axi_clk);
- if (mdss->vsync_clk)
clk_prepare_enable(mdss->vsync_clk);
clk_prepare_enable(mdp5_mdss->ahb_clk);
if (mdp5_mdss->axi_clk)
clk_prepare_enable(mdp5_mdss->axi_clk);
if (mdp5_mdss->vsync_clk)
clk_prepare_enable(mdp5_mdss->vsync_clk);
return 0; }
-int msm_mdss_disable(struct msm_mdss *mdss) +static int mdp5_mdss_disable(struct msm_mdss *mdss) {
- struct mdp5_mdss *mdp5_mdss = to_mdp5_mdss(mdss); DBG("");
- if (mdss->vsync_clk)
clk_disable_unprepare(mdss->vsync_clk);
- if (mdss->axi_clk)
clk_disable_unprepare(mdss->axi_clk);
- clk_disable_unprepare(mdss->ahb_clk);
if (mdp5_mdss->vsync_clk)
clk_disable_unprepare(mdp5_mdss->vsync_clk);
if (mdp5_mdss->axi_clk)
clk_disable_unprepare(mdp5_mdss->axi_clk);
clk_disable_unprepare(mdp5_mdss->ahb_clk);
return 0; }
-static int msm_mdss_get_clocks(struct msm_mdss *mdss) +static int msm_mdss_get_clocks(struct mdp5_mdss *mdp5_mdss) {
- struct platform_device *pdev = to_platform_device(mdss->dev->dev);
- struct platform_device *pdev =
to_platform_device(mdp5_mdss->base.dev->dev);
- mdss->ahb_clk = msm_clk_get(pdev, "iface");
- if (IS_ERR(mdss->ahb_clk))
mdss->ahb_clk = NULL;
- mdp5_mdss->ahb_clk = msm_clk_get(pdev, "iface");
- if (IS_ERR(mdp5_mdss->ahb_clk))
mdp5_mdss->ahb_clk = NULL;
- mdss->axi_clk = msm_clk_get(pdev, "bus");
- if (IS_ERR(mdss->axi_clk))
mdss->axi_clk = NULL;
- mdp5_mdss->axi_clk = msm_clk_get(pdev, "bus");
- if (IS_ERR(mdp5_mdss->axi_clk))
mdp5_mdss->axi_clk = NULL;
- mdss->vsync_clk = msm_clk_get(pdev, "vsync");
- if (IS_ERR(mdss->vsync_clk))
mdss->vsync_clk = NULL;
mdp5_mdss->vsync_clk = msm_clk_get(pdev, "vsync");
if (IS_ERR(mdp5_mdss->vsync_clk))
mdp5_mdss->vsync_clk = NULL;
return 0; }
-void msm_mdss_destroy(struct drm_device *dev) +static void mdp5_mdss_destroy(struct drm_device *dev) { struct msm_drm_private *priv = dev->dev_private;
- struct msm_mdss *mdss = priv->mdss;
- struct mdp5_mdss *mdp5_mdss = to_mdp5_mdss(priv->mdss);
- if (!mdss)
- if (!mdp5_mdss) return;
- irq_domain_remove(mdss->irqcontroller.domain);
- mdss->irqcontroller.domain = NULL;
- irq_domain_remove(mdp5_mdss->irqcontroller.domain);
- mdp5_mdss->irqcontroller.domain = NULL;
- regulator_disable(mdss->vdd);
regulator_disable(mdp5_mdss->vdd);
pm_runtime_disable(dev->dev); }
-int msm_mdss_init(struct drm_device *dev) +static const struct msm_mdss_funcs mdss_funcs = {
- .enable = mdp5_mdss_enable,
- .disable = mdp5_mdss_disable,
- .destroy = mdp5_mdss_destroy,
+};
+int mdp5_mdss_init(struct drm_device *dev) { struct platform_device *pdev = to_platform_device(dev->dev); struct msm_drm_private *priv = dev->dev_private;
- struct msm_mdss *mdss;
struct mdp5_mdss *mdp5_mdss; int ret;
DBG("");
@@ -217,40 +224,40 @@ int msm_mdss_init(struct drm_device *dev) if (!of_device_is_compatible(dev->dev->of_node, "qcom,mdss")) return 0;
- mdss = devm_kzalloc(dev->dev, sizeof(*mdss), GFP_KERNEL);
- if (!mdss) {
- mdp5_mdss = devm_kzalloc(dev->dev, sizeof(*mdp5_mdss), GFP_KERNEL);
- if (!mdp5_mdss) { ret = -ENOMEM; goto fail; }
- mdss->dev = dev;
- mdp5_mdss->base.dev = dev;
- mdss->mmio = msm_ioremap(pdev, "mdss_phys", "MDSS");
- if (IS_ERR(mdss->mmio)) {
ret = PTR_ERR(mdss->mmio);
- mdp5_mdss->mmio = msm_ioremap(pdev, "mdss_phys", "MDSS");
- if (IS_ERR(mdp5_mdss->mmio)) {
goto fail; }ret = PTR_ERR(mdp5_mdss->mmio);
- mdss->vbif = msm_ioremap(pdev, "vbif_phys", "VBIF");
- if (IS_ERR(mdss->vbif)) {
ret = PTR_ERR(mdss->vbif);
- mdp5_mdss->vbif = msm_ioremap(pdev, "vbif_phys", "VBIF");
- if (IS_ERR(mdp5_mdss->vbif)) {
goto fail; }ret = PTR_ERR(mdp5_mdss->vbif);
- ret = msm_mdss_get_clocks(mdss);
ret = msm_mdss_get_clocks(mdp5_mdss); if (ret) { dev_err(dev->dev, "failed to get clocks: %d\n", ret); goto fail; }
/* Regulator to enable GDSCs in downstream kernels */
- mdss->vdd = devm_regulator_get(dev->dev, "vdd");
- if (IS_ERR(mdss->vdd)) {
ret = PTR_ERR(mdss->vdd);
- mdp5_mdss->vdd = devm_regulator_get(dev->dev, "vdd");
- if (IS_ERR(mdp5_mdss->vdd)) {
goto fail; }ret = PTR_ERR(mdp5_mdss->vdd);
- ret = regulator_enable(mdss->vdd);
- ret = regulator_enable(mdp5_mdss->vdd); if (ret) { dev_err(dev->dev, "failed to enable regulator vdd: %d\n", ret);
@@ -258,25 +265,26 @@ int msm_mdss_init(struct drm_device *dev) }
ret = devm_request_irq(dev->dev, platform_get_irq(pdev, 0),
mdss_irq, 0, "mdss_isr", mdss);
if (ret) { dev_err(dev->dev, "failed to init irq: %d\n", ret); goto fail_irq; }mdss_irq, 0, "mdss_isr", mdp5_mdss);
- ret = mdss_irq_domain_init(mdss);
- ret = mdss_irq_domain_init(mdp5_mdss); if (ret) { dev_err(dev->dev, "failed to init sub-block irqs: %d\n", ret); goto fail_irq; }
- priv->mdss = mdss;
mdp5_mdss->base.funcs = &mdss_funcs;
priv->mdss = &mdp5_mdss->base;
pm_runtime_enable(dev->dev);
return 0; fail_irq:
- regulator_disable(mdss->vdd);
- regulator_disable(mdp5_mdss->vdd); fail: return ret; }
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 7f7321eb5312..2608d3f77956 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -208,6 +208,7 @@ static int msm_drm_uninit(struct device *dev) struct drm_device *ddev = platform_get_drvdata(pdev); struct msm_drm_private *priv = ddev->dev_private; struct msm_kms *kms = priv->kms;
- struct msm_mdss *mdss = priv->mdss; struct msm_vblank_ctrl *vbl_ctrl = &priv->vblank_ctrl; struct vblank_event *vbl_ev, *tmp;
@@ -258,7 +259,8 @@ static int msm_drm_uninit(struct device *dev)
component_unbind_all(dev, ddev);
- msm_mdss_destroy(ddev);
if (mdss && mdss->funcs)
mdss->funcs->destroy(ddev);
ddev->dev_private = NULL; drm_dev_unref(ddev);
@@ -357,6 +359,7 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv) struct drm_device *ddev; struct msm_drm_private *priv; struct msm_kms *kms;
struct msm_mdss *mdss; int ret;
ddev = drm_dev_alloc(drv, dev);
@@ -376,13 +379,15 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv) ddev->dev_private = priv; priv->dev = ddev;
- ret = msm_mdss_init(ddev);
ret = mdp5_mdss_init(ddev); if (ret) { kfree(priv); drm_dev_unref(ddev); return ret; }
mdss = priv->mdss;
priv->wq = alloc_ordered_workqueue("msm", 0); priv->atomic_wq = alloc_ordered_workqueue("msm:atomic", 0);
@@ -396,7 +401,8 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv) /* Bind all our sub-components: */ ret = component_bind_all(dev, ddev); if (ret) {
msm_mdss_destroy(ddev);
if (mdss && mdss->funcs)
kfree(priv); drm_dev_unref(ddev); return ret;mdss->funcs->destroy(ddev);
@@ -924,11 +930,12 @@ static int msm_runtime_suspend(struct device *dev) { struct drm_device *ddev = dev_get_drvdata(dev); struct msm_drm_private *priv = ddev->dev_private;
struct msm_mdss *mdss = priv->mdss;
DBG("");
- if (priv->mdss)
return msm_mdss_disable(priv->mdss);
if (mdss && mdss->funcs)
return mdss->funcs->disable(mdss);
return 0; }
@@ -937,11 +944,12 @@ static int msm_runtime_resume(struct device *dev) { struct drm_device *ddev = dev_get_drvdata(dev); struct msm_drm_private *priv = ddev->dev_private;
struct msm_mdss *mdss = priv->mdss;
DBG("");
- if (priv->mdss)
return msm_mdss_enable(priv->mdss);
if (mdss && mdss->funcs)
return mdss->funcs->enable(mdss);
return 0; }
diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h index dfd92947de2c..76c14221ffdf 100644 --- a/drivers/gpu/drm/msm/msm_kms.h +++ b/drivers/gpu/drm/msm/msm_kms.h @@ -86,9 +86,18 @@ static inline void msm_kms_init(struct msm_kms *kms,
struct msm_kms *mdp4_kms_init(struct drm_device *dev); struct msm_kms *mdp5_kms_init(struct drm_device *dev); -int msm_mdss_init(struct drm_device *dev); -void msm_mdss_destroy(struct drm_device *dev); -int msm_mdss_enable(struct msm_mdss *mdss); -int msm_mdss_disable(struct msm_mdss *mdss);
+struct msm_mdss_funcs {
- int (*enable)(struct msm_mdss *mdss);
- int (*disable)(struct msm_mdss *mdss);
- void (*destroy)(struct drm_device *dev);
+};
+struct msm_mdss {
- struct drm_device *dev;
- const struct msm_mdss_funcs *funcs;
+};
+int mdp5_mdss_init(struct drm_device *dev);
#endif /* __MSM_KMS_H__ */
From: Jeykumar Sankaran jsanka@codeaurora.org
Enable drm core zpos normalization for planes.
changes in v2: - none changes in v3: - rebased on https://gitlab.freedesktop.org/seanpaul/ dpu-staging/commit/481d29d31cd629fd216381b53de5695f645465d5
Signed-off-by: Jeykumar Sankaran jsanka@codeaurora.org Reviewed-by: Sean Paul seanpaul@chromium.org Signed-off-by: Sean Paul seanpaul@chromium.org --- drivers/gpu/drm/msm/msm_drv.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 2608d3f77956..9c760cee5156 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -439,6 +439,9 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv) goto fail; }
+ /* Enable normalization of plane zpos */ + ddev->mode_config.normalize_zpos = true; + if (kms) { ret = kms->funcs->hw_init(kms); if (ret) {
From: Abhinav Kumar abhinavk@codeaurora.org
Make the pclk_rate u64 to accommodate higher pixel clock rates.
Changes in v4: - fixed commit message
Signed-off-by: Abhinav Kumar abhinavk@codeaurora.org Signed-off-by: Sean Paul seanpaul@chromium.org --- drivers/gpu/drm/msm/dsi/dsi_host.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index 671039b7b75b..73587e731a23 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -669,7 +669,8 @@ static int dsi_calc_clk_rate(struct msm_dsi_host *msm_host, bool is_dual_dsi) const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd; u8 lanes = msm_host->lanes; u32 bpp = dsi_get_bpp(msm_host->format); - u32 pclk_rate; + u64 pclk_rate; + u64 pclk_bpp;
if (!mode) { pr_err("%s: mode not set\n", __func__); @@ -689,13 +690,15 @@ static int dsi_calc_clk_rate(struct msm_dsi_host *msm_host, bool is_dual_dsi) if (is_dual_dsi) pclk_rate /= 2;
+ pclk_bpp = pclk_rate * bpp; if (lanes > 0) { - msm_host->byte_clk_rate = (pclk_rate * bpp) / (8 * lanes); + do_div(pclk_bpp, (8 * lanes)); } else { pr_err("%s: forcing mdss_dsi lanes to 1\n", __func__); - msm_host->byte_clk_rate = (pclk_rate * bpp) / 8; + do_div(pclk_bpp, 8); } msm_host->pixel_clk_rate = pclk_rate; + msm_host->byte_clk_rate = pclk_bpp;
DBG("pclk=%d, bclk=%d", msm_host->pixel_clk_rate, msm_host->byte_clk_rate);
On Monday 09 July 2018 11:01 PM, Sean Paul wrote:
From: Abhinav Kumar abhinavk@codeaurora.org
Make the pclk_rate u64 to accommodate higher pixel clock rates.
Changes in v4:
- fixed commit message
Signed-off-by: Abhinav Kumar abhinavk@codeaurora.org Signed-off-by: Sean Paul seanpaul@chromium.org
drivers/gpu/drm/msm/dsi/dsi_host.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index 671039b7b75b..73587e731a23 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -669,7 +669,8 @@ static int dsi_calc_clk_rate(struct msm_dsi_host *msm_host, bool is_dual_dsi) const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd; u8 lanes = msm_host->lanes; u32 bpp = dsi_get_bpp(msm_host->format);
- u32 pclk_rate;
- u64 pclk_rate;
- u64 pclk_bpp;
Minor nit, I don't think we need to change pclk_rate to u64. A u32 can hold up to a 2.14 Ghz pixel clock, which we're still quite far away from in real life. u64 for pclk_bpp is right, though.
Thanks, Archit
if (!mode) { pr_err("%s: mode not set\n", __func__); @@ -689,13 +690,15 @@ static int dsi_calc_clk_rate(struct msm_dsi_host *msm_host, bool is_dual_dsi) if (is_dual_dsi) pclk_rate /= 2;
- pclk_bpp = pclk_rate * bpp; if (lanes > 0) {
msm_host->byte_clk_rate = (pclk_rate * bpp) / (8 * lanes);
} else { pr_err("%s: forcing mdss_dsi lanes to 1\n", __func__);do_div(pclk_bpp, (8 * lanes));
msm_host->byte_clk_rate = (pclk_rate * bpp) / 8;
do_div(pclk_bpp, 8);
} msm_host->pixel_clk_rate = pclk_rate;
msm_host->byte_clk_rate = pclk_bpp;
DBG("pclk=%d, bclk=%d", msm_host->pixel_clk_rate, msm_host->byte_clk_rate);
I missed this during the atomic conversion
Signed-off-by: Sean Paul seanpaul@chromium.org --- drivers/gpu/drm/msm/msm_drv.c | 4 ---- drivers/gpu/drm/msm/msm_drv.h | 1 - 2 files changed, 5 deletions(-)
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 9c760cee5156..b73acdd52931 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -244,9 +244,6 @@ static int msm_drm_uninit(struct device *dev) flush_workqueue(priv->wq); destroy_workqueue(priv->wq);
- flush_workqueue(priv->atomic_wq); - destroy_workqueue(priv->atomic_wq); - if (kms && kms->funcs) kms->funcs->destroy(kms);
@@ -389,7 +386,6 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv) mdss = priv->mdss;
priv->wq = alloc_ordered_workqueue("msm", 0); - priv->atomic_wq = alloc_ordered_workqueue("msm:atomic", 0);
INIT_LIST_HEAD(&priv->inactive_list); INIT_LIST_HEAD(&priv->vblank_ctrl.event_list); diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 17cefca1d566..fa0376b0f42b 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -115,7 +115,6 @@ struct msm_drm_private { struct list_head inactive_list;
struct workqueue_struct *wq; - struct workqueue_struct *atomic_wq;
unsigned int num_planes; struct drm_plane *planes[16];
From: Jeykumar Sankaran jsanka@codeaurora.org
Useful for incoming DPU support
Signed-off-by: Jeykumar Sankaran jsanka@codeaurora.org [seanpaul split this from the dpu megapatch] Signed-off-by: Sean Paul seanpaul@chromium.org --- drivers/gpu/drm/msm/msm_drv.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index b73acdd52931..67816543a0d7 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -267,6 +267,9 @@ static int msm_drm_uninit(struct device *dev) return 0; }
+#define KMS_MDP4 4 +#define KMS_MDP5 5 + static int get_mdp_ver(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -411,11 +414,11 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv) msm_gem_shrinker_init(ddev);
switch (get_mdp_ver(pdev)) { - case 4: + case KMS_MDP4: kms = mdp4_kms_init(ddev); priv->kms = kms; break; - case 5: + case KMS_MDP5: kms = mdp5_kms_init(ddev); break; default: @@ -1162,8 +1165,8 @@ static int msm_pdev_remove(struct platform_device *pdev) }
static const struct of_device_id dt_match[] = { - { .compatible = "qcom,mdp4", .data = (void *)4 }, /* MDP4 */ - { .compatible = "qcom,mdss", .data = (void *)5 }, /* MDP5 MDSS */ + { .compatible = "qcom,mdp4", .data = (void *)KMS_MDP4 }, + { .compatible = "qcom,mdss", .data = (void *)KMS_MDP5 }, {} }; MODULE_DEVICE_TABLE(of, dt_match);
From: Jeykumar Sankaran jsanka@codeaurora.org
This simplifies cleanup, to make sure nothing drops out in case of error.
Signed-off-by: Jeykumar Sankaran jsanka@codeaurora.org [seanpaul split out of dpu megapatch and renamed labels] Signed-off-by: Sean Paul seanpaul@chromium.org --- drivers/gpu/drm/msm/msm_drv.c | 44 +++++++++++++++++------------------ 1 file changed, 22 insertions(+), 22 deletions(-)
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 67816543a0d7..8bd9fe831968 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -372,19 +372,16 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)
priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) { - drm_dev_unref(ddev); - return -ENOMEM; + ret = -ENOMEM; + goto err_unref_drm_dev; }
ddev->dev_private = priv; priv->dev = ddev;
ret = mdp5_mdss_init(ddev); - if (ret) { - kfree(priv); - drm_dev_unref(ddev); - return ret; - } + if (ret) + goto err_free_priv;
mdss = priv->mdss;
@@ -399,17 +396,12 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)
/* Bind all our sub-components: */ ret = component_bind_all(dev, ddev); - if (ret) { - if (mdss && mdss->funcs) - mdss->funcs->destroy(ddev); - kfree(priv); - drm_dev_unref(ddev); - return ret; - } + if (ret) + goto err_destroy_mdss;
ret = msm_init_vram(ddev); if (ret) - goto fail; + goto err_msm_uninit;
msm_gem_shrinker_init(ddev);
@@ -435,7 +427,7 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv) */ dev_err(dev, "failed to load kms\n"); ret = PTR_ERR(kms); - goto fail; + goto err_msm_uninit; }
/* Enable normalization of plane zpos */ @@ -445,7 +437,7 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv) ret = kms->funcs->hw_init(kms); if (ret) { dev_err(dev, "kms hw init failed: %d\n", ret); - goto fail; + goto err_msm_uninit; } }
@@ -455,7 +447,7 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv) ret = drm_vblank_init(ddev, priv->num_crtcs); if (ret < 0) { dev_err(dev, "failed to initialize vblank\n"); - goto fail; + goto err_msm_uninit; }
if (kms) { @@ -464,13 +456,13 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv) pm_runtime_put_sync(dev); if (ret < 0) { dev_err(dev, "failed to install IRQ handler\n"); - goto fail; + goto err_msm_uninit; } }
ret = drm_dev_register(ddev, 0); if (ret) - goto fail; + goto err_msm_uninit;
drm_mode_config_reset(ddev);
@@ -481,15 +473,23 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)
ret = msm_debugfs_late_init(ddev); if (ret) - goto fail; + goto err_msm_uninit;
drm_kms_helper_poll_init(ddev);
return 0;
-fail: +err_msm_uninit: msm_drm_uninit(dev); return ret; +err_destroy_mdss: + if (mdss && mdss->funcs) + mdss->funcs->destroy(ddev); +err_free_priv: + kfree(priv); +err_unref_drm_dev: + drm_dev_unref(ddev); + return ret; }
/*
From: Jeykumar Sankaran jsanka@codeaurora.org
dpu uses these elsewhere in the driver (in addition to increasing MAX_PLANES, that'll come later), so pull them out into #define.
Signed-off-by: Jeykumar Sankaran jsanka@codeaurora.org [seanpaul pulled this out of the dpu megapatch] Signed-off-by: Sean Paul seanpaul@chromium.org --- drivers/gpu/drm/msm/msm_drv.h | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index fa0376b0f42b..3b206ae6423f 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -54,6 +54,12 @@ struct msm_fence_context; struct msm_gem_address_space; struct msm_gem_vma;
+#define MAX_CRTCS 8 +#define MAX_PLANES 16 +#define MAX_ENCODERS 8 +#define MAX_BRIDGES 8 +#define MAX_CONNECTORS 8 + struct msm_file_private { rwlock_t queuelock; struct list_head submitqueues; @@ -117,19 +123,19 @@ struct msm_drm_private { struct workqueue_struct *wq;
unsigned int num_planes; - struct drm_plane *planes[16]; + struct drm_plane *planes[MAX_PLANES];
unsigned int num_crtcs; - struct drm_crtc *crtcs[8]; + struct drm_crtc *crtcs[MAX_CRTCS];
unsigned int num_encoders; - struct drm_encoder *encoders[8]; + struct drm_encoder *encoders[MAX_ENCODERS];
unsigned int num_bridges; - struct drm_bridge *bridges[8]; + struct drm_bridge *bridges[MAX_BRIDGES];
unsigned int num_connectors; - struct drm_connector *connectors[8]; + struct drm_connector *connectors[MAX_CONNECTORS];
/* Properties */ struct drm_property *plane_property[PLANE_PROP_MAX_NUM];
From: Jeykumar Sankaran jsanka@codeaurora.org
Called right before wait_for_commit_done() to perform kickoff for active crtcs.
Signed-off-by: Jeykumar Sankaran jsanka@codeaurora.org [seanpaul split this out of the megapatch] Signed-off-by: Sean Paul seanpaul@chromium.org --- drivers/gpu/drm/msm/msm_atomic.c | 5 +++++ drivers/gpu/drm/msm/msm_kms.h | 1 + 2 files changed, 6 insertions(+)
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c index e6f1e25c60af..c1f1779c980f 100644 --- a/drivers/gpu/drm/msm/msm_atomic.c +++ b/drivers/gpu/drm/msm/msm_atomic.c @@ -71,6 +71,11 @@ void msm_atomic_commit_tail(struct drm_atomic_state *state)
drm_atomic_helper_commit_modeset_enables(dev, state);
+ if (kms->funcs->commit) { + DRM_DEBUG_ATOMIC("triggering commit\n"); + kms->funcs->commit(kms, state); + } + msm_atomic_wait_for_commit_done(dev, state);
kms->funcs->complete_commit(kms, state); diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h index 76c14221ffdf..761bb07cd7bf 100644 --- a/drivers/gpu/drm/msm/msm_kms.h +++ b/drivers/gpu/drm/msm/msm_kms.h @@ -42,6 +42,7 @@ struct msm_kms_funcs { void (*disable_vblank)(struct msm_kms *kms, struct drm_crtc *crtc); /* modeset, bracketing atomic_commit(): */ void (*prepare_commit)(struct msm_kms *kms, struct drm_atomic_state *state); + void (*commit)(struct msm_kms *kms, struct drm_atomic_state *state); void (*complete_commit)(struct msm_kms *kms, struct drm_atomic_state *state); /* functions to wait for atomic commit completed on each CRTC */ void (*wait_for_crtc_commit_done)(struct msm_kms *kms,
From: Jeykumar Sankaran jsanka@codeaurora.org
This is needed by the dpu driver
Signed-off-by: Jeykumar Sankaran jsanka@codeaurora.org [seanpaul split from the dpu megapatch] Signed-off-by: Sean Paul seanpaul@chromium.org --- drivers/gpu/drm/msm/msm_drv.c | 9 +++++++++ drivers/gpu/drm/msm/msm_kms.h | 1 + 2 files changed, 10 insertions(+)
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 8bd9fe831968..ed6efebabc38 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -540,6 +540,14 @@ static void context_close(struct msm_file_private *ctx) kfree(ctx); }
+static void msm_preclose(struct drm_device *dev, struct drm_file *file) +{ + struct msm_drm_private *priv = dev->dev_private; + struct msm_kms *kms = priv->kms; + + if (kms && kms->funcs && kms->funcs->preclose) + kms->funcs->preclose(kms, file); +} static void msm_postclose(struct drm_device *dev, struct drm_file *file) { struct msm_drm_private *priv = dev->dev_private; @@ -860,6 +868,7 @@ static struct drm_driver msm_driver = { DRIVER_ATOMIC | DRIVER_MODESET, .open = msm_open, + .preclose = msm_preclose, .postclose = msm_postclose, .lastclose = drm_fb_helper_lastclose, .irq_handler = msm_irq, diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h index 761bb07cd7bf..9cd7223febcf 100644 --- a/drivers/gpu/drm/msm/msm_kms.h +++ b/drivers/gpu/drm/msm/msm_kms.h @@ -58,6 +58,7 @@ struct msm_kms_funcs { struct drm_encoder *encoder, struct drm_encoder *slave_encoder, bool is_cmd_mode); + void (*preclose)(struct msm_kms *kms, struct drm_file *file); void (*set_encoder_mode)(struct msm_kms *kms, struct drm_encoder *encoder, bool cmd_mode);
From: Jeykumar Sankaran jsanka@codeaurora.org
Used by the dpu driver for custom suspend/resume.
Signed-off-by: Jeykumar Sankaran jsanka@codeaurora.org [seanpaul split this out of the megapatch] Signed-off-by: Sean Paul seanpaul@chromium.org --- drivers/gpu/drm/msm/msm_drv.c | 10 ++++++++++ drivers/gpu/drm/msm/msm_kms.h | 3 +++ 2 files changed, 13 insertions(+)
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index ed6efebabc38..cd0959783203 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -912,6 +912,11 @@ static int msm_pm_suspend(struct device *dev) { struct drm_device *ddev = dev_get_drvdata(dev); struct msm_drm_private *priv = ddev->dev_private; + struct msm_kms *kms = priv->kms; + + /* TODO: Use atomic helper suspend/resume */ + if (kms && kms->funcs && kms->funcs->pm_suspend) + return kms->funcs->pm_suspend(dev);
drm_kms_helper_poll_disable(ddev);
@@ -928,6 +933,11 @@ static int msm_pm_resume(struct device *dev) { struct drm_device *ddev = dev_get_drvdata(dev); struct msm_drm_private *priv = ddev->dev_private; + struct msm_kms *kms = priv->kms; + + /* TODO: Use atomic helper suspend/resume */ + if (kms && kms->funcs && kms->funcs->pm_resume) + return kms->funcs->pm_resume(dev);
drm_atomic_helper_resume(ddev, priv->pm_state); drm_kms_helper_poll_enable(ddev); diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h index 9cd7223febcf..36201f43fa31 100644 --- a/drivers/gpu/drm/msm/msm_kms.h +++ b/drivers/gpu/drm/msm/msm_kms.h @@ -62,6 +62,9 @@ struct msm_kms_funcs { void (*set_encoder_mode)(struct msm_kms *kms, struct drm_encoder *encoder, bool cmd_mode); + /* pm suspend/resume hooks */ + int (*pm_suspend)(struct device *dev); + int (*pm_resume)(struct device *dev); /* cleanup: */ void (*destroy)(struct msm_kms *kms); #ifdef CONFIG_DEBUG_FS
From: Jeykumar Sankaran jsanka@codeaurora.org
Adds bindings for Snapdragon 845 display processing unit
Signed-off-by: Jeykumar Sankaran jsanka@codeaurora.org Signed-off-by: Rajesh Yadav ryadav@codeaurora.org Signed-off-by: Sean Paul seanpaul@chromium.org --- .../devicetree/bindings/display/msm/dpu.txt | 128 ++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/msm/dpu.txt
diff --git a/Documentation/devicetree/bindings/display/msm/dpu.txt b/Documentation/devicetree/bindings/display/msm/dpu.txt new file mode 100644 index 000000000000..080fb77624a3 --- /dev/null +++ b/Documentation/devicetree/bindings/display/msm/dpu.txt @@ -0,0 +1,128 @@ +Qualcomm Technologies, Inc. DPU KMS + +Description: + +Device tree bindings for MSM Mobile Display Subsytem(MDSS) that encapsulates +sub-blocks like DPU display controller, DSI and DP interfaces etc. +The DPU display controller is found in SDM845 SoC. + +MDSS: +Required properties: +- compatible: "qcom,dpu-mdss" +- reg: physical base address and length of contoller's registers. +- reg-names: register region names. The following region is required: + * "mdss_phys" +- power-domains: a power domain consumer specifier according to + Documentation/devicetree/bindings/power/power_domain.txt +- clocks: list of phandles for clock device nodes needed by the device. +- clock-names: device clock names, must be in same order as clocks property. + The following clocks are required: + * "iface" + * "bus" + * "core" +- interrupts: interrupt signal from MDSS. +- interrupt-controller: identifies the node as an interrupt controller. +- #interrupt-cells: specifies the number of cells needed to encode an interrupt + source, should be 1. +- iommus: phandle of iommu device node. +- #address-cells: number of address cells for the MDSS children. Should be 1. +- #size-cells: Should be 1. +- ranges: parent bus address space is the same as the child bus address space. + +Optional properties: +- clock-frequency: list of clock frequencies sorted in the same order as the + clocks property. + +MDP: +Required properties: +- compatible: "qcom,dpu" +- reg: physical base address and length of controller's registers. +- reg-names : register region names. The following region is required: + * "mdp_phys" + * "vbif_phys" +- clocks: list of phandles for clock device nodes needed by the device. +- clock-names: device clock names, must be in same order as clocks property. + The following clocks are required. + * "bus" + * "iface" + * "core" + * "vsync" +- interrupt-parent: phandle to MDSS block. +- interrupts: interrupt line from DPU to MDSS. +- ports: contains the list of output ports from DPU device. These ports connect + to interfaces that are external to the DPU hardware, such as DSI, DP etc. + + Each output port contains an endpoint that describes how it is connected to an + external interface. These are described by the standard properties documented + here: + Documentation/devicetree/bindings/graph.txt + Documentation/devicetree/bindings/media/video-interfaces.txt + + Port 0 -> DPU_INTF1 (DSI1) + Port 1 -> DPU_INTF2 (DSI2) + +Optional properties: +- clock-frequency: list of clock frequencies sorted in the same order as the + clocks property. + +Example: + + mdss: mdss@ae00000 { + compatible = "qcom,dpu-mdss"; + reg = <0xae00000 0x1000>; + reg-names = "mdss_phys"; + + power-domains = <&clock_dispcc 0>; + + clocks = <&gcc GCC_DISP_AHB_CLK>, + <&gcc GCC_DISP_AXI_CLK>, + <&clock_dispcc DISP_CC_MDSS_MDP_CLK>; + clock-names = "iface", "bus", "core"; + clock-frequency = <0 0 300000000>; + + interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>; + interrupt-controller; + #interrupt-cells = <1>; + + iommus = <&apps_iommu 0>; + + #address-cells = <1>; + #size-cells = <1>; + ranges; + + mdss_mdp: mdp@ae01000 { + compatible = "qcom,dpu"; + reg = <0x0ae01000 0x8f000>, + <0x0aeb0000 0x2008>; + reg-names = "mdp_phys", "vbif_phys"; + + clocks = <&clock_dispcc DISP_CC_MDSS_AHB_CLK>, + <&clock_dispcc DISP_CC_MDSS_AXI_CLK>, + <&clock_dispcc DISP_CC_MDSS_MDP_CLK>, + <&clock_dispcc DISP_CC_MDSS_VSYNC_CLK>; + clock-names = "iface", "bus", "core", "vsync"; + clock-frequency = <0 0 300000000 19200000>; + + interrupt-parent = <&mdss>; + interrupts = <0 IRQ_TYPE_LEVEL_HIGH>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dpu_intf1_out: endpoint { + remote-endpoint = <&dsi0_in>; + }; + }; + + port@1 { + reg = <1>; + dpu_intf2_out: endpoint { + remote-endpoint = <&dsi1_in>; + }; + }; + }; + }; + };
From: Jeykumar Sankaran jsanka@codeaurora.org
Adds bindings for Snapdragon 845 display processing unit
Changes in v2: - Use SoC specific compatibles for mdss and dpu - Use assigned-clocks to set initial clock frequency
Signed-off-by: Jeykumar Sankaran jsanka@codeaurora.org Signed-off-by: Rajesh Yadav ryadav@codeaurora.org Signed-off-by: Sean Paul seanpaul@chromium.org --- .../devicetree/bindings/display/msm/dpu.txt | 136 ++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/msm/dpu.txt
diff --git a/Documentation/devicetree/bindings/display/msm/dpu.txt b/Documentation/devicetree/bindings/display/msm/dpu.txt new file mode 100644 index 000000000000..a998028896ba --- /dev/null +++ b/Documentation/devicetree/bindings/display/msm/dpu.txt @@ -0,0 +1,136 @@ +Qualcomm Technologies, Inc. DPU KMS + +Description: + +Device tree bindings for MSM Mobile Display Subsytem(MDSS) that encapsulates +sub-blocks like DPU display controller, DSI and DP interfaces etc. +The DPU display controller is found in SDM845 SoC. + +MDSS: +Required properties: +- compatible: "qcom,sdm845-mdss" +- reg: physical base address and length of contoller's registers. +- reg-names: register region names. The following region is required: + * "mdss_phys" +- power-domains: a power domain consumer specifier according to + Documentation/devicetree/bindings/power/power_domain.txt +- clocks: list of phandles for clock device nodes needed by the device. +- clock-names: device clock names, must be in same order as clocks property. + The following clocks are required: + * "iface" + * "bus" + * "core" +- interrupts: interrupt signal from MDSS. +- interrupt-controller: identifies the node as an interrupt controller. +- #interrupt-cells: specifies the number of cells needed to encode an interrupt + source, should be 1. +- iommus: phandle of iommu device node. +- #address-cells: number of address cells for the MDSS children. Should be 1. +- #size-cells: Should be 1. +- ranges: parent bus address space is the same as the child bus address space. + +Optional properties: +- assigned-clocks: list of phandles for clock device nodes needing rate + assignment +- assigned-clock-rates: list of clock frequencies sorted in the same order as + the assigned-clocks property. + +MDP: +Required properties: +- compatible: "qcom,sdm845-dpu" +- reg: physical base address and length of controller's registers. +- reg-names : register region names. The following region is required: + * "mdp_phys" + * "vbif_phys" +- clocks: list of phandles for clock device nodes needed by the device. +- clock-names: device clock names, must be in same order as clocks property. + The following clocks are required. + * "bus" + * "iface" + * "core" + * "vsync" +- interrupt-parent: phandle to MDSS block. +- interrupts: interrupt line from DPU to MDSS. +- ports: contains the list of output ports from DPU device. These ports connect + to interfaces that are external to the DPU hardware, such as DSI, DP etc. + + Each output port contains an endpoint that describes how it is connected to an + external interface. These are described by the standard properties documented + here: + Documentation/devicetree/bindings/graph.txt + Documentation/devicetree/bindings/media/video-interfaces.txt + + Port 0 -> DPU_INTF1 (DSI1) + Port 1 -> DPU_INTF2 (DSI2) + +Optional properties: +- assigned-clocks: list of phandles for clock device nodes needing rate + assignment +- assigned-clock-rates: list of clock frequencies sorted in the same order as + the assigned-clocks property. + +Example: + + mdss: mdss@ae00000 { + compatible = "qcom,sdm845-mdss"; + reg = <0xae00000 0x1000>; + reg-names = "mdss_phys"; + + power-domains = <&clock_dispcc 0>; + + clocks = <&gcc GCC_DISP_AHB_CLK>, <&gcc GCC_DISP_AXI_CLK>, + <&clock_dispcc DISP_CC_MDSS_MDP_CLK>; + clock-names = "iface", "bus", "core"; + + assigned-clocks = <&clock_dispcc DISP_CC_MDSS_MDP_CLK>; + assigned-clock-rates = <300000000>; + + interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>; + interrupt-controller; + #interrupt-cells = <1>; + + iommus = <&apps_iommu 0>; + + #address-cells = <1>; + #size-cells = <1>; + ranges; + + mdss_mdp: mdp@ae01000 { + compatible = "qcom,sdm845-dpu"; + reg = <0x0ae01000 0x8f000>, + <0x0aeb0000 0x2008>; + reg-names = "mdp_phys", "vbif_phys"; + + clocks = <&clock_dispcc DISP_CC_MDSS_AHB_CLK>, + <&clock_dispcc DISP_CC_MDSS_AXI_CLK>, + <&clock_dispcc DISP_CC_MDSS_MDP_CLK>, + <&clock_dispcc DISP_CC_MDSS_VSYNC_CLK>; + clock-names = "iface", "bus", "core", "vsync"; + + assigned-clocks = <&clock_dispcc DISP_CC_MDSS_MDP_CLK>, + <&clock_dispcc DISP_CC_MDSS_VSYNC_CLK>; + assigned-clock-rates = <0 0 300000000 19200000>; + + interrupt-parent = <&mdss>; + interrupts = <0 IRQ_TYPE_LEVEL_HIGH>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dpu_intf1_out: endpoint { + remote-endpoint = <&dsi0_in>; + }; + }; + + port@1 { + reg = <1>; + dpu_intf2_out: endpoint { + remote-endpoint = <&dsi1_in>; + }; + }; + }; + }; + };
On Thu, Jul 12, 2018 at 05:08:37PM -0400, Sean Paul wrote:
From: Jeykumar Sankaran jsanka@codeaurora.org
Adds bindings for Snapdragon 845 display processing unit
Changes in v2:
- Use SoC specific compatibles for mdss and dpu
- Use assigned-clocks to set initial clock frequency
Signed-off-by: Jeykumar Sankaran jsanka@codeaurora.org Signed-off-by: Rajesh Yadav ryadav@codeaurora.org Signed-off-by: Sean Paul seanpaul@chromium.org
.../devicetree/bindings/display/msm/dpu.txt | 136 ++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/msm/dpu.txt
diff --git a/Documentation/devicetree/bindings/display/msm/dpu.txt b/Documentation/devicetree/bindings/display/msm/dpu.txt new file mode 100644 index 000000000000..a998028896ba --- /dev/null +++ b/Documentation/devicetree/bindings/display/msm/dpu.txt @@ -0,0 +1,136 @@ +Qualcomm Technologies, Inc. DPU KMS
+Description:
+Device tree bindings for MSM Mobile Display Subsytem(MDSS) that encapsulates +sub-blocks like DPU display controller, DSI and DP interfaces etc. +The DPU display controller is found in SDM845 SoC.
+MDSS: +Required properties: +- compatible: "qcom,sdm845-mdss" +- reg: physical base address and length of contoller's registers. +- reg-names: register region names. The following region is required:
- "mdss_phys"
phys as in physical address? If so, that's always the case. *-names is pointless when there is only one anyways.
+- power-domains: a power domain consumer specifier according to
- Documentation/devicetree/bindings/power/power_domain.txt
+- clocks: list of phandles for clock device nodes needed by the device. +- clock-names: device clock names, must be in same order as clocks property.
- The following clocks are required:
- "iface"
- "bus"
- "core"
+- interrupts: interrupt signal from MDSS. +- interrupt-controller: identifies the node as an interrupt controller. +- #interrupt-cells: specifies the number of cells needed to encode an interrupt
- source, should be 1.
+- iommus: phandle of iommu device node. +- #address-cells: number of address cells for the MDSS children. Should be 1. +- #size-cells: Should be 1. +- ranges: parent bus address space is the same as the child bus address space.
+Optional properties: +- assigned-clocks: list of phandles for clock device nodes needing rate
It's a list of clock specifiers (phandle and id), not device nodes.
assignment
+- assigned-clock-rates: list of clock frequencies sorted in the same order as
- the assigned-clocks property.
+MDP: +Required properties: +- compatible: "qcom,sdm845-dpu" +- reg: physical base address and length of controller's registers. +- reg-names : register region names. The following region is required:
- "mdp_phys"
- "vbif_phys"
Same comment on "_phys" here.
+- clocks: list of phandles for clock device nodes needed by the device. +- clock-names: device clock names, must be in same order as clocks property.
- The following clocks are required.
- "bus"
- "iface"
- "core"
- "vsync"
+- interrupt-parent: phandle to MDSS block.
Actually, you don't need this if a parent node contains "interrupt-controller" property.
+- interrupts: interrupt line from DPU to MDSS. +- ports: contains the list of output ports from DPU device. These ports connect
- to interfaces that are external to the DPU hardware, such as DSI, DP etc.
- Each output port contains an endpoint that describes how it is connected to an
- external interface. These are described by the standard properties documented
- here:
- Documentation/devicetree/bindings/graph.txt
- Documentation/devicetree/bindings/media/video-interfaces.txt
- Port 0 -> DPU_INTF1 (DSI1)
- Port 1 -> DPU_INTF2 (DSI2)
+Optional properties: +- assigned-clocks: list of phandles for clock device nodes needing rate
assignment
+- assigned-clock-rates: list of clock frequencies sorted in the same order as
- the assigned-clocks property.
+Example:
- mdss: mdss@ae00000 {
compatible = "qcom,sdm845-mdss";
reg = <0xae00000 0x1000>;
reg-names = "mdss_phys";
power-domains = <&clock_dispcc 0>;
clocks = <&gcc GCC_DISP_AHB_CLK>, <&gcc GCC_DISP_AXI_CLK>,
<&clock_dispcc DISP_CC_MDSS_MDP_CLK>;
clock-names = "iface", "bus", "core";
assigned-clocks = <&clock_dispcc DISP_CC_MDSS_MDP_CLK>;
assigned-clock-rates = <300000000>;
interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
interrupt-controller;
#interrupt-cells = <1>;
iommus = <&apps_iommu 0>;
#address-cells = <1>;
#size-cells = <1>;
ranges;
It's preferred to put actual values in and limit the range of child nodes. Is there anything in 0xae90000-0xaeaffff?
mdss_mdp: mdp@ae01000 {
compatible = "qcom,sdm845-dpu";
reg = <0x0ae01000 0x8f000>,
<0x0aeb0000 0x2008>;
reg-names = "mdp_phys", "vbif_phys";
clocks = <&clock_dispcc DISP_CC_MDSS_AHB_CLK>,
<&clock_dispcc DISP_CC_MDSS_AXI_CLK>,
<&clock_dispcc DISP_CC_MDSS_MDP_CLK>,
<&clock_dispcc DISP_CC_MDSS_VSYNC_CLK>;
clock-names = "iface", "bus", "core", "vsync";
assigned-clocks = <&clock_dispcc DISP_CC_MDSS_MDP_CLK>,
<&clock_dispcc DISP_CC_MDSS_VSYNC_CLK>;
assigned-clock-rates = <0 0 300000000 19200000>;
interrupt-parent = <&mdss>;
interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
dpu_intf1_out: endpoint {
remote-endpoint = <&dsi0_in>;
};
};
port@1 {
reg = <1>;
dpu_intf2_out: endpoint {
remote-endpoint = <&dsi1_in>;
};
};
};
};
- };
-- Sean Paul, Software Engineer, Google / Chromium OS
Signed-off-by: Sean Paul seanpaul@chromium.org --- arch/arm64/boot/dts/qcom/sdm845.dtsi | 194 +++++++++++++++++++++++++++ 1 file changed, 194 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi index cdaabeb3c995..339afed856de 100644 --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi @@ -5,6 +5,8 @@ * Copyright (c) 2018, The Linux Foundation. All rights reserved. */
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h> +#include <dt-bindings/clock/qcom,gcc-sdm845.h> #include <dt-bindings/interrupt-controller/arm-gic.h>
/ { @@ -221,6 +223,198 @@ #interrupt-cells = <2>; };
+ mdss: mdss@ae00000 { + compatible = "qcom,dpu-mdss"; + reg = <0xae00000 0x1000>; + reg-names = "mdss_phys"; + + power-domains = <&dispcc 0>; + + clocks = <&gcc GCC_DISP_AHB_CLK>, + <&gcc GCC_DISP_AXI_CLK>, + <&dispcc DISP_CC_MDSS_MDP_CLK>; + clock-names = "iface", "bus", "core"; + clock-frequency = <0 0 300000000>; + + interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>; + interrupt-controller; + #interrupt-cells = <1>; + + /* iommus = <&apps_iommu 0>; */ + + #address-cells = <1>; + #size-cells = <1>; + ranges; + + mdss_mdp: mdp@ae01000 { + compatible = "qcom,dpu"; + reg = <0x0ae01000 0x8f000>, + <0x0aeb0000 0x2008>; + reg-names = "mdp_phys", "vbif_phys"; + + clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&dispcc DISP_CC_MDSS_AXI_CLK>, + <&dispcc DISP_CC_MDSS_MDP_CLK>, + <&dispcc DISP_CC_MDSS_VSYNC_CLK>; + clock-names = "iface", "bus", "core", "vsync"; + clock-frequency = <0 0 300000000 19200000>; + + interrupt-parent = <&mdss>; + interrupts = <0 IRQ_TYPE_LEVEL_HIGH>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dpu_intf1_out: endpoint { + remote-endpoint = <&dsi0_in>; + }; + }; + + port@1 { + reg = <1>; + dpu_intf2_out: endpoint { + remote-endpoint = <&dsi1_in>; + }; + }; + }; + }; + + dsi0: dsi@ae94000 { + compatible = "qcom,mdss-dsi-ctrl"; + reg = <0xae94000 0x400>; + reg-names = "dsi_ctrl"; + + interrupt-parent = <&mdss>; + interrupts = <4 0>; + + clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK>, + <&dispcc DISP_CC_MDSS_BYTE0_INTF_CLK>, + <&dispcc DISP_CC_MDSS_PCLK0_CLK>, + <&dispcc DISP_CC_MDSS_ESC0_CLK>, + <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&dispcc DISP_CC_MDSS_AXI_CLK>; + clock-names = "byte_clk", + "byte_intf_clk", + "pixel_clk", + "core_clk", + "iface_clk", + "bus_clk"; + + phys = <&dsi0_phy>; + phy-names = "dsi-phy"; + + #address-cells = <1>; + #size-cells = <0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dsi0_in: endpoint { + remote-endpoint = <&dpu_intf1_out>; + }; + }; + + port@1 { + reg = <1>; + dsi0_out: endpoint { + }; + }; + }; + }; + + dsi0_phy: dsi-phy@ae94400 { + compatible = "qcom,dsi-phy-10nm"; + reg = <0xae94400 0x200>, + <0xae94a00 0x1e0>, + <0xae94600 0x280>; + reg-names = "dsi_phy", + "dsi_pll", + "dsi_phy_lane"; + + #clock-cells = <1>; + #phy-cells = <0>; + + clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>; + clock-names = "iface_clk"; + }; + + dsi1: dsi@ae96000 { + compatible = "qcom,mdss-dsi-ctrl"; + reg = <0xae96000 0x400>; + reg-names = "dsi_ctrl"; + + interrupt-parent = <&mdss>; + interrupts = <5 0>; + + clocks = <&dispcc DISP_CC_MDSS_BYTE1_CLK>, + <&dispcc DISP_CC_MDSS_BYTE1_INTF_CLK>, + <&dispcc DISP_CC_MDSS_PCLK1_CLK>, + <&dispcc DISP_CC_MDSS_ESC1_CLK>, + <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&dispcc DISP_CC_MDSS_AXI_CLK>; + clock-names = "byte_clk", + "byte_intf_clk", + "pixel_clk", + "core_clk", + "iface_clk", + "bus_clk"; + + phys = <&dsi1_phy>; + phy-names = "dsi-phy"; + + #address-cells = <1>; + #size-cells = <0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dsi1_in: endpoint { + remote-endpoint = <&dpu_intf2_out>; + }; + }; + + port@1 { + reg = <1>; + dsi1_out: endpoint { + }; + }; + }; + }; + + dsi1_phy: dsi-phy@ae96400 { + compatible = "qcom,dsi-phy-10nm"; + reg = <0xae96400 0x200>, + <0xae96a00 0x10e>, + <0xae96600 0x280>; + reg-names = "dsi_phy", + "dsi_pll", + "dsi_phy_lane"; + + #clock-cells = <1>; + #phy-cells = <0>; + + clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>; + clock-names = "iface_clk"; + }; + }; + + dispcc: qcom,dispcc@af00000 { + compatible = "qcom,sdm845-dispcc"; + reg = <0xaf00000 0x10000>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; + spmi_bus: spmi@c440000 { compatible = "qcom,spmi-pmic-arb"; reg = <0xc440000 0x1100>,
On Mon, Jul 9, 2018 at 11:40 AM Sean Paul seanpaul@chromium.org wrote:
Signed-off-by: Sean Paul seanpaul@chromium.org
arch/arm64/boot/dts/qcom/sdm845.dtsi | 194 +++++++++++++++++++++++++++ 1 file changed, 194 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi index cdaabeb3c995..339afed856de 100644 --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi @@ -5,6 +5,8 @@
- Copyright (c) 2018, The Linux Foundation. All rights reserved.
*/
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h> +#include <dt-bindings/clock/qcom,gcc-sdm845.h> #include <dt-bindings/interrupt-controller/arm-gic.h>
/ { @@ -221,6 +223,198 @@ #interrupt-cells = <2>; };
mdss: mdss@ae00000 {
compatible = "qcom,dpu-mdss";
reg = <0xae00000 0x1000>;
reg-names = "mdss_phys";
power-domains = <&dispcc 0>;
clocks = <&gcc GCC_DISP_AHB_CLK>,
<&gcc GCC_DISP_AXI_CLK>,
<&dispcc DISP_CC_MDSS_MDP_CLK>;
clock-names = "iface", "bus", "core";
clock-frequency = <0 0 300000000>;
interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
interrupt-controller;
#interrupt-cells = <1>;
/* iommus = <&apps_iommu 0>; */
#address-cells = <1>;
#size-cells = <1>;
ranges;
mdss_mdp: mdp@ae01000 {
compatible = "qcom,dpu";
Needs an SoC specific compatible. Did this binding get reviewed?
reg = <0x0ae01000 0x8f000>,
<0x0aeb0000 0x2008>;
reg-names = "mdp_phys", "vbif_phys";
clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
<&dispcc DISP_CC_MDSS_AXI_CLK>,
<&dispcc DISP_CC_MDSS_MDP_CLK>,
<&dispcc DISP_CC_MDSS_VSYNC_CLK>;
clock-names = "iface", "bus", "core", "vsync";
clock-frequency = <0 0 300000000 19200000>;
That's abusing clock-frequency which is generally 1 value. Use assigned-clock-rates instead.
interrupt-parent = <&mdss>;
interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
dpu_intf1_out: endpoint {
remote-endpoint = <&dsi0_in>;
};
};
port@1 {
reg = <1>;
dpu_intf2_out: endpoint {
remote-endpoint = <&dsi1_in>;
};
};
};
};
dsi0: dsi@ae94000 {
compatible = "qcom,mdss-dsi-ctrl";
Needs an SoC specific compatible.
reg = <0xae94000 0x400>;
reg-names = "dsi_ctrl";
interrupt-parent = <&mdss>;
interrupts = <4 0>;
clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK>,
<&dispcc DISP_CC_MDSS_BYTE0_INTF_CLK>,
<&dispcc DISP_CC_MDSS_PCLK0_CLK>,
<&dispcc DISP_CC_MDSS_ESC0_CLK>,
<&dispcc DISP_CC_MDSS_AHB_CLK>,
<&dispcc DISP_CC_MDSS_AXI_CLK>;
clock-names = "byte_clk",
"byte_intf_clk",
"pixel_clk",
"core_clk",
"iface_clk",
"bus_clk";
Should have found this in binding review, but the "_clk" part is redundant.
phys = <&dsi0_phy>;
phy-names = "dsi-phy";
#address-cells = <1>;
#size-cells = <0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
dsi0_in: endpoint {
remote-endpoint = <&dpu_intf1_out>;
};
};
port@1 {
reg = <1>;
dsi0_out: endpoint {
};
};
};
};
dsi0_phy: dsi-phy@ae94400 {
compatible = "qcom,dsi-phy-10nm";
reg = <0xae94400 0x200>,
<0xae94a00 0x1e0>,
<0xae94600 0x280>;
reg-names = "dsi_phy",
"dsi_pll",
"dsi_phy_lane";
#clock-cells = <1>;
#phy-cells = <0>;
clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>;
clock-names = "iface_clk";
};
dsi1: dsi@ae96000 {
compatible = "qcom,mdss-dsi-ctrl";
reg = <0xae96000 0x400>;
reg-names = "dsi_ctrl";
interrupt-parent = <&mdss>;
interrupts = <5 0>;
clocks = <&dispcc DISP_CC_MDSS_BYTE1_CLK>,
<&dispcc DISP_CC_MDSS_BYTE1_INTF_CLK>,
<&dispcc DISP_CC_MDSS_PCLK1_CLK>,
<&dispcc DISP_CC_MDSS_ESC1_CLK>,
<&dispcc DISP_CC_MDSS_AHB_CLK>,
<&dispcc DISP_CC_MDSS_AXI_CLK>;
clock-names = "byte_clk",
"byte_intf_clk",
"pixel_clk",
"core_clk",
"iface_clk",
"bus_clk";
phys = <&dsi1_phy>;
phy-names = "dsi-phy";
#address-cells = <1>;
#size-cells = <0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
dsi1_in: endpoint {
remote-endpoint = <&dpu_intf2_out>;
};
};
port@1 {
reg = <1>;
dsi1_out: endpoint {
};
};
};
};
dsi1_phy: dsi-phy@ae96400 {
compatible = "qcom,dsi-phy-10nm";
reg = <0xae96400 0x200>,
<0xae96a00 0x10e>,
<0xae96600 0x280>;
reg-names = "dsi_phy",
"dsi_pll",
"dsi_phy_lane";
#clock-cells = <1>;
#phy-cells = <0>;
clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>;
clock-names = "iface_clk";
};
};
dispcc: qcom,dispcc@af00000 {
compatible = "qcom,sdm845-dispcc";
reg = <0xaf00000 0x10000>;
#clock-cells = <1>;
#reset-cells = <1>;
#power-domain-cells = <1>;
};
spmi_bus: spmi@c440000 { compatible = "qcom,spmi-pmic-arb"; reg = <0xc440000 0x1100>,
-- Sean Paul, Software Engineer, Google / Chromium OS
On Mon, Jul 09, 2018 at 12:07:11PM -0600, Rob Herring wrote:
On Mon, Jul 9, 2018 at 11:40 AM Sean Paul seanpaul@chromium.org wrote:
Signed-off-by: Sean Paul seanpaul@chromium.org
arch/arm64/boot/dts/qcom/sdm845.dtsi | 194 +++++++++++++++++++++++++++ 1 file changed, 194 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi index cdaabeb3c995..339afed856de 100644 --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi @@ -5,6 +5,8 @@
- Copyright (c) 2018, The Linux Foundation. All rights reserved.
*/
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h> +#include <dt-bindings/clock/qcom,gcc-sdm845.h> #include <dt-bindings/interrupt-controller/arm-gic.h>
/ { @@ -221,6 +223,198 @@ #interrupt-cells = <2>; };
mdss: mdss@ae00000 {
compatible = "qcom,dpu-mdss";
reg = <0xae00000 0x1000>;
reg-names = "mdss_phys";
power-domains = <&dispcc 0>;
clocks = <&gcc GCC_DISP_AHB_CLK>,
<&gcc GCC_DISP_AXI_CLK>,
<&dispcc DISP_CC_MDSS_MDP_CLK>;
clock-names = "iface", "bus", "core";
clock-frequency = <0 0 300000000>;
interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
interrupt-controller;
#interrupt-cells = <1>;
/* iommus = <&apps_iommu 0>; */
#address-cells = <1>;
#size-cells = <1>;
ranges;
mdss_mdp: mdp@ae01000 {
compatible = "qcom,dpu";
Hi Rob, Thanks for the quick turnaround! In addition to below, I'll also beef up the commit message, since I forgot to add any description of the change.
Needs an SoC specific compatible. Did this binding get reviewed?
No, it's part of this set ([PATCH 19/21] dt-bindings: msm/disp: Add bindings for Snapdragon 845 DPU).
reg = <0x0ae01000 0x8f000>,
<0x0aeb0000 0x2008>;
reg-names = "mdp_phys", "vbif_phys";
clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
<&dispcc DISP_CC_MDSS_AXI_CLK>,
<&dispcc DISP_CC_MDSS_MDP_CLK>,
<&dispcc DISP_CC_MDSS_VSYNC_CLK>;
clock-names = "iface", "bus", "core", "vsync";
clock-frequency = <0 0 300000000 19200000>;
That's abusing clock-frequency which is generally 1 value. Use assigned-clock-rates instead.
Thanks, will change.
interrupt-parent = <&mdss>;
interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
dpu_intf1_out: endpoint {
remote-endpoint = <&dsi0_in>;
};
};
port@1 {
reg = <1>;
dpu_intf2_out: endpoint {
remote-endpoint = <&dsi1_in>;
};
};
};
};
dsi0: dsi@ae94000 {
compatible = "qcom,mdss-dsi-ctrl";
Needs an SoC specific compatible.
Ok, will add.
reg = <0xae94000 0x400>;
reg-names = "dsi_ctrl";
interrupt-parent = <&mdss>;
interrupts = <4 0>;
clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK>,
<&dispcc DISP_CC_MDSS_BYTE0_INTF_CLK>,
<&dispcc DISP_CC_MDSS_PCLK0_CLK>,
<&dispcc DISP_CC_MDSS_ESC0_CLK>,
<&dispcc DISP_CC_MDSS_AHB_CLK>,
<&dispcc DISP_CC_MDSS_AXI_CLK>;
clock-names = "byte_clk",
"byte_intf_clk",
"pixel_clk",
"core_clk",
"iface_clk",
"bus_clk";
Should have found this in binding review, but the "_clk" part is redundant.
This binding is already in mainline (Documentation/devicetree/bindings/display/msm/dsi.txt), which is why _clk is here, but not above.
Sean
phys = <&dsi0_phy>;
phy-names = "dsi-phy";
#address-cells = <1>;
#size-cells = <0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
dsi0_in: endpoint {
remote-endpoint = <&dpu_intf1_out>;
};
};
port@1 {
reg = <1>;
dsi0_out: endpoint {
};
};
};
};
dsi0_phy: dsi-phy@ae94400 {
compatible = "qcom,dsi-phy-10nm";
reg = <0xae94400 0x200>,
<0xae94a00 0x1e0>,
<0xae94600 0x280>;
reg-names = "dsi_phy",
"dsi_pll",
"dsi_phy_lane";
#clock-cells = <1>;
#phy-cells = <0>;
clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>;
clock-names = "iface_clk";
};
dsi1: dsi@ae96000 {
compatible = "qcom,mdss-dsi-ctrl";
reg = <0xae96000 0x400>;
reg-names = "dsi_ctrl";
interrupt-parent = <&mdss>;
interrupts = <5 0>;
clocks = <&dispcc DISP_CC_MDSS_BYTE1_CLK>,
<&dispcc DISP_CC_MDSS_BYTE1_INTF_CLK>,
<&dispcc DISP_CC_MDSS_PCLK1_CLK>,
<&dispcc DISP_CC_MDSS_ESC1_CLK>,
<&dispcc DISP_CC_MDSS_AHB_CLK>,
<&dispcc DISP_CC_MDSS_AXI_CLK>;
clock-names = "byte_clk",
"byte_intf_clk",
"pixel_clk",
"core_clk",
"iface_clk",
"bus_clk";
phys = <&dsi1_phy>;
phy-names = "dsi-phy";
#address-cells = <1>;
#size-cells = <0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
dsi1_in: endpoint {
remote-endpoint = <&dpu_intf2_out>;
};
};
port@1 {
reg = <1>;
dsi1_out: endpoint {
};
};
};
};
dsi1_phy: dsi-phy@ae96400 {
compatible = "qcom,dsi-phy-10nm";
reg = <0xae96400 0x200>,
<0xae96a00 0x10e>,
<0xae96600 0x280>;
reg-names = "dsi_phy",
"dsi_pll",
"dsi_phy_lane";
#clock-cells = <1>;
#phy-cells = <0>;
clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>;
clock-names = "iface_clk";
};
};
dispcc: qcom,dispcc@af00000 {
compatible = "qcom,sdm845-dispcc";
reg = <0xaf00000 0x10000>;
#clock-cells = <1>;
#reset-cells = <1>;
#power-domain-cells = <1>;
};
spmi_bus: spmi@c440000 { compatible = "qcom,spmi-pmic-arb"; reg = <0xc440000 0x1100>,
-- Sean Paul, Software Engineer, Google / Chromium OS
On Mon, Jul 9, 2018 at 2:35 PM, Sean Paul seanpaul@chromium.org wrote:
On Mon, Jul 09, 2018 at 12:07:11PM -0600, Rob Herring wrote:
On Mon, Jul 9, 2018 at 11:40 AM Sean Paul seanpaul@chromium.org wrote:
Signed-off-by: Sean Paul seanpaul@chromium.org
arch/arm64/boot/dts/qcom/sdm845.dtsi | 194 +++++++++++++++++++++++++++ 1 file changed, 194 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi index cdaabeb3c995..339afed856de 100644 --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi @@ -5,6 +5,8 @@
- Copyright (c) 2018, The Linux Foundation. All rights reserved.
*/
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h> +#include <dt-bindings/clock/qcom,gcc-sdm845.h> #include <dt-bindings/interrupt-controller/arm-gic.h>
/ { @@ -221,6 +223,198 @@ #interrupt-cells = <2>; };
mdss: mdss@ae00000 {
compatible = "qcom,dpu-mdss";
reg = <0xae00000 0x1000>;
reg-names = "mdss_phys";
power-domains = <&dispcc 0>;
clocks = <&gcc GCC_DISP_AHB_CLK>,
<&gcc GCC_DISP_AXI_CLK>,
<&dispcc DISP_CC_MDSS_MDP_CLK>;
clock-names = "iface", "bus", "core";
clock-frequency = <0 0 300000000>;
interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
interrupt-controller;
#interrupt-cells = <1>;
/* iommus = <&apps_iommu 0>; */
#address-cells = <1>;
#size-cells = <1>;
ranges;
mdss_mdp: mdp@ae01000 {
compatible = "qcom,dpu";
Hi Rob, Thanks for the quick turnaround! In addition to below, I'll also beef up the commit message, since I forgot to add any description of the change.
Needs an SoC specific compatible. Did this binding get reviewed?
No, it's part of this set ([PATCH 19/21] dt-bindings: msm/disp: Add bindings for Snapdragon 845 DPU).
note that for display controller and DSI we've been able to reliably read the version of the block from hardware.
BR, -R
reg = <0x0ae01000 0x8f000>,
<0x0aeb0000 0x2008>;
reg-names = "mdp_phys", "vbif_phys";
clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
<&dispcc DISP_CC_MDSS_AXI_CLK>,
<&dispcc DISP_CC_MDSS_MDP_CLK>,
<&dispcc DISP_CC_MDSS_VSYNC_CLK>;
clock-names = "iface", "bus", "core", "vsync";
clock-frequency = <0 0 300000000 19200000>;
That's abusing clock-frequency which is generally 1 value. Use assigned-clock-rates instead.
Thanks, will change.
interrupt-parent = <&mdss>;
interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
dpu_intf1_out: endpoint {
remote-endpoint = <&dsi0_in>;
};
};
port@1 {
reg = <1>;
dpu_intf2_out: endpoint {
remote-endpoint = <&dsi1_in>;
};
};
};
};
dsi0: dsi@ae94000 {
compatible = "qcom,mdss-dsi-ctrl";
Needs an SoC specific compatible.
Ok, will add.
reg = <0xae94000 0x400>;
reg-names = "dsi_ctrl";
interrupt-parent = <&mdss>;
interrupts = <4 0>;
clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK>,
<&dispcc DISP_CC_MDSS_BYTE0_INTF_CLK>,
<&dispcc DISP_CC_MDSS_PCLK0_CLK>,
<&dispcc DISP_CC_MDSS_ESC0_CLK>,
<&dispcc DISP_CC_MDSS_AHB_CLK>,
<&dispcc DISP_CC_MDSS_AXI_CLK>;
clock-names = "byte_clk",
"byte_intf_clk",
"pixel_clk",
"core_clk",
"iface_clk",
"bus_clk";
Should have found this in binding review, but the "_clk" part is redundant.
This binding is already in mainline (Documentation/devicetree/bindings/display/msm/dsi.txt), which is why _clk is here, but not above.
Sean
phys = <&dsi0_phy>;
phy-names = "dsi-phy";
#address-cells = <1>;
#size-cells = <0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
dsi0_in: endpoint {
remote-endpoint = <&dpu_intf1_out>;
};
};
port@1 {
reg = <1>;
dsi0_out: endpoint {
};
};
};
};
dsi0_phy: dsi-phy@ae94400 {
compatible = "qcom,dsi-phy-10nm";
reg = <0xae94400 0x200>,
<0xae94a00 0x1e0>,
<0xae94600 0x280>;
reg-names = "dsi_phy",
"dsi_pll",
"dsi_phy_lane";
#clock-cells = <1>;
#phy-cells = <0>;
clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>;
clock-names = "iface_clk";
};
dsi1: dsi@ae96000 {
compatible = "qcom,mdss-dsi-ctrl";
reg = <0xae96000 0x400>;
reg-names = "dsi_ctrl";
interrupt-parent = <&mdss>;
interrupts = <5 0>;
clocks = <&dispcc DISP_CC_MDSS_BYTE1_CLK>,
<&dispcc DISP_CC_MDSS_BYTE1_INTF_CLK>,
<&dispcc DISP_CC_MDSS_PCLK1_CLK>,
<&dispcc DISP_CC_MDSS_ESC1_CLK>,
<&dispcc DISP_CC_MDSS_AHB_CLK>,
<&dispcc DISP_CC_MDSS_AXI_CLK>;
clock-names = "byte_clk",
"byte_intf_clk",
"pixel_clk",
"core_clk",
"iface_clk",
"bus_clk";
phys = <&dsi1_phy>;
phy-names = "dsi-phy";
#address-cells = <1>;
#size-cells = <0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
dsi1_in: endpoint {
remote-endpoint = <&dpu_intf2_out>;
};
};
port@1 {
reg = <1>;
dsi1_out: endpoint {
};
};
};
};
dsi1_phy: dsi-phy@ae96400 {
compatible = "qcom,dsi-phy-10nm";
reg = <0xae96400 0x200>,
<0xae96a00 0x10e>,
<0xae96600 0x280>;
reg-names = "dsi_phy",
"dsi_pll",
"dsi_phy_lane";
#clock-cells = <1>;
#phy-cells = <0>;
clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>;
clock-names = "iface_clk";
};
};
dispcc: qcom,dispcc@af00000 {
compatible = "qcom,sdm845-dispcc";
reg = <0xaf00000 0x10000>;
#clock-cells = <1>;
#reset-cells = <1>;
#power-domain-cells = <1>;
};
spmi_bus: spmi@c440000 { compatible = "qcom,spmi-pmic-arb"; reg = <0xc440000 0x1100>,
-- Sean Paul, Software Engineer, Google / Chromium OS
-- Sean Paul, Software Engineer, Google / Chromium OS
DPU is short for the Display Processing Unit. It is the display controller on Qualcomm SDM845 chips.
While the dts is pretty sparse for sdm845 atm, the only piece we're missing is the iommu. It's commented out for now, and should be uncommented once support is provided.
Changes in v2: - Beefed up commit message - Use SoC specific compatibles for mdss and dpu - Use assigned-clocks to set initial clock frequency
Signed-off-by: Sean Paul seanpaul@chromium.org --- arch/arm64/boot/dts/qcom/sdm845.dtsi | 200 +++++++++++++++++++++++++++ 1 file changed, 200 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi index cdaabeb3c995..f1f4cdc9cb63 100644 --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi @@ -5,6 +5,8 @@ * Copyright (c) 2018, The Linux Foundation. All rights reserved. */
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h> +#include <dt-bindings/clock/qcom,gcc-sdm845.h> #include <dt-bindings/interrupt-controller/arm-gic.h>
/ { @@ -221,6 +223,204 @@ #interrupt-cells = <2>; };
+ mdss: mdss@ae00000 { + compatible = "qcom,sdm845-mdss"; + reg = <0xae00000 0x1000>; + reg-names = "mdss_phys"; + + power-domains = <&dispcc 0>; + + clocks = <&gcc GCC_DISP_AHB_CLK>, + <&gcc GCC_DISP_AXI_CLK>, + <&dispcc DISP_CC_MDSS_MDP_CLK>; + clock-names = "iface", "bus", "core"; + + assigned-clocks = <&dispcc DISP_CC_MDSS_MDP_CLK>; + assigned-clock-rates = <300000000>; + + interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>; + interrupt-controller; + #interrupt-cells = <1>; + + /* iommus = <&apps_iommu 0>; */ + + #address-cells = <1>; + #size-cells = <1>; + ranges; + + mdss_mdp: mdp@ae01000 { + compatible = "qcom,sdm845-dpu"; + reg = <0x0ae01000 0x8f000>, + <0x0aeb0000 0x2008>; + reg-names = "mdp_phys", "vbif_phys"; + + clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&dispcc DISP_CC_MDSS_AXI_CLK>, + <&dispcc DISP_CC_MDSS_MDP_CLK>, + <&dispcc DISP_CC_MDSS_VSYNC_CLK>; + clock-names = "iface", "bus", "core", "vsync"; + + assigned-clocks = <&dispcc DISP_CC_MDSS_MDP_CLK>, + <&dispcc DISP_CC_MDSS_VSYNC_CLK>; + assigned-clock-rates = <300000000>, + <19200000>; + + interrupt-parent = <&mdss>; + interrupts = <0 IRQ_TYPE_LEVEL_HIGH>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dpu_intf1_out: endpoint { + remote-endpoint = <&dsi0_in>; + }; + }; + + port@1 { + reg = <1>; + dpu_intf2_out: endpoint { + remote-endpoint = <&dsi1_in>; + }; + }; + }; + }; + + dsi0: dsi@ae94000 { + compatible = "qcom,mdss-dsi-ctrl"; + reg = <0xae94000 0x400>; + reg-names = "dsi_ctrl"; + + interrupt-parent = <&mdss>; + interrupts = <4 0>; + + clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK>, + <&dispcc DISP_CC_MDSS_BYTE0_INTF_CLK>, + <&dispcc DISP_CC_MDSS_PCLK0_CLK>, + <&dispcc DISP_CC_MDSS_ESC0_CLK>, + <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&dispcc DISP_CC_MDSS_AXI_CLK>; + clock-names = "byte_clk", + "byte_intf_clk", + "pixel_clk", + "core_clk", + "iface_clk", + "bus_clk"; + + phys = <&dsi0_phy>; + phy-names = "dsi-phy"; + + #address-cells = <1>; + #size-cells = <0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dsi0_in: endpoint { + remote-endpoint = <&dpu_intf1_out>; + }; + }; + + port@1 { + reg = <1>; + dsi0_out: endpoint { + }; + }; + }; + }; + + dsi0_phy: dsi-phy@ae94400 { + compatible = "qcom,dsi-phy-10nm"; + reg = <0xae94400 0x200>, + <0xae94a00 0x1e0>, + <0xae94600 0x280>; + reg-names = "dsi_phy", + "dsi_pll", + "dsi_phy_lane"; + + #clock-cells = <1>; + #phy-cells = <0>; + + clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>; + clock-names = "iface_clk"; + }; + + dsi1: dsi@ae96000 { + compatible = "qcom,mdss-dsi-ctrl"; + reg = <0xae96000 0x400>; + reg-names = "dsi_ctrl"; + + interrupt-parent = <&mdss>; + interrupts = <5 0>; + + clocks = <&dispcc DISP_CC_MDSS_BYTE1_CLK>, + <&dispcc DISP_CC_MDSS_BYTE1_INTF_CLK>, + <&dispcc DISP_CC_MDSS_PCLK1_CLK>, + <&dispcc DISP_CC_MDSS_ESC1_CLK>, + <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&dispcc DISP_CC_MDSS_AXI_CLK>; + clock-names = "byte_clk", + "byte_intf_clk", + "pixel_clk", + "core_clk", + "iface_clk", + "bus_clk"; + + phys = <&dsi1_phy>; + phy-names = "dsi-phy"; + + #address-cells = <1>; + #size-cells = <0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dsi1_in: endpoint { + remote-endpoint = <&dpu_intf2_out>; + }; + }; + + port@1 { + reg = <1>; + dsi1_out: endpoint { + }; + }; + }; + }; + + dsi1_phy: dsi-phy@ae96400 { + compatible = "qcom,dsi-phy-10nm"; + reg = <0xae96400 0x200>, + <0xae96a00 0x10e>, + <0xae96600 0x280>; + reg-names = "dsi_phy", + "dsi_pll", + "dsi_phy_lane"; + + #clock-cells = <1>; + #phy-cells = <0>; + + clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>; + clock-names = "iface_clk"; + }; + }; + + dispcc: qcom,dispcc@af00000 { + compatible = "qcom,sdm845-dispcc"; + reg = <0xaf00000 0x10000>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; + spmi_bus: spmi@c440000 { compatible = "qcom,spmi-pmic-arb"; reg = <0xc440000 0x1100>,
The patch was rejected for being too big. Please refer to https://gitlab.freedesktop.org/seanpaul/dpu-staging/commit/b4215cf040d197828...
Sean
On Tue, Jul 10, 2018 at 11:45 AM, Sean Paul seanpaul@chromium.org wrote:
The patch was rejected for being too big. Please refer to https://gitlab.freedesktop.org/seanpaul/dpu-staging/commit/b4215cf040d197828...
heh, and also seems to be too big for gmail to reply to..
That said, +30k is a nice improvement over the +110k where this started. But a few comments..
+static void dpu_kms_preclose(struct msm_kms *kms, struct drm_file *file) +{ + struct dpu_kms *dpu_kms = to_dpu_kms(kms); + struct drm_device *dev = dpu_kms->dev; + struct msm_drm_private *priv = dev->dev_private; + unsigned int i; + + for (i = 0; i < priv->num_crtcs; i++) + dpu_crtc_cancel_pending_flip(priv->crtcs[i], file); +}
So, not totally a fan of bringing back preclose() from the dead, esp. since it is only supposed to be used by legacy drivers. Since all this does is fire off pending events, I think it could be dropped entirely... drm_events_release() should unlink unsent events from the drm_file, and if that isn't working properly, that seems like a bug that should be fixed in drm core.
+static int _dpu_core_irq_enable(struct dpu_kms *dpu_kms, int irq_idx) +{ + unsigned long irq_flags; + int ret = 0, enable_count; + + if (!dpu_kms || !dpu_kms->hw_intr || + !dpu_kms->irq_obj.enable_counts || + !dpu_kms->irq_obj.irq_counts) { + DPU_ERROR("invalid params\n"); + return -EINVAL; + } + + if (irq_idx < 0 || irq_idx >= dpu_kms->hw_intr->irq_idx_tbl_size) { + DPU_ERROR("invalid IRQ index: [%d]\n", irq_idx); + return -EINVAL; + } ... +int dpu_core_irq_enable(struct dpu_kms *dpu_kms, int *irq_idxs, u32 irq_count) +{ + int i, ret = 0, counts; + + if (!dpu_kms || !irq_idxs || !irq_count) { + DPU_ERROR("invalid params\n"); + return -EINVAL; + } ...
there is a *whole* lot of multiple levels of null checks like this for things that are only ever called internally (ie. not something that can be triggered by parameters passed from userspace).. which is really unnecessary.
(maybe something that someone who knows coccinelle better than I, could automate cleaning up?)
+/** + * dpu_core_irq_disable_nolock - disable core interrupt given by the index + * without lock + * @dpu_kms: Pointer to dpu kms context + * @irq_idx: interrupt index + */ +int dpu_core_irq_disable_nolock(struct dpu_kms *dpu_kms, int irq_idx) +{
appears to be unused? dpu_core_irq_read_nolock() also seems unused, and maybe some others.
diff --git a/include/uapi/media/msm_media_info.h b/include/uapi/media/msm_media_info.h new file mode 100644 index 000000000000..4f12e5c534c8 --- /dev/null +++ b/include/uapi/media/msm_media_info.h @@ -0,0 +1,1376 @@ +#ifndef __MEDIA_INFO_H__ +#define __MEDIA_INFO_H__ + ...
Not quite sure where this belongs, but (at least for now) include/uapi/media seems very wrong.
Maybe just move into drm/msm for now? We can always move it back to include/uapi later (but the other direction isn't so cool)
------------------
Anyways, if I notice anything else to complain about, I'll send more replies. Overall it looks much better than where we started, and I'm open to the idea of pulling it in to msm-next soon. I think moving msm_media_info.h out of uapi, and probably nuking preclose, should happen first.
BR, -R
dri-devel@lists.freedesktop.org