Commit a5f2fafe authored by Dave Airlie's avatar Dave Airlie

Merge https://gitlab.freedesktop.org/drm/msm into drm-next

On the display side, cleanups and fixes to enabled modifiers
(QCOM_COMPRESSED).  And otherwise mostly misc fixes all around.
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
From: Rob Clark <robdclark@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/CAF6AEGuZ5uBKpf=fHvKpTiD10nychuEY8rnE+HeRz0QMvtY5_A@mail.gmail.com
parents 71f4e45a 860433ed
Qualcomm adreno/snapdragon GMU (Graphics management unit)
The GMU is a programmable power controller for the GPU. the CPU controls the
GMU which in turn handles power controls for the GPU.
Required properties:
- compatible: "qcom,adreno-gmu-XYZ.W", "qcom,adreno-gmu"
for example: "qcom,adreno-gmu-630.2", "qcom,adreno-gmu"
Note that you need to list the less specific "qcom,adreno-gmu"
for generic matches and the more specific identifier to identify
the specific device.
- reg: Physical base address and length of the GMU registers.
- reg-names: Matching names for the register regions
* "gmu"
* "gmu_pdc"
* "gmu_pdc_seg"
- interrupts: The interrupt signals from the GMU.
- interrupt-names: Matching names for the interrupts
* "hfi"
* "gmu"
- clocks: phandles to the device clocks
- clock-names: Matching names for the clocks
* "gmu"
* "cxo"
* "axi"
* "mnoc"
- power-domains: should be <&clock_gpucc GPU_CX_GDSC>
- iommus: phandle to the adreno iommu
- operating-points-v2: phandle to the OPP operating points
Example:
/ {
...
gmu: gmu@506a000 {
compatible="qcom,adreno-gmu-630.2", "qcom,adreno-gmu";
reg = <0x506a000 0x30000>,
<0xb280000 0x10000>,
<0xb480000 0x10000>;
reg-names = "gmu", "gmu_pdc", "gmu_pdc_seq";
interrupts = <GIC_SPI 304 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 305 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "hfi", "gmu";
clocks = <&gpucc GPU_CC_CX_GMU_CLK>,
<&gpucc GPU_CC_CXO_CLK>,
<&gcc GCC_DDRSS_GPU_AXI_CLK>,
<&gcc GCC_GPU_MEMNOC_GFX_CLK>;
clock-names = "gmu", "cxo", "axi", "memnoc";
power-domains = <&gpucc GPU_CX_GDSC>;
iommus = <&adreno_smmu 5>;
operating-points-v2 = <&gmu_opp_table>;
};
};
......@@ -10,14 +10,23 @@ Required properties:
If "amd,imageon" is used, there should be no top level msm device.
- reg: Physical base address and length of the controller's registers.
- interrupts: The interrupt signal from the gpu.
- clocks: device clocks
- clocks: device clocks (if applicable)
See ../clocks/clock-bindings.txt for details.
- clock-names: the following clocks are required:
- clock-names: the following clocks are required by a3xx, a4xx and a5xx
cores:
* "core"
* "iface"
* "mem_iface"
For GMU attached devices the GPU clocks are not used and are not required. The
following devices should not list clocks:
- qcom,adreno-630.2
- iommus: optional phandle to an adreno iommu instance
- operating-points-v2: optional phandle to the OPP operating points
- qcom,gmu: For GMU attached devices a phandle to the GMU device that will
control the power for the GPU. Applicable targets:
- qcom,adreno-630.2
Example:
Example 3xx/4xx/a5xx:
/ {
...
......@@ -37,3 +46,30 @@ Example:
<&mmcc MMSS_IMEM_AHB_CLK>;
};
};
Example a6xx (with GMU):
/ {
...
gpu@5000000 {
compatible = "qcom,adreno-630.2", "qcom,adreno";
#stream-id-cells = <16>;
reg = <0x5000000 0x40000>, <0x509e000 0x10>;
reg-names = "kgsl_3d0_reg_memory", "cx_mem";
/*
* Look ma, no clocks! The GPU clocks and power are
* controlled entirely by the GMU
*/
interrupts = <GIC_SPI 300 IRQ_TYPE_LEVEL_HIGH>;
iommus = <&adreno_smmu 0>;
operating-points-v2 = <&gpu_opp_table>;
qcom,gmu = <&gmu>;
};
};
......@@ -4851,10 +4851,11 @@ F: Documentation/devicetree/bindings/display/multi-inno,mi0283qt.txt
DRM DRIVER FOR MSM ADRENO GPU
M: Rob Clark <robdclark@gmail.com>
M: Sean Paul <sean@poorly.run>
L: linux-arm-msm@vger.kernel.org
L: dri-devel@lists.freedesktop.org
L: freedreno@lists.freedesktop.org
T: git git://people.freedesktop.org/~robclark/linux
T: git https://gitlab.freedesktop.org/drm/msm.git
S: Maintained
F: drivers/gpu/drm/msm/
F: include/uapi/drm/msm_drm.h
......
......@@ -465,8 +465,6 @@ static void _dpu_crtc_setup_mixer_for_encoder(
return;
}
mixer->encoder = enc;
cstate->num_mixers++;
DPU_DEBUG("setup mixer %d: lm %d\n",
i, mixer->hw_lm->idx - LM_0);
......@@ -718,11 +716,8 @@ void dpu_crtc_commit_kickoff(struct drm_crtc *crtc, bool async)
* may delay and flush at an irq event (e.g. ppdone)
*/
drm_for_each_encoder_mask(encoder, crtc->dev,
crtc->state->encoder_mask) {
struct dpu_encoder_kickoff_params params = { 0 };
dpu_encoder_prepare_for_kickoff(encoder, &params, async);
}
crtc->state->encoder_mask)
dpu_encoder_prepare_for_kickoff(encoder, async);
if (!async) {
/* wait for frame_event_done completion */
......
......@@ -84,14 +84,12 @@ struct dpu_crtc_smmu_state_data {
* struct dpu_crtc_mixer: stores the map for each virtual pipeline in the CRTC
* @hw_lm: LM HW Driver context
* @lm_ctl: CTL Path HW driver context
* @encoder: Encoder attached to this lm & ctl
* @mixer_op_mode: mixer blending operation mode
* @flush_mask: mixer flush mask for ctl, mixer and pipe
*/
struct dpu_crtc_mixer {
struct dpu_hw_mixer *hw_lm;
struct dpu_hw_ctl *lm_ctl;
struct drm_encoder *encoder;
u32 mixer_op_mode;
u32 flush_mask;
};
......
......@@ -205,7 +205,7 @@ struct dpu_encoder_virt {
bool idle_pc_supported;
struct mutex rc_lock;
enum dpu_enc_rc_states rc_state;
struct kthread_delayed_work delayed_off_work;
struct delayed_work delayed_off_work;
struct kthread_work vsync_event_work;
struct msm_display_topology topology;
bool mode_set_complete;
......@@ -742,7 +742,6 @@ static int dpu_encoder_resource_control(struct drm_encoder *drm_enc,
{
struct dpu_encoder_virt *dpu_enc;
struct msm_drm_private *priv;
struct msm_drm_thread *disp_thread;
bool is_vid_mode = false;
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,
is_vid_mode = dpu_enc->disp_info.capabilities &
MSM_DISPLAY_CAP_VID_MODE;
if (drm_enc->crtc->index >= ARRAY_SIZE(priv->disp_thread)) {
DPU_ERROR("invalid crtc index\n");
return -EINVAL;
}
disp_thread = &priv->disp_thread[drm_enc->crtc->index];
/*
* when idle_pc is not supported, process only KICKOFF, STOP and MODESET
* 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,
switch (sw_event) {
case DPU_ENC_RC_EVENT_KICKOFF:
/* cancel delayed off work, if any */
if (kthread_cancel_delayed_work_sync(
&dpu_enc->delayed_off_work))
if (cancel_delayed_work_sync(&dpu_enc->delayed_off_work))
DPU_DEBUG_ENC(dpu_enc, "sw_event:%d, work cancelled\n",
sw_event);
......@@ -837,10 +829,8 @@ static int dpu_encoder_resource_control(struct drm_encoder *drm_enc,
return 0;
}
kthread_queue_delayed_work(
&disp_thread->worker,
&dpu_enc->delayed_off_work,
msecs_to_jiffies(dpu_enc->idle_timeout));
queue_delayed_work(priv->wq, &dpu_enc->delayed_off_work,
msecs_to_jiffies(dpu_enc->idle_timeout));
trace_dpu_enc_rc(DRMID(drm_enc), sw_event,
dpu_enc->idle_pc_supported, dpu_enc->rc_state,
......@@ -849,8 +839,7 @@ static int dpu_encoder_resource_control(struct drm_encoder *drm_enc,
case DPU_ENC_RC_EVENT_PRE_STOP:
/* cancel delayed off work, if any */
if (kthread_cancel_delayed_work_sync(
&dpu_enc->delayed_off_work))
if (cancel_delayed_work_sync(&dpu_enc->delayed_off_work))
DPU_DEBUG_ENC(dpu_enc, "sw_event:%d, work cancelled\n",
sw_event);
......@@ -1368,7 +1357,7 @@ static void dpu_encoder_frame_done_callback(
}
}
static void dpu_encoder_off_work(struct kthread_work *work)
static void dpu_encoder_off_work(struct work_struct *work)
{
struct dpu_encoder_virt *dpu_enc = container_of(work,
struct dpu_encoder_virt, delayed_off_work.work);
......@@ -1756,15 +1745,14 @@ static void dpu_encoder_vsync_event_work_handler(struct kthread_work *work)
nsecs_to_jiffies(ktime_to_ns(wakeup_time)));
}
void dpu_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc,
struct dpu_encoder_kickoff_params *params, bool async)
void dpu_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, bool async)
{
struct dpu_encoder_virt *dpu_enc;
struct dpu_encoder_phys *phys;
bool needs_hw_reset = false;
unsigned int i;
if (!drm_enc || !params) {
if (!drm_enc) {
DPU_ERROR("invalid args\n");
return;
}
......@@ -1778,7 +1766,7 @@ void dpu_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc,
phys = dpu_enc->phys_encs[i];
if (phys) {
if (phys->ops.prepare_for_kickoff)
phys->ops.prepare_for_kickoff(phys, params);
phys->ops.prepare_for_kickoff(phys);
if (phys->enable_state == DPU_ENC_ERR_NEEDS_HW_RESET)
needs_hw_reset = true;
}
......@@ -2193,7 +2181,7 @@ int dpu_encoder_setup(struct drm_device *dev, struct drm_encoder *enc,
mutex_init(&dpu_enc->rc_lock);
kthread_init_delayed_work(&dpu_enc->delayed_off_work,
INIT_DELAYED_WORK(&dpu_enc->delayed_off_work,
dpu_encoder_off_work);
dpu_enc->idle_timeout = IDLE_TIMEOUT;
......
......@@ -37,15 +37,6 @@ struct dpu_encoder_hw_resources {
enum dpu_intf_mode intfs[INTF_MAX];
};
/**
* dpu_encoder_kickoff_params - info encoder requires at kickoff
* @affected_displays: bitmask, bit set means the ROI of the commit lies within
* the bounds of the physical display at the bit index
*/
struct dpu_encoder_kickoff_params {
unsigned long affected_displays;
};
/**
* dpu_encoder_get_hw_resources - Populate table of required hardware resources
* @encoder: encoder pointer
......@@ -88,11 +79,9 @@ void dpu_encoder_register_frame_event_callback(struct drm_encoder *encoder,
* Immediately: if no previous commit is outstanding.
* Delayed: Block until next trigger can be issued.
* @encoder: encoder pointer
* @params: kickoff time parameters
* @async: true if this is an asynchronous commit
*/
void dpu_encoder_prepare_for_kickoff(struct drm_encoder *encoder,
struct dpu_encoder_kickoff_params *params, bool async);
void dpu_encoder_prepare_for_kickoff(struct drm_encoder *encoder, bool async);
/**
* dpu_encoder_trigger_kickoff_pending - Clear the flush bits from previous
......
......@@ -144,8 +144,7 @@ struct dpu_encoder_phys_ops {
int (*wait_for_commit_done)(struct dpu_encoder_phys *phys_enc);
int (*wait_for_tx_complete)(struct dpu_encoder_phys *phys_enc);
int (*wait_for_vblank)(struct dpu_encoder_phys *phys_enc);
void (*prepare_for_kickoff)(struct dpu_encoder_phys *phys_enc,
struct dpu_encoder_kickoff_params *params);
void (*prepare_for_kickoff)(struct dpu_encoder_phys *phys_enc);
void (*handle_post_kickoff)(struct dpu_encoder_phys *phys_enc);
void (*trigger_start)(struct dpu_encoder_phys *phys_enc);
bool (*needs_single_flush)(struct dpu_encoder_phys *phys_enc);
......
......@@ -594,8 +594,7 @@ static void dpu_encoder_phys_cmd_get_hw_resources(
}
static void dpu_encoder_phys_cmd_prepare_for_kickoff(
struct dpu_encoder_phys *phys_enc,
struct dpu_encoder_kickoff_params *params)
struct dpu_encoder_phys *phys_enc)
{
struct dpu_encoder_phys_cmd *cmd_enc =
to_dpu_encoder_phys_cmd(phys_enc);
......@@ -693,7 +692,7 @@ static int dpu_encoder_phys_cmd_wait_for_commit_done(
/* required for both controllers */
if (!rc && cmd_enc->serialize_wait4pp)
dpu_encoder_phys_cmd_prepare_for_kickoff(phys_enc, NULL);
dpu_encoder_phys_cmd_prepare_for_kickoff(phys_enc);
return rc;
}
......
......@@ -587,14 +587,13 @@ static int dpu_encoder_phys_vid_wait_for_vblank(
}
static void dpu_encoder_phys_vid_prepare_for_kickoff(
struct dpu_encoder_phys *phys_enc,
struct dpu_encoder_kickoff_params *params)
struct dpu_encoder_phys *phys_enc)
{
struct dpu_encoder_phys_vid *vid_enc;
struct dpu_hw_ctl *ctl;
int rc;
if (!phys_enc || !params) {
if (!phys_enc) {
DPU_ERROR("invalid encoder/parameters\n");
return;
}
......
......@@ -263,13 +263,13 @@ static const struct dpu_format dpu_format_map[] = {
INTERLEAVED_RGB_FMT(RGB565,
0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT,
C1_B_Cb, C0_G_Y, C2_R_Cr, 0, 3,
C2_R_Cr, C0_G_Y, C1_B_Cb, 0, 3,
false, 2, 0,
DPU_FETCH_LINEAR, 1),
INTERLEAVED_RGB_FMT(BGR565,
0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT,
C2_R_Cr, C0_G_Y, C1_B_Cb, 0, 3,
C1_B_Cb, C0_G_Y, C2_R_Cr, 0, 3,
false, 2, 0,
DPU_FETCH_LINEAR, 1),
......@@ -1137,36 +1137,3 @@ const struct msm_format *dpu_get_msm_format(
return &fmt->base;
return NULL;
}
uint32_t dpu_populate_formats(
const struct dpu_format_extended *format_list,
uint32_t *pixel_formats,
uint64_t *pixel_modifiers,
uint32_t pixel_formats_max)
{
uint32_t i, fourcc_format;
if (!format_list || !pixel_formats)
return 0;
for (i = 0, fourcc_format = 0;
format_list->fourcc_format && i < pixel_formats_max;
++format_list) {
/* verify if listed format is in dpu_format_map? */
/* optionally return modified formats */
if (pixel_modifiers) {
/* assume same modifier for all fb planes */
pixel_formats[i] = format_list->fourcc_format;
pixel_modifiers[i++] = format_list->modifier;
} else {
/* assume base formats grouped together */
if (fourcc_format != format_list->fourcc_format) {
fourcc_format = format_list->fourcc_format;
pixel_formats[i++] = fourcc_format;
}
}
}
return i;
}
......@@ -40,20 +40,6 @@ const struct msm_format *dpu_get_msm_format(
const uint32_t format,
const uint64_t modifiers);
/**
* dpu_populate_formats - populate the given array with fourcc codes supported
* @format_list: pointer to list of possible formats
* @pixel_formats: array to populate with fourcc codes
* @pixel_modifiers: array to populate with drm modifiers, can be NULL
* @pixel_formats_max: length of pixel formats array
* Return: number of elements populated
*/
uint32_t dpu_populate_formats(
const struct dpu_format_extended *format_list,
uint32_t *pixel_formats,
uint64_t *pixel_modifiers,
uint32_t pixel_formats_max);
/**
* dpu_format_check_modified_format - validate format and buffers for
* dpu non-standard, i.e. modified format
......
......@@ -151,7 +151,9 @@ static const struct dpu_sspp_blks_common sdm845_sspp_common = {
.id = DPU_SSPP_CSC_10BIT, \
.base = 0x1a00, .len = 0x100,}, \
.format_list = plane_formats_yuv, \
.num_formats = ARRAY_SIZE(plane_formats_yuv), \
.virt_format_list = plane_formats, \
.virt_num_formats = ARRAY_SIZE(plane_formats), \
}
#define _DMA_SBLK(num, sdma_pri) \
......@@ -163,7 +165,9 @@ static const struct dpu_sspp_blks_common sdm845_sspp_common = {
.src_blk = {.name = STRCAT("sspp_src_", num), \
.id = DPU_SSPP_SRC, .base = 0x00, .len = 0x150,}, \
.format_list = plane_formats, \
.num_formats = ARRAY_SIZE(plane_formats), \
.virt_format_list = plane_formats, \
.virt_num_formats = ARRAY_SIZE(plane_formats), \
}
static const struct dpu_sspp_sub_blks sdm845_vig_sblk_0 = _VIG_SBLK("0", 5);
......
......@@ -251,17 +251,6 @@ struct dpu_pp_blk {
u32 version;
};
/**
* struct dpu_format_extended - define dpu specific pixel format+modifier
* @fourcc_format: Base FOURCC pixel format code
* @modifier: 64-bit drm format modifier, same modifier must be applied to all
* framebuffer planes
*/
struct dpu_format_extended {
uint32_t fourcc_format;
uint64_t modifier;
};
/**
* enum dpu_qos_lut_usage - define QoS LUT use cases
*/
......@@ -348,7 +337,9 @@ struct dpu_sspp_blks_common {
* @pcc_blk:
* @igc_blk:
* @format_list: Pointer to list of supported formats
* @num_formats: Number of supported formats
* @virt_format_list: Pointer to list of supported formats for virtual planes
* @virt_num_formats: Number of supported formats for virtual planes
*/
struct dpu_sspp_sub_blks {
const struct dpu_sspp_blks_common *common;
......@@ -366,8 +357,10 @@ struct dpu_sspp_sub_blks {
struct dpu_pp_blk pcc_blk;
struct dpu_pp_blk igc_blk;
const struct dpu_format_extended *format_list;
const struct dpu_format_extended *virt_format_list;
const u32 *format_list;
u32 num_formats;
const u32 *virt_format_list;
u32 virt_num_formats;
};
/**
......
......@@ -12,157 +12,81 @@
#include "dpu_hw_mdss.h"
static const struct dpu_format_extended plane_formats[] = {
{DRM_FORMAT_ARGB8888, 0},
{DRM_FORMAT_ABGR8888, 0},
{DRM_FORMAT_RGBA8888, 0},
{DRM_FORMAT_ABGR8888, DRM_FORMAT_MOD_QCOM_COMPRESSED},
{DRM_FORMAT_BGRA8888, 0},
{DRM_FORMAT_XRGB8888, 0},
{DRM_FORMAT_RGBX8888, 0},
{DRM_FORMAT_BGRX8888, 0},
{DRM_FORMAT_XBGR8888, 0},
{DRM_FORMAT_XBGR8888, DRM_FORMAT_MOD_QCOM_COMPRESSED},
{DRM_FORMAT_RGB888, 0},
{DRM_FORMAT_BGR888, 0},
{DRM_FORMAT_RGB565, 0},
{DRM_FORMAT_BGR565, DRM_FORMAT_MOD_QCOM_COMPRESSED},
{DRM_FORMAT_BGR565, 0},
{DRM_FORMAT_ARGB1555, 0},
{DRM_FORMAT_ABGR1555, 0},
{DRM_FORMAT_RGBA5551, 0},
{DRM_FORMAT_BGRA5551, 0},
{DRM_FORMAT_XRGB1555, 0},
{DRM_FORMAT_XBGR1555, 0},
{DRM_FORMAT_RGBX5551, 0},
{DRM_FORMAT_BGRX5551, 0},
{DRM_FORMAT_ARGB4444, 0},
{DRM_FORMAT_ABGR4444, 0},
{DRM_FORMAT_RGBA4444, 0},
{DRM_FORMAT_BGRA4444, 0},
{DRM_FORMAT_XRGB4444, 0},
{DRM_FORMAT_XBGR4444, 0},
{DRM_FORMAT_RGBX4444, 0},
{DRM_FORMAT_BGRX4444, 0},
{0, 0},
static const uint32_t qcom_compressed_supported_formats[] = {
DRM_FORMAT_ABGR8888,
DRM_FORMAT_XBGR8888,
DRM_FORMAT_BGR565,
};
static const struct dpu_format_extended plane_formats_yuv[] = {
{DRM_FORMAT_ARGB8888, 0},
{DRM_FORMAT_ABGR8888, 0},
{DRM_FORMAT_RGBA8888, 0},
{DRM_FORMAT_BGRX8888, 0},
{DRM_FORMAT_ABGR8888, DRM_FORMAT_MOD_QCOM_COMPRESSED},
{DRM_FORMAT_BGRA8888, 0},
{DRM_FORMAT_XRGB8888, 0},
{DRM_FORMAT_XBGR8888, 0},
{DRM_FORMAT_RGBX8888, 0},
{DRM_FORMAT_XBGR8888, DRM_FORMAT_MOD_QCOM_COMPRESSED},
{DRM_FORMAT_RGB888, 0},
{DRM_FORMAT_BGR888, 0},
{DRM_FORMAT_RGB565, 0},
{DRM_FORMAT_BGR565, DRM_FORMAT_MOD_QCOM_COMPRESSED},
{DRM_FORMAT_BGR565, 0},
{DRM_FORMAT_ARGB1555, 0},
{DRM_FORMAT_ABGR1555, 0},
{DRM_FORMAT_RGBA5551, 0},
{DRM_FORMAT_BGRA5551, 0},
{DRM_FORMAT_XRGB1555, 0},
{DRM_FORMAT_XBGR1555, 0},
{DRM_FORMAT_RGBX5551, 0},
{DRM_FORMAT_BGRX5551, 0},
{DRM_FORMAT_ARGB4444, 0},
{DRM_FORMAT_ABGR4444, 0},
{DRM_FORMAT_RGBA4444, 0},
{DRM_FORMAT_BGRA4444, 0},
{DRM_FORMAT_XRGB4444, 0},
{DRM_FORMAT_XBGR4444, 0},
{DRM_FORMAT_RGBX4444, 0},
{DRM_FORMAT_BGRX4444, 0},
{DRM_FORMAT_NV12, 0},
{DRM_FORMAT_NV12, DRM_FORMAT_MOD_QCOM_COMPRESSED},
{DRM_FORMAT_NV21, 0},
{DRM_FORMAT_NV16, 0},
{DRM_FORMAT_NV61, 0},
{DRM_FORMAT_VYUY, 0},
{DRM_FORMAT_UYVY, 0},
{DRM_FORMAT_YUYV, 0},
{DRM_FORMAT_YVYU, 0},
{DRM_FORMAT_YUV420, 0},
{DRM_FORMAT_YVU420, 0},
{0, 0},
};
static const struct dpu_format_extended cursor_formats[] = {
{DRM_FORMAT_ARGB8888, 0},
{DRM_FORMAT_ABGR8888, 0},
{DRM_FORMAT_RGBA8888, 0},
{DRM_FORMAT_BGRA8888, 0},
{DRM_FORMAT_XRGB8888, 0},
{DRM_FORMAT_ARGB1555, 0},
{DRM_FORMAT_ABGR1555, 0},
{DRM_FORMAT_RGBA5551, 0},
{DRM_FORMAT_BGRA5551, 0},
{DRM_FORMAT_ARGB4444, 0},
{DRM_FORMAT_ABGR4444, 0},
{DRM_FORMAT_RGBA4444, 0},
{DRM_FORMAT_BGRA4444, 0},
{0, 0},
static const uint32_t plane_formats[] = {
DRM_FORMAT_ARGB8888,
DRM_FORMAT_ABGR8888,
DRM_FORMAT_RGBA8888,
DRM_FORMAT_BGRA8888,
DRM_FORMAT_XRGB8888,
DRM_FORMAT_RGBX8888,
DRM_FORMAT_BGRX8888,
DRM_FORMAT_XBGR8888,
DRM_FORMAT_RGB888,
DRM_FORMAT_BGR888,
DRM_FORMAT_RGB565,
DRM_FORMAT_BGR565,
DRM_FORMAT_ARGB1555,
DRM_FORMAT_ABGR1555,
DRM_FORMAT_RGBA5551,
DRM_FORMAT_BGRA5551,
DRM_FORMAT_XRGB1555,
DRM_FORMAT_XBGR1555,
DRM_FORMAT_RGBX5551,
DRM_FORMAT_BGRX5551,
DRM_FORMAT_ARGB4444,
DRM_FORMAT_ABGR4444,
DRM_FORMAT_RGBA4444,
DRM_FORMAT_BGRA4444,
DRM_FORMAT_XRGB4444,
DRM_FORMAT_XBGR4444,
DRM_FORMAT_RGBX4444,
DRM_FORMAT_BGRX4444,
};
static const struct dpu_format_extended wb2_formats[] = {
{DRM_FORMAT_RGB565, 0},
{DRM_FORMAT_BGR565, DRM_FORMAT_MOD_QCOM_COMPRESSED},
{DRM_FORMAT_RGB888, 0},
{DRM_FORMAT_ARGB8888, 0},
{DRM_FORMAT_RGBA8888, 0},
{DRM_FORMAT_ABGR8888, DRM_FORMAT_MOD_QCOM_COMPRESSED},
{DRM_FORMAT_XRGB8888, 0},
{DRM_FORMAT_RGBX8888, 0},
{DRM_FORMAT_XBGR8888, DRM_FORMAT_MOD_QCOM_COMPRESSED},
{DRM_FORMAT_ARGB1555, 0},
{DRM_FORMAT_RGBA5551, 0},
{DRM_FORMAT_XRGB1555, 0},
{DRM_FORMAT_RGBX5551, 0},
{DRM_FORMAT_ARGB4444, 0},
{DRM_FORMAT_RGBA4444, 0},
{DRM_FORMAT_RGBX4444, 0},
{DRM_FORMAT_XRGB4444, 0},
{DRM_FORMAT_BGR565, 0},
{DRM_FORMAT_BGR888, 0},
{DRM_FORMAT_ABGR8888, 0},
{DRM_FORMAT_BGRA8888, 0},
{DRM_FORMAT_BGRX8888, 0},
{DRM_FORMAT_XBGR8888, 0},
{DRM_FORMAT_ABGR1555, 0},
{DRM_FORMAT_BGRA5551, 0},
{DRM_FORMAT_XBGR1555, 0},
{DRM_FORMAT_BGRX5551, 0},
{DRM_FORMAT_ABGR4444, 0},
{DRM_FORMAT_BGRA4444, 0},
{DRM_FORMAT_BGRX4444, 0},
{DRM_FORMAT_XBGR4444, 0},
{DRM_FORMAT_YUV420, 0},
{DRM_FORMAT_NV12, 0},
{DRM_FORMAT_NV12, DRM_FORMAT_MOD_QCOM_COMPRESSED},
{DRM_FORMAT_NV16, 0},
{DRM_FORMAT_YUYV, 0},
{0, 0},
};
static const uint32_t plane_formats_yuv[] = {
DRM_FORMAT_ARGB8888,
DRM_FORMAT_ABGR8888,
DRM_FORMAT_RGBA8888,
DRM_FORMAT_BGRX8888,
DRM_FORMAT_BGRA8888,
DRM_FORMAT_XRGB8888,
DRM_FORMAT_XBGR8888,
DRM_FORMAT_RGBX8888,
DRM_FORMAT_RGB888,
DRM_FORMAT_BGR888,
DRM_FORMAT_RGB565,
DRM_FORMAT_BGR565,
DRM_FORMAT_ARGB1555,
DRM_FORMAT_ABGR1555,
DRM_FORMAT_RGBA5551,
DRM_FORMAT_BGRA5551,
DRM_FORMAT_XRGB1555,
DRM_FORMAT_XBGR1555,
DRM_FORMAT_RGBX5551,
DRM_FORMAT_BGRX5551,
DRM_FORMAT_ARGB4444,
DRM_FORMAT_ABGR4444,
DRM_FORMAT_RGBA4444,
DRM_FORMAT_BGRA4444,
DRM_FORMAT_XRGB4444,
DRM_FORMAT_XBGR4444,
DRM_FORMAT_RGBX4444,
DRM_FORMAT_BGRX4444,
static const struct dpu_format_extended rgb_10bit_formats[] = {
{DRM_FORMAT_BGRA1010102, 0},
{DRM_FORMAT_BGRX1010102, 0},
{DRM_FORMAT_RGBA1010102, 0},
{DRM_FORMAT_RGBX1010102, 0},
{DRM_FORMAT_ABGR2101010, 0},
{DRM_FORMAT_ABGR2101010, DRM_FORMAT_MOD_QCOM_COMPRESSED},
{DRM_FORMAT_XBGR2101010, 0},
{DRM_FORMAT_XBGR2101010, DRM_FORMAT_MOD_QCOM_COMPRESSED},
{DRM_FORMAT_ARGB2101010, 0},
{DRM_FORMAT_XRGB2101010, 0},
DRM_FORMAT_NV12,
DRM_FORMAT_NV21,
DRM_FORMAT_NV16,
DRM_FORMAT_NV61,
DRM_FORMAT_VYUY,
DRM_FORMAT_UYVY,
DRM_FORMAT_YUYV,
DRM_FORMAT_YVYU,
DRM_FORMAT_YUV420,
DRM_FORMAT_YVU420,
};
......@@ -170,10 +170,6 @@
/**
* AD4 interrupt status bit definitions
*/
#define DPU_INTR_BRIGHTPR_UPDATED BIT(4)
#define DPU_INTR_DARKENH_UPDATED BIT(3)
#define DPU_INTR_STREN_OUTROI_UPDATED BIT(2)
#define DPU_INTR_STREN_INROI_UPDATED BIT(1)
#define DPU_INTR_BACKLIGHT_UPDATED BIT(0)
/**
* 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,
return -EINVAL;
}
static void dpu_hw_intr_set_mask(struct dpu_hw_intr *intr, uint32_t reg_off,
uint32_t mask)
{
if (!intr)
return;
DPU_REG_WRITE(&intr->hw, reg_off, mask);
/* ensure register writes go through */
wmb();
}
static void dpu_hw_intr_dispatch_irq(struct dpu_hw_intr *intr,
void (*cbfunc)(void *, int),
void *arg)
......@@ -1004,18 +988,6 @@ static int dpu_hw_intr_disable_irqs(struct dpu_hw_intr *intr)
return 0;
}
static int dpu_hw_intr_get_valid_interrupts(struct dpu_hw_intr *intr,
uint32_t *mask)
{
if (!intr || !mask)
return -EINVAL;
*mask = IRQ_SOURCE_MDP | IRQ_SOURCE_DSI0 | IRQ_SOURCE_DSI1
| IRQ_SOURCE_HDMI | IRQ_SOURCE_EDP;
return 0;
}
static void dpu_hw_intr_get_interrupt_statuses(struct dpu_hw_intr *intr)
{
int i;
......@@ -1065,19 +1037,6 @@ static void dpu_hw_intr_clear_intr_status_nolock(struct dpu_hw_intr *intr,
wmb();
}
static void dpu_hw_intr_clear_interrupt_status(struct dpu_hw_intr *intr,
int irq_idx)
{
unsigned long irq_flags;
if (!intr)
return;
spin_lock_irqsave(&intr->irq_lock, irq_flags);
dpu_hw_intr_clear_intr_status_nolock(intr, irq_idx);
spin_unlock_irqrestore(&intr->irq_lock, irq_flags);
}
static u32 dpu_hw_intr_get_interrupt_status(struct dpu_hw_intr *intr,
int irq_idx, bool clear)
{
......@@ -1113,16 +1072,13 @@ static u32 dpu_hw_intr_get_interrupt_status(struct dpu_hw_intr *intr,
static void __setup_intr_ops(struct dpu_hw_intr_ops *ops)
{
ops->set_mask = dpu_hw_intr_set_mask;
ops->irq_idx_lookup = dpu_hw_intr_irqidx_lookup;
ops->enable_irq = dpu_hw_intr_enable_irq;
ops->disable_irq = dpu_hw_intr_disable_irq;
ops->dispatch_irqs = dpu_hw_intr_dispatch_irq;
ops->clear_all_irqs = dpu_hw_intr_clear_irqs;
ops->disable_all_irqs = dpu_hw_intr_disable_irqs;
ops->get_valid_interrupts = dpu_hw_intr_get_valid_interrupts;
ops->get_interrupt_statuses = dpu_hw_intr_get_interrupt_statuses;
ops->clear_interrupt_status = dpu_hw_intr_clear_interrupt_status;
ops->clear_intr_status_nolock = dpu_hw_intr_clear_intr_status_nolock;
ops->get_interrupt_status = dpu_hw_intr_get_interrupt_status;
}
......
......@@ -20,13 +20,6 @@
#include "dpu_hw_util.h"
#include "dpu_hw_mdss.h"
#define IRQ_SOURCE_MDP BIT(0)
#define IRQ_SOURCE_DSI0 BIT(4)
#define IRQ_SOURCE_DSI1 BIT(5)
#define IRQ_SOURCE_HDMI BIT(8)
#define IRQ_SOURCE_EDP BIT(12)
#define IRQ_SOURCE_MHL BIT(16)
/**
* dpu_intr_type - HW Interrupt Type
* @DPU_IRQ_TYPE_WB_ROT_COMP: WB rotator done
......@@ -95,18 +88,6 @@ struct dpu_hw_intr;
* Interrupt operations.
*/
struct dpu_hw_intr_ops {
/**
* set_mask - Programs the given interrupt register with the
* given interrupt mask. Register value will get overwritten.
* @intr: HW interrupt handle
* @reg_off: MDSS HW register offset
* @irqmask: IRQ mask value
*/
void (*set_mask)(
struct dpu_hw_intr *intr,
uint32_t reg,
uint32_t irqmask);
/**
* irq_idx_lookup - Lookup IRQ index on the HW interrupt type
* Used for all irq related ops
......@@ -176,16 +157,6 @@ struct dpu_hw_intr_ops {
void (*get_interrupt_statuses)(
struct dpu_hw_intr *intr);
/**
* clear_interrupt_status - Clears HW interrupt status based on given
* lookup IRQ index.
* @intr: HW interrupt handle
* @irq_idx: Lookup irq index return from irq_idx_lookup
*/
void (*clear_interrupt_status)(
struct dpu_hw_intr *intr,
int irq_idx);
/**
* clear_intr_status_nolock() - clears the HW interrupts without lock
* @intr: HW interrupt handle
......@@ -206,21 +177,6 @@ struct dpu_hw_intr_ops {
struct dpu_hw_intr *intr,
int irq_idx,
bool clear);
/**
* get_valid_interrupts - Gets a mask of all valid interrupt sources
* within DPU. These are actually status bits
* within interrupt registers that specify the
* source of the interrupt in IRQs. For example,
* valid interrupt sources can be MDP, DSI,
* HDMI etc.
* @intr: HW interrupt handle
* @mask: Returning the interrupt source MASK
* @return: 0 for success, otherwise failure
*/
int (*get_valid_interrupts)(
struct dpu_hw_intr *intr,
uint32_t *mask);
};
/**
......
......@@ -258,12 +258,6 @@ enum dpu_vbif {
VBIF_NRT = VBIF_1
};
enum dpu_iommu_domain {
DPU_IOMMU_DOMAIN_UNSECURE,
DPU_IOMMU_DOMAIN_SECURE,
DPU_IOMMU_DOMAIN_MAX
};
/**
* DPU HW,Component order color map
*/
......@@ -358,7 +352,6 @@ enum dpu_3d_blend_mode {
* @alpha_enable: whether the format has an alpha channel
* @num_planes: number of planes (including meta data planes)
* @fetch_mode: linear, tiled, or ubwc hw fetch behavior
* @is_yuv: is format a yuv variant
* @flag: usage bit flags
* @tile_width: format tile width
* @tile_height: format tile height
......
......@@ -18,7 +18,6 @@
#include "dpu_hw_mdss.h"
#define REG_MASK(n) ((BIT(n)) - 1)
struct dpu_format_extended;
/*
* 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,
}
}
static void _dpu_kms_initialize_dsi(struct drm_device *dev,
static int _dpu_kms_initialize_dsi(struct drm_device *dev,
struct msm_drm_private *priv,
struct dpu_kms *dpu_kms)
{
struct drm_encoder *encoder = NULL;
int i, rc;
int i, rc = 0;
if (!(priv->dsi[0] || priv->dsi[1]))
return rc;
/*TODO: Support two independent DSI connectors */
encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_DSI);
if (IS_ERR_OR_NULL(encoder)) {
if (IS_ERR(encoder)) {
DPU_ERROR("encoder init failed for dsi display\n");
return;
return PTR_ERR(encoder);
}
priv->encoders[priv->num_encoders++] = encoder;
for (i = 0; i < ARRAY_SIZE(priv->dsi); i++) {
if (!priv->dsi[i]) {
DPU_DEBUG("invalid msm_dsi for ctrl %d\n", i);
return;
}
if (!priv->dsi[i])
continue;
rc = msm_dsi_modeset_init(priv->dsi[i], dev, encoder);
if (rc) {
DPU_ERROR("modeset_init failed for dsi[%d], rc = %d\n",
i, rc);
continue;
break;
}
}
return rc;
}
/**
......@@ -444,16 +447,16 @@ static void _dpu_kms_initialize_dsi(struct drm_device *dev,
* @dpu_kms: Pointer to dpu kms structure
* Returns: Zero on success
*/
static void _dpu_kms_setup_displays(struct drm_device *dev,
static int _dpu_kms_setup_displays(struct drm_device *dev,
struct msm_drm_private *priv,
struct dpu_kms *dpu_kms)
{
_dpu_kms_initialize_dsi(dev, priv, dpu_kms);
/**
* Extend this function to initialize other
* types of displays
*/
return _dpu_kms_initialize_dsi(dev, priv, dpu_kms);
}
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)
* Create encoder and query display drivers to create
* bridges and connectors
*/
_dpu_kms_setup_displays(dev, priv, dpu_kms);
ret = _dpu_kms_setup_displays(dev, priv, dpu_kms);
if (ret)
goto fail;
max_crtc_count = min(catalog->mixer_count, priv->num_encoders);
......@@ -627,6 +632,10 @@ static void _dpu_kms_hw_destroy(struct dpu_kms *dpu_kms)
devm_iounmap(&dpu_kms->pdev->dev, dpu_kms->vbif[VBIF_RT]);
dpu_kms->vbif[VBIF_RT] = NULL;
if (dpu_kms->hw_mdp)
dpu_hw_mdp_destroy(dpu_kms->hw_mdp);
dpu_kms->hw_mdp = NULL;
if (dpu_kms->mmio)
devm_iounmap(&dpu_kms->pdev->dev, dpu_kms->mmio);
dpu_kms->mmio = NULL;
......@@ -877,8 +886,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
goto power_error;
}
rc = dpu_rm_init(&dpu_kms->rm, dpu_kms->catalog, dpu_kms->mmio,
dpu_kms->dev);
rc = dpu_rm_init(&dpu_kms->rm, dpu_kms->catalog, dpu_kms->mmio);
if (rc) {
DPU_ERROR("rm init failed: %d\n", rc);
goto power_error;
......@@ -886,11 +894,10 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
dpu_kms->rm_init = true;
dpu_kms->hw_mdp = dpu_rm_get_mdp(&dpu_kms->rm);
if (IS_ERR_OR_NULL(dpu_kms->hw_mdp)) {
dpu_kms->hw_mdp = dpu_hw_mdptop_init(MDP_TOP, dpu_kms->mmio,
dpu_kms->catalog);
if (IS_ERR(dpu_kms->hw_mdp)) {
rc = PTR_ERR(dpu_kms->hw_mdp);
if (!dpu_kms->hw_mdp)
rc = -EINVAL;
DPU_ERROR("failed to get hw_mdp: %d\n", rc);
dpu_kms->hw_mdp = NULL;
goto power_error;
......@@ -926,16 +933,6 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
goto hw_intr_init_err;
}
/*
* _dpu_kms_drm_obj_init should create the DRM related objects
* i.e. CRTCs, planes, encoders, connectors and so forth
*/
rc = _dpu_kms_drm_obj_init(dpu_kms);
if (rc) {
DPU_ERROR("modeset init failed: %d\n", rc);
goto drm_obj_init_err;
}
dev->mode_config.min_width = 0;
dev->mode_config.min_height = 0;
......@@ -952,6 +949,16 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
*/
dev->mode_config.allow_fb_modifiers = true;
/*
* _dpu_kms_drm_obj_init should create the DRM related objects
* i.e. CRTCs, planes, encoders, connectors and so forth
*/
rc = _dpu_kms_drm_obj_init(dpu_kms);
if (rc) {
DPU_ERROR("modeset init failed: %d\n", rc);
goto drm_obj_init_err;
}
dpu_vbif_init_memtypes(dpu_kms);
pm_runtime_put_sync(&dpu_kms->pdev->dev);
......
......@@ -23,11 +23,14 @@ struct dpu_mdss {
struct dpu_irq_controller irq_controller;
};
static irqreturn_t dpu_mdss_irq(int irq, void *arg)
static void dpu_mdss_irq(struct irq_desc *desc)
{
struct dpu_mdss *dpu_mdss = arg;
struct dpu_mdss *dpu_mdss = irq_desc_get_handler_data(desc);
struct irq_chip *chip = irq_desc_get_chip(desc);
u32 interrupts;
chained_irq_enter(chip, desc);
interrupts = readl_relaxed(dpu_mdss->mmio + HW_INTR_STATUS);
while (interrupts) {
......@@ -39,20 +42,20 @@ static irqreturn_t dpu_mdss_irq(int irq, void *arg)
hwirq);
if (mapping == 0) {
DRM_ERROR("couldn't find irq mapping for %lu\n", hwirq);
return IRQ_NONE;
break;
}
rc = generic_handle_irq(mapping);
if (rc < 0) {
DRM_ERROR("handle irq fail: irq=%lu mapping=%u rc=%d\n",
hwirq, mapping, rc);
return IRQ_NONE;
break;
}
interrupts &= ~(1 << hwirq);
}
return IRQ_HANDLED;
chained_irq_exit(chip, desc);
}
static void dpu_mdss_irq_mask(struct irq_data *irqd)
......@@ -83,16 +86,16 @@ static struct irq_chip dpu_mdss_irq_chip = {
.irq_unmask = dpu_mdss_irq_unmask,
};
static struct lock_class_key dpu_mdss_lock_key, dpu_mdss_request_key;
static int dpu_mdss_irqdomain_map(struct irq_domain *domain,
unsigned int irq, irq_hw_number_t hwirq)
{
struct dpu_mdss *dpu_mdss = domain->host_data;
int ret;
irq_set_lockdep_class(irq, &dpu_mdss_lock_key, &dpu_mdss_request_key);
irq_set_chip_and_handler(irq, &dpu_mdss_irq_chip, handle_level_irq);
ret = irq_set_chip_data(irq, dpu_mdss);
return ret;
return irq_set_chip_data(irq, dpu_mdss);
}
static const struct irq_domain_ops dpu_mdss_irqdomain_ops = {
......@@ -159,11 +162,13 @@ static void dpu_mdss_destroy(struct drm_device *dev)
struct msm_drm_private *priv = dev->dev_private;
struct dpu_mdss *dpu_mdss = to_dpu_mdss(priv->mdss);
struct dss_module_power *mp = &dpu_mdss->mp;
int irq;
pm_runtime_suspend(dev->dev);
pm_runtime_disable(dev->dev);
_dpu_mdss_irq_domain_fini(dpu_mdss);
free_irq(platform_get_irq(pdev, 0), dpu_mdss);
irq = platform_get_irq(pdev, 0);
irq_set_chained_handler_and_data(irq, NULL, NULL);
msm_dss_put_clk(mp->clk_config, mp->num_clk);
devm_kfree(&pdev->dev, mp->clk_config);
......@@ -187,6 +192,7 @@ int dpu_mdss_init(struct drm_device *dev)
struct dpu_mdss *dpu_mdss;
struct dss_module_power *mp;
int ret = 0;
int irq;
dpu_mdss = devm_kzalloc(dev->dev, sizeof(*dpu_mdss), GFP_KERNEL);
if (!dpu_mdss)
......@@ -219,12 +225,12 @@ int dpu_mdss_init(struct drm_device *dev)
if (ret)
goto irq_domain_error;
ret = request_irq(platform_get_irq(pdev, 0),
dpu_mdss_irq, 0, "dpu_mdss_isr", dpu_mdss);
if (ret) {
DPU_ERROR("failed to init irq: %d\n", ret);
irq = platform_get_irq(pdev, 0);
if (irq < 0)
goto irq_error;
}
irq_set_chained_handler_and_data(irq, dpu_mdss_irq,
dpu_mdss);
pm_runtime_enable(dev->dev);
......
......@@ -95,8 +95,6 @@ struct dpu_plane {
enum dpu_sspp pipe;
uint32_t features; /* capabilities from catalog */
uint32_t nformats;
uint32_t formats[64];
struct dpu_hw_pipe *pipe_hw;
struct dpu_hw_pipe_cfg pipe_cfg;
......@@ -121,6 +119,12 @@ struct dpu_plane {
bool debugfs_default_scale;
};
static const uint64_t supported_format_modifiers[] = {
DRM_FORMAT_MOD_QCOM_COMPRESSED,
DRM_FORMAT_MOD_LINEAR,
DRM_FORMAT_MOD_INVALID
};
#define to_dpu_plane(x) container_of(x, struct dpu_plane, base)
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)
debugfs_remove_recursive(pdpu->debugfs_root);
}
static bool dpu_plane_format_mod_supported(struct drm_plane *plane,
uint32_t format, uint64_t modifier)
{
if (modifier == DRM_FORMAT_MOD_LINEAR)
return true;
if (modifier == DRM_FORMAT_MOD_QCOM_COMPRESSED) {
int i;
for (i = 0; i < ARRAY_SIZE(qcom_compressed_supported_formats); i++) {
if (format == qcom_compressed_supported_formats[i])
return true;
}
}
return false;
}
static const struct drm_plane_funcs dpu_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
......@@ -1419,6 +1440,7 @@ static const struct drm_plane_funcs dpu_plane_funcs = {
.atomic_destroy_state = dpu_plane_destroy_state,
.late_register = dpu_plane_late_register,
.early_unregister = dpu_plane_early_unregister,
.format_mod_supported = dpu_plane_format_mod_supported,
};
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,
unsigned long possible_crtcs, u32 master_plane_id)
{
struct drm_plane *plane = NULL, *master_plane = NULL;
const struct dpu_format_extended *format_list;
const uint32_t *format_list;
struct dpu_plane *pdpu;
struct msm_drm_private *priv = dev->dev_private;
struct dpu_kms *kms = to_dpu_kms(priv->kms);
int zpos_max = DPU_ZPOS_MAX;
uint32_t num_formats;
int ret = -EINVAL;
/* create and zero local structure */
......@@ -1491,24 +1514,18 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev,
goto clean_sspp;
}
if (!master_plane_id)
format_list = pdpu->pipe_sblk->format_list;
else
if (pdpu->is_virtual) {
format_list = pdpu->pipe_sblk->virt_format_list;
pdpu->nformats = dpu_populate_formats(format_list,
pdpu->formats,
0,
ARRAY_SIZE(pdpu->formats));
if (!pdpu->nformats) {
DPU_ERROR("[%u]no valid formats for plane\n", pipe);
goto clean_sspp;
num_formats = pdpu->pipe_sblk->virt_num_formats;
}
else {
format_list = pdpu->pipe_sblk->format_list;
num_formats = pdpu->pipe_sblk->num_formats;
}
ret = drm_universal_plane_init(dev, plane, 0xff, &dpu_plane_funcs,
pdpu->formats, pdpu->nformats,
NULL, type, NULL);
format_list, num_formats,
supported_format_modifiers, type, NULL);
if (ret)
goto clean_sspp;
......
......@@ -28,23 +28,18 @@
/**
* struct dpu_plane_state: Define dpu extension of drm plane state object
* @base: base drm plane state object
* @property_state: Local storage for msm_prop properties
* @property_values: cached plane property values
* @aspace: pointer to address space for input/output buffers
* @input_fence: dereferenced input fence pointer
* @stage: assigned by crtc blender
* @multirect_index: index of the rectangle of SSPP
* @multirect_mode: parallel or time multiplex multirect mode
* @pending: whether the current update is still pending
* @scaler3_cfg: configuration data for scaler3
* @pixel_ext: configuration data for pixel extensions
* @scaler_check_state: indicates status of user provided pixel extension data
* @cdp_cfg: CDP configuration
*/
struct dpu_plane_state {
struct drm_plane_state base;
struct msm_gem_address_space *aspace;
void *input_fence;
enum dpu_stage stage;
uint32_t multirect_index;
uint32_t multirect_mode;
......@@ -106,12 +101,6 @@ void dpu_plane_restore(struct drm_plane *plane);
*/
void dpu_plane_flush(struct drm_plane *plane);
/**
* dpu_plane_kickoff - final plane operations before commit kickoff
* @plane: Pointer to drm plane structure
*/
void dpu_plane_kickoff(struct drm_plane *plane);
/**
* dpu_plane_set_error: enable/disable error condition
* @plane: pointer to drm_plane structure
......@@ -146,14 +135,6 @@ int dpu_plane_validate_multirect_v2(struct dpu_multirect_plane_states *plane);
*/
void dpu_plane_clear_multirect(const struct drm_plane_state *drm_state);
/**
* dpu_plane_wait_input_fence - wait for input fence object
* @plane: Pointer to DRM plane object
* @wait_ms: Wait timeout value
* Returns: Zero on success
*/
int dpu_plane_wait_input_fence(struct drm_plane *plane, uint32_t wait_ms);
/**
* dpu_plane_color_fill - enables color fill on plane
* @plane: Pointer to DRM plane object
......@@ -164,12 +145,4 @@ int dpu_plane_wait_input_fence(struct drm_plane *plane, uint32_t wait_ms);
int dpu_plane_color_fill(struct drm_plane *plane,
uint32_t color, uint32_t alpha);
/**
* dpu_plane_set_revalidate - sets revalidate flag which forces a full
* validation of the plane properties in the next atomic check
* @plane: Pointer to DRM plane object
* @enable: Boolean to set/unset the flag
*/
void dpu_plane_set_revalidate(struct drm_plane *plane, bool enable);
#endif /* _DPU_PLANE_H_ */
This diff is collapsed.
......@@ -22,22 +22,14 @@
/**
* struct dpu_rm - DPU dynamic hardware resource manager
* @dev: device handle for event logging purposes
* @rsvps: list of hardware reservations by each crtc->encoder->connector
* @hw_blks: array of lists of hardware resources present in the system, one
* list per type of hardware block
* @hw_mdp: hardware object for mdp_top
* @lm_max_width: cached layer mixer maximum width
* @rsvp_next_seq: sequence number for next reservation for debugging purposes
* @rm_lock: resource manager mutex
*/
struct dpu_rm {
struct drm_device *dev;
struct list_head rsvps;
struct list_head hw_blks[DPU_HW_BLK_MAX];
struct dpu_hw_mdp *hw_mdp;
uint32_t lm_max_width;
uint32_t rsvp_next_seq;
struct mutex rm_lock;
};
......@@ -67,13 +59,11 @@ struct dpu_rm_hw_iter {
* @rm: DPU Resource Manager handle
* @cat: Pointer to hardware catalog
* @mmio: mapped register io address of MDP
* @dev: device handle for event logging purposes
* @Return: 0 on Success otherwise -ERROR
*/
int dpu_rm_init(struct dpu_rm *rm,
struct dpu_mdss_cfg *cat,
void __iomem *mmio,
struct drm_device *dev);
void __iomem *mmio);
/**
* dpu_rm_destroy - Free all memory allocated by dpu_rm_init
......@@ -111,14 +101,6 @@ int dpu_rm_reserve(struct dpu_rm *rm,
*/
void dpu_rm_release(struct dpu_rm *rm, struct drm_encoder *enc);
/**
* dpu_rm_get_mdp - Retrieve HW block for MDP TOP.
* This is never reserved, and is usable by any display.
* @rm: DPU Resource Manager handle
* @Return: Pointer to hw block or NULL
*/
struct dpu_hw_mdp *dpu_rm_get_mdp(struct dpu_rm *rm);
/**
* dpu_rm_init_hw_iter - setup given iterator for new iteration over hw list
* using dpu_rm_get_hw
......@@ -144,12 +126,4 @@ void dpu_rm_init_hw_iter(
* @Return: true on match found, false on no match found
*/
bool dpu_rm_get_hw(struct dpu_rm *rm, struct dpu_rm_hw_iter *iter);
/**
* dpu_rm_check_property_topctl - validate property bitmask before it is set
* @val: user's proposed topology control bitmask
* @Return: 0 on success or error
*/
int dpu_rm_check_property_topctl(uint64_t val);
#endif /* __DPU_RM_H__ */
......@@ -831,48 +831,42 @@ TRACE_EVENT(dpu_plane_disable,
);
DECLARE_EVENT_CLASS(dpu_rm_iter_template,
TP_PROTO(uint32_t id, enum dpu_hw_blk_type type, uint32_t enc_id),
TP_ARGS(id, type, enc_id),
TP_PROTO(uint32_t id, uint32_t enc_id),
TP_ARGS(id, enc_id),
TP_STRUCT__entry(
__field( uint32_t, id )
__field( enum dpu_hw_blk_type, type )
__field( uint32_t, enc_id )
),
TP_fast_assign(
__entry->id = id;
__entry->type = type;
__entry->enc_id = enc_id;
),
TP_printk("id:%d type:%d enc_id:%u", __entry->id, __entry->type,
__entry->enc_id)
TP_printk("id:%d enc_id:%u", __entry->id, __entry->enc_id)
);
DEFINE_EVENT(dpu_rm_iter_template, dpu_rm_reserve_intf,
TP_PROTO(uint32_t id, enum dpu_hw_blk_type type, uint32_t enc_id),
TP_ARGS(id, type, enc_id)
TP_PROTO(uint32_t id, uint32_t enc_id),
TP_ARGS(id, enc_id)
);
DEFINE_EVENT(dpu_rm_iter_template, dpu_rm_reserve_ctls,
TP_PROTO(uint32_t id, enum dpu_hw_blk_type type, uint32_t enc_id),
TP_ARGS(id, type, enc_id)
TP_PROTO(uint32_t id, uint32_t enc_id),
TP_ARGS(id, enc_id)
);
TRACE_EVENT(dpu_rm_reserve_lms,
TP_PROTO(uint32_t id, enum dpu_hw_blk_type type, uint32_t enc_id,
uint32_t pp_id),
TP_ARGS(id, type, enc_id, pp_id),
TP_PROTO(uint32_t id, uint32_t enc_id, uint32_t pp_id),
TP_ARGS(id, enc_id, pp_id),
TP_STRUCT__entry(
__field( uint32_t, id )
__field( enum dpu_hw_blk_type, type )
__field( uint32_t, enc_id )
__field( uint32_t, pp_id )
),
TP_fast_assign(
__entry->id = id;
__entry->type = type;
__entry->enc_id = enc_id;
__entry->pp_id = pp_id;
),
TP_printk("id:%d type:%d enc_id:%u pp_id:%u", __entry->id,
__entry->type, __entry->enc_id, __entry->pp_id)
TP_printk("id:%d enc_id:%u pp_id:%u", __entry->id,
__entry->enc_id, __entry->pp_id)
);
TRACE_EVENT(dpu_vbif_wait_xin_halt_fail,
......
......@@ -207,62 +207,44 @@ u32 msm_readl(const void __iomem *addr)
return val;
}
struct vblank_event {
struct list_head node;
struct msm_vblank_work {
struct work_struct work;
int crtc_id;
bool enable;
struct msm_drm_private *priv;
};
static void vblank_ctrl_worker(struct kthread_work *work)
static void vblank_ctrl_worker(struct work_struct *work)
{
struct msm_vblank_ctrl *vbl_ctrl = container_of(work,
struct msm_vblank_ctrl, work);
struct msm_drm_private *priv = container_of(vbl_ctrl,
struct msm_drm_private, vblank_ctrl);
struct msm_vblank_work *vbl_work = container_of(work,
struct msm_vblank_work, work);
struct msm_drm_private *priv = vbl_work->priv;
struct msm_kms *kms = priv->kms;
struct vblank_event *vbl_ev, *tmp;
unsigned long flags;
spin_lock_irqsave(&vbl_ctrl->lock, flags);
list_for_each_entry_safe(vbl_ev, tmp, &vbl_ctrl->event_list, node) {
list_del(&vbl_ev->node);
spin_unlock_irqrestore(&vbl_ctrl->lock, flags);
if (vbl_ev->enable)
kms->funcs->enable_vblank(kms,
priv->crtcs[vbl_ev->crtc_id]);
else
kms->funcs->disable_vblank(kms,
priv->crtcs[vbl_ev->crtc_id]);
kfree(vbl_ev);
spin_lock_irqsave(&vbl_ctrl->lock, flags);
}
if (vbl_work->enable)
kms->funcs->enable_vblank(kms, priv->crtcs[vbl_work->crtc_id]);
else
kms->funcs->disable_vblank(kms, priv->crtcs[vbl_work->crtc_id]);
spin_unlock_irqrestore(&vbl_ctrl->lock, flags);
kfree(vbl_work);
}
static int vblank_ctrl_queue_work(struct msm_drm_private *priv,
int crtc_id, bool enable)
{
struct msm_vblank_ctrl *vbl_ctrl = &priv->vblank_ctrl;
struct vblank_event *vbl_ev;
unsigned long flags;
struct msm_vblank_work *vbl_work;
vbl_ev = kzalloc(sizeof(*vbl_ev), GFP_ATOMIC);
if (!vbl_ev)
vbl_work = kzalloc(sizeof(*vbl_work), GFP_ATOMIC);
if (!vbl_work)
return -ENOMEM;
vbl_ev->crtc_id = crtc_id;
vbl_ev->enable = enable;
INIT_WORK(&vbl_work->work, vblank_ctrl_worker);
spin_lock_irqsave(&vbl_ctrl->lock, flags);
list_add_tail(&vbl_ev->node, &vbl_ctrl->event_list);
spin_unlock_irqrestore(&vbl_ctrl->lock, flags);
vbl_work->crtc_id = crtc_id;
vbl_work->enable = enable;
vbl_work->priv = priv;
kthread_queue_work(&priv->disp_thread[crtc_id].worker,
&vbl_ctrl->work);
queue_work(priv->wq, &vbl_work->work);
return 0;
}
......@@ -274,31 +256,20 @@ static int msm_drm_uninit(struct device *dev)
struct msm_drm_private *priv = ddev->dev_private;
struct msm_kms *kms = priv->kms;
struct msm_mdss *mdss = priv->mdss;
struct msm_vblank_ctrl *vbl_ctrl = &priv->vblank_ctrl;
struct vblank_event *vbl_ev, *tmp;
int i;
/* We must cancel and cleanup any pending vblank enable/disable
* work before drm_irq_uninstall() to avoid work re-enabling an
* irq after uninstall has disabled it.
*/
kthread_flush_work(&vbl_ctrl->work);
list_for_each_entry_safe(vbl_ev, tmp, &vbl_ctrl->event_list, node) {
list_del(&vbl_ev->node);
kfree(vbl_ev);
}
/* clean up display commit/event worker threads */
for (i = 0; i < priv->num_crtcs; i++) {
if (priv->disp_thread[i].thread) {
kthread_flush_worker(&priv->disp_thread[i].worker);
kthread_stop(priv->disp_thread[i].thread);
priv->disp_thread[i].thread = NULL;
}
flush_workqueue(priv->wq);
destroy_workqueue(priv->wq);
/* clean up event worker threads */
for (i = 0; i < priv->num_crtcs; i++) {
if (priv->event_thread[i].thread) {
kthread_flush_worker(&priv->event_thread[i].worker);
kthread_stop(priv->event_thread[i].thread);
kthread_destroy_worker(&priv->event_thread[i].worker);
priv->event_thread[i].thread = NULL;
}
}
......@@ -323,9 +294,6 @@ static int msm_drm_uninit(struct device *dev)
drm_irq_uninstall(ddev);
pm_runtime_put_sync(dev);
flush_workqueue(priv->wq);
destroy_workqueue(priv->wq);
if (kms && kms->funcs)
kms->funcs->destroy(kms);
......@@ -490,9 +458,6 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)
priv->wq = alloc_ordered_workqueue("msm", 0);
INIT_LIST_HEAD(&priv->inactive_list);
INIT_LIST_HEAD(&priv->vblank_ctrl.event_list);
kthread_init_work(&priv->vblank_ctrl.work, vblank_ctrl_worker);
spin_lock_init(&priv->vblank_ctrl.lock);
drm_mode_config_init(ddev);
......@@ -554,27 +519,6 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)
*/
param.sched_priority = 16;
for (i = 0; i < priv->num_crtcs; i++) {
/* initialize display thread */
priv->disp_thread[i].crtc_id = priv->crtcs[i]->base.id;
kthread_init_worker(&priv->disp_thread[i].worker);
priv->disp_thread[i].dev = ddev;
priv->disp_thread[i].thread =
kthread_run(kthread_worker_fn,
&priv->disp_thread[i].worker,
"crtc_commit:%d", priv->disp_thread[i].crtc_id);
if (IS_ERR(priv->disp_thread[i].thread)) {
DRM_DEV_ERROR(dev, "failed to create crtc_commit kthread\n");
priv->disp_thread[i].thread = NULL;
goto err_msm_uninit;
}
ret = sched_setscheduler(priv->disp_thread[i].thread,
SCHED_FIFO, &param);
if (ret)
dev_warn(dev, "disp_thread set priority failed: %d\n",
ret);
/* initialize event thread */
priv->event_thread[i].crtc_id = priv->crtcs[i]->base.id;
kthread_init_worker(&priv->event_thread[i].worker);
......@@ -589,13 +533,6 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)
goto err_msm_uninit;
}
/**
* event thread should also run at same priority as disp_thread
* because it is handling frame_done events. A lower priority
* event thread and higher priority disp_thread can causes
* frame_pending counters beyond 2. This can lead to commit
* failure at crtc commit level.
*/
ret = sched_setscheduler(priv->event_thread[i].thread,
SCHED_FIFO, &param);
if (ret)
......@@ -914,8 +851,12 @@ static int msm_ioctl_gem_info(struct drm_device *dev, void *data,
ret = -EINVAL;
break;
}
ret = copy_from_user(msm_obj->name,
u64_to_user_ptr(args->value), args->len);
if (copy_from_user(msm_obj->name, u64_to_user_ptr(args->value),
args->len)) {
msm_obj->name[0] = '\0';
ret = -EFAULT;
break;
}
msm_obj->name[args->len] = '\0';
for (i = 0; i < args->len; i++) {
if (!isprint(msm_obj->name[i])) {
......@@ -931,8 +872,9 @@ static int msm_ioctl_gem_info(struct drm_device *dev, void *data,
}
args->len = strlen(msm_obj->name);
if (args->value) {
ret = copy_to_user(u64_to_user_ptr(args->value),
msm_obj->name, args->len);
if (copy_to_user(u64_to_user_ptr(args->value),
msm_obj->name, args->len))
ret = -EFAULT;
}
break;
}
......
......@@ -77,12 +77,6 @@ enum msm_mdp_plane_property {
PLANE_PROP_MAX_NUM
};
struct msm_vblank_ctrl {
struct kthread_work work;
struct list_head event_list;
spinlock_t lock;
};
#define MSM_GPU_MAX_RINGS 4
#define MAX_H_TILES_PER_DISPLAY 2
......@@ -126,7 +120,7 @@ struct msm_display_topology {
/**
* struct msm_display_info - defines display properties
* @intf_type: DRM_MODE_CONNECTOR_ display type
* @intf_type: DRM_MODE_ENCODER_ type
* @capabilities: Bitmask of display flags
* @num_of_h_tiles: Number of horizontal tiles in case of split interface
* @h_tile_instance: Controller instance used per tile. Number of elements is
......@@ -199,7 +193,6 @@ struct msm_drm_private {
unsigned int num_crtcs;
struct drm_crtc *crtcs[MAX_CRTCS];
struct msm_drm_thread disp_thread[MAX_CRTCS];
struct msm_drm_thread event_thread[MAX_CRTCS];
unsigned int num_encoders;
......@@ -228,7 +221,6 @@ struct msm_drm_private {
struct notifier_block vmap_notifier;
struct shrinker shrinker;
struct msm_vblank_ctrl vblank_ctrl;
struct drm_atomic_state *pm_state;
};
......
......@@ -560,6 +560,8 @@
# define DP_TEST_LINK_EDID_READ (1 << 2)
# define DP_TEST_LINK_PHY_TEST_PATTERN (1 << 3) /* DPCD >= 1.1 */
# define DP_TEST_LINK_FAUX_PATTERN (1 << 4) /* DPCD >= 1.2 */
# define DP_TEST_LINK_AUDIO_PATTERN (1 << 5) /* DPCD >= 1.2 */
# define DP_TEST_LINK_AUDIO_DISABLED_VIDEO (1 << 6) /* DPCD >= 1.2 */
#define DP_TEST_LINK_RATE 0x219
# define DP_LINK_RATE_162 (0x6)
......@@ -608,6 +610,7 @@
# define DP_COLOR_FORMAT_RGB (0 << 1)
# define DP_COLOR_FORMAT_YCbCr422 (1 << 1)
# define DP_COLOR_FORMAT_YCbCr444 (2 << 1)
# define DP_TEST_DYNAMIC_RANGE_VESA (0 << 3)
# define DP_TEST_DYNAMIC_RANGE_CEA (1 << 3)
# define DP_TEST_YCBCR_COEFFICIENTS (1 << 4)
# define DP_YCBCR_COEFFICIENTS_ITU601 (0 << 4)
......@@ -657,6 +660,16 @@
#define DP_TEST_SINK 0x270
# define DP_TEST_SINK_START (1 << 0)
#define DP_TEST_AUDIO_MODE 0x271
#define DP_TEST_AUDIO_PATTERN_TYPE 0x272
#define DP_TEST_AUDIO_PERIOD_CH1 0x273
#define DP_TEST_AUDIO_PERIOD_CH2 0x274
#define DP_TEST_AUDIO_PERIOD_CH3 0x275
#define DP_TEST_AUDIO_PERIOD_CH4 0x276
#define DP_TEST_AUDIO_PERIOD_CH5 0x277
#define DP_TEST_AUDIO_PERIOD_CH6 0x278
#define DP_TEST_AUDIO_PERIOD_CH7 0x279
#define DP_TEST_AUDIO_PERIOD_CH8 0x27A
#define DP_FEC_STATUS 0x280 /* 1.4 */
# define DP_FEC_DECODE_EN_DETECTED (1 << 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment