On the display side, cleanups and fixes to enabled modifiers (QCOM_COMPRESSED). And otherwise mostly misc fixes all around.
Unified · Split
| @@ -0,0 +1,59 @@ | ||
| 1 | +Qualcomm adreno/snapdragon GMU (Graphics management unit) | |
| 2 | + | |
| 3 | +The GMU is a programmable power controller for the GPU. the CPU controls the | |
| 4 | +GMU which in turn handles power controls for the GPU. | |
| 5 | + | |
| 6 | +Required properties: | |
| 7 | +- compatible: "qcom,adreno-gmu-XYZ.W", "qcom,adreno-gmu" | |
| 8 | + for example: "qcom,adreno-gmu-630.2", "qcom,adreno-gmu" | |
| 9 | + Note that you need to list the less specific "qcom,adreno-gmu" | |
| 10 | + for generic matches and the more specific identifier to identify | |
| 11 | + the specific device. | |
| 12 | +- reg: Physical base address and length of the GMU registers. | |
| 13 | +- reg-names: Matching names for the register regions | |
| 14 | + * "gmu" | |
| 15 | + * "gmu_pdc" | |
| 16 | + * "gmu_pdc_seg" | |
| 17 | +- interrupts: The interrupt signals from the GMU. | |
| 18 | +- interrupt-names: Matching names for the interrupts | |
| 19 | + * "hfi" | |
| 20 | + * "gmu" | |
| 21 | +- clocks: phandles to the device clocks | |
| 22 | +- clock-names: Matching names for the clocks | |
| 23 | + * "gmu" | |
| 24 | + * "cxo" | |
| 25 | + * "axi" | |
| 26 | + * "mnoc" | |
| 27 | +- power-domains: should be <&clock_gpucc GPU_CX_GDSC> | |
| 28 | +- iommus: phandle to the adreno iommu | |
| 29 | +- operating-points-v2: phandle to the OPP operating points | |
| 30 | + | |
| 31 | +Example: | |
| 32 | + | |
| 33 | +/ { | |
| 34 | + ... | |
| 35 | + | |
| 36 | + gmu: gmu@506a000 { | |
| 37 | + compatible="qcom,adreno-gmu-630.2", "qcom,adreno-gmu"; | |
| 38 | + | |
| 39 | + reg = <0x506a000 0x30000>, | |
| 40 | + <0xb280000 0x10000>, | |
| 41 | + <0xb480000 0x10000>; | |
| 42 | + reg-names = "gmu", "gmu_pdc", "gmu_pdc_seq"; | |
| 43 | + | |
| 44 | + interrupts = <GIC_SPI 304 IRQ_TYPE_LEVEL_HIGH>, | |
| 45 | + <GIC_SPI 305 IRQ_TYPE_LEVEL_HIGH>; | |
| 46 | + interrupt-names = "hfi", "gmu"; | |
| 47 | + | |
| 48 | + clocks = <&gpucc GPU_CC_CX_GMU_CLK>, | |
| 49 | + <&gpucc GPU_CC_CXO_CLK>, | |
| 50 | + <&gcc GCC_DDRSS_GPU_AXI_CLK>, | |
| 51 | + <&gcc GCC_GPU_MEMNOC_GFX_CLK>; | |
| 52 | + clock-names = "gmu", "cxo", "axi", "memnoc"; | |
| 53 | + | |
| 54 | + power-domains = <&gpucc GPU_CX_GDSC>; | |
| 55 | + iommus = <&adreno_smmu 5>; | |
| 56 | + | |
| 57 | + operating-points-v2 = <&gmu_opp_table>; | |
| 58 | + }; | |
| 59 | +}; | |
| @@ -10,14 +10,23 @@ Required properties: · 9 unmodified lines | ||
| 10 | 10 | If "amd,imageon" is used, there should be no top level msm device. |
| 11 | 11 | - reg: Physical base address and length of the controller's registers. |
| 12 | 12 | - interrupts: The interrupt signal from the gpu. |
| 13 | −- clocks: device clocks | |
| 13 | +- clocks: device clocks (if applicable) | |
| 14 | 14 | See ../clocks/clock-bindings.txt for details. |
| 15 | −- clock-names: the following clocks are required: | |
| 15 | +- clock-names: the following clocks are required by a3xx, a4xx and a5xx | |
| 16 | + cores: | |
| 16 | 17 | * "core" |
| 17 | 18 | * "iface" |
| 18 | 19 | * "mem_iface" |
| 20 | + For GMU attached devices the GPU clocks are not used and are not required. The | |
| 21 | + following devices should not list clocks: | |
| 22 | + - qcom,adreno-630.2 | |
| 23 | +- iommus: optional phandle to an adreno iommu instance | |
| 24 | +- operating-points-v2: optional phandle to the OPP operating points | |
| 25 | +- qcom,gmu: For GMU attached devices a phandle to the GMU device that will | |
| 26 | + control the power for the GPU. Applicable targets: | |
| 27 | + - qcom,adreno-630.2 | |
| 19 | 28 | |
| 20 | −Example: | |
| 29 | +Example 3xx/4xx/a5xx: | |
| 21 | 30 | |
| 22 | 31 | / { |
| 23 | 32 | ... |
| @@ -37,3 +46,30 @@ Example: · 13 unmodified lines | ||
| 37 | 46 | <&mmcc MMSS_IMEM_AHB_CLK>; |
| 38 | 47 | }; |
| 39 | 48 | }; |
| 49 | + | |
| 50 | +Example a6xx (with GMU): | |
| 51 | + | |
| 52 | +/ { | |
| 53 | + ... | |
| 54 | + | |
| 55 | + gpu@5000000 { | |
| 56 | + compatible = "qcom,adreno-630.2", "qcom,adreno"; | |
| 57 | + #stream-id-cells = <16>; | |
| 58 | + | |
| 59 | + reg = <0x5000000 0x40000>, <0x509e000 0x10>; | |
| 60 | + reg-names = "kgsl_3d0_reg_memory", "cx_mem"; | |
| 61 | + | |
| 62 | + /* | |
| 63 | + * Look ma, no clocks! The GPU clocks and power are | |
| 64 | + * controlled entirely by the GMU | |
| 65 | + */ | |
| 66 | + | |
| 67 | + interrupts = <GIC_SPI 300 IRQ_TYPE_LEVEL_HIGH>; | |
| 68 | + | |
| 69 | + iommus = <&adreno_smmu 0>; | |
| 70 | + | |
| 71 | + operating-points-v2 = <&gpu_opp_table>; | |
| 72 | + | |
| 73 | + qcom,gmu = <&gmu>; | |
| 74 | + }; | |
| 75 | +}; | |
| @@ -4851,10 +4851,11 @@ F: Documentation/devicetree/bindings/display/multi-inno,mi0283qt.txt · 4850 unmodified lines | ||
| 4851 | 4851 | |
| 4852 | 4852 | DRM DRIVER FOR MSM ADRENO GPU |
| 4853 | 4853 | M: Rob Clark <robdclark@gmail.com> |
| 4854 | +M: Sean Paul <sean@poorly.run> | |
| 4854 | 4855 | L: linux-arm-msm@vger.kernel.org |
| 4855 | 4856 | L: dri-devel@lists.freedesktop.org |
| 4856 | 4857 | L: freedreno@lists.freedesktop.org |
| 4857 | −T: git git://people.freedesktop.org/~robclark/linux | |
| 4858 | +T: git https://gitlab.freedesktop.org/drm/msm.git | |
| 4858 | 4859 | S: Maintained |
| 4859 | 4860 | F: drivers/gpu/drm/msm/ |
| 4860 | 4861 | F: include/uapi/drm/msm_drm.h |
| @@ -465,8 +465,6 @@ static void _dpu_crtc_setup_mixer_for_encoder( · 464 unmodified lines | ||
| 465 | 465 | return; |
| 466 | 466 | } |
| 467 | 467 | |
| 468 | − mixer->encoder = enc; | |
| 469 | − | |
| 470 | 468 | cstate->num_mixers++; |
| 471 | 469 | DPU_DEBUG("setup mixer %d: lm %d\n", |
| 472 | 470 | i, mixer->hw_lm->idx - LM_0); |
| @@ -718,11 +716,8 @@ void dpu_crtc_commit_kickoff(struct drm_crtc *crtc, bool async) · 245 unmodified lines | ||
| 718 | 716 | * may delay and flush at an irq event (e.g. ppdone) |
| 719 | 717 | */ |
| 720 | 718 | drm_for_each_encoder_mask(encoder, crtc->dev, |
| 721 | − crtc->state->encoder_mask) { | |
| 722 | − struct dpu_encoder_kickoff_params params = { 0 }; | |
| 723 | − dpu_encoder_prepare_for_kickoff(encoder, ¶ms, async); | |
| 724 | − } | |
| 725 | − | |
| 719 | + crtc->state->encoder_mask) | |
| 720 | + dpu_encoder_prepare_for_kickoff(encoder, async); | |
| 726 | 721 | |
| 727 | 722 | if (!async) { |
| 728 | 723 | /* wait for frame_event_done completion */ |
| @@ -84,14 +84,12 @@ struct dpu_crtc_smmu_state_data { · 83 unmodified lines | ||
| 84 | 84 | * struct dpu_crtc_mixer: stores the map for each virtual pipeline in the CRTC |
| 85 | 85 | * @hw_lm: LM HW Driver context |
| 86 | 86 | * @lm_ctl: CTL Path HW driver context |
| 87 | − * @encoder: Encoder attached to this lm & ctl | |
| 88 | 87 | * @mixer_op_mode: mixer blending operation mode |
| 89 | 88 | * @flush_mask: mixer flush mask for ctl, mixer and pipe |
| 90 | 89 | */ |
| 91 | 90 | struct dpu_crtc_mixer { |
| 92 | 91 | struct dpu_hw_mixer *hw_lm; |
| 93 | 92 | struct dpu_hw_ctl *lm_ctl; |
| 94 | − struct drm_encoder *encoder; | |
| 95 | 93 | u32 mixer_op_mode; |
| 96 | 94 | u32 flush_mask; |
| 97 | 95 | }; |
| @@ -205,7 +205,7 @@ struct dpu_encoder_virt { · 204 unmodified lines | ||
| 205 | 205 | bool idle_pc_supported; |
| 206 | 206 | struct mutex rc_lock; |
| 207 | 207 | enum dpu_enc_rc_states rc_state; |
| 208 | − struct kthread_delayed_work delayed_off_work; | |
| 208 | + struct delayed_work delayed_off_work; | |
| 209 | 209 | struct kthread_work vsync_event_work; |
| 210 | 210 | struct msm_display_topology topology; |
| 211 | 211 | bool mode_set_complete; |
| @@ -742,7 +742,6 @@ static int dpu_encoder_resource_control(struct drm_encoder *drm_enc, · 530 unmodified lines | ||
| 742 | 742 | { |
| 743 | 743 | struct dpu_encoder_virt *dpu_enc; |
| 744 | 744 | struct msm_drm_private *priv; |
| 745 | − struct msm_drm_thread *disp_thread; | |
| 746 | 745 | bool is_vid_mode = false; |
| 747 | 746 | |
| 748 | 747 | if (!drm_enc || !drm_enc->dev || !drm_enc->dev->dev_private || |
| @@ -755,12 +754,6 @@ static int dpu_encoder_resource_control(struct drm_encoder *drm_enc, · 6 unmodified lines | ||
| 755 | 754 | is_vid_mode = dpu_enc->disp_info.capabilities & |
| 756 | 755 | MSM_DISPLAY_CAP_VID_MODE; |
| 757 | 756 | |
| 758 | − if (drm_enc->crtc->index >= ARRAY_SIZE(priv->disp_thread)) { | |
| 759 | − DPU_ERROR("invalid crtc index\n"); | |
| 760 | − return -EINVAL; | |
| 761 | − } | |
| 762 | − disp_thread = &priv->disp_thread[drm_enc->crtc->index]; | |
| 763 | − | |
| 764 | 757 | /* |
| 765 | 758 | * when idle_pc is not supported, process only KICKOFF, STOP and MODESET |
| 766 | 759 | * events and return early for other events (ie wb display). |
| @@ -777,8 +770,7 @@ static int dpu_encoder_resource_control(struct drm_encoder *drm_enc, · 10 unmodified lines | ||
| 777 | 770 | switch (sw_event) { |
| 778 | 771 | case DPU_ENC_RC_EVENT_KICKOFF: |
| 779 | 772 | /* cancel delayed off work, if any */ |
| 780 | − if (kthread_cancel_delayed_work_sync( | |
| 781 | − &dpu_enc->delayed_off_work)) | |
| 773 | + if (cancel_delayed_work_sync(&dpu_enc->delayed_off_work)) | |
| 782 | 774 | DPU_DEBUG_ENC(dpu_enc, "sw_event:%d, work cancelled\n", |
| 783 | 775 | sw_event); |
| 784 | 776 | |
| @@ -837,10 +829,8 @@ static int dpu_encoder_resource_control(struct drm_encoder *drm_enc, · 52 unmodified lines | ||
| 837 | 829 | return 0; |
| 838 | 830 | } |
| 839 | 831 | |
| 840 | − kthread_queue_delayed_work( | |
| 841 | − &disp_thread->worker, | |
| 842 | − &dpu_enc->delayed_off_work, | |
| 843 | − msecs_to_jiffies(dpu_enc->idle_timeout)); | |
| 832 | + queue_delayed_work(priv->wq, &dpu_enc->delayed_off_work, | |
| 833 | + msecs_to_jiffies(dpu_enc->idle_timeout)); | |
| 844 | 834 | |
| 845 | 835 | trace_dpu_enc_rc(DRMID(drm_enc), sw_event, |
| 846 | 836 | dpu_enc->idle_pc_supported, dpu_enc->rc_state, |
| @@ -849,8 +839,7 @@ static int dpu_encoder_resource_control(struct drm_encoder *drm_enc, · 2 unmodified lines | ||
| 849 | 839 | |
| 850 | 840 | case DPU_ENC_RC_EVENT_PRE_STOP: |
| 851 | 841 | /* cancel delayed off work, if any */ |
| 852 | − if (kthread_cancel_delayed_work_sync( | |
| 853 | − &dpu_enc->delayed_off_work)) | |
| 842 | + if (cancel_delayed_work_sync(&dpu_enc->delayed_off_work)) | |
| 854 | 843 | DPU_DEBUG_ENC(dpu_enc, "sw_event:%d, work cancelled\n", |
| 855 | 844 | sw_event); |
| 856 | 845 | |
| @@ -1368,7 +1357,7 @@ static void dpu_encoder_frame_done_callback( · 511 unmodified lines | ||
| 1368 | 1357 | } |
| 1369 | 1358 | } |
| 1370 | 1359 | |
| 1371 | −static void dpu_encoder_off_work(struct kthread_work *work) | |
| 1360 | +static void dpu_encoder_off_work(struct work_struct *work) | |
| 1372 | 1361 | { |
| 1373 | 1362 | struct dpu_encoder_virt *dpu_enc = container_of(work, |
| 1374 | 1363 | struct dpu_encoder_virt, delayed_off_work.work); |
| @@ -1756,15 +1745,14 @@ static void dpu_encoder_vsync_event_work_handler(struct kthread_work *work) · 381 unmodified lines | ||
| 1756 | 1745 | nsecs_to_jiffies(ktime_to_ns(wakeup_time))); |
| 1757 | 1746 | } |
| 1758 | 1747 | |
| 1759 | −void dpu_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, | |
| 1760 | − struct dpu_encoder_kickoff_params *params, bool async) | |
| 1748 | +void dpu_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, bool async) | |
| 1761 | 1749 | { |
| 1762 | 1750 | struct dpu_encoder_virt *dpu_enc; |
| 1763 | 1751 | struct dpu_encoder_phys *phys; |
| 1764 | 1752 | bool needs_hw_reset = false; |
| 1765 | 1753 | unsigned int i; |
| 1766 | 1754 | |
| 1767 | − if (!drm_enc || !params) { | |
| 1755 | + if (!drm_enc) { | |
| 1768 | 1756 | DPU_ERROR("invalid args\n"); |
| 1769 | 1757 | return; |
| 1770 | 1758 | } |
| @@ -1778,7 +1766,7 @@ void dpu_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, · 7 unmodified lines | ||
| 1778 | 1766 | phys = dpu_enc->phys_encs[i]; |
| 1779 | 1767 | if (phys) { |
| 1780 | 1768 | if (phys->ops.prepare_for_kickoff) |
| 1781 | − phys->ops.prepare_for_kickoff(phys, params); | |
| 1769 | + phys->ops.prepare_for_kickoff(phys); | |
| 1782 | 1770 | if (phys->enable_state == DPU_ENC_ERR_NEEDS_HW_RESET) |
| 1783 | 1771 | needs_hw_reset = true; |
| 1784 | 1772 | } |
| @@ -2193,7 +2181,7 @@ int dpu_encoder_setup(struct drm_device *dev, struct drm_encoder *enc, · 408 unmodified lines | ||
| 2193 | 2181 | |
| 2194 | 2182 | |
| 2195 | 2183 | mutex_init(&dpu_enc->rc_lock); |
| 2196 | − kthread_init_delayed_work(&dpu_enc->delayed_off_work, | |
| 2184 | + INIT_DELAYED_WORK(&dpu_enc->delayed_off_work, | |
| 2197 | 2185 | dpu_encoder_off_work); |
| 2198 | 2186 | dpu_enc->idle_timeout = IDLE_TIMEOUT; |
| 2199 | 2187 | |
| @@ -37,15 +37,6 @@ struct dpu_encoder_hw_resources { · 36 unmodified lines | ||
| 37 | 37 | enum dpu_intf_mode intfs[INTF_MAX]; |
| 38 | 38 | }; |
| 39 | 39 | |
| 40 | −/** | |
| 41 | − * dpu_encoder_kickoff_params - info encoder requires at kickoff | |
| 42 | − * @affected_displays: bitmask, bit set means the ROI of the commit lies within | |
| 43 | − * the bounds of the physical display at the bit index | |
| 44 | − */ | |
| 45 | −struct dpu_encoder_kickoff_params { | |
| 46 | − unsigned long affected_displays; | |
| 47 | −}; | |
| 48 | − | |
| 49 | 40 | /** |
| 50 | 41 | * dpu_encoder_get_hw_resources - Populate table of required hardware resources |
| 51 | 42 | * @encoder: encoder pointer |
| @@ -88,11 +79,9 @@ void dpu_encoder_register_frame_event_callback(struct drm_encoder *encoder, · 36 unmodified lines | ||
| 88 | 79 | * Immediately: if no previous commit is outstanding. |
| 89 | 80 | * Delayed: Block until next trigger can be issued. |
| 90 | 81 | * @encoder: encoder pointer |
| 91 | − * @params: kickoff time parameters | |
| 92 | 82 | * @async: true if this is an asynchronous commit |
| 93 | 83 | */ |
| 94 | −void dpu_encoder_prepare_for_kickoff(struct drm_encoder *encoder, | |
| 95 | − struct dpu_encoder_kickoff_params *params, bool async); | |
| 84 | +void dpu_encoder_prepare_for_kickoff(struct drm_encoder *encoder, bool async); | |
| 96 | 85 | |
| 97 | 86 | /** |
| 98 | 87 | * dpu_encoder_trigger_kickoff_pending - Clear the flush bits from previous |
| @@ -144,8 +144,7 @@ struct dpu_encoder_phys_ops { · 143 unmodified lines | ||
| 144 | 144 | int (*wait_for_commit_done)(struct dpu_encoder_phys *phys_enc); |
| 145 | 145 | int (*wait_for_tx_complete)(struct dpu_encoder_phys *phys_enc); |
| 146 | 146 | int (*wait_for_vblank)(struct dpu_encoder_phys *phys_enc); |
| 147 | − void (*prepare_for_kickoff)(struct dpu_encoder_phys *phys_enc, | |
| 148 | − struct dpu_encoder_kickoff_params *params); | |
| 147 | + void (*prepare_for_kickoff)(struct dpu_encoder_phys *phys_enc); | |
| 149 | 148 | void (*handle_post_kickoff)(struct dpu_encoder_phys *phys_enc); |
| 150 | 149 | void (*trigger_start)(struct dpu_encoder_phys *phys_enc); |
| 151 | 150 | bool (*needs_single_flush)(struct dpu_encoder_phys *phys_enc); |
| @@ -594,8 +594,7 @@ static void dpu_encoder_phys_cmd_get_hw_resources( · 593 unmodified lines | ||
| 594 | 594 | } |
| 595 | 595 | |
| 596 | 596 | static void dpu_encoder_phys_cmd_prepare_for_kickoff( |
| 597 | − struct dpu_encoder_phys *phys_enc, | |
| 598 | − struct dpu_encoder_kickoff_params *params) | |
| 597 | + struct dpu_encoder_phys *phys_enc) | |
| 599 | 598 | { |
| 600 | 599 | struct dpu_encoder_phys_cmd *cmd_enc = |
| 601 | 600 | to_dpu_encoder_phys_cmd(phys_enc); |
| @@ -693,7 +692,7 @@ static int dpu_encoder_phys_cmd_wait_for_commit_done( · 91 unmodified lines | ||
| 693 | 692 | |
| 694 | 693 | /* required for both controllers */ |
| 695 | 694 | if (!rc && cmd_enc->serialize_wait4pp) |
| 696 | − dpu_encoder_phys_cmd_prepare_for_kickoff(phys_enc, NULL); | |
| 695 | + dpu_encoder_phys_cmd_prepare_for_kickoff(phys_enc); | |
| 697 | 696 | |
| 698 | 697 | return rc; |
| 699 | 698 | } |
| @@ -587,14 +587,13 @@ static int dpu_encoder_phys_vid_wait_for_vblank( · 586 unmodified lines | ||
| 587 | 587 | } |
| 588 | 588 | |
| 589 | 589 | static void dpu_encoder_phys_vid_prepare_for_kickoff( |
| 590 | − struct dpu_encoder_phys *phys_enc, | |
| 591 | − struct dpu_encoder_kickoff_params *params) | |
| 590 | + struct dpu_encoder_phys *phys_enc) | |
| 592 | 591 | { |
| 593 | 592 | struct dpu_encoder_phys_vid *vid_enc; |
| 594 | 593 | struct dpu_hw_ctl *ctl; |
| 595 | 594 | int rc; |
| 596 | 595 | |
| 597 | − if (!phys_enc || !params) { | |
| 596 | + if (!phys_enc) { | |
| 598 | 597 | DPU_ERROR("invalid encoder/parameters\n"); |
| 599 | 598 | return; |
| 600 | 599 | } |
| @@ -263,13 +263,13 @@ static const struct dpu_format dpu_format_map[] = { · 262 unmodified lines | ||
| 263 | 263 | |
| 264 | 264 | INTERLEAVED_RGB_FMT(RGB565, |
| 265 | 265 | 0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT, |
| 266 | − C1_B_Cb, C0_G_Y, C2_R_Cr, 0, 3, | |
| 266 | + C2_R_Cr, C0_G_Y, C1_B_Cb, 0, 3, | |
| 267 | 267 | false, 2, 0, |
| 268 | 268 | DPU_FETCH_LINEAR, 1), |
| 269 | 269 | |
| 270 | 270 | INTERLEAVED_RGB_FMT(BGR565, |
| 271 | 271 | 0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT, |
| 272 | − C2_R_Cr, C0_G_Y, C1_B_Cb, 0, 3, | |
| 272 | + C1_B_Cb, C0_G_Y, C2_R_Cr, 0, 3, | |
| 273 | 273 | false, 2, 0, |
| 274 | 274 | DPU_FETCH_LINEAR, 1), |
| 275 | 275 | |
| @@ -1137,36 +1137,3 @@ const struct msm_format *dpu_get_msm_format( · 861 unmodified lines | ||
| 1137 | 1137 | return &fmt->base; |
| 1138 | 1138 | return NULL; |
| 1139 | 1139 | } |
| 1140 | − | |
| 1141 | −uint32_t dpu_populate_formats( | |
| 1142 | − const struct dpu_format_extended *format_list, | |
| 1143 | − uint32_t *pixel_formats, | |
| 1144 | − uint64_t *pixel_modifiers, | |
| 1145 | − uint32_t pixel_formats_max) | |
| 1146 | −{ | |
| 1147 | − uint32_t i, fourcc_format; | |
| 1148 | − | |
| 1149 | − if (!format_list || !pixel_formats) | |
| 1150 | − return 0; | |
| 1151 | − | |
| 1152 | − for (i = 0, fourcc_format = 0; | |
| 1153 | − format_list->fourcc_format && i < pixel_formats_max; | |
| 1154 | − ++format_list) { | |
| 1155 | − /* verify if listed format is in dpu_format_map? */ | |
| 1156 | − | |
| 1157 | − /* optionally return modified formats */ | |
| 1158 | − if (pixel_modifiers) { | |
| 1159 | − /* assume same modifier for all fb planes */ | |
| 1160 | − pixel_formats[i] = format_list->fourcc_format; | |
| 1161 | − pixel_modifiers[i++] = format_list->modifier; | |
| 1162 | − } else { | |
| 1163 | − /* assume base formats grouped together */ | |
| 1164 | − if (fourcc_format != format_list->fourcc_format) { | |
| 1165 | − fourcc_format = format_list->fourcc_format; | |
| 1166 | − pixel_formats[i++] = fourcc_format; | |
| 1167 | − } | |
| 1168 | − } | |
| 1169 | − } | |
| 1170 | − | |
| 1171 | − return i; | |
| 1172 | −} | |
| @@ -40,20 +40,6 @@ const struct msm_format *dpu_get_msm_format( · 39 unmodified lines | ||
| 40 | 40 | const uint32_t format, |
| 41 | 41 | const uint64_t modifiers); |
| 42 | 42 | |
| 43 | −/** | |
| 44 | − * dpu_populate_formats - populate the given array with fourcc codes supported | |
| 45 | − * @format_list: pointer to list of possible formats | |
| 46 | − * @pixel_formats: array to populate with fourcc codes | |
| 47 | − * @pixel_modifiers: array to populate with drm modifiers, can be NULL | |
| 48 | − * @pixel_formats_max: length of pixel formats array | |
| 49 | − * Return: number of elements populated | |
| 50 | − */ | |
| 51 | −uint32_t dpu_populate_formats( | |
| 52 | − const struct dpu_format_extended *format_list, | |
| 53 | − uint32_t *pixel_formats, | |
| 54 | − uint64_t *pixel_modifiers, | |
| 55 | − uint32_t pixel_formats_max); | |
| 56 | − | |
| 57 | 43 | /** |
| 58 | 44 | * dpu_format_check_modified_format - validate format and buffers for |
| 59 | 45 | * dpu non-standard, i.e. modified format |
| @@ -151,7 +151,9 @@ static const struct dpu_sspp_blks_common sdm845_sspp_common = { · 150 unmodified lines | ||
| 151 | 151 | .id = DPU_SSPP_CSC_10BIT, \ |
| 152 | 152 | .base = 0x1a00, .len = 0x100,}, \ |
| 153 | 153 | .format_list = plane_formats_yuv, \ |
| 154 | + .num_formats = ARRAY_SIZE(plane_formats_yuv), \ | |
| 154 | 155 | .virt_format_list = plane_formats, \ |
| 156 | + .virt_num_formats = ARRAY_SIZE(plane_formats), \ | |
| 155 | 157 | } |
| 156 | 158 | |
| 157 | 159 | #define _DMA_SBLK(num, sdma_pri) \ |
| @@ -163,7 +165,9 @@ static const struct dpu_sspp_blks_common sdm845_sspp_common = { · 5 unmodified lines | ||
| 163 | 165 | .src_blk = {.name = STRCAT("sspp_src_", num), \ |
| 164 | 166 | .id = DPU_SSPP_SRC, .base = 0x00, .len = 0x150,}, \ |
| 165 | 167 | .format_list = plane_formats, \ |
| 168 | + .num_formats = ARRAY_SIZE(plane_formats), \ | |
| 166 | 169 | .virt_format_list = plane_formats, \ |
| 170 | + .virt_num_formats = ARRAY_SIZE(plane_formats), \ | |
| 167 | 171 | } |
| 168 | 172 | |
| 169 | 173 | static const struct dpu_sspp_sub_blks sdm845_vig_sblk_0 = _VIG_SBLK("0", 5); |
| @@ -251,17 +251,6 @@ struct dpu_pp_blk { · 250 unmodified lines | ||
| 251 | 251 | u32 version; |
| 252 | 252 | }; |
| 253 | 253 | |
| 254 | −/** | |
| 255 | − * struct dpu_format_extended - define dpu specific pixel format+modifier | |
| 256 | − * @fourcc_format: Base FOURCC pixel format code | |
| 257 | − * @modifier: 64-bit drm format modifier, same modifier must be applied to all | |
| 258 | − * framebuffer planes | |
| 259 | − */ | |
| 260 | −struct dpu_format_extended { | |
| 261 | − uint32_t fourcc_format; | |
| 262 | − uint64_t modifier; | |
| 263 | −}; | |
| 264 | − | |
| 265 | 254 | /** |
| 266 | 255 | * enum dpu_qos_lut_usage - define QoS LUT use cases |
| 267 | 256 | */ |
| @@ -348,7 +337,9 @@ struct dpu_sspp_blks_common { · 80 unmodified lines | ||
| 348 | 337 | * @pcc_blk: |
| 349 | 338 | * @igc_blk: |
| 350 | 339 | * @format_list: Pointer to list of supported formats |
| 340 | + * @num_formats: Number of supported formats | |
| 351 | 341 | * @virt_format_list: Pointer to list of supported formats for virtual planes |
| 342 | + * @virt_num_formats: Number of supported formats for virtual planes | |
| 352 | 343 | */ |
| 353 | 344 | struct dpu_sspp_sub_blks { |
| 354 | 345 | const struct dpu_sspp_blks_common *common; |
| @@ -366,8 +357,10 @@ struct dpu_sspp_sub_blks { · 11 unmodified lines | ||
| 366 | 357 | struct dpu_pp_blk pcc_blk; |
| 367 | 358 | struct dpu_pp_blk igc_blk; |
| 368 | 359 | |
| 369 | − const struct dpu_format_extended *format_list; | |
| 370 | − const struct dpu_format_extended *virt_format_list; | |
| 360 | + const u32 *format_list; | |
| 361 | + u32 num_formats; | |
| 362 | + const u32 *virt_format_list; | |
| 363 | + u32 virt_num_formats; | |
| 371 | 364 | }; |
| 372 | 365 | |
| 373 | 366 | /** |
| @@ -12,157 +12,81 @@ · 11 unmodified lines | ||
| 12 | 12 | |
| 13 | 13 | #include "dpu_hw_mdss.h" |
| 14 | 14 | |
| 15 | −static const struct dpu_format_extended plane_formats[] = { | |
| 16 | − {DRM_FORMAT_ARGB8888, 0}, | |
| 17 | − {DRM_FORMAT_ABGR8888, 0}, | |
| 18 | − {DRM_FORMAT_RGBA8888, 0}, | |
| 19 | − {DRM_FORMAT_ABGR8888, DRM_FORMAT_MOD_QCOM_COMPRESSED}, | |
| 20 | − {DRM_FORMAT_BGRA8888, 0}, | |
| 21 | − {DRM_FORMAT_XRGB8888, 0}, | |
| 22 | − {DRM_FORMAT_RGBX8888, 0}, | |
| 23 | − {DRM_FORMAT_BGRX8888, 0}, | |
| 24 | − {DRM_FORMAT_XBGR8888, 0}, | |
| 25 | − {DRM_FORMAT_XBGR8888, DRM_FORMAT_MOD_QCOM_COMPRESSED}, | |
| 26 | − {DRM_FORMAT_RGB888, 0}, | |
| 27 | − {DRM_FORMAT_BGR888, 0}, | |
| 28 | − {DRM_FORMAT_RGB565, 0}, | |
| 29 | − {DRM_FORMAT_BGR565, DRM_FORMAT_MOD_QCOM_COMPRESSED}, | |
| 30 | − {DRM_FORMAT_BGR565, 0}, | |
| 31 | − {DRM_FORMAT_ARGB1555, 0}, | |
| 32 | − {DRM_FORMAT_ABGR1555, 0}, | |
| 33 | − {DRM_FORMAT_RGBA5551, 0}, | |
| 34 | − {DRM_FORMAT_BGRA5551, 0}, | |
| 35 | − {DRM_FORMAT_XRGB1555, 0}, | |
| 36 | − {DRM_FORMAT_XBGR1555, 0}, | |
| 37 | − {DRM_FORMAT_RGBX5551, 0}, | |
| 38 | − {DRM_FORMAT_BGRX5551, 0}, | |
| 39 | − {DRM_FORMAT_ARGB4444, 0}, | |
| 40 | − {DRM_FORMAT_ABGR4444, 0}, | |
| 41 | − {DRM_FORMAT_RGBA4444, 0}, | |
| 42 | − {DRM_FORMAT_BGRA4444, 0}, | |
| 43 | − {DRM_FORMAT_XRGB4444, 0}, | |
| 44 | − {DRM_FORMAT_XBGR4444, 0}, | |
| 45 | − {DRM_FORMAT_RGBX4444, 0}, | |
| 46 | − {DRM_FORMAT_BGRX4444, 0}, | |
| 47 | − {0, 0}, | |
| 15 | +static const uint32_t qcom_compressed_supported_formats[] = { | |
| 16 | + DRM_FORMAT_ABGR8888, | |
| 17 | + DRM_FORMAT_XBGR8888, | |
| 18 | + DRM_FORMAT_BGR565, | |
| 48 | 19 | }; |
| 49 | 20 | |
| 50 | −static const struct dpu_format_extended plane_formats_yuv[] = { | |
| 51 | − {DRM_FORMAT_ARGB8888, 0}, | |
| 52 | − {DRM_FORMAT_ABGR8888, 0}, | |
| 53 | − {DRM_FORMAT_RGBA8888, 0}, | |
| 54 | − {DRM_FORMAT_BGRX8888, 0}, | |
| 55 | − {DRM_FORMAT_ABGR8888, DRM_FORMAT_MOD_QCOM_COMPRESSED}, | |
| 56 | − {DRM_FORMAT_BGRA8888, 0}, | |
| 57 | − {DRM_FORMAT_XRGB8888, 0}, | |
| 58 | − {DRM_FORMAT_XBGR8888, 0}, | |
| 59 | − {DRM_FORMAT_RGBX8888, 0}, | |
| 60 | − {DRM_FORMAT_XBGR8888, DRM_FORMAT_MOD_QCOM_COMPRESSED}, | |
| 61 | − {DRM_FORMAT_RGB888, 0}, | |
| 62 | − {DRM_FORMAT_BGR888, 0}, | |
| 63 | − {DRM_FORMAT_RGB565, 0}, | |
| 64 | − {DRM_FORMAT_BGR565, DRM_FORMAT_MOD_QCOM_COMPRESSED}, | |
| 65 | − {DRM_FORMAT_BGR565, 0}, | |
| 66 | − {DRM_FORMAT_ARGB1555, 0}, | |
| 67 | − {DRM_FORMAT_ABGR1555, 0}, | |
| 68 | − {DRM_FORMAT_RGBA5551, 0}, | |
| 69 | − {DRM_FORMAT_BGRA5551, 0}, | |
| 70 | − {DRM_FORMAT_XRGB1555, 0}, | |
| 71 | − {DRM_FORMAT_XBGR1555, 0}, | |
| 72 | − {DRM_FORMAT_RGBX5551, 0}, | |
| 73 | − {DRM_FORMAT_BGRX5551, 0}, | |
| 74 | − {DRM_FORMAT_ARGB4444, 0}, | |
| 75 | − {DRM_FORMAT_ABGR4444, 0}, | |
| 76 | − {DRM_FORMAT_RGBA4444, 0}, | |
| 77 | − {DRM_FORMAT_BGRA4444, 0}, | |
| 78 | − {DRM_FORMAT_XRGB4444, 0}, | |
| 79 | − {DRM_FORMAT_XBGR4444, 0}, | |
| 80 | − {DRM_FORMAT_RGBX4444, 0}, | |
| 81 | − {DRM_FORMAT_BGRX4444, 0}, | |
| 82 | − | |
| 83 | − {DRM_FORMAT_NV12, 0}, | |
| 84 | − {DRM_FORMAT_NV12, DRM_FORMAT_MOD_QCOM_COMPRESSED}, | |
| 85 | − {DRM_FORMAT_NV21, 0}, | |
| 86 | − {DRM_FORMAT_NV16, 0}, | |
| 87 | − {DRM_FORMAT_NV61, 0}, | |
| 88 | − {DRM_FORMAT_VYUY, 0}, | |
| 89 | − {DRM_FORMAT_UYVY, 0}, | |
| 90 | − {DRM_FORMAT_YUYV, 0}, | |
| 91 | − {DRM_FORMAT_YVYU, 0}, | |
| 92 | − {DRM_FORMAT_YUV420, 0}, | |
| 93 | − {DRM_FORMAT_YVU420, 0}, | |
| 94 | − {0, 0}, | |
| 95 | −}; | |
| 96 | − | |
| 97 | −static const struct dpu_format_extended cursor_formats[] = { | |
| 98 | − {DRM_FORMAT_ARGB8888, 0}, | |
| 99 | − {DRM_FORMAT_ABGR8888, 0}, | |
| 100 | − {DRM_FORMAT_RGBA8888, 0}, | |
| 101 | − {DRM_FORMAT_BGRA8888, 0}, | |
| 102 | − {DRM_FORMAT_XRGB8888, 0}, | |
| 103 | − {DRM_FORMAT_ARGB1555, 0}, | |
| 104 | − {DRM_FORMAT_ABGR1555, 0}, | |
| 105 | − {DRM_FORMAT_RGBA5551, 0}, | |
| 106 | − {DRM_FORMAT_BGRA5551, 0}, | |
| 107 | − {DRM_FORMAT_ARGB4444, 0}, | |
| 108 | − {DRM_FORMAT_ABGR4444, 0}, | |
| 109 | − {DRM_FORMAT_RGBA4444, 0}, | |
| 110 | − {DRM_FORMAT_BGRA4444, 0}, | |
| 111 | − {0, 0}, | |
| 21 | +static const uint32_t plane_formats[] = { | |
| 22 | + DRM_FORMAT_ARGB8888, | |
| 23 | + DRM_FORMAT_ABGR8888, | |
| 24 | + DRM_FORMAT_RGBA8888, | |
| 25 | + DRM_FORMAT_BGRA8888, | |
| 26 | + DRM_FORMAT_XRGB8888, | |
| 27 | + DRM_FORMAT_RGBX8888, | |
| 28 | + DRM_FORMAT_BGRX8888, | |
| 29 | + DRM_FORMAT_XBGR8888, | |
| 30 | + DRM_FORMAT_RGB888, | |
| 31 | + DRM_FORMAT_BGR888, | |
| 32 | + DRM_FORMAT_RGB565, | |
| 33 | + DRM_FORMAT_BGR565, | |
| 34 | + DRM_FORMAT_ARGB1555, | |
| 35 | + DRM_FORMAT_ABGR1555, | |
| 36 | + DRM_FORMAT_RGBA5551, | |
| 37 | + DRM_FORMAT_BGRA5551, | |
| 38 | + DRM_FORMAT_XRGB1555, | |
| 39 | + DRM_FORMAT_XBGR1555, | |
| 40 | + DRM_FORMAT_RGBX5551, | |
| 41 | + DRM_FORMAT_BGRX5551, | |
| 42 | + DRM_FORMAT_ARGB4444, | |
| 43 | + DRM_FORMAT_ABGR4444, | |
| 44 | + DRM_FORMAT_RGBA4444, | |
| 45 | + DRM_FORMAT_BGRA4444, | |
| 46 | + DRM_FORMAT_XRGB4444, | |
| 47 | + DRM_FORMAT_XBGR4444, | |
| 48 | + DRM_FORMAT_RGBX4444, | |
| 49 | + DRM_FORMAT_BGRX4444, | |
| 112 | 50 | }; |
| 113 | 51 | |
| 114 | −static const struct dpu_format_extended wb2_formats[] = { | |
| 115 | − {DRM_FORMAT_RGB565, 0}, | |
| 116 | − {DRM_FORMAT_BGR565, DRM_FORMAT_MOD_QCOM_COMPRESSED}, | |
| 117 | − {DRM_FORMAT_RGB888, 0}, | |
| 118 | − {DRM_FORMAT_ARGB8888, 0}, | |
| 119 | − {DRM_FORMAT_RGBA8888, 0}, | |
| 120 | − {DRM_FORMAT_ABGR8888, DRM_FORMAT_MOD_QCOM_COMPRESSED}, | |
| 121 | − {DRM_FORMAT_XRGB8888, 0}, | |
| 122 | − {DRM_FORMAT_RGBX8888, 0}, | |
| 123 | − {DRM_FORMAT_XBGR8888, DRM_FORMAT_MOD_QCOM_COMPRESSED}, | |
| 124 | − {DRM_FORMAT_ARGB1555, 0}, | |
| 125 | − {DRM_FORMAT_RGBA5551, 0}, | |
| 126 | − {DRM_FORMAT_XRGB1555, 0}, | |
| 127 | − {DRM_FORMAT_RGBX5551, 0}, | |
| 128 | − {DRM_FORMAT_ARGB4444, 0}, | |
| 129 | − {DRM_FORMAT_RGBA4444, 0}, | |
| 130 | − {DRM_FORMAT_RGBX4444, 0}, | |
| 131 | − {DRM_FORMAT_XRGB4444, 0}, | |
| 132 | − | |
| 133 | − {DRM_FORMAT_BGR565, 0}, | |
| 134 | − {DRM_FORMAT_BGR888, 0}, | |
| 135 | − {DRM_FORMAT_ABGR8888, 0}, | |
| 136 | − {DRM_FORMAT_BGRA8888, 0}, | |
| 137 | − {DRM_FORMAT_BGRX8888, 0}, | |
| 138 | − {DRM_FORMAT_XBGR8888, 0}, | |
| 139 | − {DRM_FORMAT_ABGR1555, 0}, | |
| 140 | − {DRM_FORMAT_BGRA5551, 0}, | |
| 141 | − {DRM_FORMAT_XBGR1555, 0}, | |
| 142 | − {DRM_FORMAT_BGRX5551, 0}, | |
| 143 | − {DRM_FORMAT_ABGR4444, 0}, | |
| 144 | − {DRM_FORMAT_BGRA4444, 0}, | |
| 145 | − {DRM_FORMAT_BGRX4444, 0}, | |
| 146 | − {DRM_FORMAT_XBGR4444, 0}, | |
| 147 | − | |
| 148 | − {DRM_FORMAT_YUV420, 0}, | |
| 149 | − {DRM_FORMAT_NV12, 0}, | |
| 150 | − {DRM_FORMAT_NV12, DRM_FORMAT_MOD_QCOM_COMPRESSED}, | |
| 151 | − {DRM_FORMAT_NV16, 0}, | |
| 152 | − {DRM_FORMAT_YUYV, 0}, | |
| 153 | − | |
| 154 | − {0, 0}, | |
| 155 | −}; | |
| 52 | +static const uint32_t plane_formats_yuv[] = { | |
| 53 | + DRM_FORMAT_ARGB8888, | |
| 54 | + DRM_FORMAT_ABGR8888, | |
| 55 | + DRM_FORMAT_RGBA8888, | |
| 56 | + DRM_FORMAT_BGRX8888, | |
| 57 | + DRM_FORMAT_BGRA8888, | |
| 58 | + DRM_FORMAT_XRGB8888, | |
| 59 | + DRM_FORMAT_XBGR8888, | |
| 60 | + DRM_FORMAT_RGBX8888, | |
| 61 | + DRM_FORMAT_RGB888, | |
| 62 | + DRM_FORMAT_BGR888, | |
| 63 | + DRM_FORMAT_RGB565, | |
| 64 | + DRM_FORMAT_BGR565, | |
| 65 | + DRM_FORMAT_ARGB1555, | |
| 66 | + DRM_FORMAT_ABGR1555, | |
| 67 | + DRM_FORMAT_RGBA5551, | |
| 68 | + DRM_FORMAT_BGRA5551, | |
| 69 | + DRM_FORMAT_XRGB1555, | |
| 70 | + DRM_FORMAT_XBGR1555, | |
| 71 | + DRM_FORMAT_RGBX5551, | |
| 72 | + DRM_FORMAT_BGRX5551, | |
| 73 | + DRM_FORMAT_ARGB4444, | |
| 74 | + DRM_FORMAT_ABGR4444, | |
| 75 | + DRM_FORMAT_RGBA4444, | |
| 76 | + DRM_FORMAT_BGRA4444, | |
| 77 | + DRM_FORMAT_XRGB4444, | |
| 78 | + DRM_FORMAT_XBGR4444, | |
| 79 | + DRM_FORMAT_RGBX4444, | |
| 80 | + DRM_FORMAT_BGRX4444, | |
| 156 | 81 | |
| 157 | −static const struct dpu_format_extended rgb_10bit_formats[] = { | |
| 158 | − {DRM_FORMAT_BGRA1010102, 0}, | |
| 159 | − {DRM_FORMAT_BGRX1010102, 0}, | |
| 160 | − {DRM_FORMAT_RGBA1010102, 0}, | |
| 161 | − {DRM_FORMAT_RGBX1010102, 0}, | |
| 162 | − {DRM_FORMAT_ABGR2101010, 0}, | |
| 163 | − {DRM_FORMAT_ABGR2101010, DRM_FORMAT_MOD_QCOM_COMPRESSED}, | |
| 164 | − {DRM_FORMAT_XBGR2101010, 0}, | |
| 165 | − {DRM_FORMAT_XBGR2101010, DRM_FORMAT_MOD_QCOM_COMPRESSED}, | |
| 166 | − {DRM_FORMAT_ARGB2101010, 0}, | |
| 167 | − {DRM_FORMAT_XRGB2101010, 0}, | |
| 82 | + DRM_FORMAT_NV12, | |
| 83 | + DRM_FORMAT_NV21, | |
| 84 | + DRM_FORMAT_NV16, | |
| 85 | + DRM_FORMAT_NV61, | |
| 86 | + DRM_FORMAT_VYUY, | |
| 87 | + DRM_FORMAT_UYVY, | |
| 88 | + DRM_FORMAT_YUYV, | |
| 89 | + DRM_FORMAT_YVYU, | |
| 90 | + DRM_FORMAT_YUV420, | |
| 91 | + DRM_FORMAT_YVU420, | |
| 168 | 92 | }; |
| @@ -170,10 +170,6 @@ · 169 unmodified lines | ||
| 170 | 170 | /** |
| 171 | 171 | * AD4 interrupt status bit definitions |
| 172 | 172 | */ |
| 173 | −#define DPU_INTR_BRIGHTPR_UPDATED BIT(4) | |
| 174 | −#define DPU_INTR_DARKENH_UPDATED BIT(3) | |
| 175 | −#define DPU_INTR_STREN_OUTROI_UPDATED BIT(2) | |
| 176 | −#define DPU_INTR_STREN_INROI_UPDATED BIT(1) | |
| 177 | 173 | #define DPU_INTR_BACKLIGHT_UPDATED BIT(0) |
| 178 | 174 | /** |
| 179 | 175 | * struct dpu_intr_reg - array of DPU register sets |
| @@ -782,18 +778,6 @@ static int dpu_hw_intr_irqidx_lookup(enum dpu_intr_type intr_type, · 602 unmodified lines | ||
| 782 | 778 | return -EINVAL; |
| 783 | 779 | } |
| 784 | 780 | |
| 785 | −static void dpu_hw_intr_set_mask(struct dpu_hw_intr *intr, uint32_t reg_off, | |
| 786 | − uint32_t mask) | |
| 787 | −{ | |
| 788 | − if (!intr) | |
| 789 | − return; | |
| 790 | − | |
| 791 | − DPU_REG_WRITE(&intr->hw, reg_off, mask); | |
| 792 | − | |
| 793 | − /* ensure register writes go through */ | |
| 794 | − wmb(); | |
| 795 | −} | |
| 796 | − | |
| 797 | 781 | static void dpu_hw_intr_dispatch_irq(struct dpu_hw_intr *intr, |
| 798 | 782 | void (*cbfunc)(void *, int), |
| 799 | 783 | void *arg) |
| @@ -1004,18 +988,6 @@ static int dpu_hw_intr_disable_irqs(struct dpu_hw_intr *intr) · 204 unmodified lines | ||
| 1004 | 988 | return 0; |
| 1005 | 989 | } |
| 1006 | 990 | |
| 1007 | −static int dpu_hw_intr_get_valid_interrupts(struct dpu_hw_intr *intr, | |
| 1008 | − uint32_t *mask) | |
| 1009 | −{ | |
| 1010 | − if (!intr || !mask) | |
| 1011 | − return -EINVAL; | |
| 1012 | − | |
| 1013 | − *mask = IRQ_SOURCE_MDP | IRQ_SOURCE_DSI0 | IRQ_SOURCE_DSI1 | |
| 1014 | − | IRQ_SOURCE_HDMI | IRQ_SOURCE_EDP; | |
| 1015 | − | |
| 1016 | − return 0; | |
| 1017 | −} | |
| 1018 | − | |
| 1019 | 991 | static void dpu_hw_intr_get_interrupt_statuses(struct dpu_hw_intr *intr) |
| 1020 | 992 | { |
| 1021 | 993 | int i; |
| @@ -1065,19 +1037,6 @@ static void dpu_hw_intr_clear_intr_status_nolock(struct dpu_hw_intr *intr, · 43 unmodified lines | ||
| 1065 | 1037 | wmb(); |
| 1066 | 1038 | } |
| 1067 | 1039 | |
| 1068 | −static void dpu_hw_intr_clear_interrupt_status(struct dpu_hw_intr *intr, | |
| 1069 | − int irq_idx) | |
| 1070 | −{ | |
| 1071 | − unsigned long irq_flags; | |
| 1072 | − | |
| 1073 | − if (!intr) | |
| 1074 | − return; | |
| 1075 | − | |
| 1076 | − spin_lock_irqsave(&intr->irq_lock, irq_flags); | |
| 1077 | − dpu_hw_intr_clear_intr_status_nolock(intr, irq_idx); | |
| 1078 | − spin_unlock_irqrestore(&intr->irq_lock, irq_flags); | |
| 1079 | −} | |
| 1080 | − | |
| 1081 | 1040 | static u32 dpu_hw_intr_get_interrupt_status(struct dpu_hw_intr *intr, |
| 1082 | 1041 | int irq_idx, bool clear) |
| 1083 | 1042 | { |
| @@ -1113,16 +1072,13 @@ static u32 dpu_hw_intr_get_interrupt_status(struct dpu_hw_intr *intr, · 29 unmodified lines | ||
| 1113 | 1072 | |
| 1114 | 1073 | static void __setup_intr_ops(struct dpu_hw_intr_ops *ops) |
| 1115 | 1074 | { |
| 1116 | − ops->set_mask = dpu_hw_intr_set_mask; | |
| 1117 | 1075 | ops->irq_idx_lookup = dpu_hw_intr_irqidx_lookup; |
| 1118 | 1076 | ops->enable_irq = dpu_hw_intr_enable_irq; |
| 1119 | 1077 | ops->disable_irq = dpu_hw_intr_disable_irq; |
| 1120 | 1078 | ops->dispatch_irqs = dpu_hw_intr_dispatch_irq; |
| 1121 | 1079 | ops->clear_all_irqs = dpu_hw_intr_clear_irqs; |
| 1122 | 1080 | ops->disable_all_irqs = dpu_hw_intr_disable_irqs; |
| 1123 | − ops->get_valid_interrupts = dpu_hw_intr_get_valid_interrupts; | |
| 1124 | 1081 | ops->get_interrupt_statuses = dpu_hw_intr_get_interrupt_statuses; |
| 1125 | − ops->clear_interrupt_status = dpu_hw_intr_clear_interrupt_status; | |
| 1126 | 1082 | ops->clear_intr_status_nolock = dpu_hw_intr_clear_intr_status_nolock; |
| 1127 | 1083 | ops->get_interrupt_status = dpu_hw_intr_get_interrupt_status; |
| 1128 | 1084 | } |
| @@ -20,13 +20,6 @@ · 19 unmodified lines | ||
| 20 | 20 | #include "dpu_hw_util.h" |
| 21 | 21 | #include "dpu_hw_mdss.h" |
| 22 | 22 | |
| 23 | −#define IRQ_SOURCE_MDP BIT(0) | |
| 24 | −#define IRQ_SOURCE_DSI0 BIT(4) | |
| 25 | −#define IRQ_SOURCE_DSI1 BIT(5) | |
| 26 | −#define IRQ_SOURCE_HDMI BIT(8) | |
| 27 | −#define IRQ_SOURCE_EDP BIT(12) | |
| 28 | −#define IRQ_SOURCE_MHL BIT(16) | |
| 29 | − | |
| 30 | 23 | /** |
| 31 | 24 | * dpu_intr_type - HW Interrupt Type |
| 32 | 25 | * @DPU_IRQ_TYPE_WB_ROT_COMP: WB rotator done |
| @@ -95,18 +88,6 @@ struct dpu_hw_intr; · 62 unmodified lines | ||
| 95 | 88 | * Interrupt operations. |
| 96 | 89 | */ |
| 97 | 90 | struct dpu_hw_intr_ops { |
| 98 | − /** | |
| 99 | − * set_mask - Programs the given interrupt register with the | |
| 100 | − * given interrupt mask. Register value will get overwritten. | |
| 101 | − * @intr: HW interrupt handle | |
| 102 | − * @reg_off: MDSS HW register offset | |
| 103 | − * @irqmask: IRQ mask value | |
| 104 | − */ | |
| 105 | − void (*set_mask)( | |
| 106 | − struct dpu_hw_intr *intr, | |
| 107 | − uint32_t reg, | |
| 108 | − uint32_t irqmask); | |
| 109 | − | |
| 110 | 91 | /** |
| 111 | 92 | * irq_idx_lookup - Lookup IRQ index on the HW interrupt type |
| 112 | 93 | * Used for all irq related ops |
| @@ -176,16 +157,6 @@ struct dpu_hw_intr_ops { · 63 unmodified lines | ||
| 176 | 157 | void (*get_interrupt_statuses)( |
| 177 | 158 | struct dpu_hw_intr *intr); |
| 178 | 159 | |
| 179 | − /** | |
| 180 | − * clear_interrupt_status - Clears HW interrupt status based on given | |
| 181 | − * lookup IRQ index. | |
| 182 | − * @intr: HW interrupt handle | |
| 183 | − * @irq_idx: Lookup irq index return from irq_idx_lookup | |
| 184 | − */ | |
| 185 | − void (*clear_interrupt_status)( | |
| 186 | − struct dpu_hw_intr *intr, | |
| 187 | − int irq_idx); | |
| 188 | − | |
| 189 | 160 | /** |
| 190 | 161 | * clear_intr_status_nolock() - clears the HW interrupts without lock |
| 191 | 162 | * @intr: HW interrupt handle |
| @@ -206,21 +177,6 @@ struct dpu_hw_intr_ops { · 14 unmodified lines | ||
| 206 | 177 | struct dpu_hw_intr *intr, |
| 207 | 178 | int irq_idx, |
| 208 | 179 | bool clear); |
| 209 | − | |
| 210 | − /** | |
| 211 | − * get_valid_interrupts - Gets a mask of all valid interrupt sources | |
| 212 | − * within DPU. These are actually status bits | |
| 213 | − * within interrupt registers that specify the | |
| 214 | − * source of the interrupt in IRQs. For example, | |
| 215 | − * valid interrupt sources can be MDP, DSI, | |
| 216 | − * HDMI etc. | |
| 217 | − * @intr: HW interrupt handle | |
| 218 | − * @mask: Returning the interrupt source MASK | |
| 219 | − * @return: 0 for success, otherwise failure | |
| 220 | − */ | |
| 221 | − int (*get_valid_interrupts)( | |
| 222 | − struct dpu_hw_intr *intr, | |
| 223 | − uint32_t *mask); | |
| 224 | 180 | }; |
| 225 | 181 | |
| 226 | 182 | /** |
| @@ -258,12 +258,6 @@ enum dpu_vbif { · 257 unmodified lines | ||
| 258 | 258 | VBIF_NRT = VBIF_1 |
| 259 | 259 | }; |
| 260 | 260 | |
| 261 | −enum dpu_iommu_domain { | |
| 262 | − DPU_IOMMU_DOMAIN_UNSECURE, | |
| 263 | − DPU_IOMMU_DOMAIN_SECURE, | |
| 264 | − DPU_IOMMU_DOMAIN_MAX | |
| 265 | −}; | |
| 266 | − | |
| 267 | 261 | /** |
| 268 | 262 | * DPU HW,Component order color map |
| 269 | 263 | */ |
| @@ -358,7 +352,6 @@ enum dpu_3d_blend_mode { · 88 unmodified lines | ||
| 358 | 352 | * @alpha_enable: whether the format has an alpha channel |
| 359 | 353 | * @num_planes: number of planes (including meta data planes) |
| 360 | 354 | * @fetch_mode: linear, tiled, or ubwc hw fetch behavior |
| 361 | − * @is_yuv: is format a yuv variant | |
| 362 | 355 | * @flag: usage bit flags |
| 363 | 356 | * @tile_width: format tile width |
| 364 | 357 | * @tile_height: format tile height |
| @@ -18,7 +18,6 @@ · 17 unmodified lines | ||
| 18 | 18 | #include "dpu_hw_mdss.h" |
| 19 | 19 | |
| 20 | 20 | #define REG_MASK(n) ((BIT(n)) - 1) |
| 21 | −struct dpu_format_extended; | |
| 22 | 21 | |
| 23 | 22 | /* |
| 24 | 23 | * This is the common struct maintained by each sub block |
| @@ -405,35 +405,38 @@ static void dpu_kms_wait_for_commit_done(struct msm_kms *kms, · 404 unmodified lines | ||
| 405 | 405 | } |
| 406 | 406 | } |
| 407 | 407 | |
| 408 | −static void _dpu_kms_initialize_dsi(struct drm_device *dev, | |
| 408 | +static int _dpu_kms_initialize_dsi(struct drm_device *dev, | |
| 409 | 409 | struct msm_drm_private *priv, |
| 410 | 410 | struct dpu_kms *dpu_kms) |
| 411 | 411 | { |
| 412 | 412 | struct drm_encoder *encoder = NULL; |
| 413 | − int i, rc; | |
| 413 | + int i, rc = 0; | |
| 414 | + | |
| 415 | + if (!(priv->dsi[0] || priv->dsi[1])) | |
| 416 | + return rc; | |
| 414 | 417 | |
| 415 | 418 | /*TODO: Support two independent DSI connectors */ |
| 416 | 419 | encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_DSI); |
| 417 | − if (IS_ERR_OR_NULL(encoder)) { | |
| 420 | + if (IS_ERR(encoder)) { | |
| 418 | 421 | DPU_ERROR("encoder init failed for dsi display\n"); |
| 419 | − return; | |
| 422 | + return PTR_ERR(encoder); | |
| 420 | 423 | } |
| 421 | 424 | |
| 422 | 425 | priv->encoders[priv->num_encoders++] = encoder; |
| 423 | 426 | |
| 424 | 427 | for (i = 0; i < ARRAY_SIZE(priv->dsi); i++) { |
| 425 | − if (!priv->dsi[i]) { | |
| 426 | − DPU_DEBUG("invalid msm_dsi for ctrl %d\n", i); | |
| 427 | − return; | |
| 428 | − } | |
| 428 | + if (!priv->dsi[i]) | |
| 429 | + continue; | |
| 429 | 430 | |
| 430 | 431 | rc = msm_dsi_modeset_init(priv->dsi[i], dev, encoder); |
| 431 | 432 | if (rc) { |
| 432 | 433 | DPU_ERROR("modeset_init failed for dsi[%d], rc = %d\n", |
| 433 | 434 | i, rc); |
| 434 | − continue; | |
| 435 | + break; | |
| 435 | 436 | } |
| 436 | 437 | } |
| 438 | + | |
| 439 | + return rc; | |
| 437 | 440 | } |
| 438 | 441 | |
| 439 | 442 | /** |
| @@ -444,16 +447,16 @@ static void _dpu_kms_initialize_dsi(struct drm_device *dev, · 4 unmodified lines | ||
| 444 | 447 | * @dpu_kms: Pointer to dpu kms structure |
| 445 | 448 | * Returns: Zero on success |
| 446 | 449 | */ |
| 447 | −static void _dpu_kms_setup_displays(struct drm_device *dev, | |
| 450 | +static int _dpu_kms_setup_displays(struct drm_device *dev, | |
| 448 | 451 | struct msm_drm_private *priv, |
| 449 | 452 | struct dpu_kms *dpu_kms) |
| 450 | 453 | { |
| 451 | − _dpu_kms_initialize_dsi(dev, priv, dpu_kms); | |
| 452 | − | |
| 453 | 454 | /** |
| 454 | 455 | * Extend this function to initialize other |
| 455 | 456 | * types of displays |
| 456 | 457 | */ |
| 458 | + | |
| 459 | + return _dpu_kms_initialize_dsi(dev, priv, dpu_kms); | |
| 457 | 460 | } |
| 458 | 461 | |
| 459 | 462 | static void _dpu_kms_drm_obj_destroy(struct dpu_kms *dpu_kms) |
| @@ -516,7 +519,9 @@ static int _dpu_kms_drm_obj_init(struct dpu_kms *dpu_kms) · 56 unmodified lines | ||
| 516 | 519 | * Create encoder and query display drivers to create |
| 517 | 520 | * bridges and connectors |
| 518 | 521 | */ |
| 519 | − _dpu_kms_setup_displays(dev, priv, dpu_kms); | |
| 522 | + ret = _dpu_kms_setup_displays(dev, priv, dpu_kms); | |
| 523 | + if (ret) | |
| 524 | + goto fail; | |
| 520 | 525 | |
| 521 | 526 | max_crtc_count = min(catalog->mixer_count, priv->num_encoders); |
| 522 | 527 | |
| @@ -627,6 +632,10 @@ static void _dpu_kms_hw_destroy(struct dpu_kms *dpu_kms) · 104 unmodified lines | ||
| 627 | 632 | devm_iounmap(&dpu_kms->pdev->dev, dpu_kms->vbif[VBIF_RT]); |
| 628 | 633 | dpu_kms->vbif[VBIF_RT] = NULL; |
| 629 | 634 | |
| 635 | + if (dpu_kms->hw_mdp) | |
| 636 | + dpu_hw_mdp_destroy(dpu_kms->hw_mdp); | |
| 637 | + dpu_kms->hw_mdp = NULL; | |
| 638 | + | |
| 630 | 639 | if (dpu_kms->mmio) |
| 631 | 640 | devm_iounmap(&dpu_kms->pdev->dev, dpu_kms->mmio); |
| 632 | 641 | dpu_kms->mmio = NULL; |
| @@ -877,8 +886,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) · 244 unmodified lines | ||
| 877 | 886 | goto power_error; |
| 878 | 887 | } |
| 879 | 888 | |
| 880 | − rc = dpu_rm_init(&dpu_kms->rm, dpu_kms->catalog, dpu_kms->mmio, | |
| 881 | − dpu_kms->dev); | |
| 889 | + rc = dpu_rm_init(&dpu_kms->rm, dpu_kms->catalog, dpu_kms->mmio); | |
| 882 | 890 | if (rc) { |
| 883 | 891 | DPU_ERROR("rm init failed: %d\n", rc); |
| 884 | 892 | goto power_error; |
| @@ -886,11 +894,10 @@ static int dpu_kms_hw_init(struct msm_kms *kms) · 1 unmodified line | ||
| 886 | 894 | |
| 887 | 895 | dpu_kms->rm_init = true; |
| 888 | 896 | |
| 889 | − dpu_kms->hw_mdp = dpu_rm_get_mdp(&dpu_kms->rm); | |
| 890 | − if (IS_ERR_OR_NULL(dpu_kms->hw_mdp)) { | |
| 897 | + dpu_kms->hw_mdp = dpu_hw_mdptop_init(MDP_TOP, dpu_kms->mmio, | |
| 898 | + dpu_kms->catalog); | |
| 899 | + if (IS_ERR(dpu_kms->hw_mdp)) { | |
| 891 | 900 | rc = PTR_ERR(dpu_kms->hw_mdp); |
| 892 | − if (!dpu_kms->hw_mdp) | |
| 893 | − rc = -EINVAL; | |
| 894 | 901 | DPU_ERROR("failed to get hw_mdp: %d\n", rc); |
| 895 | 902 | dpu_kms->hw_mdp = NULL; |
| 896 | 903 | goto power_error; |
| @@ -926,16 +933,6 @@ static int dpu_kms_hw_init(struct msm_kms *kms) · 29 unmodified lines | ||
| 926 | 933 | goto hw_intr_init_err; |
| 927 | 934 | } |
| 928 | 935 | |
| 929 | − /* | |
| 930 | − * _dpu_kms_drm_obj_init should create the DRM related objects | |
| 931 | − * i.e. CRTCs, planes, encoders, connectors and so forth | |
| 932 | − */ | |
| 933 | − rc = _dpu_kms_drm_obj_init(dpu_kms); | |
| 934 | − if (rc) { | |
| 935 | − DPU_ERROR("modeset init failed: %d\n", rc); | |
| 936 | − goto drm_obj_init_err; | |
| 937 | − } | |
| 938 | − | |
| 939 | 936 | dev->mode_config.min_width = 0; |
| 940 | 937 | dev->mode_config.min_height = 0; |
| 941 | 938 | |
| @@ -952,6 +949,16 @@ static int dpu_kms_hw_init(struct msm_kms *kms) · 10 unmodified lines | ||
| 952 | 949 | */ |
| 953 | 950 | dev->mode_config.allow_fb_modifiers = true; |
| 954 | 951 | |
| 952 | + /* | |
| 953 | + * _dpu_kms_drm_obj_init should create the DRM related objects | |
| 954 | + * i.e. CRTCs, planes, encoders, connectors and so forth | |
| 955 | + */ | |
| 956 | + rc = _dpu_kms_drm_obj_init(dpu_kms); | |
| 957 | + if (rc) { | |
| 958 | + DPU_ERROR("modeset init failed: %d\n", rc); | |
| 959 | + goto drm_obj_init_err; | |
| 960 | + } | |
| 961 | + | |
| 955 | 962 | dpu_vbif_init_memtypes(dpu_kms); |
| 956 | 963 | |
| 957 | 964 | pm_runtime_put_sync(&dpu_kms->pdev->dev); |
| @@ -23,11 +23,14 @@ struct dpu_mdss { · 22 unmodified lines | ||
| 23 | 23 | struct dpu_irq_controller irq_controller; |
| 24 | 24 | }; |
| 25 | 25 | |
| 26 | −static irqreturn_t dpu_mdss_irq(int irq, void *arg) | |
| 26 | +static void dpu_mdss_irq(struct irq_desc *desc) | |
| 27 | 27 | { |
| 28 | − struct dpu_mdss *dpu_mdss = arg; | |
| 28 | + struct dpu_mdss *dpu_mdss = irq_desc_get_handler_data(desc); | |
| 29 | + struct irq_chip *chip = irq_desc_get_chip(desc); | |
| 29 | 30 | u32 interrupts; |
| 30 | 31 | |
| 32 | + chained_irq_enter(chip, desc); | |
| 33 | + | |
| 31 | 34 | interrupts = readl_relaxed(dpu_mdss->mmio + HW_INTR_STATUS); |
| 32 | 35 | |
| 33 | 36 | while (interrupts) { |
| @@ -39,20 +42,20 @@ static irqreturn_t dpu_mdss_irq(int irq, void *arg) · 5 unmodified lines | ||
| 39 | 42 | hwirq); |
| 40 | 43 | if (mapping == 0) { |
| 41 | 44 | DRM_ERROR("couldn't find irq mapping for %lu\n", hwirq); |
| 42 | − return IRQ_NONE; | |
| 45 | + break; | |
| 43 | 46 | } |
| 44 | 47 | |
| 45 | 48 | rc = generic_handle_irq(mapping); |
| 46 | 49 | if (rc < 0) { |
| 47 | 50 | DRM_ERROR("handle irq fail: irq=%lu mapping=%u rc=%d\n", |
| 48 | 51 | hwirq, mapping, rc); |
| 49 | − return IRQ_NONE; | |
| 52 | + break; | |
| 50 | 53 | } |
| 51 | 54 | |
| 52 | 55 | interrupts &= ~(1 << hwirq); |
| 53 | 56 | } |
| 54 | 57 | |
| 55 | − return IRQ_HANDLED; | |
| 58 | + chained_irq_exit(chip, desc); | |
| 56 | 59 | } |
| 57 | 60 | |
| 58 | 61 | static void dpu_mdss_irq_mask(struct irq_data *irqd) |
| @@ -83,16 +86,16 @@ static struct irq_chip dpu_mdss_irq_chip = { · 24 unmodified lines | ||
| 83 | 86 | .irq_unmask = dpu_mdss_irq_unmask, |
| 84 | 87 | }; |
| 85 | 88 | |
| 89 | +static struct lock_class_key dpu_mdss_lock_key, dpu_mdss_request_key; | |
| 90 | + | |
| 86 | 91 | static int dpu_mdss_irqdomain_map(struct irq_domain *domain, |
| 87 | 92 | unsigned int irq, irq_hw_number_t hwirq) |
| 88 | 93 | { |
| 89 | 94 | struct dpu_mdss *dpu_mdss = domain->host_data; |
| 90 | − int ret; | |
| 91 | 95 | |
| 96 | + irq_set_lockdep_class(irq, &dpu_mdss_lock_key, &dpu_mdss_request_key); | |
| 92 | 97 | irq_set_chip_and_handler(irq, &dpu_mdss_irq_chip, handle_level_irq); |
| 93 | − ret = irq_set_chip_data(irq, dpu_mdss); | |
| 94 | − | |
| 95 | − return ret; | |
| 98 | + return irq_set_chip_data(irq, dpu_mdss); | |
| 96 | 99 | } |
| 97 | 100 | |
| 98 | 101 | static const struct irq_domain_ops dpu_mdss_irqdomain_ops = { |
| @@ -159,11 +162,13 @@ static void dpu_mdss_destroy(struct drm_device *dev) · 60 unmodified lines | ||
| 159 | 162 | struct msm_drm_private *priv = dev->dev_private; |
| 160 | 163 | struct dpu_mdss *dpu_mdss = to_dpu_mdss(priv->mdss); |
| 161 | 164 | struct dss_module_power *mp = &dpu_mdss->mp; |
| 165 | + int irq; | |
| 162 | 166 | |
| 163 | 167 | pm_runtime_suspend(dev->dev); |
| 164 | 168 | pm_runtime_disable(dev->dev); |
| 165 | 169 | _dpu_mdss_irq_domain_fini(dpu_mdss); |
| 166 | − free_irq(platform_get_irq(pdev, 0), dpu_mdss); | |
| 170 | + irq = platform_get_irq(pdev, 0); | |
| 171 | + irq_set_chained_handler_and_data(irq, NULL, NULL); | |
| 167 | 172 | msm_dss_put_clk(mp->clk_config, mp->num_clk); |
| 168 | 173 | devm_kfree(&pdev->dev, mp->clk_config); |
| 169 | 174 | |
| @@ -187,6 +192,7 @@ int dpu_mdss_init(struct drm_device *dev) · 17 unmodified lines | ||
| 187 | 192 | struct dpu_mdss *dpu_mdss; |
| 188 | 193 | struct dss_module_power *mp; |
| 189 | 194 | int ret = 0; |
| 195 | + int irq; | |
| 190 | 196 | |
| 191 | 197 | dpu_mdss = devm_kzalloc(dev->dev, sizeof(*dpu_mdss), GFP_KERNEL); |
| 192 | 198 | if (!dpu_mdss) |
| @@ -219,12 +225,12 @@ int dpu_mdss_init(struct drm_device *dev) · 26 unmodified lines | ||
| 219 | 225 | if (ret) |
| 220 | 226 | goto irq_domain_error; |
| 221 | 227 | |
| 222 | − ret = request_irq(platform_get_irq(pdev, 0), | |
| 223 | − dpu_mdss_irq, 0, "dpu_mdss_isr", dpu_mdss); | |
| 224 | − if (ret) { | |
| 225 | − DPU_ERROR("failed to init irq: %d\n", ret); | |
| 228 | + irq = platform_get_irq(pdev, 0); | |
| 229 | + if (irq < 0) | |
| 226 | 230 | goto irq_error; |
| 227 | − } | |
| 231 | + | |
| 232 | + irq_set_chained_handler_and_data(irq, dpu_mdss_irq, | |
| 233 | + dpu_mdss); | |
| 228 | 234 | |
| 229 | 235 | pm_runtime_enable(dev->dev); |
| 230 | 236 | |
| @@ -95,8 +95,6 @@ struct dpu_plane { · 94 unmodified lines | ||
| 95 | 95 | |
| 96 | 96 | enum dpu_sspp pipe; |
| 97 | 97 | uint32_t features; /* capabilities from catalog */ |
| 98 | − uint32_t nformats; | |
| 99 | − uint32_t formats[64]; | |
| 100 | 98 | |
| 101 | 99 | struct dpu_hw_pipe *pipe_hw; |
| 102 | 100 | struct dpu_hw_pipe_cfg pipe_cfg; |
| @@ -121,6 +119,12 @@ struct dpu_plane { · 18 unmodified lines | ||
| 121 | 119 | bool debugfs_default_scale; |
| 122 | 120 | }; |
| 123 | 121 | |
| 122 | +static const uint64_t supported_format_modifiers[] = { | |
| 123 | + DRM_FORMAT_MOD_QCOM_COMPRESSED, | |
| 124 | + DRM_FORMAT_MOD_LINEAR, | |
| 125 | + DRM_FORMAT_MOD_INVALID | |
| 126 | +}; | |
| 127 | + | |
| 124 | 128 | #define to_dpu_plane(x) container_of(x, struct dpu_plane, base) |
| 125 | 129 | |
| 126 | 130 | static struct dpu_kms *_dpu_plane_get_kms(struct drm_plane *plane) |
| @@ -1410,6 +1414,23 @@ static void dpu_plane_early_unregister(struct drm_plane *plane) · 1283 unmodified lines | ||
| 1410 | 1414 | debugfs_remove_recursive(pdpu->debugfs_root); |
| 1411 | 1415 | } |
| 1412 | 1416 | |
| 1417 | +static bool dpu_plane_format_mod_supported(struct drm_plane *plane, | |
| 1418 | + uint32_t format, uint64_t modifier) | |
| 1419 | +{ | |
| 1420 | + if (modifier == DRM_FORMAT_MOD_LINEAR) | |
| 1421 | + return true; | |
| 1422 | + | |
| 1423 | + if (modifier == DRM_FORMAT_MOD_QCOM_COMPRESSED) { | |
| 1424 | + int i; | |
| 1425 | + for (i = 0; i < ARRAY_SIZE(qcom_compressed_supported_formats); i++) { | |
| 1426 | + if (format == qcom_compressed_supported_formats[i]) | |
| 1427 | + return true; | |
| 1428 | + } | |
| 1429 | + } | |
| 1430 | + | |
| 1431 | + return false; | |
| 1432 | +} | |
| 1433 | + | |
| 1413 | 1434 | static const struct drm_plane_funcs dpu_plane_funcs = { |
| 1414 | 1435 | .update_plane = drm_atomic_helper_update_plane, |
| 1415 | 1436 | .disable_plane = drm_atomic_helper_disable_plane, |
| @@ -1419,6 +1440,7 @@ static const struct drm_plane_funcs dpu_plane_funcs = { · 3 unmodified lines | ||
| 1419 | 1440 | .atomic_destroy_state = dpu_plane_destroy_state, |
| 1420 | 1441 | .late_register = dpu_plane_late_register, |
| 1421 | 1442 | .early_unregister = dpu_plane_early_unregister, |
| 1443 | + .format_mod_supported = dpu_plane_format_mod_supported, | |
| 1422 | 1444 | }; |
| 1423 | 1445 | |
| 1424 | 1446 | static const struct drm_plane_helper_funcs dpu_plane_helper_funcs = { |
| @@ -1444,11 +1466,12 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev, · 19 unmodified lines | ||
| 1444 | 1466 | unsigned long possible_crtcs, u32 master_plane_id) |
| 1445 | 1467 | { |
| 1446 | 1468 | struct drm_plane *plane = NULL, *master_plane = NULL; |
| 1447 | − const struct dpu_format_extended *format_list; | |
| 1469 | + const uint32_t *format_list; | |
| 1448 | 1470 | struct dpu_plane *pdpu; |
| 1449 | 1471 | struct msm_drm_private *priv = dev->dev_private; |
| 1450 | 1472 | struct dpu_kms *kms = to_dpu_kms(priv->kms); |
| 1451 | 1473 | int zpos_max = DPU_ZPOS_MAX; |
| 1474 | + uint32_t num_formats; | |
| 1452 | 1475 | int ret = -EINVAL; |
| 1453 | 1476 | |
| 1454 | 1477 | /* create and zero local structure */ |
| @@ -1491,24 +1514,18 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev, · 36 unmodified lines | ||
| 1491 | 1514 | goto clean_sspp; |
| 1492 | 1515 | } |
| 1493 | 1516 | |
| 1494 | − if (!master_plane_id) | |
| 1495 | − format_list = pdpu->pipe_sblk->format_list; | |
| 1496 | − else | |
| 1517 | + if (pdpu->is_virtual) { | |
| 1497 | 1518 | format_list = pdpu->pipe_sblk->virt_format_list; |
| 1498 | − | |
| 1499 | − pdpu->nformats = dpu_populate_formats(format_list, | |
| 1500 | − pdpu->formats, | |
| 1501 | − 0, | |
| 1502 | − ARRAY_SIZE(pdpu->formats)); | |
| 1503 | − | |
| 1504 | − if (!pdpu->nformats) { | |
| 1505 | − DPU_ERROR("[%u]no valid formats for plane\n", pipe); | |
| 1506 | − goto clean_sspp; | |
| 1519 | + num_formats = pdpu->pipe_sblk->virt_num_formats; | |
| 1520 | + } | |
| 1521 | + else { | |
| 1522 | + format_list = pdpu->pipe_sblk->format_list; | |
| 1523 | + num_formats = pdpu->pipe_sblk->num_formats; | |
| 1507 | 1524 | } |
| 1508 | 1525 | |
| 1509 | 1526 | ret = drm_universal_plane_init(dev, plane, 0xff, &dpu_plane_funcs, |
| 1510 | − pdpu->formats, pdpu->nformats, | |
| 1511 | − NULL, type, NULL); | |
| 1527 | + format_list, num_formats, | |
| 1528 | + supported_format_modifiers, type, NULL); | |
| 1512 | 1529 | if (ret) |
| 1513 | 1530 | goto clean_sspp; |
| 1514 | 1531 | |
| @@ -28,23 +28,18 @@ · 27 unmodified lines | ||
| 28 | 28 | /** |
| 29 | 29 | * struct dpu_plane_state: Define dpu extension of drm plane state object |
| 30 | 30 | * @base: base drm plane state object |
| 31 | − * @property_state: Local storage for msm_prop properties | |
| 32 | − * @property_values: cached plane property values | |
| 33 | 31 | * @aspace: pointer to address space for input/output buffers |
| 34 | − * @input_fence: dereferenced input fence pointer | |
| 35 | 32 | * @stage: assigned by crtc blender |
| 36 | 33 | * @multirect_index: index of the rectangle of SSPP |
| 37 | 34 | * @multirect_mode: parallel or time multiplex multirect mode |
| 38 | 35 | * @pending: whether the current update is still pending |
| 39 | 36 | * @scaler3_cfg: configuration data for scaler3 |
| 40 | 37 | * @pixel_ext: configuration data for pixel extensions |
| 41 | − * @scaler_check_state: indicates status of user provided pixel extension data | |
| 42 | 38 | * @cdp_cfg: CDP configuration |
| 43 | 39 | */ |
| 44 | 40 | struct dpu_plane_state { |
| 45 | 41 | struct drm_plane_state base; |
| 46 | 42 | struct msm_gem_address_space *aspace; |
| 47 | − void *input_fence; | |
| 48 | 43 | enum dpu_stage stage; |
| 49 | 44 | uint32_t multirect_index; |
| 50 | 45 | uint32_t multirect_mode; |
| @@ -106,12 +101,6 @@ void dpu_plane_restore(struct drm_plane *plane); · 55 unmodified lines | ||
| 106 | 101 | */ |
| 107 | 102 | void dpu_plane_flush(struct drm_plane *plane); |
| 108 | 103 | |
| 109 | −/** | |
| 110 | − * dpu_plane_kickoff - final plane operations before commit kickoff | |
| 111 | − * @plane: Pointer to drm plane structure | |
| 112 | − */ | |
| 113 | −void dpu_plane_kickoff(struct drm_plane *plane); | |
| 114 | − | |
| 115 | 104 | /** |
| 116 | 105 | * dpu_plane_set_error: enable/disable error condition |
| 117 | 106 | * @plane: pointer to drm_plane structure |
| @@ -146,14 +135,6 @@ int dpu_plane_validate_multirect_v2(struct dpu_multirect_plane_states *plane); · 28 unmodified lines | ||
| 146 | 135 | */ |
| 147 | 136 | void dpu_plane_clear_multirect(const struct drm_plane_state *drm_state); |
| 148 | 137 | |
| 149 | −/** | |
| 150 | − * dpu_plane_wait_input_fence - wait for input fence object | |
| 151 | − * @plane: Pointer to DRM plane object | |
| 152 | − * @wait_ms: Wait timeout value | |
| 153 | − * Returns: Zero on success | |
| 154 | − */ | |
| 155 | −int dpu_plane_wait_input_fence(struct drm_plane *plane, uint32_t wait_ms); | |
| 156 | − | |
| 157 | 138 | /** |
| 158 | 139 | * dpu_plane_color_fill - enables color fill on plane |
| 159 | 140 | * @plane: Pointer to DRM plane object |
| @@ -164,12 +145,4 @@ int dpu_plane_wait_input_fence(struct drm_plane *plane, uint32_t wait_ms); · 4 unmodified lines | ||
| 164 | 145 | int dpu_plane_color_fill(struct drm_plane *plane, |
| 165 | 146 | uint32_t color, uint32_t alpha); |
| 166 | 147 | |
| 167 | −/** | |
| 168 | − * dpu_plane_set_revalidate - sets revalidate flag which forces a full | |
| 169 | − * validation of the plane properties in the next atomic check | |
| 170 | − * @plane: Pointer to DRM plane object | |
| 171 | − * @enable: Boolean to set/unset the flag | |
| 172 | − */ | |
| 173 | −void dpu_plane_set_revalidate(struct drm_plane *plane, bool enable); | |
| 174 | − | |
| 175 | 148 | #endif /* _DPU_PLANE_H_ */ |
| @@ -21,8 +21,8 @@ · 20 unmodified lines | ||
| 21 | 21 | #include "dpu_encoder.h" |
| 22 | 22 | #include "dpu_trace.h" |
| 23 | 23 | |
| 24 | −#define RESERVED_BY_OTHER(h, r) \ | |
| 25 | − ((h)->rsvp && ((h)->rsvp->enc_id != (r)->enc_id)) | |
| 24 | +#define RESERVED_BY_OTHER(h, r) \ | |
| 25 | + ((h)->enc_id && (h)->enc_id != r) | |
| 26 | 26 | |
| 27 | 27 | /** |
| 28 | 28 | * struct dpu_rm_requirements - Reservation requirements parameter bundle |
| @@ -34,90 +34,21 @@ struct dpu_rm_requirements { · 5 unmodified lines | ||
| 34 | 34 | struct dpu_encoder_hw_resources hw_res; |
| 35 | 35 | }; |
| 36 | 36 | |
| 37 | −/** | |
| 38 | − * struct dpu_rm_rsvp - Use Case Reservation tagging structure | |
| 39 | − * Used to tag HW blocks as reserved by a CRTC->Encoder->Connector chain | |
| 40 | − * By using as a tag, rather than lists of pointers to HW blocks used | |
| 41 | − * we can avoid some list management since we don't know how many blocks | |
| 42 | − * of each type a given use case may require. | |
| 43 | − * @list: List head for list of all reservations | |
| 44 | − * @seq: Global RSVP sequence number for debugging, especially for | |
| 45 | − * differentiating differenct allocations for same encoder. | |
| 46 | − * @enc_id: Reservations are tracked by Encoder DRM object ID. | |
| 47 | − * CRTCs may be connected to multiple Encoders. | |
| 48 | − * An encoder or connector id identifies the display path. | |
| 49 | − */ | |
| 50 | −struct dpu_rm_rsvp { | |
| 51 | − struct list_head list; | |
| 52 | − uint32_t seq; | |
| 53 | − uint32_t enc_id; | |
| 54 | −}; | |
| 55 | 37 | |
| 56 | 38 | /** |
| 57 | 39 | * struct dpu_rm_hw_blk - hardware block tracking list member |
| 58 | 40 | * @list: List head for list of all hardware blocks tracking items |
| 59 | − * @rsvp: Pointer to use case reservation if reserved by a client | |
| 60 | − * @rsvp_nxt: Temporary pointer used during reservation to the incoming | |
| 61 | − * request. Will be swapped into rsvp if proposal is accepted | |
| 62 | − * @type: Type of hardware block this structure tracks | |
| 63 | 41 | * @id: Hardware ID number, within it's own space, ie. LM_X |
| 64 | − * @catalog: Pointer to the hardware catalog entry for this block | |
| 42 | + * @enc_id: Encoder id to which this blk is binded | |
| 65 | 43 | * @hw: Pointer to the hardware register access object for this block |
| 66 | 44 | */ |
| 67 | 45 | struct dpu_rm_hw_blk { |
| 68 | 46 | struct list_head list; |
| 69 | − struct dpu_rm_rsvp *rsvp; | |
| 70 | − struct dpu_rm_rsvp *rsvp_nxt; | |
| 71 | − enum dpu_hw_blk_type type; | |
| 72 | 47 | uint32_t id; |
| 48 | + uint32_t enc_id; | |
| 73 | 49 | struct dpu_hw_blk *hw; |
| 74 | 50 | }; |
| 75 | 51 | |
| 76 | −/** | |
| 77 | − * dpu_rm_dbg_rsvp_stage - enum of steps in making reservation for event logging | |
| 78 | − */ | |
| 79 | −enum dpu_rm_dbg_rsvp_stage { | |
| 80 | − DPU_RM_STAGE_BEGIN, | |
| 81 | − DPU_RM_STAGE_AFTER_CLEAR, | |
| 82 | − DPU_RM_STAGE_AFTER_RSVPNEXT, | |
| 83 | − DPU_RM_STAGE_FINAL | |
| 84 | −}; | |
| 85 | − | |
| 86 | −static void _dpu_rm_print_rsvps( | |
| 87 | − struct dpu_rm *rm, | |
| 88 | − enum dpu_rm_dbg_rsvp_stage stage) | |
| 89 | −{ | |
| 90 | − struct dpu_rm_rsvp *rsvp; | |
| 91 | − struct dpu_rm_hw_blk *blk; | |
| 92 | − enum dpu_hw_blk_type type; | |
| 93 | − | |
| 94 | − DPU_DEBUG("%d\n", stage); | |
| 95 | − | |
| 96 | − list_for_each_entry(rsvp, &rm->rsvps, list) { | |
| 97 | − DRM_DEBUG_KMS("%d rsvp[s%ue%u]\n", stage, rsvp->seq, | |
| 98 | − rsvp->enc_id); | |
| 99 | − } | |
| 100 | − | |
| 101 | − for (type = 0; type < DPU_HW_BLK_MAX; type++) { | |
| 102 | − list_for_each_entry(blk, &rm->hw_blks[type], list) { | |
| 103 | − if (!blk->rsvp && !blk->rsvp_nxt) | |
| 104 | − continue; | |
| 105 | − | |
| 106 | − DRM_DEBUG_KMS("%d rsvp[s%ue%u->s%ue%u] %d %d\n", stage, | |
| 107 | − (blk->rsvp) ? blk->rsvp->seq : 0, | |
| 108 | − (blk->rsvp) ? blk->rsvp->enc_id : 0, | |
| 109 | − (blk->rsvp_nxt) ? blk->rsvp_nxt->seq : 0, | |
| 110 | − (blk->rsvp_nxt) ? blk->rsvp_nxt->enc_id : 0, | |
| 111 | − blk->type, blk->id); | |
| 112 | − } | |
| 113 | − } | |
| 114 | −} | |
| 115 | − | |
| 116 | −struct dpu_hw_mdp *dpu_rm_get_mdp(struct dpu_rm *rm) | |
| 117 | −{ | |
| 118 | − return rm->hw_mdp; | |
| 119 | −} | |
| 120 | − | |
| 121 | 52 | void dpu_rm_init_hw_iter( |
| 122 | 53 | struct dpu_rm_hw_iter *iter, |
| 123 | 54 | uint32_t enc_id, |
| @@ -148,15 +79,7 @@ static bool _dpu_rm_get_hw_locked(struct dpu_rm *rm, struct dpu_rm_hw_iter *i) · 24 unmodified lines | ||
| 148 | 79 | i->blk = list_prepare_entry(i->blk, blk_list, list); |
| 149 | 80 | |
| 150 | 81 | list_for_each_entry_continue(i->blk, blk_list, list) { |
| 151 | − struct dpu_rm_rsvp *rsvp = i->blk->rsvp; | |
| 152 | − | |
| 153 | − if (i->blk->type != i->type) { | |
| 154 | − DPU_ERROR("found incorrect block type %d on %d list\n", | |
| 155 | − i->blk->type, i->type); | |
| 156 | − return false; | |
| 157 | − } | |
| 158 | − | |
| 159 | − if ((i->enc_id == 0) || (rsvp && rsvp->enc_id == i->enc_id)) { | |
| 82 | + if (i->enc_id == i->blk->enc_id) { | |
| 160 | 83 | i->hw = i->blk->hw; |
| 161 | 84 | DPU_DEBUG("found type %d id %d for enc %d\n", |
| 162 | 85 | i->type, i->blk->id, i->enc_id); |
| @@ -208,34 +131,18 @@ static void _dpu_rm_hw_destroy(enum dpu_hw_blk_type type, void *hw) · 45 unmodified lines | ||
| 208 | 131 | |
| 209 | 132 | int dpu_rm_destroy(struct dpu_rm *rm) |
| 210 | 133 | { |
| 211 | − | |
| 212 | − struct dpu_rm_rsvp *rsvp_cur, *rsvp_nxt; | |
| 213 | 134 | struct dpu_rm_hw_blk *hw_cur, *hw_nxt; |
| 214 | 135 | enum dpu_hw_blk_type type; |
| 215 | 136 | |
| 216 | − if (!rm) { | |
| 217 | − DPU_ERROR("invalid rm\n"); | |
| 218 | − return -EINVAL; | |
| 219 | − } | |
| 220 | − | |
| 221 | − list_for_each_entry_safe(rsvp_cur, rsvp_nxt, &rm->rsvps, list) { | |
| 222 | − list_del(&rsvp_cur->list); | |
| 223 | − kfree(rsvp_cur); | |
| 224 | − } | |
| 225 | − | |
| 226 | − | |
| 227 | 137 | for (type = 0; type < DPU_HW_BLK_MAX; type++) { |
| 228 | 138 | list_for_each_entry_safe(hw_cur, hw_nxt, &rm->hw_blks[type], |
| 229 | 139 | list) { |
| 230 | 140 | list_del(&hw_cur->list); |
| 231 | − _dpu_rm_hw_destroy(hw_cur->type, hw_cur->hw); | |
| 141 | + _dpu_rm_hw_destroy(type, hw_cur->hw); | |
| 232 | 142 | kfree(hw_cur); |
| 233 | 143 | } |
| 234 | 144 | } |
| 235 | 145 | |
| 236 | − dpu_hw_mdp_destroy(rm->hw_mdp); | |
| 237 | − rm->hw_mdp = NULL; | |
| 238 | − | |
| 239 | 146 | mutex_destroy(&rm->rm_lock); |
| 240 | 147 | |
| 241 | 148 | return 0; |
| @@ -250,11 +157,8 @@ static int _dpu_rm_hw_blk_create( · 8 unmodified lines | ||
| 250 | 157 | void *hw_catalog_info) |
| 251 | 158 | { |
| 252 | 159 | struct dpu_rm_hw_blk *blk; |
| 253 | − struct dpu_hw_mdp *hw_mdp; | |
| 254 | 160 | void *hw; |
| 255 | 161 | |
| 256 | − hw_mdp = rm->hw_mdp; | |
| 257 | − | |
| 258 | 162 | switch (type) { |
| 259 | 163 | case DPU_HW_BLK_LM: |
| 260 | 164 | hw = dpu_hw_lm_init(id, mmio, cat); |
| @@ -290,9 +194,9 @@ static int _dpu_rm_hw_blk_create( · 29 unmodified lines | ||
| 290 | 194 | return -ENOMEM; |
| 291 | 195 | } |
| 292 | 196 | |
| 293 | − blk->type = type; | |
| 294 | 197 | blk->id = id; |
| 295 | 198 | blk->hw = hw; |
| 199 | + blk->enc_id = 0; | |
| 296 | 200 | list_add_tail(&blk->list, &rm->hw_blks[type]); |
| 297 | 201 | |
| 298 | 202 | return 0; |
| @@ -300,13 +204,12 @@ static int _dpu_rm_hw_blk_create( · 1 unmodified line | ||
| 300 | 204 | |
| 301 | 205 | int dpu_rm_init(struct dpu_rm *rm, |
| 302 | 206 | struct dpu_mdss_cfg *cat, |
| 303 | − void __iomem *mmio, | |
| 304 | − struct drm_device *dev) | |
| 207 | + void __iomem *mmio) | |
| 305 | 208 | { |
| 306 | 209 | int rc, i; |
| 307 | 210 | enum dpu_hw_blk_type type; |
| 308 | 211 | |
| 309 | − if (!rm || !cat || !mmio || !dev) { | |
| 212 | + if (!rm || !cat || !mmio) { | |
| 310 | 213 | DPU_ERROR("invalid kms\n"); |
| 311 | 214 | return -EINVAL; |
| 312 | 215 | } |
| @@ -316,21 +219,9 @@ int dpu_rm_init(struct dpu_rm *rm, · 3 unmodified lines | ||
| 316 | 219 | |
| 317 | 220 | mutex_init(&rm->rm_lock); |
| 318 | 221 | |
| 319 | − INIT_LIST_HEAD(&rm->rsvps); | |
| 320 | 222 | for (type = 0; type < DPU_HW_BLK_MAX; type++) |
| 321 | 223 | INIT_LIST_HEAD(&rm->hw_blks[type]); |
| 322 | 224 | |
| 323 | − rm->dev = dev; | |
| 324 | − | |
| 325 | − /* Some of the sub-blocks require an mdptop to be created */ | |
| 326 | − rm->hw_mdp = dpu_hw_mdptop_init(MDP_TOP, mmio, cat); | |
| 327 | − if (IS_ERR_OR_NULL(rm->hw_mdp)) { | |
| 328 | − rc = PTR_ERR(rm->hw_mdp); | |
| 329 | − rm->hw_mdp = NULL; | |
| 330 | − DPU_ERROR("failed: mdp hw not available\n"); | |
| 331 | − goto fail; | |
| 332 | − } | |
| 333 | − | |
| 334 | 225 | /* Interrogate HW catalog and create tracking items for hw blocks */ |
| 335 | 226 | for (i = 0; i < cat->mixer_count; i++) { |
| 336 | 227 | struct dpu_lm_cfg *lm = &cat->mixer[i]; |
| @@ -410,7 +301,7 @@ static bool _dpu_rm_needs_split_display(const struct msm_display_topology *top) · 73 unmodified lines | ||
| 410 | 301 | * proposed use case requirements, incl. hardwired dependent blocks like |
| 411 | 302 | * pingpong |
| 412 | 303 | * @rm: dpu resource manager handle |
| 413 | − * @rsvp: reservation currently being created | |
| 304 | + * @enc_id: encoder id requesting for allocation | |
| 414 | 305 | * @reqs: proposed use case requirements |
| 415 | 306 | * @lm: proposed layer mixer, function checks if lm, and all other hardwired |
| 416 | 307 | * blocks connected to the lm (pp) is available and appropriate |
| @@ -422,7 +313,7 @@ static bool _dpu_rm_needs_split_display(const struct msm_display_topology *top) · 5 unmodified lines | ||
| 422 | 313 | */ |
| 423 | 314 | static bool _dpu_rm_check_lm_and_get_connected_blks( |
| 424 | 315 | struct dpu_rm *rm, |
| 425 | − struct dpu_rm_rsvp *rsvp, | |
| 316 | + uint32_t enc_id, | |
| 426 | 317 | struct dpu_rm_requirements *reqs, |
| 427 | 318 | struct dpu_rm_hw_blk *lm, |
| 428 | 319 | struct dpu_rm_hw_blk **pp, |
| @@ -449,7 +340,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks( · 20 unmodified lines | ||
| 449 | 340 | } |
| 450 | 341 | |
| 451 | 342 | /* Already reserved? */ |
| 452 | − if (RESERVED_BY_OTHER(lm, rsvp)) { | |
| 343 | + if (RESERVED_BY_OTHER(lm, enc_id)) { | |
| 453 | 344 | DPU_DEBUG("lm %d already reserved\n", lm_cfg->id); |
| 454 | 345 | return false; |
| 455 | 346 | } |
| @@ -467,7 +358,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks( · 11 unmodified lines | ||
| 467 | 358 | return false; |
| 468 | 359 | } |
| 469 | 360 | |
| 470 | − if (RESERVED_BY_OTHER(*pp, rsvp)) { | |
| 361 | + if (RESERVED_BY_OTHER(*pp, enc_id)) { | |
| 471 | 362 | DPU_DEBUG("lm %d pp %d already reserved\n", lm->id, |
| 472 | 363 | (*pp)->id); |
| 473 | 364 | return false; |
| @@ -476,10 +367,8 @@ static bool _dpu_rm_check_lm_and_get_connected_blks( · 2 unmodified lines | ||
| 476 | 367 | return true; |
| 477 | 368 | } |
| 478 | 369 | |
| 479 | −static int _dpu_rm_reserve_lms( | |
| 480 | − struct dpu_rm *rm, | |
| 481 | − struct dpu_rm_rsvp *rsvp, | |
| 482 | − struct dpu_rm_requirements *reqs) | |
| 370 | +static int _dpu_rm_reserve_lms(struct dpu_rm *rm, uint32_t enc_id, | |
| 371 | + struct dpu_rm_requirements *reqs) | |
| 483 | 372 | |
| 484 | 373 | { |
| 485 | 374 | struct dpu_rm_hw_blk *lm[MAX_BLOCKS]; |
| @@ -504,7 +393,7 @@ static int _dpu_rm_reserve_lms( · 18 unmodified lines | ||
| 504 | 393 | lm[lm_count] = iter_i.blk; |
| 505 | 394 | |
| 506 | 395 | if (!_dpu_rm_check_lm_and_get_connected_blks( |
| 507 | − rm, rsvp, reqs, lm[lm_count], | |
| 396 | + rm, enc_id, reqs, lm[lm_count], | |
| 508 | 397 | &pp[lm_count], NULL)) |
| 509 | 398 | continue; |
| 510 | 399 | |
| @@ -519,7 +408,7 @@ static int _dpu_rm_reserve_lms( · 8 unmodified lines | ||
| 519 | 408 | continue; |
| 520 | 409 | |
| 521 | 410 | if (!_dpu_rm_check_lm_and_get_connected_blks( |
| 522 | − rm, rsvp, reqs, iter_j.blk, | |
| 411 | + rm, enc_id, reqs, iter_j.blk, | |
| 523 | 412 | &pp[lm_count], iter_i.blk)) |
| 524 | 413 | continue; |
| 525 | 414 | |
| @@ -537,11 +426,10 @@ static int _dpu_rm_reserve_lms( · 11 unmodified lines | ||
| 537 | 426 | if (!lm[i]) |
| 538 | 427 | break; |
| 539 | 428 | |
| 540 | − lm[i]->rsvp_nxt = rsvp; | |
| 541 | − pp[i]->rsvp_nxt = rsvp; | |
| 429 | + lm[i]->enc_id = enc_id; | |
| 430 | + pp[i]->enc_id = enc_id; | |
| 542 | 431 | |
| 543 | − trace_dpu_rm_reserve_lms(lm[i]->id, lm[i]->type, rsvp->enc_id, | |
| 544 | − pp[i]->id); | |
| 432 | + trace_dpu_rm_reserve_lms(lm[i]->id, enc_id, pp[i]->id); | |
| 545 | 433 | } |
| 546 | 434 | |
| 547 | 435 | return rc; |
| @@ -549,7 +437,7 @@ static int _dpu_rm_reserve_lms( · 1 unmodified line | ||
| 549 | 437 | |
| 550 | 438 | static int _dpu_rm_reserve_ctls( |
| 551 | 439 | struct dpu_rm *rm, |
| 552 | − struct dpu_rm_rsvp *rsvp, | |
| 440 | + uint32_t enc_id, | |
| 553 | 441 | const struct msm_display_topology *top) |
| 554 | 442 | { |
| 555 | 443 | struct dpu_rm_hw_blk *ctls[MAX_BLOCKS]; |
| @@ -570,7 +458,7 @@ static int _dpu_rm_reserve_ctls( · 14 unmodified lines | ||
| 570 | 458 | unsigned long features = ctl->caps->features; |
| 571 | 459 | bool has_split_display; |
| 572 | 460 | |
| 573 | − if (RESERVED_BY_OTHER(iter.blk, rsvp)) | |
| 461 | + if (RESERVED_BY_OTHER(iter.blk, enc_id)) | |
| 574 | 462 | continue; |
| 575 | 463 | |
| 576 | 464 | has_split_display = BIT(DPU_CTL_SPLIT_DISPLAY) & features; |
| @@ -591,9 +479,8 @@ static int _dpu_rm_reserve_ctls( · 14 unmodified lines | ||
| 591 | 479 | return -ENAVAIL; |
| 592 | 480 | |
| 593 | 481 | for (i = 0; i < ARRAY_SIZE(ctls) && i < num_ctls; i++) { |
| 594 | − ctls[i]->rsvp_nxt = rsvp; | |
| 595 | − trace_dpu_rm_reserve_ctls(ctls[i]->id, ctls[i]->type, | |
| 596 | − rsvp->enc_id); | |
| 482 | + ctls[i]->enc_id = enc_id; | |
| 483 | + trace_dpu_rm_reserve_ctls(ctls[i]->id, enc_id); | |
| 597 | 484 | } |
| 598 | 485 | |
| 599 | 486 | return 0; |
| @@ -601,7 +488,7 @@ static int _dpu_rm_reserve_ctls( · 1 unmodified line | ||
| 601 | 488 | |
| 602 | 489 | static int _dpu_rm_reserve_intf( |
| 603 | 490 | struct dpu_rm *rm, |
| 604 | − struct dpu_rm_rsvp *rsvp, | |
| 491 | + uint32_t enc_id, | |
| 605 | 492 | uint32_t id, |
| 606 | 493 | enum dpu_hw_blk_type type) |
| 607 | 494 | { |
| @@ -614,14 +501,13 @@ static int _dpu_rm_reserve_intf( · 6 unmodified lines | ||
| 614 | 501 | if (iter.blk->id != id) |
| 615 | 502 | continue; |
| 616 | 503 | |
| 617 | − if (RESERVED_BY_OTHER(iter.blk, rsvp)) { | |
| 504 | + if (RESERVED_BY_OTHER(iter.blk, enc_id)) { | |
| 618 | 505 | DPU_ERROR("type %d id %d already reserved\n", type, id); |
| 619 | 506 | return -ENAVAIL; |
| 620 | 507 | } |
| 621 | 508 | |
| 622 | − iter.blk->rsvp_nxt = rsvp; | |
| 623 | − trace_dpu_rm_reserve_intf(iter.blk->id, iter.blk->type, | |
| 624 | − rsvp->enc_id); | |
| 509 | + iter.blk->enc_id = enc_id; | |
| 510 | + trace_dpu_rm_reserve_intf(iter.blk->id, enc_id); | |
| 625 | 511 | break; |
| 626 | 512 | } |
| 627 | 513 | |
| @@ -636,7 +522,7 @@ static int _dpu_rm_reserve_intf( · 8 unmodified lines | ||
| 636 | 522 | |
| 637 | 523 | static int _dpu_rm_reserve_intf_related_hw( |
| 638 | 524 | struct dpu_rm *rm, |
| 639 | − struct dpu_rm_rsvp *rsvp, | |
| 525 | + uint32_t enc_id, | |
| 640 | 526 | struct dpu_encoder_hw_resources *hw_res) |
| 641 | 527 | { |
| 642 | 528 | int i, ret = 0; |
| @@ -646,7 +532,7 @@ static int _dpu_rm_reserve_intf_related_hw( · 3 unmodified lines | ||
| 646 | 532 | if (hw_res->intfs[i] == INTF_MODE_NONE) |
| 647 | 533 | continue; |
| 648 | 534 | id = i + INTF_0; |
| 649 | − ret = _dpu_rm_reserve_intf(rm, rsvp, id, | |
| 535 | + ret = _dpu_rm_reserve_intf(rm, enc_id, id, | |
| 650 | 536 | DPU_HW_BLK_INTF); |
| 651 | 537 | if (ret) |
| 652 | 538 | return ret; |
| @@ -655,33 +541,27 @@ static int _dpu_rm_reserve_intf_related_hw( · 2 unmodified lines | ||
| 655 | 541 | return ret; |
| 656 | 542 | } |
| 657 | 543 | |
| 658 | −static int _dpu_rm_make_next_rsvp( | |
| 544 | +static int _dpu_rm_make_reservation( | |
| 659 | 545 | struct dpu_rm *rm, |
| 660 | 546 | struct drm_encoder *enc, |
| 661 | 547 | struct drm_crtc_state *crtc_state, |
| 662 | − struct dpu_rm_rsvp *rsvp, | |
| 663 | 548 | struct dpu_rm_requirements *reqs) |
| 664 | 549 | { |
| 665 | 550 | int ret; |
| 666 | 551 | |
| 667 | − /* Create reservation info, tag reserved blocks with it as we go */ | |
| 668 | − rsvp->seq = ++rm->rsvp_next_seq; | |
| 669 | − rsvp->enc_id = enc->base.id; | |
| 670 | − list_add_tail(&rsvp->list, &rm->rsvps); | |
| 671 | − | |
| 672 | − ret = _dpu_rm_reserve_lms(rm, rsvp, reqs); | |
| 552 | + ret = _dpu_rm_reserve_lms(rm, enc->base.id, reqs); | |
| 673 | 553 | if (ret) { |
| 674 | 554 | DPU_ERROR("unable to find appropriate mixers\n"); |
| 675 | 555 | return ret; |
| 676 | 556 | } |
| 677 | 557 | |
| 678 | − ret = _dpu_rm_reserve_ctls(rm, rsvp, &reqs->topology); | |
| 558 | + ret = _dpu_rm_reserve_ctls(rm, enc->base.id, &reqs->topology); | |
| 679 | 559 | if (ret) { |
| 680 | 560 | DPU_ERROR("unable to find appropriate CTL\n"); |
| 681 | 561 | return ret; |
| 682 | 562 | } |
| 683 | 563 | |
| 684 | − ret = _dpu_rm_reserve_intf_related_hw(rm, rsvp, &reqs->hw_res); | |
| 564 | + ret = _dpu_rm_reserve_intf_related_hw(rm, enc->base.id, &reqs->hw_res); | |
| 685 | 565 | if (ret) |
| 686 | 566 | return ret; |
| 687 | 567 | |
| @@ -706,108 +586,31 @@ static int _dpu_rm_populate_requirements( · 18 unmodified lines | ||
| 706 | 586 | return 0; |
| 707 | 587 | } |
| 708 | 588 | |
| 709 | −static struct dpu_rm_rsvp *_dpu_rm_get_rsvp( | |
| 710 | − struct dpu_rm *rm, | |
| 711 | − struct drm_encoder *enc) | |
| 589 | +static void _dpu_rm_release_reservation(struct dpu_rm *rm, uint32_t enc_id) | |
| 712 | 590 | { |
| 713 | − struct dpu_rm_rsvp *i; | |
| 714 | − | |
| 715 | − if (!rm || !enc) { | |
| 716 | − DPU_ERROR("invalid params\n"); | |
| 717 | − return NULL; | |
| 718 | − } | |
| 719 | − | |
| 720 | − if (list_empty(&rm->rsvps)) | |
| 721 | − return NULL; | |
| 722 | − | |
| 723 | − list_for_each_entry(i, &rm->rsvps, list) | |
| 724 | − if (i->enc_id == enc->base.id) | |
| 725 | − return i; | |
| 726 | − | |
| 727 | − return NULL; | |
| 728 | −} | |
| 729 | − | |
| 730 | −/** | |
| 731 | − * _dpu_rm_release_rsvp - release resources and release a reservation | |
| 732 | − * @rm: KMS handle | |
| 733 | − * @rsvp: RSVP pointer to release and release resources for | |
| 734 | − */ | |
| 735 | −static void _dpu_rm_release_rsvp(struct dpu_rm *rm, struct dpu_rm_rsvp *rsvp) | |
| 736 | −{ | |
| 737 | − struct dpu_rm_rsvp *rsvp_c, *rsvp_n; | |
| 738 | 591 | struct dpu_rm_hw_blk *blk; |
| 739 | 592 | enum dpu_hw_blk_type type; |
| 740 | 593 | |
| 741 | − if (!rsvp) | |
| 742 | − return; | |
| 743 | − | |
| 744 | − DPU_DEBUG("rel rsvp %d enc %d\n", rsvp->seq, rsvp->enc_id); | |
| 745 | − | |
| 746 | − list_for_each_entry_safe(rsvp_c, rsvp_n, &rm->rsvps, list) { | |
| 747 | − if (rsvp == rsvp_c) { | |
| 748 | − list_del(&rsvp_c->list); | |
| 749 | − break; | |
| 750 | − } | |
| 751 | − } | |
| 752 | − | |
| 753 | 594 | for (type = 0; type < DPU_HW_BLK_MAX; type++) { |
| 754 | 595 | list_for_each_entry(blk, &rm->hw_blks[type], list) { |
| 755 | − if (blk->rsvp == rsvp) { | |
| 756 | − blk->rsvp = NULL; | |
| 757 | − DPU_DEBUG("rel rsvp %d enc %d %d %d\n", | |
| 758 | − rsvp->seq, rsvp->enc_id, | |
| 759 | − blk->type, blk->id); | |
| 760 | − } | |
| 761 | − if (blk->rsvp_nxt == rsvp) { | |
| 762 | − blk->rsvp_nxt = NULL; | |
| 763 | − DPU_DEBUG("rel rsvp_nxt %d enc %d %d %d\n", | |
| 764 | − rsvp->seq, rsvp->enc_id, | |
| 765 | − blk->type, blk->id); | |
| 596 | + if (blk->enc_id == enc_id) { | |
| 597 | + blk->enc_id = 0; | |
| 598 | + DPU_DEBUG("rel enc %d %d %d\n", enc_id, | |
| 599 | + type, blk->id); | |
| 766 | 600 | } |
| 767 | 601 | } |
| 768 | 602 | } |
| 769 | − | |
| 770 | − kfree(rsvp); | |
| 771 | 603 | } |
| 772 | 604 | |
| 773 | 605 | void dpu_rm_release(struct dpu_rm *rm, struct drm_encoder *enc) |
| 774 | 606 | { |
| 775 | − struct dpu_rm_rsvp *rsvp; | |
| 776 | − | |
| 777 | − if (!rm || !enc) { | |
| 778 | − DPU_ERROR("invalid params\n"); | |
| 779 | − return; | |
| 780 | − } | |
| 781 | − | |
| 782 | 607 | mutex_lock(&rm->rm_lock); |
| 783 | 608 | |
| 784 | − rsvp = _dpu_rm_get_rsvp(rm, enc); | |
| 785 | − if (!rsvp) { | |
| 786 | − DPU_ERROR("failed to find rsvp for enc %d\n", enc->base.id); | |
| 787 | − goto end; | |
| 788 | − } | |
| 609 | + _dpu_rm_release_reservation(rm, enc->base.id); | |
| 789 | 610 | |
| 790 | − _dpu_rm_release_rsvp(rm, rsvp); | |
| 791 | −end: | |
| 792 | 611 | mutex_unlock(&rm->rm_lock); |
| 793 | 612 | } |
| 794 | 613 | |
| 795 | −static void _dpu_rm_commit_rsvp(struct dpu_rm *rm, struct dpu_rm_rsvp *rsvp) | |
| 796 | −{ | |
| 797 | − struct dpu_rm_hw_blk *blk; | |
| 798 | − enum dpu_hw_blk_type type; | |
| 799 | − | |
| 800 | − /* Swap next rsvp to be the active */ | |
| 801 | − for (type = 0; type < DPU_HW_BLK_MAX; type++) { | |
| 802 | − list_for_each_entry(blk, &rm->hw_blks[type], list) { | |
| 803 | − if (blk->rsvp_nxt) { | |
| 804 | − blk->rsvp = blk->rsvp_nxt; | |
| 805 | − blk->rsvp_nxt = NULL; | |
| 806 | − } | |
| 807 | − } | |
| 808 | − } | |
| 809 | −} | |
| 810 | − | |
| 811 | 614 | int dpu_rm_reserve( |
| 812 | 615 | struct dpu_rm *rm, |
| 813 | 616 | struct drm_encoder *enc, |
| @@ -815,7 +618,6 @@ int dpu_rm_reserve( · 1 unmodified line | ||
| 815 | 618 | struct msm_display_topology topology, |
| 816 | 619 | bool test_only) |
| 817 | 620 | { |
| 818 | − struct dpu_rm_rsvp *rsvp_cur, *rsvp_nxt; | |
| 819 | 621 | struct dpu_rm_requirements reqs; |
| 820 | 622 | int ret; |
| 821 | 623 | |
| @@ -828,8 +630,6 @@ int dpu_rm_reserve( · 6 unmodified lines | ||
| 828 | 630 | |
| 829 | 631 | mutex_lock(&rm->rm_lock); |
| 830 | 632 | |
| 831 | − _dpu_rm_print_rsvps(rm, DPU_RM_STAGE_BEGIN); | |
| 832 | − | |
| 833 | 633 | ret = _dpu_rm_populate_requirements(rm, enc, crtc_state, &reqs, |
| 834 | 634 | topology); |
| 835 | 635 | if (ret) { |
| @@ -837,50 +637,17 @@ int dpu_rm_reserve( · 1 unmodified line | ||
| 837 | 637 | goto end; |
| 838 | 638 | } |
| 839 | 639 | |
| 840 | − /* | |
| 841 | − * We only support one active reservation per-hw-block. But to implement | |
| 842 | − * transactional semantics for test-only, and for allowing failure while | |
| 843 | − * modifying your existing reservation, over the course of this | |
| 844 | − * function we can have two reservations: | |
| 845 | − * Current: Existing reservation | |
| 846 | − * Next: Proposed reservation. The proposed reservation may fail, or may | |
| 847 | − * be discarded if in test-only mode. | |
| 848 | − * If reservation is successful, and we're not in test-only, then we | |
| 849 | − * replace the current with the next. | |
| 850 | − */ | |
| 851 | − rsvp_nxt = kzalloc(sizeof(*rsvp_nxt), GFP_KERNEL); | |
| 852 | − if (!rsvp_nxt) { | |
| 853 | − ret = -ENOMEM; | |
| 854 | − goto end; | |
| 855 | − } | |
| 856 | − | |
| 857 | − rsvp_cur = _dpu_rm_get_rsvp(rm, enc); | |
| 858 | − | |
| 859 | − /* Check the proposed reservation, store it in hw's "next" field */ | |
| 860 | − ret = _dpu_rm_make_next_rsvp(rm, enc, crtc_state, rsvp_nxt, &reqs); | |
| 861 | − | |
| 862 | − _dpu_rm_print_rsvps(rm, DPU_RM_STAGE_AFTER_RSVPNEXT); | |
| 863 | − | |
| 640 | + ret = _dpu_rm_make_reservation(rm, enc, crtc_state, &reqs); | |
| 864 | 641 | if (ret) { |
| 865 | 642 | DPU_ERROR("failed to reserve hw resources: %d\n", ret); |
| 866 | − _dpu_rm_release_rsvp(rm, rsvp_nxt); | |
| 643 | + _dpu_rm_release_reservation(rm, enc->base.id); | |
| 867 | 644 | } else if (test_only) { |
| 868 | − /* | |
| 869 | − * Normally, if test_only, test the reservation and then undo | |
| 870 | − * However, if the user requests LOCK, then keep the reservation | |
| 871 | − * made during the atomic_check phase. | |
| 872 | − */ | |
| 873 | − DPU_DEBUG("test_only: discard test rsvp[s%de%d]\n", | |
| 874 | − rsvp_nxt->seq, rsvp_nxt->enc_id); | |
| 875 | − _dpu_rm_release_rsvp(rm, rsvp_nxt); | |
| 876 | − } else { | |
| 877 | − _dpu_rm_release_rsvp(rm, rsvp_cur); | |
| 878 | − | |
| 879 | − _dpu_rm_commit_rsvp(rm, rsvp_nxt); | |
| 645 | + /* test_only: test the reservation and then undo */ | |
| 646 | + DPU_DEBUG("test_only: discard test [enc: %d]\n", | |
| 647 | + enc->base.id); | |
| 648 | + _dpu_rm_release_reservation(rm, enc->base.id); | |
| 880 | 649 | } |
| 881 | 650 | |
| 882 | − _dpu_rm_print_rsvps(rm, DPU_RM_STAGE_FINAL); | |
| 883 | − | |
| 884 | 651 | end: |
| 885 | 652 | mutex_unlock(&rm->rm_lock); |
| 886 | 653 | |
| @@ -22,22 +22,14 @@ · 21 unmodified lines | ||
| 22 | 22 | |
| 23 | 23 | /** |
| 24 | 24 | * struct dpu_rm - DPU dynamic hardware resource manager |
| 25 | − * @dev: device handle for event logging purposes | |
| 26 | − * @rsvps: list of hardware reservations by each crtc->encoder->connector | |
| 27 | 25 | * @hw_blks: array of lists of hardware resources present in the system, one |
| 28 | 26 | * list per type of hardware block |
| 29 | − * @hw_mdp: hardware object for mdp_top | |
| 30 | 27 | * @lm_max_width: cached layer mixer maximum width |
| 31 | − * @rsvp_next_seq: sequence number for next reservation for debugging purposes | |
| 32 | 28 | * @rm_lock: resource manager mutex |
| 33 | 29 | */ |
| 34 | 30 | struct dpu_rm { |
| 35 | − struct drm_device *dev; | |
| 36 | − struct list_head rsvps; | |
| 37 | 31 | struct list_head hw_blks[DPU_HW_BLK_MAX]; |
| 38 | − struct dpu_hw_mdp *hw_mdp; | |
| 39 | 32 | uint32_t lm_max_width; |
| 40 | − uint32_t rsvp_next_seq; | |
| 41 | 33 | struct mutex rm_lock; |
| 42 | 34 | }; |
| 43 | 35 | |
| @@ -67,13 +59,11 @@ struct dpu_rm_hw_iter { · 23 unmodified lines | ||
| 67 | 59 | * @rm: DPU Resource Manager handle |
| 68 | 60 | * @cat: Pointer to hardware catalog |
| 69 | 61 | * @mmio: mapped register io address of MDP |
| 70 | − * @dev: device handle for event logging purposes | |
| 71 | 62 | * @Return: 0 on Success otherwise -ERROR |
| 72 | 63 | */ |
| 73 | 64 | int dpu_rm_init(struct dpu_rm *rm, |
| 74 | 65 | struct dpu_mdss_cfg *cat, |
| 75 | − void __iomem *mmio, | |
| 76 | − struct drm_device *dev); | |
| 66 | + void __iomem *mmio); | |
| 77 | 67 | |
| 78 | 68 | /** |
| 79 | 69 | * dpu_rm_destroy - Free all memory allocated by dpu_rm_init |
| @@ -111,14 +101,6 @@ int dpu_rm_reserve(struct dpu_rm *rm, · 31 unmodified lines | ||
| 111 | 101 | */ |
| 112 | 102 | void dpu_rm_release(struct dpu_rm *rm, struct drm_encoder *enc); |
| 113 | 103 | |
| 114 | −/** | |
| 115 | − * dpu_rm_get_mdp - Retrieve HW block for MDP TOP. | |
| 116 | − * This is never reserved, and is usable by any display. | |
| 117 | − * @rm: DPU Resource Manager handle | |
| 118 | − * @Return: Pointer to hw block or NULL | |
| 119 | − */ | |
| 120 | −struct dpu_hw_mdp *dpu_rm_get_mdp(struct dpu_rm *rm); | |
| 121 | − | |
| 122 | 104 | /** |
| 123 | 105 | * dpu_rm_init_hw_iter - setup given iterator for new iteration over hw list |
| 124 | 106 | * using dpu_rm_get_hw |
| @@ -144,12 +126,4 @@ void dpu_rm_init_hw_iter( · 19 unmodified lines | ||
| 144 | 126 | * @Return: true on match found, false on no match found |
| 145 | 127 | */ |
| 146 | 128 | bool dpu_rm_get_hw(struct dpu_rm *rm, struct dpu_rm_hw_iter *iter); |
| 147 | − | |
| 148 | −/** | |
| 149 | − * dpu_rm_check_property_topctl - validate property bitmask before it is set | |
| 150 | − * @val: user's proposed topology control bitmask | |
| 151 | − * @Return: 0 on success or error | |
| 152 | − */ | |
| 153 | −int dpu_rm_check_property_topctl(uint64_t val); | |
| 154 | − | |
| 155 | 129 | #endif /* __DPU_RM_H__ */ |
| @@ -831,48 +831,42 @@ TRACE_EVENT(dpu_plane_disable, · 830 unmodified lines | ||
| 831 | 831 | ); |
| 832 | 832 | |
| 833 | 833 | DECLARE_EVENT_CLASS(dpu_rm_iter_template, |
| 834 | − TP_PROTO(uint32_t id, enum dpu_hw_blk_type type, uint32_t enc_id), | |
| 835 | − TP_ARGS(id, type, enc_id), | |
| 834 | + TP_PROTO(uint32_t id, uint32_t enc_id), | |
| 835 | + TP_ARGS(id, enc_id), | |
| 836 | 836 | TP_STRUCT__entry( |
| 837 | 837 | __field( uint32_t, id ) |
| 838 | − __field( enum dpu_hw_blk_type, type ) | |
| 839 | 838 | __field( uint32_t, enc_id ) |
| 840 | 839 | ), |
| 841 | 840 | TP_fast_assign( |
| 842 | 841 | __entry->id = id; |
| 843 | − __entry->type = type; | |
| 844 | 842 | __entry->enc_id = enc_id; |
| 845 | 843 | ), |
| 846 | − TP_printk("id:%d type:%d enc_id:%u", __entry->id, __entry->type, | |
| 847 | − __entry->enc_id) | |
| 844 | + TP_printk("id:%d enc_id:%u", __entry->id, __entry->enc_id) | |
| 848 | 845 | ); |
| 849 | 846 | DEFINE_EVENT(dpu_rm_iter_template, dpu_rm_reserve_intf, |
| 850 | − TP_PROTO(uint32_t id, enum dpu_hw_blk_type type, uint32_t enc_id), | |
| 851 | − TP_ARGS(id, type, enc_id) | |
| 847 | + TP_PROTO(uint32_t id, uint32_t enc_id), | |
| 848 | + TP_ARGS(id, enc_id) | |
| 852 | 849 | ); |
| 853 | 850 | DEFINE_EVENT(dpu_rm_iter_template, dpu_rm_reserve_ctls, |
| 854 | − TP_PROTO(uint32_t id, enum dpu_hw_blk_type type, uint32_t enc_id), | |
| 855 | − TP_ARGS(id, type, enc_id) | |
| 851 | + TP_PROTO(uint32_t id, uint32_t enc_id), | |
| 852 | + TP_ARGS(id, enc_id) | |
| 856 | 853 | ); |
| 857 | 854 | |
| 858 | 855 | TRACE_EVENT(dpu_rm_reserve_lms, |
| 859 | − TP_PROTO(uint32_t id, enum dpu_hw_blk_type type, uint32_t enc_id, | |
| 860 | − uint32_t pp_id), | |
| 861 | − TP_ARGS(id, type, enc_id, pp_id), | |
| 856 | + TP_PROTO(uint32_t id, uint32_t enc_id, uint32_t pp_id), | |
| 857 | + TP_ARGS(id, enc_id, pp_id), | |
| 862 | 858 | TP_STRUCT__entry( |
| 863 | 859 | __field( uint32_t, id ) |
| 864 | − __field( enum dpu_hw_blk_type, type ) | |
| 865 | 860 | __field( uint32_t, enc_id ) |
| 866 | 861 | __field( uint32_t, pp_id ) |
| 867 | 862 | ), |
| 868 | 863 | TP_fast_assign( |
| 869 | 864 | __entry->id = id; |
| 870 | − __entry->type = type; | |
| 871 | 865 | __entry->enc_id = enc_id; |
| 872 | 866 | __entry->pp_id = pp_id; |
| 873 | 867 | ), |
| 874 | − TP_printk("id:%d type:%d enc_id:%u pp_id:%u", __entry->id, | |
| 875 | − __entry->type, __entry->enc_id, __entry->pp_id) | |
| 868 | + TP_printk("id:%d enc_id:%u pp_id:%u", __entry->id, | |
| 869 | + __entry->enc_id, __entry->pp_id) | |
| 876 | 870 | ); |
| 877 | 871 | |
| 878 | 872 | TRACE_EVENT(dpu_vbif_wait_xin_halt_fail, |
| @@ -207,62 +207,44 @@ u32 msm_readl(const void __iomem *addr) · 206 unmodified lines | ||
| 207 | 207 | return val; |
| 208 | 208 | } |
| 209 | 209 | |
| 210 | −struct vblank_event { | |
| 211 | − struct list_head node; | |
| 210 | +struct msm_vblank_work { | |
| 211 | + struct work_struct work; | |
| 212 | 212 | int crtc_id; |
| 213 | 213 | bool enable; |
| 214 | + struct msm_drm_private *priv; | |
| 214 | 215 | }; |
| 215 | 216 | |
| 216 | −static void vblank_ctrl_worker(struct kthread_work *work) | |
| 217 | +static void vblank_ctrl_worker(struct work_struct *work) | |
| 217 | 218 | { |
| 218 | − struct msm_vblank_ctrl *vbl_ctrl = container_of(work, | |
| 219 | − struct msm_vblank_ctrl, work); | |
| 220 | − struct msm_drm_private *priv = container_of(vbl_ctrl, | |
| 221 | − struct msm_drm_private, vblank_ctrl); | |
| 219 | + struct msm_vblank_work *vbl_work = container_of(work, | |
| 220 | + struct msm_vblank_work, work); | |
| 221 | + struct msm_drm_private *priv = vbl_work->priv; | |
| 222 | 222 | struct msm_kms *kms = priv->kms; |
| 223 | − struct vblank_event *vbl_ev, *tmp; | |
| 224 | − unsigned long flags; | |
| 225 | − | |
| 226 | − spin_lock_irqsave(&vbl_ctrl->lock, flags); | |
| 227 | − list_for_each_entry_safe(vbl_ev, tmp, &vbl_ctrl->event_list, node) { | |
| 228 | − list_del(&vbl_ev->node); | |
| 229 | − spin_unlock_irqrestore(&vbl_ctrl->lock, flags); | |
| 230 | − | |
| 231 | − if (vbl_ev->enable) | |
| 232 | − kms->funcs->enable_vblank(kms, | |
| 233 | − priv->crtcs[vbl_ev->crtc_id]); | |
| 234 | − else | |
| 235 | − kms->funcs->disable_vblank(kms, | |
| 236 | − priv->crtcs[vbl_ev->crtc_id]); | |
| 237 | − | |
| 238 | − kfree(vbl_ev); | |
| 239 | 223 | |
| 240 | − spin_lock_irqsave(&vbl_ctrl->lock, flags); | |
| 241 | − } | |
| 224 | + if (vbl_work->enable) | |
| 225 | + kms->funcs->enable_vblank(kms, priv->crtcs[vbl_work->crtc_id]); | |
| 226 | + else | |
| 227 | + kms->funcs->disable_vblank(kms, priv->crtcs[vbl_work->crtc_id]); | |
| 242 | 228 | |
| 243 | − spin_unlock_irqrestore(&vbl_ctrl->lock, flags); | |
| 229 | + kfree(vbl_work); | |
| 244 | 230 | } |
| 245 | 231 | |
| 246 | 232 | static int vblank_ctrl_queue_work(struct msm_drm_private *priv, |
| 247 | 233 | int crtc_id, bool enable) |
| 248 | 234 | { |
| 249 | − struct msm_vblank_ctrl *vbl_ctrl = &priv->vblank_ctrl; | |
| 250 | − struct vblank_event *vbl_ev; | |
| 251 | − unsigned long flags; | |
| 235 | + struct msm_vblank_work *vbl_work; | |
| 252 | 236 | |
| 253 | − vbl_ev = kzalloc(sizeof(*vbl_ev), GFP_ATOMIC); | |
| 254 | − if (!vbl_ev) | |
| 237 | + vbl_work = kzalloc(sizeof(*vbl_work), GFP_ATOMIC); | |
| 238 | + if (!vbl_work) | |
| 255 | 239 | return -ENOMEM; |
| 256 | 240 | |
| 257 | − vbl_ev->crtc_id = crtc_id; | |
| 258 | − vbl_ev->enable = enable; | |
| 241 | + INIT_WORK(&vbl_work->work, vblank_ctrl_worker); | |
| 259 | 242 | |
| 260 | − spin_lock_irqsave(&vbl_ctrl->lock, flags); | |
| 261 | − list_add_tail(&vbl_ev->node, &vbl_ctrl->event_list); | |
| 262 | − spin_unlock_irqrestore(&vbl_ctrl->lock, flags); | |
| 243 | + vbl_work->crtc_id = crtc_id; | |
| 244 | + vbl_work->enable = enable; | |
| 245 | + vbl_work->priv = priv; | |
| 263 | 246 | |
| 264 | − kthread_queue_work(&priv->disp_thread[crtc_id].worker, | |
| 265 | − &vbl_ctrl->work); | |
| 247 | + queue_work(priv->wq, &vbl_work->work); | |
| 266 | 248 | |
| 267 | 249 | return 0; |
| 268 | 250 | } |
| @@ -274,31 +256,20 @@ static int msm_drm_uninit(struct device *dev) · 5 unmodified lines | ||
| 274 | 256 | struct msm_drm_private *priv = ddev->dev_private; |
| 275 | 257 | struct msm_kms *kms = priv->kms; |
| 276 | 258 | struct msm_mdss *mdss = priv->mdss; |
| 277 | − struct msm_vblank_ctrl *vbl_ctrl = &priv->vblank_ctrl; | |
| 278 | − struct vblank_event *vbl_ev, *tmp; | |
| 279 | 259 | int i; |
| 280 | 260 | |
| 281 | 261 | /* We must cancel and cleanup any pending vblank enable/disable |
| 282 | 262 | * work before drm_irq_uninstall() to avoid work re-enabling an |
| 283 | 263 | * irq after uninstall has disabled it. |
| 284 | 264 | */ |
| 285 | − kthread_flush_work(&vbl_ctrl->work); | |
| 286 | − list_for_each_entry_safe(vbl_ev, tmp, &vbl_ctrl->event_list, node) { | |
| 287 | − list_del(&vbl_ev->node); | |
| 288 | − kfree(vbl_ev); | |
| 289 | − } | |
| 290 | 265 | |
| 291 | − /* clean up display commit/event worker threads */ | |
| 292 | − for (i = 0; i < priv->num_crtcs; i++) { | |
| 293 | − if (priv->disp_thread[i].thread) { | |
| 294 | − kthread_flush_worker(&priv->disp_thread[i].worker); | |
| 295 | − kthread_stop(priv->disp_thread[i].thread); | |
| 296 | − priv->disp_thread[i].thread = NULL; | |
| 297 | − } | |
| 266 | + flush_workqueue(priv->wq); | |
| 267 | + destroy_workqueue(priv->wq); | |
| 298 | 268 | |
| 269 | + /* clean up event worker threads */ | |
| 270 | + for (i = 0; i < priv->num_crtcs; i++) { | |
| 299 | 271 | if (priv->event_thread[i].thread) { |
| 300 | − kthread_flush_worker(&priv->event_thread[i].worker); | |
| 301 | − kthread_stop(priv->event_thread[i].thread); | |
| 272 | + kthread_destroy_worker(&priv->event_thread[i].worker); | |
| 302 | 273 | priv->event_thread[i].thread = NULL; |
| 303 | 274 | } |
| 304 | 275 | } |
| @@ -323,9 +294,6 @@ static int msm_drm_uninit(struct device *dev) · 18 unmodified lines | ||
| 323 | 294 | drm_irq_uninstall(ddev); |
| 324 | 295 | pm_runtime_put_sync(dev); |
| 325 | 296 | |
| 326 | − flush_workqueue(priv->wq); | |
| 327 | − destroy_workqueue(priv->wq); | |
| 328 | − | |
| 329 | 297 | if (kms && kms->funcs) |
| 330 | 298 | kms->funcs->destroy(kms); |
| 331 | 299 | |
| @@ -490,9 +458,6 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv) · 158 unmodified lines | ||
| 490 | 458 | priv->wq = alloc_ordered_workqueue("msm", 0); |
| 491 | 459 | |
| 492 | 460 | INIT_LIST_HEAD(&priv->inactive_list); |
| 493 | − INIT_LIST_HEAD(&priv->vblank_ctrl.event_list); | |
| 494 | − kthread_init_work(&priv->vblank_ctrl.work, vblank_ctrl_worker); | |
| 495 | − spin_lock_init(&priv->vblank_ctrl.lock); | |
| 496 | 461 | |
| 497 | 462 | drm_mode_config_init(ddev); |
| 498 | 463 | |
| @@ -554,27 +519,6 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv) · 55 unmodified lines | ||
| 554 | 519 | */ |
| 555 | 520 | param.sched_priority = 16; |
| 556 | 521 | for (i = 0; i < priv->num_crtcs; i++) { |
| 557 | − | |
| 558 | − /* initialize display thread */ | |
| 559 | − priv->disp_thread[i].crtc_id = priv->crtcs[i]->base.id; | |
| 560 | − kthread_init_worker(&priv->disp_thread[i].worker); | |
| 561 | − priv->disp_thread[i].dev = ddev; | |
| 562 | − priv->disp_thread[i].thread = | |
| 563 | − kthread_run(kthread_worker_fn, | |
| 564 | − &priv->disp_thread[i].worker, | |
| 565 | − "crtc_commit:%d", priv->disp_thread[i].crtc_id); | |
| 566 | − if (IS_ERR(priv->disp_thread[i].thread)) { | |
| 567 | − DRM_DEV_ERROR(dev, "failed to create crtc_commit kthread\n"); | |
| 568 | − priv->disp_thread[i].thread = NULL; | |
| 569 | − goto err_msm_uninit; | |
| 570 | − } | |
| 571 | − | |
| 572 | − ret = sched_setscheduler(priv->disp_thread[i].thread, | |
| 573 | − SCHED_FIFO, ¶m); | |
| 574 | − if (ret) | |
| 575 | − dev_warn(dev, "disp_thread set priority failed: %d\n", | |
| 576 | − ret); | |
| 577 | − | |
| 578 | 522 | /* initialize event thread */ |
| 579 | 523 | priv->event_thread[i].crtc_id = priv->crtcs[i]->base.id; |
| 580 | 524 | kthread_init_worker(&priv->event_thread[i].worker); |
| @@ -589,13 +533,6 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv) · 8 unmodified lines | ||
| 589 | 533 | goto err_msm_uninit; |
| 590 | 534 | } |
| 591 | 535 | |
| 592 | − /** | |
| 593 | − * event thread should also run at same priority as disp_thread | |
| 594 | − * because it is handling frame_done events. A lower priority | |
| 595 | − * event thread and higher priority disp_thread can causes | |
| 596 | − * frame_pending counters beyond 2. This can lead to commit | |
| 597 | − * failure at crtc commit level. | |
| 598 | − */ | |
| 599 | 536 | ret = sched_setscheduler(priv->event_thread[i].thread, |
| 600 | 537 | SCHED_FIFO, ¶m); |
| 601 | 538 | if (ret) |
| @@ -914,8 +851,12 @@ static int msm_ioctl_gem_info(struct drm_device *dev, void *data, · 312 unmodified lines | ||
| 914 | 851 | ret = -EINVAL; |
| 915 | 852 | break; |
| 916 | 853 | } |
| 917 | − ret = copy_from_user(msm_obj->name, | |
| 918 | − u64_to_user_ptr(args->value), args->len); | |
| 854 | + if (copy_from_user(msm_obj->name, u64_to_user_ptr(args->value), | |
| 855 | + args->len)) { | |
| 856 | + msm_obj->name[0] = '\0'; | |
| 857 | + ret = -EFAULT; | |
| 858 | + break; | |
| 859 | + } | |
| 919 | 860 | msm_obj->name[args->len] = '\0'; |
| 920 | 861 | for (i = 0; i < args->len; i++) { |
| 921 | 862 | if (!isprint(msm_obj->name[i])) { |
| @@ -931,8 +872,9 @@ static int msm_ioctl_gem_info(struct drm_device *dev, void *data, · 9 unmodified lines | ||
| 931 | 872 | } |
| 932 | 873 | args->len = strlen(msm_obj->name); |
| 933 | 874 | if (args->value) { |
| 934 | − ret = copy_to_user(u64_to_user_ptr(args->value), | |
| 935 | − msm_obj->name, args->len); | |
| 875 | + if (copy_to_user(u64_to_user_ptr(args->value), | |
| 876 | + msm_obj->name, args->len)) | |
| 877 | + ret = -EFAULT; | |
| 936 | 878 | } |
| 937 | 879 | break; |
| 938 | 880 | } |
| @@ -77,12 +77,6 @@ enum msm_mdp_plane_property { · 76 unmodified lines | ||
| 77 | 77 | PLANE_PROP_MAX_NUM |
| 78 | 78 | }; |
| 79 | 79 | |
| 80 | −struct msm_vblank_ctrl { | |
| 81 | − struct kthread_work work; | |
| 82 | − struct list_head event_list; | |
| 83 | − spinlock_t lock; | |
| 84 | −}; | |
| 85 | − | |
| 86 | 80 | #define MSM_GPU_MAX_RINGS 4 |
| 87 | 81 | #define MAX_H_TILES_PER_DISPLAY 2 |
| 88 | 82 | |
| @@ -126,7 +120,7 @@ struct msm_display_topology { · 37 unmodified lines | ||
| 126 | 120 | |
| 127 | 121 | /** |
| 128 | 122 | * struct msm_display_info - defines display properties |
| 129 | − * @intf_type: DRM_MODE_CONNECTOR_ display type | |
| 123 | + * @intf_type: DRM_MODE_ENCODER_ type | |
| 130 | 124 | * @capabilities: Bitmask of display flags |
| 131 | 125 | * @num_of_h_tiles: Number of horizontal tiles in case of split interface |
| 132 | 126 | * @h_tile_instance: Controller instance used per tile. Number of elements is |
| @@ -199,7 +193,6 @@ struct msm_drm_private { · 66 unmodified lines | ||
| 199 | 193 | unsigned int num_crtcs; |
| 200 | 194 | struct drm_crtc *crtcs[MAX_CRTCS]; |
| 201 | 195 | |
| 202 | − struct msm_drm_thread disp_thread[MAX_CRTCS]; | |
| 203 | 196 | struct msm_drm_thread event_thread[MAX_CRTCS]; |
| 204 | 197 | |
| 205 | 198 | unsigned int num_encoders; |
| @@ -228,7 +221,6 @@ struct msm_drm_private { · 22 unmodified lines | ||
| 228 | 221 | struct notifier_block vmap_notifier; |
| 229 | 222 | struct shrinker shrinker; |
| 230 | 223 | |
| 231 | − struct msm_vblank_ctrl vblank_ctrl; | |
| 232 | 224 | struct drm_atomic_state *pm_state; |
| 233 | 225 | }; |
| 234 | 226 | |
| @@ -560,6 +560,8 @@ · 559 unmodified lines | ||
| 560 | 560 | # define DP_TEST_LINK_EDID_READ (1 << 2) |
| 561 | 561 | # define DP_TEST_LINK_PHY_TEST_PATTERN (1 << 3) /* DPCD >= 1.1 */ |
| 562 | 562 | # define DP_TEST_LINK_FAUX_PATTERN (1 << 4) /* DPCD >= 1.2 */ |
| 563 | +# define DP_TEST_LINK_AUDIO_PATTERN (1 << 5) /* DPCD >= 1.2 */ | |
| 564 | +# define DP_TEST_LINK_AUDIO_DISABLED_VIDEO (1 << 6) /* DPCD >= 1.2 */ | |
| 563 | 565 | |
| 564 | 566 | #define DP_TEST_LINK_RATE 0x219 |
| 565 | 567 | # define DP_LINK_RATE_162 (0x6) |
| @@ -608,6 +610,7 @@ · 42 unmodified lines | ||
| 608 | 610 | # define DP_COLOR_FORMAT_RGB (0 << 1) |
| 609 | 611 | # define DP_COLOR_FORMAT_YCbCr422 (1 << 1) |
| 610 | 612 | # define DP_COLOR_FORMAT_YCbCr444 (2 << 1) |
| 613 | +# define DP_TEST_DYNAMIC_RANGE_VESA (0 << 3) | |
| 611 | 614 | # define DP_TEST_DYNAMIC_RANGE_CEA (1 << 3) |
| 612 | 615 | # define DP_TEST_YCBCR_COEFFICIENTS (1 << 4) |
| 613 | 616 | # define DP_YCBCR_COEFFICIENTS_ITU601 (0 << 4) |
| @@ -657,6 +660,16 @@ · 43 unmodified lines | ||
| 657 | 660 | |
| 658 | 661 | #define DP_TEST_SINK 0x270 |
| 659 | 662 | # define DP_TEST_SINK_START (1 << 0) |
| 663 | +#define DP_TEST_AUDIO_MODE 0x271 | |
| 664 | +#define DP_TEST_AUDIO_PATTERN_TYPE 0x272 | |
| 665 | +#define DP_TEST_AUDIO_PERIOD_CH1 0x273 | |
| 666 | +#define DP_TEST_AUDIO_PERIOD_CH2 0x274 | |
| 667 | +#define DP_TEST_AUDIO_PERIOD_CH3 0x275 | |
| 668 | +#define DP_TEST_AUDIO_PERIOD_CH4 0x276 | |
| 669 | +#define DP_TEST_AUDIO_PERIOD_CH5 0x277 | |
| 670 | +#define DP_TEST_AUDIO_PERIOD_CH6 0x278 | |
| 671 | +#define DP_TEST_AUDIO_PERIOD_CH7 0x279 | |
| 672 | +#define DP_TEST_AUDIO_PERIOD_CH8 0x27A | |
| 660 | 673 | |
| 661 | 674 | #define DP_FEC_STATUS 0x280 /* 1.4 */ |
| 662 | 675 | # define DP_FEC_DECODE_EN_DETECTED (1 << 0) |