[PATCH] drm/msm/mdp: Clear pending interrupt status before enable interrupt
Pending interrupt status needs to be cleared before enable the interrupt. Otherwise it's possible to get a pending interrupt instead of an incoming interrupt. Signed-off-by: Jilai Wang --- drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c | 10 +++--- drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h | 3 ++- drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c | 10 +++--- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h | 3 ++- drivers/gpu/drm/msm/mdp/mdp_kms.c | 3 ++- drivers/gpu/drm/msm/mdp/mdp_kms.h | 4 +++- 6 files changed, 23 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c index 7369ee7f..b6d491c 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c @@ -19,8 +19,11 @@ #include "msm_drv.h" #include "mdp4_kms.h" -void mdp4_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask) +void mdp4_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask, + uint32_t old_irqmask) { + mdp4_write(to_mdp5_kms(mdp_kms), REG_MDP4_INTR_CLEAR, + irqmask ^ (irqmask & old_irqmask)); mdp4_write(to_mdp4_kms(mdp_kms), REG_MDP4_INTR_ENABLE, irqmask); } @@ -68,9 +71,10 @@ irqreturn_t mdp4_irq(struct msm_kms *kms) struct drm_device *dev = mdp4_kms->dev; struct msm_drm_private *priv = dev->dev_private; unsigned int id; - uint32_t status; + uint32_t status, enable; - status = mdp4_read(mdp4_kms, REG_MDP4_INTR_STATUS); + enable = mdp4_read(mdp4_kms, REG_MDP4_INTR_ENABLE); + status = mdp4_read(mdp4_kms, REG_MDP4_INTR_STATUS) & enable; mdp4_write(mdp4_kms, REG_MDP4_INTR_CLEAR, status); VERB("status=%08x", status); diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h index 1aaedad..0cdf777 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h @@ -167,7 +167,8 @@ static inline uint32_t mixercfg(uint32_t mixer_cfg, int mixer, int mdp4_disable(struct mdp4_kms *mdp4_kms); int mdp4_enable(struct mdp4_kms *mdp4_kms); -void mdp4_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask); +void mdp4_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask, + uint32_t old_irqmask); void mdp4_irq_preinstall(struct msm_kms *kms); int mdp4_irq_postinstall(struct msm_kms *kms); void mdp4_irq_uninstall(struct msm_kms *kms); diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c index 33bd4c6..7115043 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c @@ -21,8 +21,11 @@ #include "msm_drv.h" #include "mdp5_kms.h" -void mdp5_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask) +void mdp5_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask, + uint32_t old_irqmask) { + mdp5_write(to_mdp5_kms(mdp_kms), REG_MDP5_MDP_INTR_CLEAR(0), + irqmask ^ (irqmask & old_irqmask)); mdp5_write(to_mdp5_kms(mdp_kms), REG_MDP5_MDP_INTR_EN(0), irqmask); } @@ -71,9 +74,10 @@ static void mdp5_irq_mdp(struct mdp_kms *mdp_kms) struct drm_device *dev = mdp5_kms->dev; struct msm_drm_private *priv = dev->dev_private; unsigned int id; - uint32_t status; + uint32_t status, enable; - status = mdp5_read(mdp5_kms, REG_MDP5_MDP_INTR_STATUS(0)); + enable = mdp5_read(mdp5_kms, REG_MDP5_MDP_INTR_EN(0)); + status = mdp5_read(mdp5_kms, REG_MDP5_MDP_INTR_STATUS(0)) & enable; mdp5_write(mdp5_kms, REG_MDP5_MDP_INTR_CLEAR(0), status); VERB("status=%08x", status); diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h index 8542b30..403a6f5 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h @@ -186,7 +186,8 @@ static inline uint32_t lm2ppdone(int lm) int mdp5_disable(struct mdp5_kms *mdp5_kms); int mdp5_enable(struct mdp5_kms *mdp5_kms); -void mdp5_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask); +void mdp5_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask, + uint32_t old_irqmask); void mdp5_irq_preinstall(struct msm_kms *kms); int mdp5_irq_postinstall(struct msm_kms *kms); void mdp5_irq_uninstall(struct msm_kms *kms); diff --git a/drivers/gpu/drm/msm/mdp/mdp_kms.c b/drivers/gpu/drm/msm/mdp/mdp_kms.c index 1988c24..6428730 100644 --- a/drivers/gpu/drm/msm/mdp/mdp_kms.c +++ b/drivers/gpu/drm/msm/mdp/mdp_kms.c @@ -39,7 +39,8 @@ static void update_irq(struct mdp_kms *mdp_kms) list_for_each_entry(irq, _kms->irq_list, node) irqmask |= irq->irqmask; - mdp_kms->funcs->set_irqmask(mdp_kms, irqmask); + mdp_kms->funcs->set_irqmask(mdp_kms, irqmask, mdp_kms->cur_irq_mask); + mdp_kms->cur_irq_mask =
[PATCH] drm/msm/mdp5: Add hflip/vflip support to MDP5 planes (v2)
MDP5 SSPPs can flip the input source horizontally or vertically. This change is to add this support to MDP5 planes. v1: Initial change v2: Use existing "rotation" property instead of creating msm specific properties. In order to be compatiable with legacy non-atomic set_property, switch to drm_atomic_helper_plane_set_property helper function. Signed-off-by: Jilai Wang --- drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 49 ++- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c index 1fbb17d..ec5b24c6 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c @@ -88,6 +88,26 @@ static const struct drm_prop_enum_list premultiplied_prop_enum_list[] = { { 1, "true" }, }; +static void mdp5_plane_install_rotation_property(struct drm_device *dev, + struct drm_plane *plane) +{ + struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane); + + if (!(mdp5_plane->caps & MDP_PIPE_CAP_HFLIP) && + !(mdp5_plane->caps & MDP_PIPE_CAP_VFLIP)) + return; + + if (!dev->mode_config.rotation_property) + dev->mode_config.rotation_property = + drm_mode_create_rotation_property(dev, + BIT(DRM_REFLECT_X) | BIT(DRM_REFLECT_Y)); + + if (dev->mode_config.rotation_property) + drm_object_attach_property(>base, + dev->mode_config.rotation_property, + 0); +} + /* helper to install properties which are common to planes and crtcs */ void mdp5_plane_install_properties(struct drm_plane *plane, struct drm_mode_object *obj) @@ -125,6 +145,8 @@ void mdp5_plane_install_properties(struct drm_plane *plane, INSTALL_RANGE_PROPERTY(alpha, ALPHA, 0, 255, 255); INSTALL_ENUM_PROPERTY(premultiplied, PREMULTIPLIED, 0); + mdp5_plane_install_rotation_property(dev, plane); + #undef INSTALL_RANGE_PROPERTY #undef INSTALL_ENUM_PROPERTY #undef INSTALL_PROPERTY @@ -160,13 +182,6 @@ done: #undef SET_PROPERTY } -static int mdp5_plane_set_property(struct drm_plane *plane, - struct drm_property *property, uint64_t val) -{ - return mdp5_plane_atomic_set_property(plane, plane->state, property, - val); -} - static int mdp5_plane_atomic_get_property(struct drm_plane *plane, const struct drm_plane_state *state, struct drm_property *property, uint64_t *val) @@ -254,7 +269,7 @@ static const struct drm_plane_funcs mdp5_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, .destroy = mdp5_plane_destroy, - .set_property = mdp5_plane_set_property, + .set_property = drm_atomic_helper_plane_set_property, .atomic_set_property = mdp5_plane_atomic_set_property, .atomic_get_property = mdp5_plane_atomic_get_property, .reset = mdp5_plane_reset, @@ -290,6 +305,7 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane, struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane); struct drm_plane_state *old_state = plane->state; const struct mdp_format *format; + bool vflip, hflip; DBG("%s: check (%d -> %d)", mdp5_plane->name, plane_enabled(old_state), plane_enabled(state)); @@ -314,6 +330,16 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane, return -EINVAL; } + + hflip = !!(state->rotation & BIT(DRM_REFLECT_X)); + vflip = !!(state->rotation & BIT(DRM_REFLECT_Y)); + if ((vflip && !(mdp5_plane->caps & MDP_PIPE_CAP_VFLIP)) || + (hflip && !(mdp5_plane->caps & MDP_PIPE_CAP_HFLIP))) { + dev_err(plane->dev->dev, + "Pipe doesn't support flip\n"); + + return -EINVAL; + } } if (plane_enabled(state) && plane_enabled(old_state)) { @@ -565,6 +591,7 @@ static int mdp5_plane_mode_set(struct drm_plane *plane, uint32_t src_w, uint32_t src_h) { struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane); + struct drm_plane_state *pstate = plane->state; struct mdp5_kms *mdp5_kms = get_kms(plane); struct device *dev = mdp5_kms->dev->dev; enum mdp5_pipe pipe = mdp5_plane->pipe; @@ -574,6 +601,7 @@ static int mdp5_plane_mode_set(struct drm_plane *plane, uint32_t phasex_step[2] = {0,}, phasey_step[2] = {0,}; uint32_t hdecm = 0, vdecm = 0; uint32_t p
[PATCH 2/2] drm/msm/mdp5: Add hflip/vflip support to MDP5 planes
MDP5 SSPPs can flip the input source horizontally or vertically. This change is to support this feature by adding vflip/hflip properties to MDP5 planes. Signed-off-by: Jilai Wang --- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h | 2 ++ drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 25 + drivers/gpu/drm/msm/msm_drv.h | 2 ++ 3 files changed, 29 insertions(+) diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h index 8542b30..93545ec 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h @@ -74,6 +74,8 @@ struct mdp5_plane_state { uint8_t premultiplied; uint8_t zpos; uint8_t alpha; + uint8_t hflip; + uint8_t vflip; /* assigned by crtc blender */ enum mdp_mixer_stage_id stage; diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c index 1fbb17d..edd20025 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c @@ -88,6 +88,16 @@ static const struct drm_prop_enum_list premultiplied_prop_enum_list[] = { { 1, "true" }, }; +static const struct drm_prop_enum_list hflip_prop_enum_list[] = { + { 0, "off" }, + { 1, "on" }, +}; + +static const struct drm_prop_enum_list vflip_prop_enum_list[] = { + { 0, "off" }, + { 1, "on" }, +}; + /* helper to install properties which are common to planes and crtcs */ void mdp5_plane_install_properties(struct drm_plane *plane, struct drm_mode_object *obj) @@ -95,6 +105,7 @@ void mdp5_plane_install_properties(struct drm_plane *plane, struct drm_device *dev = plane->dev; struct msm_drm_private *dev_priv = dev->dev_private; struct drm_property *prop; + struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane); #define INSTALL_PROPERTY(name, NAME, init_val, fnc, ...) do { \ prop = dev_priv->plane_property[PLANE_PROP_##NAME]; \ @@ -125,6 +136,11 @@ void mdp5_plane_install_properties(struct drm_plane *plane, INSTALL_RANGE_PROPERTY(alpha, ALPHA, 0, 255, 255); INSTALL_ENUM_PROPERTY(premultiplied, PREMULTIPLIED, 0); + if (mdp5_plane->caps & MDP_PIPE_CAP_HFLIP) + INSTALL_ENUM_PROPERTY(hflip, HFLIP, 0); + if (mdp5_plane->caps & MDP_PIPE_CAP_VFLIP) + INSTALL_ENUM_PROPERTY(vflip, VFLIP, 0); + #undef INSTALL_RANGE_PROPERTY #undef INSTALL_ENUM_PROPERTY #undef INSTALL_PROPERTY @@ -152,6 +168,8 @@ static int mdp5_plane_atomic_set_property(struct drm_plane *plane, SET_PROPERTY(zpos, ZPOS, uint8_t); SET_PROPERTY(alpha, ALPHA, uint8_t); SET_PROPERTY(premultiplied, PREMULTIPLIED, uint8_t); + SET_PROPERTY(hflip, HFLIP, uint8_t); + SET_PROPERTY(vflip, VFLIP, uint8_t); dev_err(dev->dev, "Invalid property\n"); ret = -EINVAL; @@ -189,6 +207,8 @@ static int mdp5_plane_atomic_get_property(struct drm_plane *plane, GET_PROPERTY(zpos, ZPOS, uint8_t); GET_PROPERTY(alpha, ALPHA, uint8_t); GET_PROPERTY(premultiplied, PREMULTIPLIED, uint8_t); + GET_PROPERTY(hflip, HFLIP, uint8_t); + GET_PROPERTY(vflip, VFLIP, uint8_t); dev_err(dev->dev, "Invalid property\n"); ret = -EINVAL; @@ -210,6 +230,8 @@ static void mdp5_plane_reset(struct drm_plane *plane) /* assign default blend parameters */ mdp5_state->alpha = 255; mdp5_state->premultiplied = 0; + mdp5_state->hflip = 0; + mdp5_state->vflip = 0; if (plane->type == DRM_PLANE_TYPE_PRIMARY) mdp5_state->zpos = STAGE_BASE; @@ -565,6 +587,7 @@ static int mdp5_plane_mode_set(struct drm_plane *plane, uint32_t src_w, uint32_t src_h) { struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane); + struct mdp5_plane_state *pstate = to_mdp5_plane_state(plane->state); struct mdp5_kms *mdp5_kms = get_kms(plane); struct device *dev = mdp5_kms->dev->dev; enum mdp5_pipe pipe = mdp5_plane->pipe; @@ -675,6 +698,8 @@ static int mdp5_plane_mode_set(struct drm_plane *plane, MDP5_PIPE_SRC_UNPACK_ELEM3(format->unpack[3])); mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_OP_MODE(pipe), + (pstate->hflip ? MDP5_PIPE_SRC_OP_MODE_FLIP_LR : 0) | + (pstate->vflip ? MDP5_PIPE_SRC_OP_MODE_FLIP_UD : 0) | MDP5_PIPE_SRC_OP_MODE_BWC(BWC_LOSSLESS)); /* not using secure mode: */ diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index bd64a82..e047fec 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -68,6 +68,8 @@ enum msm_mdp_plane_property { PLANE_PROP_ZPOS, PLANE_PROP_ALP
[PATCH 1/2] drm/doc: Add hflip/vflip property descriptions in msm
Add plane properties hflip/vflip which are used in MDP driver to flip the input horizontally/vertically. Signed-off-by: Jilai Wang --- Documentation/DocBook/drm.tmpl | 18 -- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index d9f5613..bef6d34 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -3501,8 +3501,8 @@ void intel_crt_init(struct drm_device *dev) TBD - msm - Generic + msm + Generic "premultiplied" ENUM { "false", "true" } @@ -3523,6 +3523,20 @@ void intel_crt_init(struct drm_device *dev) Plane property to set plane's z position during blending + + "hflip" + ENUM + { "off", "on" } + Plane + property to flip the input horizontally + + + "vflip" + ENUM + { "off", "on" } + Plane + property to flip the input vertically + -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH] drm/msm/mdp5: Add support for msm8x74v1
msm8x74v1 has different MDP5 version (v1.0) from msm8x74v2 (v1.2). Add a separate config data to support msm8x74v1. Signed-off-by: Jilai Wang --- drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c | 77 +++-- 1 file changed, 73 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c index ac1d58f..835a276 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c @@ -22,7 +22,76 @@ struct mdp5_cfg_handler { /* mdp5_cfg must be exposed (used in mdp5.xml.h) */ const struct mdp5_cfg_hw *mdp5_cfg = NULL; -const struct mdp5_cfg_hw msm8x74_config = { +const struct mdp5_cfg_hw msm8x74v1_config = { + .name = "msm8x74v1", + .mdp = { + .count = 1, + .base = { 0x00100 }, + }, + .smp = { + .mmb_count = 22, + .mmb_size = 4096, + .clients = { + [SSPP_VIG0] = 1, [SSPP_VIG1] = 4, [SSPP_VIG2] = 7, + [SSPP_DMA0] = 10, [SSPP_DMA1] = 13, + [SSPP_RGB0] = 16, [SSPP_RGB1] = 17, [SSPP_RGB2] = 18, + }, + }, + .ctl = { + .count = 5, + .base = { 0x00600, 0x00700, 0x00800, 0x00900, 0x00a00 }, + .flush_hw_mask = 0x0003, + }, + .pipe_vig = { + .count = 3, + .base = { 0x01200, 0x01600, 0x01a00 }, + .caps = MDP_PIPE_CAP_HFLIP | + MDP_PIPE_CAP_VFLIP | + MDP_PIPE_CAP_SCALE | + MDP_PIPE_CAP_CSC | + 0, + }, + .pipe_rgb = { + .count = 3, + .base = { 0x01e00, 0x02200, 0x02600 }, + .caps = MDP_PIPE_CAP_HFLIP | + MDP_PIPE_CAP_VFLIP | + MDP_PIPE_CAP_SCALE | + 0, + }, + .pipe_dma = { + .count = 2, + .base = { 0x02a00, 0x02e00 }, + .caps = MDP_PIPE_CAP_HFLIP | + MDP_PIPE_CAP_VFLIP | + 0, + }, + .lm = { + .count = 5, + .base = { 0x03200, 0x03600, 0x03a00, 0x03e00, 0x04200 }, + .nb_stages = 5, + }, + .dspp = { + .count = 3, + .base = { 0x04600, 0x04a00, 0x04e00 }, + }, + .pp = { + .count = 3, + .base = { 0x21b00, 0x21c00, 0x21d00 }, + }, + .intf = { + .base = { 0x21100, 0x21300, 0x21500, 0x21700 }, + .connect = { + [0] = INTF_eDP, + [1] = INTF_DSI, + [2] = INTF_DSI, + [3] = INTF_HDMI, + }, + }, + .max_clk = 2, +}; + +const struct mdp5_cfg_hw msm8x74v2_config = { .name = "msm8x74", .mdp = { .count = 1, @@ -71,7 +140,7 @@ const struct mdp5_cfg_hw msm8x74_config = { }, .ad = { .count = 2, - .base = { 0x13100, 0x13300 }, /* NOTE: no ad in v1.0 */ + .base = { 0x13100, 0x13300 }, }, .pp = { .count = 3, @@ -297,8 +366,8 @@ const struct mdp5_cfg_hw msm8x94_config = { }; static const struct mdp5_cfg_handler cfg_handlers[] = { - { .revision = 0, .config = { .hw = _config } }, - { .revision = 2, .config = { .hw = _config } }, + { .revision = 0, .config = { .hw = _config } }, + { .revision = 2, .config = { .hw = _config } }, { .revision = 3, .config = { .hw = _config } }, { .revision = 6, .config = { .hw = _config } }, { .revision = 9, .config = { .hw = _config } }, -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH] drm/msm/mdp: Add capabilities to MDP planes(V2)
MDP planes can be implemented using different type of HW pipes, RGB/VIG/DMA pipes for MDP5 and RGB/VG/DMA pipes for MDP4. Each type of pipe has different HW capabilities such as scaling, color space conversion, decimation... Add a variable in plane data structure to specify the difference of each plane which comes from mdp5_cfg data and use it to differenciate the plane operation. V1: Initial change V2: Fix a typo in mdp4_kms.h Signed-off-by: Jilai Wang --- drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h | 19 drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c | 7 ++- drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c | 26 ++- drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h | 11 +++-- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 4 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h | 24 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 73 ++- drivers/gpu/drm/msm/mdp/mdp_kms.h | 13 ++ 8 files changed, 114 insertions(+), 63 deletions(-) diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h index c1ecb9d..1aaedad 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h @@ -175,27 +175,24 @@ irqreturn_t mdp4_irq(struct msm_kms *kms); int mdp4_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc); void mdp4_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc); -static inline bool pipe_supports_yuv(enum mdp4_pipe pipe) +static inline uint32_t mdp4_pipe_caps(enum mdp4_pipe pipe) { switch (pipe) { case VG1: case VG2: case VG3: case VG4: - return true; + return MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP | + MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_CSC; + case RGB1: + case RGB2: + case RGB3: + return MDP_PIPE_CAP_SCALE; default: - return false; + return 0; } } -static inline -uint32_t mdp4_get_formats(enum mdp4_pipe pipe_id, uint32_t *pixel_formats, - uint32_t max_formats) -{ - return mdp_get_formats(pixel_formats, max_formats, - !pipe_supports_yuv(pipe_id)); -} - void mdp4_plane_install_properties(struct drm_plane *plane, struct drm_mode_object *obj); enum mdp4_pipe mdp4_plane_pipe(struct drm_plane *plane); diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c index 0d1dbb7..c749489 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c @@ -26,6 +26,7 @@ struct mdp4_plane { enum mdp4_pipe pipe; + uint32_t caps; uint32_t nformats; uint32_t formats[32]; @@ -380,9 +381,11 @@ struct drm_plane *mdp4_plane_init(struct drm_device *dev, mdp4_plane->pipe = pipe_id; mdp4_plane->name = pipe_names[pipe_id]; + mdp4_plane->caps = mdp4_pipe_caps(pipe_id); - mdp4_plane->nformats = mdp4_get_formats(pipe_id, mdp4_plane->formats, - ARRAY_SIZE(mdp4_plane->formats)); + mdp4_plane->nformats = mdp_get_formats(mdp4_plane->formats, + ARRAY_SIZE(mdp4_plane->formats), + !pipe_supports_yuv(mdp4_plane->caps)); type = private_plane ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY; ret = drm_universal_plane_init(dev, plane, 0xff, _plane_funcs, diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c index 789b02f..ac1d58f 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c @@ -45,14 +45,20 @@ const struct mdp5_cfg_hw msm8x74_config = { .pipe_vig = { .count = 3, .base = { 0x01200, 0x01600, 0x01a00 }, + .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP | + MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_CSC | + MDP_PIPE_CAP_DECIMATION, }, .pipe_rgb = { .count = 3, .base = { 0x01e00, 0x02200, 0x02600 }, + .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP | + MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_DECIMATION, }, .pipe_dma = { .count = 2, .base = { 0x02a00, 0x02e00 }, + .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP, }, .lm = { .count = 5, @@ -113,14 +119,20 @@ const struct mdp5_cfg_hw apq8084_config = { .pipe_vig = { .count = 4, .base = { 0x01200, 0x01600, 0x01a00, 0x01e00 }, + .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP | + MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_CSC | + MDP_PIPE_CAP_DECIMATION, }, .pipe_rgb = { .co
[PATCH] drm/msm/mdp5:Add DMA pipe planes for MDP5
This change is to add planes which use DMA pipes for MDP5. Signed-off-by: Jilai Wang --- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 23 --- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c index cbda41d..f40896d 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c @@ -316,9 +316,12 @@ static int modeset_init(struct mdp5_kms *mdp5_kms) static const enum mdp5_pipe crtcs[] = { SSPP_RGB0, SSPP_RGB1, SSPP_RGB2, SSPP_RGB3, }; - static const enum mdp5_pipe pub_planes[] = { + static const enum mdp5_pipe vig_planes[] = { SSPP_VIG0, SSPP_VIG1, SSPP_VIG2, SSPP_VIG3, }; + static const enum mdp5_pipe dma_planes[] = { + SSPP_DMA0, SSPP_DMA1, + }; struct drm_device *dev = mdp5_kms->dev; struct msm_drm_private *priv = dev->dev_private; const struct mdp5_cfg_hw *hw_cfg; @@ -361,12 +364,26 @@ static int modeset_init(struct mdp5_kms *mdp5_kms) for (i = 0; i < hw_cfg->pipe_vig.count; i++) { struct drm_plane *plane; - plane = mdp5_plane_init(dev, pub_planes[i], false, + plane = mdp5_plane_init(dev, vig_planes[i], false, hw_cfg->pipe_vig.base[i], hw_cfg->pipe_vig.caps); if (IS_ERR(plane)) { ret = PTR_ERR(plane); dev_err(dev->dev, "failed to construct %s plane: %d\n", - pipe2name(pub_planes[i]), ret); + pipe2name(vig_planes[i]), ret); + goto fail; + } + } + + /* DMA planes */ + for (i = 0; i < hw_cfg->pipe_dma.count; i++) { + struct drm_plane *plane; + + plane = mdp5_plane_init(dev, dma_planes[i], false, + hw_cfg->pipe_dma.base[i], hw_cfg->pipe_dma.caps); + if (IS_ERR(plane)) { + ret = PTR_ERR(plane); + dev_err(dev->dev, "failed to construct %s plane: %d\n", + pipe2name(dma_planes[i]), ret); goto fail; } } -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH] drm/msm/mdp: Add capabilities to MDP planes
MDP planes can be implemented using different type of HW pipes, RGB/VIG/DMA pipes for MDP5 and RGB/VG/DMA pipes for MDP4. Each type of pipe has different HW capabilities such as scaling, color space conversion, decimation... Add a variable in plane data structure to specify the difference of each plane which comes from mdp5_cfg data and use it to differenciate the plane operation. Signed-off-by: Jilai Wang --- drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h | 19 drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c | 7 ++- drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c | 26 ++- drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h | 11 +++-- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 4 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h | 24 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 73 ++- drivers/gpu/drm/msm/mdp/mdp_kms.h | 13 ++ 8 files changed, 114 insertions(+), 63 deletions(-) diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h index c1ecb9d..83a54d0 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h @@ -175,27 +175,24 @@ irqreturn_t mdp4_irq(struct msm_kms *kms); int mdp4_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc); void mdp4_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc); -static inline bool pipe_supports_yuv(enum mdp4_pipe pipe) +static inline uint32_t mdp4_pipe_caps(enum mdp4_pipe pipe) { switch (pipe) { case VG1: case VG2: case VG3: case VG4: - return true; + return MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP | + MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_CSC; + case RGB1: + case RGB2: + case RBG2: + return MDP_PIPE_CAP_SCALE; default: - return false; + return 0; } } -static inline -uint32_t mdp4_get_formats(enum mdp4_pipe pipe_id, uint32_t *pixel_formats, - uint32_t max_formats) -{ - return mdp_get_formats(pixel_formats, max_formats, - !pipe_supports_yuv(pipe_id)); -} - void mdp4_plane_install_properties(struct drm_plane *plane, struct drm_mode_object *obj); enum mdp4_pipe mdp4_plane_pipe(struct drm_plane *plane); diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c index 0d1dbb7..c749489 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c @@ -26,6 +26,7 @@ struct mdp4_plane { enum mdp4_pipe pipe; + uint32_t caps; uint32_t nformats; uint32_t formats[32]; @@ -380,9 +381,11 @@ struct drm_plane *mdp4_plane_init(struct drm_device *dev, mdp4_plane->pipe = pipe_id; mdp4_plane->name = pipe_names[pipe_id]; + mdp4_plane->caps = mdp4_pipe_caps(pipe_id); - mdp4_plane->nformats = mdp4_get_formats(pipe_id, mdp4_plane->formats, - ARRAY_SIZE(mdp4_plane->formats)); + mdp4_plane->nformats = mdp_get_formats(mdp4_plane->formats, + ARRAY_SIZE(mdp4_plane->formats), + !pipe_supports_yuv(mdp4_plane->caps)); type = private_plane ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY; ret = drm_universal_plane_init(dev, plane, 0xff, _plane_funcs, diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c index 789b02f..ac1d58f 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c @@ -45,14 +45,20 @@ const struct mdp5_cfg_hw msm8x74_config = { .pipe_vig = { .count = 3, .base = { 0x01200, 0x01600, 0x01a00 }, + .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP | + MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_CSC | + MDP_PIPE_CAP_DECIMATION, }, .pipe_rgb = { .count = 3, .base = { 0x01e00, 0x02200, 0x02600 }, + .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP | + MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_DECIMATION, }, .pipe_dma = { .count = 2, .base = { 0x02a00, 0x02e00 }, + .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP, }, .lm = { .count = 5, @@ -113,14 +119,20 @@ const struct mdp5_cfg_hw apq8084_config = { .pipe_vig = { .count = 4, .base = { 0x01200, 0x01600, 0x01a00, 0x01e00 }, + .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP | + MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_CSC | + MDP_PIPE_CAP_DECIMATION, }, .pipe_rgb = { .count = 4, .base = { 0x02
[PATCH 3/3] drm/msm/mdp5: Add plane blending operation support for MDP5(V2)
This change is to add properties alpha/zpos/blend_mode to mdp5 plane for alpha blending operation to generate the blended output. V1: Initial change V2: Change "premultilied" property to enum (Rob's comment) Signed-off-by: Jilai Wang --- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 110 ++ drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c | 66 ++-- drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h | 32 ++-- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h | 16 ++-- drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 124 +++--- drivers/gpu/drm/msm/msm_drv.h | 10 +++ 6 files changed, 273 insertions(+), 85 deletions(-) diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c index dea3d2e..e6e53b8 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c @@ -160,7 +160,7 @@ static void complete_flip(struct drm_crtc *crtc, struct drm_file *file) if (mdp5_crtc->ctl && !crtc->state->enable) { /* set STAGE_UNUSED for all layers */ - mdp5_ctl_blend(mdp5_crtc->ctl, mdp5_crtc->lm, 0x); + mdp5_ctl_blend(mdp5_crtc->ctl, mdp5_crtc->lm, NULL, 0, 0); mdp5_ctl_release(mdp5_crtc->ctl); mdp5_crtc->ctl = NULL; } @@ -196,13 +196,9 @@ static bool mdp5_crtc_mode_fixup(struct drm_crtc *crtc, /* * blend_setup() - blend all the planes of a CRTC * - * When border is enabled, the border color will ALWAYS be the base layer. - * Therefore, the first plane (private RGB pipe) will start at STAGE0. - * If disabled, the first plane starts at STAGE_BASE. - * - * Note: - * Border is not enabled here because the private plane is exactly - * the CRTC resolution. + * If no base layer is available, border will be enabled as the base layer. + * Otherwise all layers will be blended based on their stage calculated + * in mdp5_crtc_atomic_check. */ static void blend_setup(struct drm_crtc *crtc) { @@ -210,9 +206,14 @@ static void blend_setup(struct drm_crtc *crtc) struct mdp5_kms *mdp5_kms = get_kms(crtc); struct drm_plane *plane; const struct mdp5_cfg_hw *hw_cfg; - uint32_t lm = mdp5_crtc->lm, blend_cfg = 0; + struct mdp5_plane_state *pstate, *pstates[STAGE_MAX + 1] = {NULL}; + const struct mdp_format *format; + uint32_t lm = mdp5_crtc->lm; + uint32_t blend_op, fg_alpha, bg_alpha, ctl_blend_flags = 0; unsigned long flags; -#define blender(stage) ((stage) - STAGE_BASE) + uint8_t stage[STAGE_MAX + 1]; + int i, plane_cnt = 0; +#define blender(stage) ((stage) - STAGE0) hw_cfg = mdp5_cfg_get_hw_config(mdp5_kms->cfg); @@ -222,33 +223,73 @@ static void blend_setup(struct drm_crtc *crtc) if (!mdp5_crtc->ctl) goto out; + /* Collect all plane information */ drm_atomic_crtc_for_each_plane(plane, crtc) { - enum mdp_mixer_stage_id stage = - to_mdp5_plane_state(plane->state)->stage; + pstate = to_mdp5_plane_state(plane->state); + pstates[pstate->stage] = pstate; + stage[pstate->stage] = mdp5_plane_pipe(plane); + plane_cnt++; + } - /* -* Note: This cannot happen with current implementation but -* we need to check this condition once z property is added -*/ - BUG_ON(stage > hw_cfg->lm.nb_stages); + /* + * If there is no base layer, enable border color. + * Although it's not possbile in current blend logic, + * put it here as a reminder. + */ + if (!pstates[STAGE_BASE] && plane_cnt) { + ctl_blend_flags |= MDP5_CTL_BLEND_OP_FLAG_BORDER_OUT; + DBG("Border Color is enabled"); + } - /* LM */ - mdp5_write(mdp5_kms, - REG_MDP5_LM_BLEND_OP_MODE(lm, blender(stage)), - MDP5_LM_BLEND_OP_MODE_FG_ALPHA(FG_CONST) | - MDP5_LM_BLEND_OP_MODE_BG_ALPHA(BG_CONST)); + /* The reset for blending */ + for (i = STAGE0; i <= STAGE_MAX; i++) { + if (!pstates[i]) + continue; + + format = to_mdp_format( + msm_framebuffer_format(pstates[i]->base.fb)); + plane = pstates[i]->base.plane; + blend_op = MDP5_LM_BLEND_OP_MODE_FG_ALPHA(FG_CONST) | + MDP5_LM_BLEND_OP_MODE_BG_ALPHA(BG_CONST); + fg_alpha = pstates[i]->alpha; + bg_alpha = 0xFF - pstates[i]->alpha; + DBG("Stage %d fg_alpha %x bg_alpha %x", i, fg_alpha, bg_alpha); + + if (format
[PATCH 1/3] drm/doc: Add description of drm properties in msm(V2)
Add plane properties "premultiplied/zpos/alpha" used in msm MDP driver to perform proper blending operation. V1: Initial change V2: Change "premultiplied" property to enum (Rob's comment) Signed-off-by: Jilai Wang --- Documentation/DocBook/drm.tmpl | 23 +++ 1 file changed, 23 insertions(+) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 109fde8..d9f5613 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -3500,6 +3500,29 @@ void intel_crt_init(struct drm_device *dev) Plane TBD + + msm + Generic + "premultiplied" + ENUM + { "false", "true" } + Plane + property to indicate the framebuffer used by this plane is alpha pre-multiplied + + + "alpha" + RANGE + Min=0, Max=255 + Plane + property to set plane's global alpha value + + + "zpos" + RANGE + Min=1, Max=255 + Plane + property to set plane's z position during blending + -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH 2/3] drm/msm/mdp5: Update generated header files(V2)
To support mdp5 blending for mdp5 v1.5 and later V1: Initial change V2: After the stage number is increased to 7, BLENDx registers are not continuous now. Using the offset for each BLEND stage to fix it. Signed-off-by: Jilai Wang --- drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h | 95 drivers/gpu/drm/msm/mdp/mdp_common.xml.h | 4 ++ 2 files changed, 77 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h index 50e1752..b35b85f 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h @@ -381,49 +381,49 @@ static inline uint32_t REG_MDP5_CTL_LAYER(uint32_t i0, uint32_t i1) { return 0x0 static inline uint32_t REG_MDP5_CTL_LAYER_REG(uint32_t i0, uint32_t i1) { return 0x + __offset_CTL(i0) + __offset_LAYER(i1); } #define MDP5_CTL_LAYER_REG_VIG0__MASK 0x0007 #define MDP5_CTL_LAYER_REG_VIG0__SHIFT 0 -static inline uint32_t MDP5_CTL_LAYER_REG_VIG0(enum mdp_mixer_stage_id val) +static inline uint32_t MDP5_CTL_LAYER_REG_VIG0(uint32_t val) { return ((val) << MDP5_CTL_LAYER_REG_VIG0__SHIFT) & MDP5_CTL_LAYER_REG_VIG0__MASK; } #define MDP5_CTL_LAYER_REG_VIG1__MASK 0x0038 #define MDP5_CTL_LAYER_REG_VIG1__SHIFT 3 -static inline uint32_t MDP5_CTL_LAYER_REG_VIG1(enum mdp_mixer_stage_id val) +static inline uint32_t MDP5_CTL_LAYER_REG_VIG1(uint32_t val) { return ((val) << MDP5_CTL_LAYER_REG_VIG1__SHIFT) & MDP5_CTL_LAYER_REG_VIG1__MASK; } #define MDP5_CTL_LAYER_REG_VIG2__MASK 0x01c0 #define MDP5_CTL_LAYER_REG_VIG2__SHIFT 6 -static inline uint32_t MDP5_CTL_LAYER_REG_VIG2(enum mdp_mixer_stage_id val) +static inline uint32_t MDP5_CTL_LAYER_REG_VIG2(uint32_t val) { return ((val) << MDP5_CTL_LAYER_REG_VIG2__SHIFT) & MDP5_CTL_LAYER_REG_VIG2__MASK; } #define MDP5_CTL_LAYER_REG_RGB0__MASK 0x0e00 #define MDP5_CTL_LAYER_REG_RGB0__SHIFT 9 -static inline uint32_t MDP5_CTL_LAYER_REG_RGB0(enum mdp_mixer_stage_id val) +static inline uint32_t MDP5_CTL_LAYER_REG_RGB0(uint32_t val) { return ((val) << MDP5_CTL_LAYER_REG_RGB0__SHIFT) & MDP5_CTL_LAYER_REG_RGB0__MASK; } #define MDP5_CTL_LAYER_REG_RGB1__MASK 0x7000 #define MDP5_CTL_LAYER_REG_RGB1__SHIFT 12 -static inline uint32_t MDP5_CTL_LAYER_REG_RGB1(enum mdp_mixer_stage_id val) +static inline uint32_t MDP5_CTL_LAYER_REG_RGB1(uint32_t val) { return ((val) << MDP5_CTL_LAYER_REG_RGB1__SHIFT) & MDP5_CTL_LAYER_REG_RGB1__MASK; } #define MDP5_CTL_LAYER_REG_RGB2__MASK 0x00038000 #define MDP5_CTL_LAYER_REG_RGB2__SHIFT 15 -static inline uint32_t MDP5_CTL_LAYER_REG_RGB2(enum mdp_mixer_stage_id val) +static inline uint32_t MDP5_CTL_LAYER_REG_RGB2(uint32_t val) { return ((val) << MDP5_CTL_LAYER_REG_RGB2__SHIFT) & MDP5_CTL_LAYER_REG_RGB2__MASK; } #define MDP5_CTL_LAYER_REG_DMA0__MASK 0x001c #define MDP5_CTL_LAYER_REG_DMA0__SHIFT 18 -static inline uint32_t MDP5_CTL_LAYER_REG_DMA0(enum mdp_mixer_stage_id val) +static inline uint32_t MDP5_CTL_LAYER_REG_DMA0(uint32_t val) { return ((val) << MDP5_CTL_LAYER_REG_DMA0__SHIFT) & MDP5_CTL_LAYER_REG_DMA0__MASK; } #define MDP5_CTL_LAYER_REG_DMA1__MASK 0x00e0 #define MDP5_CTL_LAYER_REG_DMA1__SHIFT 21 -static inline uint32_t MDP5_CTL_LAYER_REG_DMA1(enum mdp_mixer_stage_id val) +static inline uint32_t MDP5_CTL_LAYER_REG_DMA1(uint32_t val) { return ((val) << MDP5_CTL_LAYER_REG_DMA1__SHIFT) & MDP5_CTL_LAYER_REG_DMA1__MASK; } @@ -431,13 +431,13 @@ static inline uint32_t MDP5_CTL_LAYER_REG_DMA1(enum mdp_mixer_stage_id val) #define MDP5_CTL_LAYER_REG_CURSOR_OUT 0x0200 #define MDP5_CTL_LAYER_REG_VIG3__MASK 0x1c00 #define MDP5_CTL_LAYER_REG_VIG3__SHIFT 26 -static inline uint32_t MDP5_CTL_LAYER_REG_VIG3(enum mdp_mixer_stage_id val) +static inline uint32_t MDP5_CTL_LAYER_REG_VIG3(uint32_t val) { return ((val) << MDP5_CTL_LAYER_REG_VIG3__SHIFT) & MDP5_CTL_LAYER_REG_VIG3__MASK; } #define MDP5_CTL_LAYER_REG_RGB3__MASK 0xe000 #define MDP5_CTL_LAYER_REG_RGB3__SHIFT 29 -static inline uint32_t MDP5_CTL_LAYER_REG_RGB3(enum mdp_mixer_stage_id val) +static inline uint32_t MDP5_CTL_LAYER_REG_RGB3(uint32_t val) { return ((val) << MDP5_CTL_LAYER_REG_RGB3__SHIFT) & MDP5_CTL_LAYER_REG_RGB3__MASK; } @@ -499,6 +499,44 @@ static inline uint32_t REG_MDP5_CTL_STA
[PATCH] rnndb: Increase stage number for MDP1.5 (V2)
MDP1.5 can support 7 stages. Update xml file accordingly. V1: Initial change V2: After the stage number is increased to 7, BLENDx registers are not continuous now. Using the offset for each BLEND stage to fix it. Signed-off-by: Jilai Wang --- rnndb/mdp/mdp5.xml | 38 +++--- rnndb/mdp/mdp_common.xml | 4 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/rnndb/mdp/mdp5.xml b/rnndb/mdp/mdp5.xml index 6e92e54..6f08aca 100644 --- a/rnndb/mdp/mdp5.xml +++ b/rnndb/mdp/mdp5.xml @@ -212,18 +212,18 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ rules-ng.xsd"> - - - - - - - - + + + + + + + + - - + + @@ -266,6 +266,22 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ rules-ng.xsd"> + + + + + + + + + + + + + + + + @@ -414,7 +430,7 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ rules-ng.xsd"> - + diff --git a/rnndb/mdp/mdp_common.xml b/rnndb/mdp/mdp_common.xml index b4d1949..f666d1a 100644 --- a/rnndb/mdp/mdp_common.xml +++ b/rnndb/mdp/mdp_common.xml @@ -26,6 +26,10 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ rules-ng.xsd"> + + + + -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH] rnndb: Increase stage number for MDP1.5
MDP1.5 can support 7 stages. Update xml file accordingly. Signed-off-by: Jilai Wang --- rnndb/mdp/mdp5.xml | 36 ++-- rnndb/mdp/mdp_common.xml | 4 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/rnndb/mdp/mdp5.xml b/rnndb/mdp/mdp5.xml index 6e92e54..c9aa10c 100644 --- a/rnndb/mdp/mdp5.xml +++ b/rnndb/mdp/mdp5.xml @@ -212,18 +212,18 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ rules-ng.xsd"> - - - - - - - - + + + + + + + + - - + + @@ -266,6 +266,22 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ rules-ng.xsd"> + + + + + + + + + + + + + + + + diff --git a/rnndb/mdp/mdp_common.xml b/rnndb/mdp/mdp_common.xml index b4d1949..f666d1a 100644 --- a/rnndb/mdp/mdp_common.xml +++ b/rnndb/mdp/mdp_common.xml @@ -26,6 +26,10 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ rules-ng.xsd"> + + + + -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH 3/3] drm/msm/mdp5: Add plane blending operation support for MDP5
This change is to add properties alpha/zpos/premultiplied to mdp5 plane for alpha blending operation to generate the blended output. Signed-off-by: Jilai Wang --- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 110 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c | 66 -- drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h | 32 ++--- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h | 16 ++--- drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 107 ++--- drivers/gpu/drm/msm/msm_drv.h | 10 +++ 6 files changed, 256 insertions(+), 85 deletions(-) diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c index dea3d2e..e6e53b8 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c @@ -160,7 +160,7 @@ static void complete_flip(struct drm_crtc *crtc, struct drm_file *file) if (mdp5_crtc->ctl && !crtc->state->enable) { /* set STAGE_UNUSED for all layers */ - mdp5_ctl_blend(mdp5_crtc->ctl, mdp5_crtc->lm, 0x); + mdp5_ctl_blend(mdp5_crtc->ctl, mdp5_crtc->lm, NULL, 0, 0); mdp5_ctl_release(mdp5_crtc->ctl); mdp5_crtc->ctl = NULL; } @@ -196,13 +196,9 @@ static bool mdp5_crtc_mode_fixup(struct drm_crtc *crtc, /* * blend_setup() - blend all the planes of a CRTC * - * When border is enabled, the border color will ALWAYS be the base layer. - * Therefore, the first plane (private RGB pipe) will start at STAGE0. - * If disabled, the first plane starts at STAGE_BASE. - * - * Note: - * Border is not enabled here because the private plane is exactly - * the CRTC resolution. + * If no base layer is available, border will be enabled as the base layer. + * Otherwise all layers will be blended based on their stage calculated + * in mdp5_crtc_atomic_check. */ static void blend_setup(struct drm_crtc *crtc) { @@ -210,9 +206,14 @@ static void blend_setup(struct drm_crtc *crtc) struct mdp5_kms *mdp5_kms = get_kms(crtc); struct drm_plane *plane; const struct mdp5_cfg_hw *hw_cfg; - uint32_t lm = mdp5_crtc->lm, blend_cfg = 0; + struct mdp5_plane_state *pstate, *pstates[STAGE_MAX + 1] = {NULL}; + const struct mdp_format *format; + uint32_t lm = mdp5_crtc->lm; + uint32_t blend_op, fg_alpha, bg_alpha, ctl_blend_flags = 0; unsigned long flags; -#define blender(stage) ((stage) - STAGE_BASE) + uint8_t stage[STAGE_MAX + 1]; + int i, plane_cnt = 0; +#define blender(stage) ((stage) - STAGE0) hw_cfg = mdp5_cfg_get_hw_config(mdp5_kms->cfg); @@ -222,33 +223,73 @@ static void blend_setup(struct drm_crtc *crtc) if (!mdp5_crtc->ctl) goto out; + /* Collect all plane information */ drm_atomic_crtc_for_each_plane(plane, crtc) { - enum mdp_mixer_stage_id stage = - to_mdp5_plane_state(plane->state)->stage; + pstate = to_mdp5_plane_state(plane->state); + pstates[pstate->stage] = pstate; + stage[pstate->stage] = mdp5_plane_pipe(plane); + plane_cnt++; + } - /* -* Note: This cannot happen with current implementation but -* we need to check this condition once z property is added -*/ - BUG_ON(stage > hw_cfg->lm.nb_stages); + /* + * If there is no base layer, enable border color. + * Although it's not possbile in current blend logic, + * put it here as a reminder. + */ + if (!pstates[STAGE_BASE] && plane_cnt) { + ctl_blend_flags |= MDP5_CTL_BLEND_OP_FLAG_BORDER_OUT; + DBG("Border Color is enabled"); + } - /* LM */ - mdp5_write(mdp5_kms, - REG_MDP5_LM_BLEND_OP_MODE(lm, blender(stage)), - MDP5_LM_BLEND_OP_MODE_FG_ALPHA(FG_CONST) | - MDP5_LM_BLEND_OP_MODE_BG_ALPHA(BG_CONST)); + /* The reset for blending */ + for (i = STAGE0; i <= STAGE_MAX; i++) { + if (!pstates[i]) + continue; + + format = to_mdp_format( + msm_framebuffer_format(pstates[i]->base.fb)); + plane = pstates[i]->base.plane; + blend_op = MDP5_LM_BLEND_OP_MODE_FG_ALPHA(FG_CONST) | + MDP5_LM_BLEND_OP_MODE_BG_ALPHA(BG_CONST); + fg_alpha = pstates[i]->alpha; + bg_alpha = 0xFF - pstates[i]->alpha; + DBG("Stage %d fg_alpha %x bg_alpha %x", i, fg_alpha, bg_alpha); + + if (format->alpha_enable && pstates[i]->premultiplied) { +
[PATCH 2/3] drm/msm/mdp5: Update generated header files
To support mdp5 blending for mdp5 v1.5 and later Signed-off-by: Jilai Wang --- drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h | 58 ++-- drivers/gpu/drm/msm/mdp/mdp_common.xml.h | 4 +++ 2 files changed, 52 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h index 50e1752..d037921 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h @@ -381,49 +381,49 @@ static inline uint32_t REG_MDP5_CTL_LAYER(uint32_t i0, uint32_t i1) { return 0x0 static inline uint32_t REG_MDP5_CTL_LAYER_REG(uint32_t i0, uint32_t i1) { return 0x + __offset_CTL(i0) + __offset_LAYER(i1); } #define MDP5_CTL_LAYER_REG_VIG0__MASK 0x0007 #define MDP5_CTL_LAYER_REG_VIG0__SHIFT 0 -static inline uint32_t MDP5_CTL_LAYER_REG_VIG0(enum mdp_mixer_stage_id val) +static inline uint32_t MDP5_CTL_LAYER_REG_VIG0(uint32_t val) { return ((val) << MDP5_CTL_LAYER_REG_VIG0__SHIFT) & MDP5_CTL_LAYER_REG_VIG0__MASK; } #define MDP5_CTL_LAYER_REG_VIG1__MASK 0x0038 #define MDP5_CTL_LAYER_REG_VIG1__SHIFT 3 -static inline uint32_t MDP5_CTL_LAYER_REG_VIG1(enum mdp_mixer_stage_id val) +static inline uint32_t MDP5_CTL_LAYER_REG_VIG1(uint32_t val) { return ((val) << MDP5_CTL_LAYER_REG_VIG1__SHIFT) & MDP5_CTL_LAYER_REG_VIG1__MASK; } #define MDP5_CTL_LAYER_REG_VIG2__MASK 0x01c0 #define MDP5_CTL_LAYER_REG_VIG2__SHIFT 6 -static inline uint32_t MDP5_CTL_LAYER_REG_VIG2(enum mdp_mixer_stage_id val) +static inline uint32_t MDP5_CTL_LAYER_REG_VIG2(uint32_t val) { return ((val) << MDP5_CTL_LAYER_REG_VIG2__SHIFT) & MDP5_CTL_LAYER_REG_VIG2__MASK; } #define MDP5_CTL_LAYER_REG_RGB0__MASK 0x0e00 #define MDP5_CTL_LAYER_REG_RGB0__SHIFT 9 -static inline uint32_t MDP5_CTL_LAYER_REG_RGB0(enum mdp_mixer_stage_id val) +static inline uint32_t MDP5_CTL_LAYER_REG_RGB0(uint32_t val) { return ((val) << MDP5_CTL_LAYER_REG_RGB0__SHIFT) & MDP5_CTL_LAYER_REG_RGB0__MASK; } #define MDP5_CTL_LAYER_REG_RGB1__MASK 0x7000 #define MDP5_CTL_LAYER_REG_RGB1__SHIFT 12 -static inline uint32_t MDP5_CTL_LAYER_REG_RGB1(enum mdp_mixer_stage_id val) +static inline uint32_t MDP5_CTL_LAYER_REG_RGB1(uint32_t val) { return ((val) << MDP5_CTL_LAYER_REG_RGB1__SHIFT) & MDP5_CTL_LAYER_REG_RGB1__MASK; } #define MDP5_CTL_LAYER_REG_RGB2__MASK 0x00038000 #define MDP5_CTL_LAYER_REG_RGB2__SHIFT 15 -static inline uint32_t MDP5_CTL_LAYER_REG_RGB2(enum mdp_mixer_stage_id val) +static inline uint32_t MDP5_CTL_LAYER_REG_RGB2(uint32_t val) { return ((val) << MDP5_CTL_LAYER_REG_RGB2__SHIFT) & MDP5_CTL_LAYER_REG_RGB2__MASK; } #define MDP5_CTL_LAYER_REG_DMA0__MASK 0x001c #define MDP5_CTL_LAYER_REG_DMA0__SHIFT 18 -static inline uint32_t MDP5_CTL_LAYER_REG_DMA0(enum mdp_mixer_stage_id val) +static inline uint32_t MDP5_CTL_LAYER_REG_DMA0(uint32_t val) { return ((val) << MDP5_CTL_LAYER_REG_DMA0__SHIFT) & MDP5_CTL_LAYER_REG_DMA0__MASK; } #define MDP5_CTL_LAYER_REG_DMA1__MASK 0x00e0 #define MDP5_CTL_LAYER_REG_DMA1__SHIFT 21 -static inline uint32_t MDP5_CTL_LAYER_REG_DMA1(enum mdp_mixer_stage_id val) +static inline uint32_t MDP5_CTL_LAYER_REG_DMA1(uint32_t val) { return ((val) << MDP5_CTL_LAYER_REG_DMA1__SHIFT) & MDP5_CTL_LAYER_REG_DMA1__MASK; } @@ -431,13 +431,13 @@ static inline uint32_t MDP5_CTL_LAYER_REG_DMA1(enum mdp_mixer_stage_id val) #define MDP5_CTL_LAYER_REG_CURSOR_OUT 0x0200 #define MDP5_CTL_LAYER_REG_VIG3__MASK 0x1c00 #define MDP5_CTL_LAYER_REG_VIG3__SHIFT 26 -static inline uint32_t MDP5_CTL_LAYER_REG_VIG3(enum mdp_mixer_stage_id val) +static inline uint32_t MDP5_CTL_LAYER_REG_VIG3(uint32_t val) { return ((val) << MDP5_CTL_LAYER_REG_VIG3__SHIFT) & MDP5_CTL_LAYER_REG_VIG3__MASK; } #define MDP5_CTL_LAYER_REG_RGB3__MASK 0xe000 #define MDP5_CTL_LAYER_REG_RGB3__SHIFT 29 -static inline uint32_t MDP5_CTL_LAYER_REG_RGB3(enum mdp_mixer_stage_id val) +static inline uint32_t MDP5_CTL_LAYER_REG_RGB3(uint32_t val) { return ((val) << MDP5_CTL_LAYER_REG_RGB3__SHIFT) & MDP5_CTL_LAYER_REG_RGB3__MASK; } @@ -499,6 +499,44 @@ static inline uint32_t REG_MDP5_CTL_START(uint32_t i0) { return 0x001c + __o static inline uint32_t REG_MDP5_CTL_PACK_3D(uint32_t i0) { return 0x0020 + __offset_CTL(i0); } +static inlin
[PATCH 1/3] drm/doc: Add description of drm properties in msm
Add plane properties "premultiplied/zpos/alpha" used in msm MDP driver to perform proper blending operation. Signed-off-by: Jilai Wang --- Documentation/DocBook/drm.tmpl | 23 +++ 1 file changed, 23 insertions(+) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 109fde8..9dc0940 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -3500,6 +3500,29 @@ void intel_crt_init(struct drm_device *dev) Plane TBD + + msm + Generic + "premultiplied" + RANGE + Min=0, Max=1 + Plane + property to indicate the framebuffer used by this plane is alpha pre-multiplied + + + "alpha" + RANGE + Min=0, Max=255 + Plane + property to set plane's global alpha value + + + "zpos" + RANGE + Min=1, Max=255 + Plane + property to set plane's z position during blending + -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH 0/3]drm/msm/mdp5: Add plane blending operation support for MDP5
Jilai Wang (3): drm/doc: Add description of drm properties in msm drm/msm/mdp5: Update generated header files drm/msm/mdp5: Add plane blending operation support for MDP5 Documentation/DocBook/drm.tmpl| 23 +++ drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h | 58 +--- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 110 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c | 66 -- drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h | 32 ++--- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h | 16 ++--- drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 107 ++--- drivers/gpu/drm/msm/mdp/mdp_common.xml.h | 4 ++ drivers/gpu/drm/msm/msm_drv.h | 10 +++ 9 files changed, 331 insertions(+), 95 deletions(-) -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH 2/3] drm:msm: Initial Add Writeback Support (V2)
Add writeback support in msm kms framework. V1: Initial change V2: Address Rob/Paul/Emil's comments Signed-off-by: Jilai Wang --- drivers/gpu/drm/msm/Kconfig | 10 + drivers/gpu/drm/msm/Makefile | 7 + drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c | 10 + drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h | 1 + drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 17 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h | 8 + drivers/gpu/drm/msm/mdp/mdp5/mdp5_wb_encoder.c| 466 drivers/gpu/drm/msm/mdp/mdp_kms.h | 2 +- drivers/gpu/drm/msm/mdp/mdp_wb/mdp_wb.c | 311 ++ drivers/gpu/drm/msm/mdp/mdp_wb/mdp_wb.h | 98 + drivers/gpu/drm/msm/mdp/mdp_wb/mdp_wb_connector.c | 157 +++ drivers/gpu/drm/msm/mdp/mdp_wb/mdp_wb_v4l2.c | 501 ++ drivers/gpu/drm/msm/msm_drv.c | 2 + drivers/gpu/drm/msm/msm_drv.h | 15 + drivers/gpu/drm/msm/msm_fbdev.c | 34 +- 15 files changed, 1636 insertions(+), 3 deletions(-) create mode 100644 drivers/gpu/drm/msm/mdp/mdp5/mdp5_wb_encoder.c create mode 100644 drivers/gpu/drm/msm/mdp/mdp_wb/mdp_wb.c create mode 100644 drivers/gpu/drm/msm/mdp/mdp_wb/mdp_wb.h create mode 100644 drivers/gpu/drm/msm/mdp/mdp_wb/mdp_wb_connector.c create mode 100644 drivers/gpu/drm/msm/mdp/mdp_wb/mdp_wb_v4l2.c diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig index 0a6f676..5754d12 100644 --- a/drivers/gpu/drm/msm/Kconfig +++ b/drivers/gpu/drm/msm/Kconfig @@ -46,3 +46,13 @@ config DRM_MSM_DSI Choose this option if you have a need for MIPI DSI connector support. +config DRM_MSM_WB + bool "Enable writeback support for MSM modesetting driver" + depends on DRM_MSM + depends on VIDEO_V4L2 + select VIDEOBUF2_CORE + default y + help + Choose this option if you have a need to support writeback + connector. + diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index ab20867..fd2b0bb 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -1,4 +1,5 @@ ccflags-y := -Iinclude/drm -Idrivers/gpu/drm/msm +ccflags-$(CONFIG_DRM_MSM_WB) += -Idrivers/gpu/drm/msm/mdp/mdp_wb msm-y := \ adreno/adreno_device.o \ @@ -56,4 +57,10 @@ msm-$(CONFIG_DRM_MSM_DSI) += dsi/dsi.o \ dsi/dsi_phy.o \ mdp/mdp5/mdp5_cmd_encoder.o +msm-$(CONFIG_DRM_MSM_WB) += \ + mdp/mdp5/mdp5_wb_encoder.o \ + mdp/mdp_wb/mdp_wb.o \ + mdp/mdp_wb/mdp_wb_connector.o \ + mdp/mdp_wb/mdp_wb_v4l2.o + obj-$(CONFIG_DRM_MSM) += msm.o diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c index e001e6b..3666384 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c @@ -75,11 +75,16 @@ const struct mdp5_cfg_hw msm8x74_config = { .count = 4, .base = { 0x12500, 0x12700, 0x12900, 0x12b00 }, }, + .wb = { + .count = 5, + .base = { 0x11100, 0x13100, 0x15100, 0x17100, 0x19100 }, + }, .intfs = { [0] = INTF_eDP, [1] = INTF_DSI, [2] = INTF_DSI, [3] = INTF_HDMI, + [4] = INTF_WB, }, .max_clk = 2, }; @@ -145,11 +150,16 @@ const struct mdp5_cfg_hw apq8084_config = { .count = 5, .base = { 0x12500, 0x12700, 0x12900, 0x12b00, 0x12d00 }, }, + .wb = { + .count = 5, + .base = { 0x11100, 0x11500, 0x11900, 0x11d00, 0x12100 }, + }, .intfs = { [0] = INTF_eDP, [1] = INTF_DSI, [2] = INTF_DSI, [3] = INTF_HDMI, + [4] = INTF_WB, }, .max_clk = 32000, }; diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h index 3a551b0..4834cdb 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h @@ -73,6 +73,7 @@ struct mdp5_cfg_hw { struct mdp5_sub_block ad; struct mdp5_sub_block pp; struct mdp5_sub_block intf; + struct mdp5_sub_block wb; u32 intfs[MDP5_INTF_NUM_MAX]; /* array of enum mdp5_intf_type */ diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c index dfa8beb..e6e8817 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c @@ -187,7 +187,9 @@ static struct drm_encoder *construct_encoder(struct mdp5_kms *mdp5_kms, .mode = intf_mode, }; - if ((intf_type == INTF_DSI) && + if (intf_type == INTF_WB) + encoder = mdp5_w
[PATCH] drm/msm: Call drm_prime_gem_destroy to clean up imported GEM object
If the GEM object is imported, drm_prime_gem_destroy needs to be called to clean up dma buffer related information. Signed-off-by: Jilai Wang --- drivers/gpu/drm/msm/msm_gem.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 479d8af..5dbfffc 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -540,6 +540,7 @@ void msm_gem_free_object(struct drm_gem_object *obj) if (msm_obj->pages) drm_free_large(msm_obj->pages); + drm_prime_gem_destroy(obj, msm_obj->sgt); } else { vunmap(msm_obj->vaddr); put_pages(obj); -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH] drm/msm/hdmi: add hdmi hdcp support (V3)
Add HDMI HDCP support including HDCP PartI/II/III authentication. V1: Initial Change V2: Address Bjorn's comments Refactor the authentication process to use single work instead of multiple work for different authentication stages. V3: Update to align with qcom SCM api. Signed-off-by: Jilai Wang --- drivers/gpu/drm/msm/Makefile |1 + drivers/gpu/drm/msm/hdmi/hdmi.c | 45 +- drivers/gpu/drm/msm/hdmi/hdmi.h | 31 + drivers/gpu/drm/msm/hdmi/hdmi_audio.c |1 - drivers/gpu/drm/msm/hdmi/hdmi_bridge.c|8 +- drivers/gpu/drm/msm/hdmi/hdmi_connector.c |7 +- drivers/gpu/drm/msm/hdmi/hdmi_hdcp.c | 1437 + 7 files changed, 1522 insertions(+), 8 deletions(-) create mode 100644 drivers/gpu/drm/msm/hdmi/hdmi_hdcp.c diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index 674a132..be1f7ff 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -9,6 +9,7 @@ msm-y := \ hdmi/hdmi_audio.o \ hdmi/hdmi_bridge.o \ hdmi/hdmi_connector.o \ + hdmi/hdmi_hdcp.o \ hdmi/hdmi_i2c.o \ hdmi/hdmi_phy_8960.o \ hdmi/hdmi_phy_8x60.o \ diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c index 8145362..049723d 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -22,7 +22,9 @@ void hdmi_set_mode(struct hdmi *hdmi, bool power_on) { uint32_t ctrl = 0; + unsigned long flags; + spin_lock_irqsave(>reg_lock, flags); if (power_on) { ctrl |= HDMI_CTRL_ENABLE; if (!hdmi->hdmi_mode) { @@ -37,6 +39,7 @@ void hdmi_set_mode(struct hdmi *hdmi, bool power_on) } hdmi_write(hdmi, REG_HDMI_CTRL, ctrl); + spin_unlock_irqrestore(>reg_lock, flags); DBG("HDMI Core: %s, HDMI_CTRL=0x%08x", power_on ? "Enable" : "Disable", ctrl); } @@ -51,6 +54,10 @@ static irqreturn_t hdmi_irq(int irq, void *dev_id) /* Process DDC: */ hdmi_i2c_irq(hdmi->i2c); + /* Process HDCP: */ + if (hdmi->hdcp_ctrl) + hdmi_hdcp_irq(hdmi->hdcp_ctrl); + /* TODO audio.. */ return IRQ_HANDLED; @@ -60,6 +67,15 @@ static void hdmi_destroy(struct hdmi *hdmi) { struct hdmi_phy *phy = hdmi->phy; + /* +* at this point, hpd has been disabled, +* after flush workq, it's safe to deinit hdcp +*/ + if (hdmi->workq) { + flush_workqueue(hdmi->workq); + destroy_workqueue(hdmi->workq); + } + hdmi_hdcp_destroy(hdmi); if (phy) phy->funcs->destroy(phy); @@ -77,6 +93,7 @@ static struct hdmi *hdmi_init(struct platform_device *pdev) { struct hdmi_platform_config *config = pdev->dev.platform_data; struct hdmi *hdmi = NULL; + struct resource *res; int i, ret; hdmi = devm_kzalloc(>dev, sizeof(*hdmi), GFP_KERNEL); @@ -87,6 +104,7 @@ static struct hdmi *hdmi_init(struct platform_device *pdev) hdmi->pdev = pdev; hdmi->config = config; + spin_lock_init(>reg_lock); /* not sure about which phy maps to which msm.. probably I miss some */ if (config->phy_init) @@ -107,6 +125,18 @@ static struct hdmi *hdmi_init(struct platform_device *pdev) goto fail; } + /* HDCP needs physical address of hdmi register */ + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + config->mmio_name); + hdmi->mmio_phy_addr = res->start; + + hdmi->qfprom_mmio = msm_ioremap(pdev, + config->qfprom_mmio_name, "HDMI_QFPROM"); + if (IS_ERR(hdmi->qfprom_mmio)) { + dev_info(>dev, "can't find qfprom resource\n"); + hdmi->qfprom_mmio = NULL; + } + hdmi->hpd_regs = devm_kzalloc(>dev, sizeof(hdmi->hpd_regs[0]) * config->hpd_reg_cnt, GFP_KERNEL); if (!hdmi->hpd_regs) { @@ -189,6 +219,8 @@ static struct hdmi *hdmi_init(struct platform_device *pdev) hdmi->pwr_clks[i] = clk; } + hdmi->workq = alloc_ordered_workqueue("msm_hdmi", 0); + hdmi->i2c = hdmi_i2c_init(hdmi); if (IS_ERR(hdmi->i2c)) { ret = PTR_ERR(hdmi->i2c); @@ -197,6 +229,12 @@ static struct hdmi *hdmi_init(struct platform_device *pdev) goto fail; } + hdmi->hdcp_ctrl = hdmi_hdcp_init(hdmi); + if (IS_ERR(hdmi->hdcp_ctrl)) { + dev_warn(>dev, "failed to init hdcp: disabled\n"); + hdmi->hdcp_ctrl = NULL; + } + return hdmi; fail: @@ -376,6 +414,7 @@ static int hdmi_bind(struct device *dev, struct dev
[PATCH 2/3] drm:msm: Initial Add Writeback Support
Add writeback support in msm kms framework. Signed-off-by: Jilai Wang --- drivers/gpu/drm/msm/Kconfig | 10 + drivers/gpu/drm/msm/Makefile | 9 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c | 10 + drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h | 1 + drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 19 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h | 7 + drivers/gpu/drm/msm/mdp/mdp5/mdp5_wb_encoder.c| 460 +++ drivers/gpu/drm/msm/mdp/mdp_kms.h | 2 +- drivers/gpu/drm/msm/mdp/mdp_wb/mdp_wb.c | 319 + drivers/gpu/drm/msm/mdp/mdp_wb/mdp_wb.h | 98 drivers/gpu/drm/msm/mdp/mdp_wb/mdp_wb_connector.c | 157 +++ drivers/gpu/drm/msm/mdp/mdp_wb/mdp_wb_v4l2.c | 522 ++ drivers/gpu/drm/msm/msm_drv.c | 2 + drivers/gpu/drm/msm/msm_drv.h | 19 +- drivers/gpu/drm/msm/msm_fbdev.c | 34 +- drivers/gpu/drm/msm/msm_gem.c | 1 + 16 files changed, 1664 insertions(+), 6 deletions(-) create mode 100644 drivers/gpu/drm/msm/mdp/mdp5/mdp5_wb_encoder.c create mode 100644 drivers/gpu/drm/msm/mdp/mdp_wb/mdp_wb.c create mode 100644 drivers/gpu/drm/msm/mdp/mdp_wb/mdp_wb.h create mode 100644 drivers/gpu/drm/msm/mdp/mdp_wb/mdp_wb_connector.c create mode 100644 drivers/gpu/drm/msm/mdp/mdp_wb/mdp_wb_v4l2.c diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig index 1e6a907..f6c7914 100644 --- a/drivers/gpu/drm/msm/Kconfig +++ b/drivers/gpu/drm/msm/Kconfig @@ -27,6 +27,16 @@ config DRM_MSM_FBDEV support. Note that this support also provide the linux console support on top of the MSM modesetting driver. +config DRM_MSM_WB + bool "Enable writeback support for MSM modesetting driver" + depends on DRM_MSM + depends on VIDEO_V4L2 + select VIDEOBUF2_CORE + default y + help + Choose this option if you have a need to support writeback + connector. + config DRM_MSM_REGISTER_LOGGING bool "MSM DRM register logging" depends on DRM_MSM diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index 674a132..e5bf334 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -1,4 +1,5 @@ -ccflags-y := -Iinclude/drm -Idrivers/gpu/drm/msm +ccflags-y := -Iinclude/drm -Idrivers/gpu/drm/msm -Idrivers/gpu/drm/msm/mdp_wb +ccflags-$(CONFIG_DRM_MSM_WB) += -Idrivers/gpu/drm/msm/mdp/mdp_wb msm-y := \ adreno/adreno_device.o \ @@ -51,4 +52,10 @@ msm-y := \ msm-$(CONFIG_DRM_MSM_FBDEV) += msm_fbdev.o msm-$(CONFIG_COMMON_CLK) += mdp/mdp4/mdp4_lvds_pll.o +msm-$(CONFIG_DRM_MSM_WB) += \ + mdp/mdp5/mdp5_wb_encoder.o \ + mdp/mdp_wb/mdp_wb.o \ + mdp/mdp_wb/mdp_wb_connector.o \ + mdp/mdp_wb/mdp_wb_v4l2.o + obj-$(CONFIG_DRM_MSM) += msm.o diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c index 1fe7315..e87cf74 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c @@ -71,9 +71,14 @@ const struct mdp5_cfg_hw msm8x74_config = { .count = 4, .base = { 0x12500, 0x12700, 0x12900, 0x12b00 }, }, + .wb = { + .count = 5, + .base = { 0x11100, 0x13100, 0x15100, 0x17100, 0x19100 }, + }, .intfs = { [0] = INTF_eDP, [3] = INTF_HDMI, + [4] = INTF_WB, }, .max_clk = 2, }; @@ -135,9 +140,14 @@ const struct mdp5_cfg_hw apq8084_config = { .count = 5, .base = { 0x12500, 0x12700, 0x12900, 0x12b00, 0x12d00 }, }, + .wb = { + .count = 5, + .base = { 0x11100, 0x11500, 0x11900, 0x11d00, 0x12100 }, + }, .intfs = { [0] = INTF_eDP, [3] = INTF_HDMI, + [4] = INTF_WB, }, .max_clk = 32000, }; diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h index f47328d..ccb6048c 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h @@ -74,6 +74,7 @@ struct mdp5_cfg_hw { struct mdp5_sub_block dspp; struct mdp5_sub_block ad; struct mdp5_sub_block intf; + struct mdp5_sub_block wb; u32 intfs[MDP5_INTF_NUM_MAX]; /* array of enum mdp5_intf_type */ diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c index ff9201b..1b1569d 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c @@ -179,7 +179,11 @@ static struct drm_encoder *construct_encoder(struct mdp5_kms *mdp5_kms, .mode = intf_mode, }; - encoder = m
[PATCH 1/3] drm/msm/mdp5: Update generated header files with writeback support
Add register field for MDP5 writeback block Signed-off-by: Jilai Wang --- drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h | 373 ++- drivers/gpu/drm/msm/mdp/mdp_common.xml.h | 18 +- 2 files changed, 373 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h index 09bfaff..ea470a2 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h @@ -8,9 +8,9 @@ http://github.com/freedreno/envytools/ git clone https://github.com/freedreno/envytools.git The rules-ng-ng source files this header was generated from are: -- /local/mnt2/workspace2/sviau/envytools/rnndb/mdp/mdp5.xml( 26608 bytes, from 2015-02-05 23:01:09) -- /local/mnt2/workspace2/sviau/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2014-06-02 18:31:15) -- /local/mnt2/workspace2/sviau/envytools/rnndb/mdp/mdp_common.xml ( 2357 bytes, from 2015-01-23 16:20:19) +- /local/mnt2/workspace2/jilaiw/chromeos/envytools/envytools/rnndb/mdp/mdp5.xml ( 31502 bytes, from 2015-01-16 22:36:33) +- /local/mnt2/workspace2/jilaiw/chromeos/envytools/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2014-11-24 22:27:21) +- /local/mnt2/workspace2/jilaiw/chromeos/envytools/envytools/rnndb/mdp/mdp_common.xml ( 2352 bytes, from 2015-01-16 22:37:14) Copyright (C) 2013-2015 by the following authors: - Rob Clark (robclark) @@ -120,6 +120,21 @@ enum mdp5_data_format { DATA_FORMAT_YUV = 1, }; +enum mdp5_block_size { + BLOCK_SIZE_64 = 0, + BLOCK_SIZE_128 = 1, +}; + +enum mdp5_rotate_mode { + ROTATE_0 = 0, + ROTATE_90 = 1, +}; + +enum mdp5_chroma_downsample_method { + DS_MTHD_NO_PIXEL_DROP = 0, + DS_MTHD_PIXEL_DROP = 1, +}; + #define MDP5_IRQ_WB_0_DONE 0x0001 #define MDP5_IRQ_WB_1_DONE 0x0002 #define MDP5_IRQ_WB_2_DONE 0x0010 @@ -757,7 +772,7 @@ static inline uint32_t MDP5_PIPE_SRC_FORMAT_UNPACK_COUNT(uint32_t val) #define MDP5_PIPE_SRC_FORMAT_UNPACK_ALIGN_MSB 0x0004 #define MDP5_PIPE_SRC_FORMAT_NUM_PLANES__MASK 0x0018 #define MDP5_PIPE_SRC_FORMAT_NUM_PLANES__SHIFT 19 -static inline uint32_t MDP5_PIPE_SRC_FORMAT_NUM_PLANES(enum mdp_sspp_fetch_type val) +static inline uint32_t MDP5_PIPE_SRC_FORMAT_NUM_PLANES(enum mdp_fetch_type val) { return ((val) << MDP5_PIPE_SRC_FORMAT_NUM_PLANES__SHIFT) & MDP5_PIPE_SRC_FORMAT_NUM_PLANES__MASK; } @@ -1121,6 +1136,356 @@ static inline uint32_t REG_MDP5_DSPP_GAMUT_BASE(uint32_t i0) { return 0x02dc static inline uint32_t REG_MDP5_DSPP_GC_BASE(uint32_t i0) { return 0x02b0 + __offset_DSPP(i0); } +static inline uint32_t __offset_WB(uint32_t idx) +{ + switch (idx) { + case 0: return (mdp5_cfg->wb.base[0]); + case 1: return (mdp5_cfg->wb.base[1]); + case 2: return (mdp5_cfg->wb.base[2]); + case 3: return (mdp5_cfg->wb.base[3]); + case 4: return (mdp5_cfg->wb.base[4]); + default: return INVALID_IDX(idx); + } +} +static inline uint32_t REG_MDP5_WB(uint32_t i0) { return 0x + __offset_WB(i0); } + +static inline uint32_t REG_MDP5_WB_DST_FORMAT(uint32_t i0) { return 0x + __offset_WB(i0); } +#define MDP5_WB_DST_FORMAT_DSTC0_OUT__MASK 0x0003 +#define MDP5_WB_DST_FORMAT_DSTC0_OUT__SHIFT0 +static inline uint32_t MDP5_WB_DST_FORMAT_DSTC0_OUT(uint32_t val) +{ + return ((val) << MDP5_WB_DST_FORMAT_DSTC0_OUT__SHIFT) & MDP5_WB_DST_FORMAT_DSTC0_OUT__MASK; +} +#define MDP5_WB_DST_FORMAT_DSTC1_OUT__MASK 0x000c +#define MDP5_WB_DST_FORMAT_DSTC1_OUT__SHIFT2 +static inline uint32_t MDP5_WB_DST_FORMAT_DSTC1_OUT(uint32_t val) +{ + return ((val) << MDP5_WB_DST_FORMAT_DSTC1_OUT__SHIFT) & MDP5_WB_DST_FORMAT_DSTC1_OUT__MASK; +} +#define MDP5_WB_DST_FORMAT_DSTC2_OUT__MASK 0x0030 +#define MDP5_WB_DST_FORMAT_DSTC2_OUT__SHIFT4 +static inline uint32_t MDP5_WB_DST_FORMAT_DSTC2_OUT(uint32_t val) +{ + return ((val) << MDP5_WB_DST_FORMAT_DSTC2_OUT__SHIFT) & MDP5_WB_DST_FORMAT_DSTC2_OUT__MASK; +} +#define MDP5_WB_DST_FORMAT_DSTC3_OUT__MASK 0x00c0 +#define MDP5_WB_DST_FORMAT_DSTC3_OUT__SHIFT6 +static inline uint32_t MDP5_WB_DST_FORMAT_DSTC3_OUT(uint32_t val) +{ + return ((val) << MDP5_WB_DST_FORMAT_DSTC3_OUT__SHIFT) & MDP5_WB_DST_FORMAT_DSTC3_OUT__MASK; +} +#define MDP5_WB_DST_FORMAT_DSTC3_EN0x0100 +#define MDP5_WB_DST_FORMAT_DST_BPP__MASK 0x0600 +#define MDP5_WB_DST_FORMAT_DST_BPP__SHIFT
[PATCH] rnndb: Add register description in mdp5 writeback block
This patch adds the register description in mdp5 writeback block. Signed-off-by: Jilai Wang --- rnndb/mdp/mdp5.xml | 126 ++- rnndb/mdp/mdp_common.xml | 2 +- 2 files changed, 126 insertions(+), 2 deletions(-) diff --git a/rnndb/mdp/mdp5.xml b/rnndb/mdp/mdp5.xml index 29c5992..f1a6397 100644 --- a/rnndb/mdp/mdp5.xml +++ b/rnndb/mdp/mdp5.xml @@ -332,7 +332,7 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ rules-ng.xsd"> - + @@ -454,6 +454,130 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ rules-ng.xsd"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/rnndb/mdp/mdp_common.xml b/rnndb/mdp/mdp_common.xml index 6f805f7..b4d1949 100644 --- a/rnndb/mdp/mdp_common.xml +++ b/rnndb/mdp/mdp_common.xml @@ -13,7 +13,7 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ rules-ng.xsd"> - + -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH] drm/msm: Refactor msm drm driver by introducing msm_drm_sub_dev
Introduce msm_drm_sub_dev for each mdp interface component such as HDMI/eDP/DSI to contain common information shared with MDP. Signed-off-by: Jilai Wang --- drivers/gpu/drm/msm/edp/edp.c | 18 +-- drivers/gpu/drm/msm/edp/edp.h | 1 + drivers/gpu/drm/msm/hdmi/hdmi.c | 22 ++--- drivers/gpu/drm/msm/hdmi/hdmi.h | 1 + drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c | 3 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 56 - drivers/gpu/drm/msm/msm_drv.h | 23 +- 7 files changed, 80 insertions(+), 44 deletions(-) diff --git a/drivers/gpu/drm/msm/edp/edp.c b/drivers/gpu/drm/msm/edp/edp.c index 0940e84..8d8b7e9 100644 --- a/drivers/gpu/drm/msm/edp/edp.c +++ b/drivers/gpu/drm/msm/edp/edp.c @@ -14,6 +14,9 @@ #include #include "edp.h" +static int msm_edp_modeset_init(struct msm_drm_sub_dev *base, + struct drm_device *dev); + static irqreturn_t edp_irq(int irq, void *dev_id) { struct msm_edp *edp = dev_id; @@ -63,6 +66,8 @@ static struct msm_edp *edp_init(struct platform_device *pdev) if (ret) goto fail; + edp->base.modeset_init = msm_edp_modeset_init; + return edp; fail: @@ -82,7 +87,8 @@ static int edp_bind(struct device *dev, struct device *master, void *data) edp = edp_init(to_platform_device(dev)); if (IS_ERR(edp)) return PTR_ERR(edp); - priv->edp = edp; + + priv->edp = >base; return 0; } @@ -144,13 +150,19 @@ void __exit msm_edp_unregister(void) } /* Second part of initialization, the drm/kms level modeset_init */ -int msm_edp_modeset_init(struct msm_edp *edp, struct drm_device *dev, - struct drm_encoder *encoder) +static int msm_edp_modeset_init(struct msm_drm_sub_dev *base, + struct drm_device *dev) { + struct msm_edp *edp = container_of(base, struct msm_edp, base); struct platform_device *pdev = edp->pdev; struct msm_drm_private *priv = dev->dev_private; + struct drm_encoder *encoder; int ret; + if (WARN_ON(base->num_encoders != 1)) + return -EINVAL; + + encoder = base->encoders[0]; edp->encoder = encoder; edp->dev = dev; diff --git a/drivers/gpu/drm/msm/edp/edp.h b/drivers/gpu/drm/msm/edp/edp.h index ba5bedd..00eff68 100644 --- a/drivers/gpu/drm/msm/edp/edp.h +++ b/drivers/gpu/drm/msm/edp/edp.h @@ -31,6 +31,7 @@ struct edp_aux; struct edp_phy; struct msm_edp { + struct msm_drm_sub_dev base; struct drm_device *dev; struct platform_device *pdev; diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c index 9a8a825..9e886ec 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -19,6 +19,9 @@ #include #include "hdmi.h" +static int hdmi_modeset_init(struct msm_drm_sub_dev *base, + struct drm_device *dev); + void hdmi_set_mode(struct hdmi *hdmi, bool power_on) { uint32_t ctrl = 0; @@ -197,6 +200,8 @@ static struct hdmi *hdmi_init(struct platform_device *pdev) goto fail; } + hdmi->base.modeset_init = hdmi_modeset_init; + return hdmi; fail: @@ -214,13 +219,19 @@ fail: * should be handled in hdmi_init() so that failure happens from * hdmi sub-device's probe. */ -int hdmi_modeset_init(struct hdmi *hdmi, - struct drm_device *dev, struct drm_encoder *encoder) +static int hdmi_modeset_init(struct msm_drm_sub_dev *base, + struct drm_device *dev) { + struct hdmi *hdmi = container_of(base, struct hdmi, base); struct msm_drm_private *priv = dev->dev_private; struct platform_device *pdev = hdmi->pdev; + struct drm_encoder *encoder; int ret; + if (WARN_ON(base->num_encoders != 1)) + return -EINVAL; + + encoder = base->encoders[0]; hdmi->dev = dev; hdmi->encoder = encoder; @@ -439,7 +450,8 @@ static int hdmi_bind(struct device *dev, struct device *master, void *data) hdmi = hdmi_init(to_platform_device(dev)); if (IS_ERR(hdmi)) return PTR_ERR(hdmi); - priv->hdmi = hdmi; + + priv->hdmi = >base; return 0; } @@ -449,8 +461,10 @@ static void hdmi_unbind(struct device *dev, struct device *master, { struct drm_device *drm = dev_get_drvdata(master); struct msm_drm_private *priv = drm->dev_private; + if (priv->hdmi) { - hdmi_destroy(priv->hdmi); + struct hdmi *hdmi = container_of(priv->hdmi, struct hdmi, base); + hdmi_destroy(hdmi); priv->hdmi = NULL; } } diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h index 68fdfb3..a1d4595 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.
[PATCH] drm/msm: Refactor msm drm driver to be able to support module
Each HW component's driver such as HDMI/eDP/DSI should be able to compiled as a module which allows user to prevent this part of code to be compiled if not needed. Signed-off-by: Jilai Wang --- drivers/gpu/drm/msm/adreno/adreno_device.c | 13 +-- drivers/gpu/drm/msm/edp/edp.c | 31 + drivers/gpu/drm/msm/edp/edp.h | 1 + drivers/gpu/drm/msm/hdmi/hdmi.c| 35 +++ drivers/gpu/drm/msm/hdmi/hdmi.h| 1 + drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c| 3 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c| 56 +++--- drivers/gpu/drm/msm/msm_drv.c | 6 drivers/gpu/drm/msm/msm_drv.h | 29 drivers/gpu/drm/msm/msm_gpu.h | 2 -- 10 files changed, 110 insertions(+), 67 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c index be83dee..ff7d743 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_device.c +++ b/drivers/gpu/drm/msm/adreno/adreno_device.c @@ -287,12 +287,19 @@ static struct platform_driver adreno_driver = { }, }; -void __init adreno_register(void) +static int __init adreno_register(void) { - platform_driver_register(_driver); + return platform_driver_register(_driver); } -void __exit adreno_unregister(void) +static void __exit adreno_unregister(void) { platform_driver_unregister(_driver); } + +module_init(adreno_register); +module_exit(adreno_unregister); + +MODULE_AUTHOR("Rob Clark #include "edp.h" +static int msm_edp_modeset_init(struct msm_drm_sub_dev *base, + struct drm_device *dev); + static irqreturn_t edp_irq(int irq, void *dev_id) { struct msm_edp *edp = dev_id; @@ -63,6 +66,8 @@ static struct msm_edp *edp_init(struct platform_device *pdev) if (ret) goto fail; + edp->base.modeset_init = msm_edp_modeset_init; + return edp; fail: @@ -82,7 +87,8 @@ static int edp_bind(struct device *dev, struct device *master, void *data) edp = edp_init(to_platform_device(dev)); if (IS_ERR(edp)) return PTR_ERR(edp); - priv->edp = edp; + + priv->edp = >base; return 0; } @@ -131,26 +137,32 @@ static struct platform_driver edp_driver = { }, }; -void __init msm_edp_register(void) +static int __init msm_edp_register(void) { DBG(""); - platform_driver_register(_driver); + return platform_driver_register(_driver); } -void __exit msm_edp_unregister(void) +static void __exit msm_edp_unregister(void) { DBG(""); platform_driver_unregister(_driver); } /* Second part of initialization, the drm/kms level modeset_init */ -int msm_edp_modeset_init(struct msm_edp *edp, struct drm_device *dev, - struct drm_encoder *encoder) +static int msm_edp_modeset_init(struct msm_drm_sub_dev *base, + struct drm_device *dev) { + struct msm_edp *edp = container_of(base, struct msm_edp, base); struct platform_device *pdev = edp->pdev; struct msm_drm_private *priv = dev->dev_private; + struct drm_encoder *encoder; int ret; + if (WARN_ON(base->num_encoders != 1)) + return -EINVAL; + + encoder = base->encoders[0]; edp->encoder = encoder; edp->dev = dev; @@ -206,3 +218,10 @@ fail: return ret; } + +module_init(msm_edp_register); +module_exit(msm_edp_unregister); + +MODULE_AUTHOR("Hai Li #include "hdmi.h" +static int hdmi_modeset_init(struct msm_drm_sub_dev *base, + struct drm_device *dev); + void hdmi_set_mode(struct hdmi *hdmi, bool power_on) { uint32_t ctrl = 0; @@ -197,6 +200,8 @@ static struct hdmi *hdmi_init(struct platform_device *pdev) goto fail; } + hdmi->base.modeset_init = hdmi_modeset_init; + return hdmi; fail: @@ -214,13 +219,19 @@ fail: * should be handled in hdmi_init() so that failure happens from * hdmi sub-device's probe. */ -int hdmi_modeset_init(struct hdmi *hdmi, - struct drm_device *dev, struct drm_encoder *encoder) +static int hdmi_modeset_init(struct msm_drm_sub_dev *base, + struct drm_device *dev) { + struct hdmi *hdmi = container_of(base, struct hdmi, base); struct msm_drm_private *priv = dev->dev_private; struct platform_device *pdev = hdmi->pdev; + struct drm_encoder *encoder; int ret; + if (WARN_ON(base->num_encoders != 1)) + return -EINVAL; + + encoder = base->encoders[0]; hdmi->dev = dev; hdmi->encoder = encoder; @@ -439,7 +450,8 @@ static int hdmi_bind(struct device *dev, struct device *master, void *data) hdmi = hdmi_init(to_platform_device(dev)); if (IS_ERR(hdmi))
[PATCH] drm/msm/mdp: full mode set if crtc enable state is changed
Crtc state may not reflect the current crtc state if drm_fb_helper_blank is called to turn dpms off without turning crtc off. A full modeset in this case to solve the problem. Signed-off-by: Jilai Wang --- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c index eea209e..60d0f58 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c @@ -310,6 +310,13 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc, return -EINVAL; } + /* +* check if the crtc state matches with the current state +* if not match, force a full mode set +*/ + if (state->enable != mdp5_crtc->enabled) + state->mode_changed = true; + /* verify that there are not too many planes attached to crtc * and that we don't have conflicting mixer stages: */ -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH 2/2] drm/msm/hdmi: add hdmi hdcp support (V2)
Add HDMI HDCP support including HDCP PartI/II/III authentication. V1: Initial Change V2: Address Bjorn's comments Refactor the authentication process to use single work instead of multiple work for different authentication stages. Signed-off-by: Jilai Wang --- drivers/gpu/drm/msm/Makefile |1 + drivers/gpu/drm/msm/hdmi/hdmi.c | 45 +- drivers/gpu/drm/msm/hdmi/hdmi.h | 31 + drivers/gpu/drm/msm/hdmi/hdmi_audio.c |1 - drivers/gpu/drm/msm/hdmi/hdmi_bridge.c|8 +- drivers/gpu/drm/msm/hdmi/hdmi_connector.c |7 +- drivers/gpu/drm/msm/hdmi/hdmi_hdcp.c | 1445 + 7 files changed, 1530 insertions(+), 8 deletions(-) create mode 100644 drivers/gpu/drm/msm/hdmi/hdmi_hdcp.c diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index e5464a0..2b32d4d 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -12,6 +12,7 @@ msm-y := \ hdmi/hdmi_audio.o \ hdmi/hdmi_bridge.o \ hdmi/hdmi_connector.o \ + hdmi/hdmi_hdcp.o \ hdmi/hdmi_i2c.o \ hdmi/hdmi_phy_8960.o \ hdmi/hdmi_phy_8x60.o \ diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c index b2e610e..7713155 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -22,7 +22,9 @@ void hdmi_set_mode(struct hdmi *hdmi, bool power_on) { uint32_t ctrl = 0; + unsigned long flags; + spin_lock_irqsave(>reg_lock, flags); if (power_on) { ctrl |= HDMI_CTRL_ENABLE; if (!hdmi->hdmi_mode) { @@ -37,6 +39,7 @@ void hdmi_set_mode(struct hdmi *hdmi, bool power_on) } hdmi_write(hdmi, REG_HDMI_CTRL, ctrl); + spin_unlock_irqrestore(>reg_lock, flags); DBG("HDMI Core: %s, HDMI_CTRL=0x%08x", power_on ? "Enable" : "Disable", ctrl); } @@ -51,6 +54,10 @@ static irqreturn_t hdmi_irq(int irq, void *dev_id) /* Process DDC: */ hdmi_i2c_irq(hdmi->i2c); + /* Process HDCP: */ + if (hdmi->hdcp_ctrl) + hdmi_hdcp_irq(hdmi->hdcp_ctrl); + /* TODO audio.. */ return IRQ_HANDLED; @@ -60,6 +67,15 @@ static void hdmi_destroy(struct hdmi *hdmi) { struct hdmi_phy *phy = hdmi->phy; + /* +* at this point, hpd has been disabled, +* after flush workq, it's safe to deinit hdcp +*/ + if (hdmi->workq) { + flush_workqueue(hdmi->workq); + destroy_workqueue(hdmi->workq); + } + hdmi_hdcp_destroy(hdmi); if (phy) phy->funcs->destroy(phy); @@ -82,6 +98,7 @@ static struct hdmi *hdmi_init(struct platform_device *pdev) { struct hdmi_platform_config *config = pdev->dev.platform_data; struct hdmi *hdmi = NULL; + struct resource *res; int i, ret; hdmi = devm_kzalloc(>dev, sizeof(*hdmi), GFP_KERNEL); @@ -92,6 +109,7 @@ static struct hdmi *hdmi_init(struct platform_device *pdev) hdmi->pdev = pdev; hdmi->config = config; + spin_lock_init(>reg_lock); /* not sure about which phy maps to which msm.. probably I miss some */ if (config->phy_init) @@ -112,6 +130,18 @@ static struct hdmi *hdmi_init(struct platform_device *pdev) goto fail; } + /* HDCP needs physical address of hdmi register */ + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + config->mmio_name); + hdmi->mmio_phy_addr = res->start; + + hdmi->qfprom_mmio = msm_ioremap(pdev, + config->qfprom_mmio_name, "HDMI_QFPROM"); + if (IS_ERR(hdmi->qfprom_mmio)) { + dev_info(>dev, "can't find qfprom resource\n"); + hdmi->qfprom_mmio = NULL; + } + hdmi->hpd_regs = devm_kzalloc(>dev, sizeof(hdmi->hpd_regs[0]) * config->hpd_reg_cnt, GFP_KERNEL); if (!hdmi->hpd_regs) { @@ -194,6 +224,8 @@ static struct hdmi *hdmi_init(struct platform_device *pdev) hdmi->pwr_clks[i] = clk; } + hdmi->workq = alloc_ordered_workqueue("msm_hdmi", 0); + hdmi->i2c = hdmi_i2c_init(hdmi); if (IS_ERR(hdmi->i2c)) { ret = PTR_ERR(hdmi->i2c); @@ -202,6 +234,12 @@ static struct hdmi *hdmi_init(struct platform_device *pdev) goto fail; } + hdmi->hdcp_ctrl = hdmi_hdcp_init(hdmi); + if (IS_ERR(hdmi->hdcp_ctrl)) { + dev_warn(>dev, "failed to init hdcp: disabled\n"); + hdmi->hdcp_ctrl = NULL; + } + return hdmi; fail: @@ -384,6 +422,7 @@ static int hdmi_bind(struct device *dev, struct device *master, void *data)
[PATCH 1/2] drm/msm/hdmi: add register description for HDMI HDCP support (V2)
Add HDCP related register description. V1: Initial Change V2: Add register bit description. Signed-off-by: Jiali Wang --- drivers/gpu/drm/msm/hdmi/hdmi.xml.h | 42 +++-- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.xml.h b/drivers/gpu/drm/msm/hdmi/hdmi.xml.h index 2d1272e..e7b455b 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.xml.h +++ b/drivers/gpu/drm/msm/hdmi/hdmi.xml.h @@ -8,17 +8,8 @@ http://github.com/freedreno/envytools/ git clone https://github.com/freedreno/envytools.git The rules-ng-ng source files this header was generated from are: -- /home/robclark/src/freedreno/envytools/rnndb/msm.xml ( 676 bytes, from 2014-12-05 15:34:49) -- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27) -- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml( 20908 bytes, from 2014-12-08 16:13:00) -- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2357 bytes, from 2014-12-08 16:13:00) -- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml( 26005 bytes, from 2014-12-08 16:13:00) -- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 11712 bytes, from 2013-08-17 17:13:43) -- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml( 344 bytes, from 2013-08-11 19:26:32) -- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2014-10-31 16:48:57) -- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2013-07-05 19:21:12) -- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 25125 bytes, from 2014-12-02 15:04:52) -- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml ( 8253 bytes, from 2014-12-08 16:13:00) +- /local/mnt2/workspace2/jilaiw/chromeos/envytools/envytools/rnndb/hdmi/hdmi.xml ( 26848 bytes, from 2014-12-11 18:18:13) +- /local/mnt2/workspace2/jilaiw/chromeos/envytools/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2014-11-24 22:27:21) Copyright (C) 2013-2014 by the following authors: - Rob Clark (robclark) @@ -203,12 +194,28 @@ static inline uint32_t HDMI_AUDIO_INFO1_LSV(uint32_t val) #define HDMI_HDCP_CTRL_ENCRYPTION_ENABLE 0x0100 #define REG_HDMI_HDCP_DEBUG_CTRL 0x0114 +#define HDMI_HDCP_DEBUG_CTRL_RNG_CIPHER 0x0004 #define REG_HDMI_HDCP_INT_CTRL 0x0118 +#define HDMI_HDCP_INT_CTRL_AUTH_SUCCESS_INT0x0001 +#define HDMI_HDCP_INT_CTRL_AUTH_SUCCESS_ACK0x0002 +#define HDMI_HDCP_INT_CTRL_AUTH_SUCCESS_MASK 0x0004 +#define HDMI_HDCP_INT_CTRL_AUTH_FAIL_INT 0x0010 +#define HDMI_HDCP_INT_CTRL_AUTH_FAIL_ACK 0x0020 +#define HDMI_HDCP_INT_CTRL_AUTH_FAIL_MASK 0x0040 +#define HDMI_HDCP_INT_CTRL_AUTH_FAIL_INFO_ACK 0x0080 +#define HDMI_HDCP_INT_CTRL_AUTH_XFER_REQ_INT 0x0100 +#define HDMI_HDCP_INT_CTRL_AUTH_XFER_REQ_ACK 0x0200 +#define HDMI_HDCP_INT_CTRL_AUTH_XFER_REQ_MASK 0x0400 +#define HDMI_HDCP_INT_CTRL_AUTH_XFER_DONE_INT 0x1000 +#define HDMI_HDCP_INT_CTRL_AUTH_XFER_DONE_ACK 0x2000 +#define HDMI_HDCP_INT_CTRL_AUTH_XFER_DONE_MASK 0x4000 #define REG_HDMI_HDCP_LINK0_STATUS 0x011c #define HDMI_HDCP_LINK0_STATUS_AN_0_READY 0x0100 #define HDMI_HDCP_LINK0_STATUS_AN_1_READY 0x0200 +#define HDMI_HDCP_LINK0_STATUS_RI_MATCHES 0x1000 +#define HDMI_HDCP_LINK0_STATUS_V_MATCHES 0x0010 #define HDMI_HDCP_LINK0_STATUS_KEY_STATE__MASK 0x7000 #define HDMI_HDCP_LINK0_STATUS_KEY_STATE__SHIFT28 static inline uint32_t HDMI_HDCP_LINK0_STATUS_KEY_STATE(enum hdmi_hdcp_key_state val) @@ -217,10 +224,19 @@ static inline uint32_t HDMI_HDCP_LINK0_STATUS_KEY_STATE(enum hdmi_hdcp_key_state } #define REG_HDMI_HDCP_DDC_CTRL_0 0x0120 +#define HDMI_HDCP_DDC_CTRL_0_DISABLE 0x0001 #define REG_HDMI_HDCP_DDC_CTRL_1 0x0124 +#define HDMI_HDCP_DDC_CTRL_1_FAILED_ACK 0x0001 #define REG_HDMI_HDCP_DDC_STATUS 0x0128 +#define HDMI_HDCP_DDC_STATUS_XFER_REQ 0x0010 +#define HDMI_HDCP_DDC_STATUS_XFER_DONE 0x0400 +#define HDMI_HDCP_DDC_STATUS_ABORTED 0x1000 +#define HDMI_HDCP_DDC_STATUS_TIMEOUT
[PATCH] rnndb: Add register fields for msm/hdmi HDCP support (V2)
This patch adds the field description for HDMI HDCP registers. V1: Initial change V2: Add register bit description. Signed-off-by: Jilai Wang --- rnndb/hdmi/hdmi.xml | 87 - 1 file changed, 79 insertions(+), 8 deletions(-) diff --git a/rnndb/hdmi/hdmi.xml b/rnndb/hdmi/hdmi.xml index 64393b4..9ac5e00 100644 --- a/rnndb/hdmi/hdmi.xml +++ b/rnndb/hdmi/hdmi.xml @@ -12,12 +12,14 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ rules-ng.xsd"> - - - - - - + + + + + + + + @@ -168,15 +170,69 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ rules-ng.xsd"> - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -238,7 +294,9 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ rules-ng.xsd"> - + + + @@ -374,6 +442,9 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ rules-ng.xsd"> + + + -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH 2/2] drm/msm/hdmi: add hdmi hdcp support
Add HDMI HDCP support including HDCP PartI/II/III authentication. Signed-off-by: Jilai Wang --- drivers/gpu/drm/msm/Makefile |1 + drivers/gpu/drm/msm/hdmi/hdmi.c | 44 + drivers/gpu/drm/msm/hdmi/hdmi.h | 31 + drivers/gpu/drm/msm/hdmi/hdmi_audio.c |1 - drivers/gpu/drm/msm/hdmi/hdmi_bridge.c|3 +- drivers/gpu/drm/msm/hdmi/hdmi_connector.c |7 +- drivers/gpu/drm/msm/hdmi/hdmi_hdcp.c | 1600 + 7 files changed, 1682 insertions(+), 5 deletions(-) create mode 100644 drivers/gpu/drm/msm/hdmi/hdmi_hdcp.c diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index 6283dcb..9d88ff3 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -11,6 +11,7 @@ msm-y := \ hdmi/hdmi_audio.o \ hdmi/hdmi_bridge.o \ hdmi/hdmi_connector.o \ + hdmi/hdmi_hdcp.o \ hdmi/hdmi_i2c.o \ hdmi/hdmi_phy_8960.o \ hdmi/hdmi_phy_8x60.o \ diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c index 9d00dcb..f0111c0 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -20,7 +20,9 @@ void hdmi_set_mode(struct hdmi *hdmi, bool power_on) { uint32_t ctrl = 0; + unsigned long flags; + spin_lock_irqsave(>reg_lock, flags); if (power_on) { ctrl |= HDMI_CTRL_ENABLE; if (!hdmi->hdmi_mode) { @@ -35,6 +37,7 @@ void hdmi_set_mode(struct hdmi *hdmi, bool power_on) } hdmi_write(hdmi, REG_HDMI_CTRL, ctrl); + spin_unlock_irqrestore(>reg_lock, flags); DBG("HDMI Core: %s, HDMI_CTRL=0x%08x", power_on ? "Enable" : "Disable", ctrl); } @@ -49,6 +52,9 @@ irqreturn_t hdmi_irq(int irq, void *dev_id) /* Process DDC: */ hdmi_i2c_irq(hdmi->i2c); + /* Process HDCP: */ + hdmi_hdcp_irq(hdmi->hdcp_ctrl); + /* TODO audio.. */ return IRQ_HANDLED; @@ -59,6 +65,16 @@ void hdmi_destroy(struct kref *kref) struct hdmi *hdmi = container_of(kref, struct hdmi, refcount); struct hdmi_phy *phy = hdmi->phy; + /* +* at this point, hpd has been disabled, +* after flush workq, it's safe to deinit hdcp +*/ + if (hdmi->workq) { + flush_workqueue(hdmi->workq); + destroy_workqueue(hdmi->workq); + } + hdmi_hdcp_destroy(hdmi); + if (phy) phy->funcs->destroy(phy); @@ -75,6 +91,7 @@ struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder) struct msm_drm_private *priv = dev->dev_private; struct platform_device *pdev = priv->hdmi_pdev; struct hdmi_platform_config *config; + struct resource *res; int i, ret; if (!pdev) { @@ -97,6 +114,7 @@ struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder) hdmi->pdev = pdev; hdmi->config = config; hdmi->encoder = encoder; + spin_lock_init(>reg_lock); hdmi_audio_infoframe_init(>audio.infoframe); @@ -119,6 +137,22 @@ struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder) goto fail; } + /* HDCP needs physical address of hdmi register */ + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + config->mmio_name); + hdmi->mmio_phy_addr = res->start; + + if (config->qfprom_mmio_name) { + hdmi->qfprom_mmio = msm_ioremap(pdev, + config->qfprom_mmio_name, "HDMI_QFPROM"); + if (IS_ERR(hdmi->qfprom_mmio)) { + dev_info(>dev, "can't find qfprom resource\n"); + hdmi->qfprom_mmio = NULL; + } + } else { + hdmi->qfprom_mmio = NULL; + } + BUG_ON(config->hpd_reg_cnt > ARRAY_SIZE(hdmi->hpd_regs)); for (i = 0; i < config->hpd_reg_cnt; i++) { struct regulator *reg; @@ -181,6 +215,8 @@ struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder) hdmi->pwr_clks[i] = clk; } + hdmi->workq = alloc_ordered_workqueue("msm_hdmi", 0); + hdmi->i2c = hdmi_i2c_init(hdmi); if (IS_ERR(hdmi->i2c)) { ret = PTR_ERR(hdmi->i2c); @@ -205,6 +241,13 @@ struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder) goto fail; } + hdmi->hdcp_ctrl = hdmi_hdcp_init(hdmi); + if (IS_ERR(hdmi->hdcp_ctrl)) { + ret = PTR_ERR(hdmi->hdcp_ctrl); + dev_warn(dev->dev, "failed to init hdcp: %d(disabled)\n", ret); + hdmi->hdcp_ctrl = NULL; + } +
[PATCH 1/2] drm/msm/hdmi: add register description for HDMI HDCP support
Add HDCP related register description. Signed-off-by: Jiali Wang --- drivers/gpu/drm/msm/hdmi/hdmi.xml.h | 76 + 1 file changed, 60 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.xml.h b/drivers/gpu/drm/msm/hdmi/hdmi.xml.h index 76fd0cf..6dd6168 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.xml.h +++ b/drivers/gpu/drm/msm/hdmi/hdmi.xml.h @@ -8,16 +8,8 @@ http://github.com/freedreno/envytools/ git clone https://github.com/freedreno/envytools.git The rules-ng-ng source files this header was generated from are: -- /home/robclark/src/freedreno/envytools/rnndb/msm.xml ( 647 bytes, from 2013-11-30 14:45:35) -- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27) -- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml( 20457 bytes, from 2014-08-01 12:22:48) -- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 1615 bytes, from 2014-07-17 15:34:33) -- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml( 22517 bytes, from 2014-07-17 15:34:33) -- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 11712 bytes, from 2013-08-17 17:13:43) -- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml( 344 bytes, from 2013-08-11 19:26:32) -- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2014-08-01 12:23:53) -- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2013-07-05 19:21:12) -- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 23613 bytes, from 2014-07-17 15:33:30) +- /local/mnt2/workspace2/jilaiw/chromeos/envytools/envytools/rnndb/hdmi/hdmi.xml ( 25125 bytes, from 2014-11-24 23:30:39) +- /local/mnt2/workspace2/jilaiw/chromeos/envytools/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2014-11-24 22:27:21) Copyright (C) 2013-2014 by the following authors: - Rob Clark (robclark) @@ -45,12 +37,14 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. enum hdmi_hdcp_key_state { - NO_KEYS = 0, - NOT_CHECKED = 1, - CHECKING = 2, - KEYS_VALID = 3, - AKSV_INVALID = 4, - CHECKSUM_MISMATCH = 5, + HDCP_KEYS_STATE_NO_KEYS = 0, + HDCP_KEYS_STATE_NOT_CHECKED = 1, + HDCP_KEYS_STATE_CHECKING = 2, + HDCP_KEYS_STATE_VALID = 3, + HDCP_KEYS_STATE_AKSV_NOT_VALID = 4, + HDCP_KEYS_STATE_CHKSUM_MISMATCH = 5, + HDCP_KEYS_STATE_PROD_AKSV = 6, + HDCP_KEYS_STATE_RESERVED = 7, }; enum hdmi_ddc_read_write { @@ -199,6 +193,8 @@ static inline uint32_t HDMI_AUDIO_INFO1_LSV(uint32_t val) #define HDMI_HDCP_CTRL_ENABLE 0x0001 #define HDMI_HDCP_CTRL_ENCRYPTION_ENABLE 0x0100 +#define REG_HDMI_HDCP_DEBUG_CTRL 0x0114 + #define REG_HDMI_HDCP_INT_CTRL 0x0118 #define REG_HDMI_HDCP_LINK0_STATUS 0x011c @@ -211,9 +207,47 @@ static inline uint32_t HDMI_HDCP_LINK0_STATUS_KEY_STATE(enum hdmi_hdcp_key_state return ((val) << HDMI_HDCP_LINK0_STATUS_KEY_STATE__SHIFT) & HDMI_HDCP_LINK0_STATUS_KEY_STATE__MASK; } +#define REG_HDMI_HDCP_DDC_CTRL_0 0x0120 + +#define REG_HDMI_HDCP_DDC_CTRL_1 0x0124 + +#define REG_HDMI_HDCP_DDC_STATUS 0x0128 + +#define REG_HDMI_HDCP_ENTROPY_CTRL00x012c + +#define REG_HDMI_HDCP_ENTROPY_CTRL10x025c + #define REG_HDMI_HDCP_RESET0x0130 #define HDMI_HDCP_RESET_LINK0_DEAUTHENTICATE 0x0001 +#define REG_HDMI_HDCP_RCVPORT_DATA00x0134 + +#define REG_HDMI_HDCP_RCVPORT_DATA10x0138 + +#define REG_HDMI_HDCP_RCVPORT_DATA2_0 0x013c + +#define REG_HDMI_HDCP_RCVPORT_DATA2_1 0x0140 + +#define REG_HDMI_HDCP_RCVPORT_DATA30x0144 + +#define REG_HDMI_HDCP_RCVPORT_DATA40x0148 + +#define REG_HDMI_HDCP_RCVPORT_DATA50x014c + +#define REG_HDMI_HDCP_RCVPORT_DATA60x0150 + +#define REG_HDMI_HDCP_RCVPORT_DATA70x0154 + +#define REG_HDMI_HDCP_RCVPORT_DATA80x0158 + +#define REG_HDMI_HDCP_RCVPORT_DATA90x015c + +#define REG_HDMI_HDCP_RCVPORT_DATA10 0x0160 + +#define REG_HDMI_HDCP_RCVPORT_DATA11 0x0164 + +#define REG_HDMI_HDCP_RCVPORT_DATA12 0x0168 + #define
[PATCH] rnndb: Add register fields for msm/hdmi HDCP support
This patch adds the field description for HDMI HDCP registers. Signed-off-by: Jilai Wang --- rnndb/hdmi/hdmi.xml | 46 -- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/rnndb/hdmi/hdmi.xml b/rnndb/hdmi/hdmi.xml index 64393b4..c67e6c1 100644 --- a/rnndb/hdmi/hdmi.xml +++ b/rnndb/hdmi/hdmi.xml @@ -12,12 +12,14 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ rules-ng.xsd"> - - - - - - + + + + + + + + @@ -168,15 +170,39 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ rules-ng.xsd"> + + + + + + + + + + + + + + + + + + + + + + + + @@ -319,6 +345,11 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ rules-ng.xsd"> + + + + + @@ -374,6 +405,9 @@ xsi:schemaLocation="http://nouveau.freedesktop.org/ rules-ng.xsd"> + + + -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH 4/4] drm/msm/hdmi: don't call clk_round_rate to check hdmi pclk for MDP5
clock driver can support dynamic rate settings for HDMI pixelclock, so don't need to use clk_round_rate to check if the clockrate for specific mode is supported therefore more display modes can be supported. Signed-off-by: Jilai Wang --- drivers/gpu/drm/msm/hdmi/hdmi_connector.c | 9 - 1 file changed, 9 deletions(-) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c index c458348..cf18896 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c @@ -355,8 +355,6 @@ static int hdmi_connector_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector); - struct hdmi *hdmi = hdmi_connector->hdmi; - const struct hdmi_platform_config *config = hdmi->config; struct msm_drm_private *priv = connector->dev->dev_private; struct msm_kms *kms = priv->kms; long actual, requested; @@ -365,13 +363,6 @@ static int hdmi_connector_mode_valid(struct drm_connector *connector, actual = kms->funcs->round_pixclk(kms, requested, hdmi_connector->hdmi->encoder); - /* for mdp5/apq8074, we manage our own pixel clk (as opposed to -* mdp4/dtv stuff where pixel clk is assigned to mdp/encoder -* instead): -*/ - if (config->pwr_clk_cnt > 0) - actual = clk_round_rate(hdmi->pwr_clks[0], actual); - DBG("requested=%ld, actual=%ld", requested, actual); if (actual != requested) -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH 3/4] drm/msm/hdmi: rework HDMI IRQ hanlder
Disable the HPD interrupt when acking it, to avoid spurious interrupt. Signed-off-by: Jilai Wang --- drivers/gpu/drm/msm/hdmi/hdmi_connector.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c index caa1301..c458348 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c @@ -251,11 +251,11 @@ void hdmi_connector_irq(struct drm_connector *connector) (hpd_int_status & HDMI_HPD_INT_STATUS_INT)) { bool detected = !!(hpd_int_status & HDMI_HPD_INT_STATUS_CABLE_DETECTED); - DBG("status=%04x, ctrl=%04x", hpd_int_status, hpd_int_ctrl); - - /* ack the irq: */ + /* ack & disable (temporarily) HPD events: */ hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, - hpd_int_ctrl | HDMI_HPD_INT_CTRL_INT_ACK); + HDMI_HPD_INT_CTRL_INT_ACK); + + DBG("status=%04x, ctrl=%04x", hpd_int_status, hpd_int_ctrl); /* detect disconnect if we are connected or visa versa: */ hpd_int_ctrl = HDMI_HPD_INT_CTRL_INT_EN; -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH 2/4] drm/msm/hdmi: enable regulators before clocks to avoid warnings
HPD regulators need to be enabled before clocks, otherwise clock driver will report warning. Signed-off-by: Jilai Wang --- drivers/gpu/drm/msm/hdmi/hdmi_connector.c | 45 +-- 1 file changed, 18 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c index 92fddd8..caa1301 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c @@ -141,6 +141,15 @@ static int hpd_enable(struct hdmi_connector *hdmi_connector) uint32_t hpd_ctrl; int i, ret; + for (i = 0; i < config->hpd_reg_cnt; i++) { + ret = regulator_enable(hdmi->hpd_regs[i]); + if (ret) { + dev_err(dev->dev, "failed to enable hpd regulator: %s (%d)\n", + config->hpd_reg_names[i], ret); + goto fail; + } + } + ret = gpio_config(hdmi, true); if (ret) { dev_err(dev->dev, "failed to configure GPIOs: %d\n", ret); @@ -164,15 +173,6 @@ static int hpd_enable(struct hdmi_connector *hdmi_connector) } } - for (i = 0; i < config->hpd_reg_cnt; i++) { - ret = regulator_enable(hdmi->hpd_regs[i]); - if (ret) { - dev_err(dev->dev, "failed to enable hpd regulator: %s (%d)\n", - config->hpd_reg_names[i], ret); - goto fail; - } - } - hdmi_set_mode(hdmi, false); phy->funcs->reset(phy); hdmi_set_mode(hdmi, true); @@ -200,7 +200,7 @@ fail: return ret; } -static int hdp_disable(struct hdmi_connector *hdmi_connector) +static void hdp_disable(struct hdmi_connector *hdmi_connector) { struct hdmi *hdmi = hdmi_connector->hdmi; const struct hdmi_platform_config *config = hdmi->config; @@ -212,28 +212,19 @@ static int hdp_disable(struct hdmi_connector *hdmi_connector) hdmi_set_mode(hdmi, false); - for (i = 0; i < config->hpd_reg_cnt; i++) { - ret = regulator_disable(hdmi->hpd_regs[i]); - if (ret) { - dev_err(dev->dev, "failed to disable hpd regulator: %s (%d)\n", - config->hpd_reg_names[i], ret); - goto fail; - } - } - for (i = 0; i < config->hpd_clk_cnt; i++) clk_disable_unprepare(hdmi->hpd_clks[i]); ret = gpio_config(hdmi, false); - if (ret) { - dev_err(dev->dev, "failed to unconfigure GPIOs: %d\n", ret); - goto fail; - } - - return 0; + if (ret) + dev_warn(dev->dev, "failed to unconfigure GPIOs: %d\n", ret); -fail: - return ret; + for (i = 0; i < config->hpd_reg_cnt; i++) { + ret = regulator_disable(hdmi->hpd_regs[i]); + if (ret) + dev_warn(dev->dev, "failed to disable hpd regulator: %s (%d)\n", + config->hpd_reg_names[i], ret); + } } static void -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH 1/4] drm/msm/hdmi: use HPD interrupt to track connector status change
HPD interrupt can be tracked for each connector, so don't need to poll the connector status for state change. Signed-off-by: Jilai Wang --- drivers/gpu/drm/msm/hdmi/hdmi_connector.c | 5 + 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c index 4aca2a3..92fddd8 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c @@ -242,7 +242,7 @@ hotplug_work(struct work_struct *work) struct hdmi_connector *hdmi_connector = container_of(work, struct hdmi_connector, hpd_work); struct drm_connector *connector = _connector->base; - drm_helper_hpd_irq_event(connector->dev); + drm_kms_helper_hotplug_event(connector->dev); } void hdmi_connector_irq(struct drm_connector *connector) @@ -431,9 +431,6 @@ struct drm_connector *hdmi_connector_init(struct hdmi *hdmi) DRM_MODE_CONNECTOR_HDMIA); drm_connector_helper_add(connector, _connector_helper_funcs); - connector->polled = DRM_CONNECTOR_POLL_CONNECT | - DRM_CONNECTOR_POLL_DISCONNECT; - connector->interlace_allowed = 1; connector->doublescan_allowed = 0; -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH 4/4] drm/msm/hdmi: don't call clk_round_rate to check hdmi pclk for MDP5
clock driver can support dynamic rate settings for HDMI pixelclock, so don't need to use clk_round_rate to check if the clockrate for specific mode is supported therefore more display modes can be supported. Change-Id: I308df4eb604438c24df463619571d8e18cc956b6 Signed-off-by: Jilai Wang --- drivers/gpu/drm/msm/hdmi/hdmi_connector.c | 9 - 1 file changed, 9 deletions(-) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c index c458348..cf18896 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c @@ -355,8 +355,6 @@ static int hdmi_connector_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector); - struct hdmi *hdmi = hdmi_connector->hdmi; - const struct hdmi_platform_config *config = hdmi->config; struct msm_drm_private *priv = connector->dev->dev_private; struct msm_kms *kms = priv->kms; long actual, requested; @@ -365,13 +363,6 @@ static int hdmi_connector_mode_valid(struct drm_connector *connector, actual = kms->funcs->round_pixclk(kms, requested, hdmi_connector->hdmi->encoder); - /* for mdp5/apq8074, we manage our own pixel clk (as opposed to -* mdp4/dtv stuff where pixel clk is assigned to mdp/encoder -* instead): -*/ - if (config->pwr_clk_cnt > 0) - actual = clk_round_rate(hdmi->pwr_clks[0], actual); - DBG("requested=%ld, actual=%ld", requested, actual); if (actual != requested) -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH 3/4] drm/msm/hdmi: rework HDMI IRQ hanlder
Disable the HPD interrupt when acking it, to avoid spurious interrupt. Change-Id: Icb64d7fa813380c7ffa3047058503ebab13ff4c4 Signed-off-by: Jilai Wang --- drivers/gpu/drm/msm/hdmi/hdmi_connector.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c index caa1301..c458348 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c @@ -251,11 +251,11 @@ void hdmi_connector_irq(struct drm_connector *connector) (hpd_int_status & HDMI_HPD_INT_STATUS_INT)) { bool detected = !!(hpd_int_status & HDMI_HPD_INT_STATUS_CABLE_DETECTED); - DBG("status=%04x, ctrl=%04x", hpd_int_status, hpd_int_ctrl); - - /* ack the irq: */ + /* ack & disable (temporarily) HPD events: */ hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, - hpd_int_ctrl | HDMI_HPD_INT_CTRL_INT_ACK); + HDMI_HPD_INT_CTRL_INT_ACK); + + DBG("status=%04x, ctrl=%04x", hpd_int_status, hpd_int_ctrl); /* detect disconnect if we are connected or visa versa: */ hpd_int_ctrl = HDMI_HPD_INT_CTRL_INT_EN; -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH 2/4] drm/msm/hdmi: enable regulators before clocks to avoid warnings
HPD regulators need to be enabled before clocks, otherwise clock driver will report warning. Change-Id: Ieca41722ae3b15873e6290649a21bbd13e1a4278 Signed-off-by: Jilai Wang --- drivers/gpu/drm/msm/hdmi/hdmi_connector.c | 45 +-- 1 file changed, 18 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c index 92fddd8..caa1301 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c @@ -141,6 +141,15 @@ static int hpd_enable(struct hdmi_connector *hdmi_connector) uint32_t hpd_ctrl; int i, ret; + for (i = 0; i < config->hpd_reg_cnt; i++) { + ret = regulator_enable(hdmi->hpd_regs[i]); + if (ret) { + dev_err(dev->dev, "failed to enable hpd regulator: %s (%d)\n", + config->hpd_reg_names[i], ret); + goto fail; + } + } + ret = gpio_config(hdmi, true); if (ret) { dev_err(dev->dev, "failed to configure GPIOs: %d\n", ret); @@ -164,15 +173,6 @@ static int hpd_enable(struct hdmi_connector *hdmi_connector) } } - for (i = 0; i < config->hpd_reg_cnt; i++) { - ret = regulator_enable(hdmi->hpd_regs[i]); - if (ret) { - dev_err(dev->dev, "failed to enable hpd regulator: %s (%d)\n", - config->hpd_reg_names[i], ret); - goto fail; - } - } - hdmi_set_mode(hdmi, false); phy->funcs->reset(phy); hdmi_set_mode(hdmi, true); @@ -200,7 +200,7 @@ fail: return ret; } -static int hdp_disable(struct hdmi_connector *hdmi_connector) +static void hdp_disable(struct hdmi_connector *hdmi_connector) { struct hdmi *hdmi = hdmi_connector->hdmi; const struct hdmi_platform_config *config = hdmi->config; @@ -212,28 +212,19 @@ static int hdp_disable(struct hdmi_connector *hdmi_connector) hdmi_set_mode(hdmi, false); - for (i = 0; i < config->hpd_reg_cnt; i++) { - ret = regulator_disable(hdmi->hpd_regs[i]); - if (ret) { - dev_err(dev->dev, "failed to disable hpd regulator: %s (%d)\n", - config->hpd_reg_names[i], ret); - goto fail; - } - } - for (i = 0; i < config->hpd_clk_cnt; i++) clk_disable_unprepare(hdmi->hpd_clks[i]); ret = gpio_config(hdmi, false); - if (ret) { - dev_err(dev->dev, "failed to unconfigure GPIOs: %d\n", ret); - goto fail; - } - - return 0; + if (ret) + dev_warn(dev->dev, "failed to unconfigure GPIOs: %d\n", ret); -fail: - return ret; + for (i = 0; i < config->hpd_reg_cnt; i++) { + ret = regulator_disable(hdmi->hpd_regs[i]); + if (ret) + dev_warn(dev->dev, "failed to disable hpd regulator: %s (%d)\n", + config->hpd_reg_names[i], ret); + } } static void -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH 1/4] drm/msm/hdmi: use HPD interrupt to track connector status change
HPD interrupt can be tracked for each connector, so don't need to poll the connector status for state change. Change-Id: I2c062838af5922d32ce87a50676a45dcaedb44f2 Signed-off-by: Jilai Wang --- drivers/gpu/drm/msm/hdmi/hdmi_connector.c | 5 + 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c index 4aca2a3..92fddd8 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c @@ -242,7 +242,7 @@ hotplug_work(struct work_struct *work) struct hdmi_connector *hdmi_connector = container_of(work, struct hdmi_connector, hpd_work); struct drm_connector *connector = _connector->base; - drm_helper_hpd_irq_event(connector->dev); + drm_kms_helper_hotplug_event(connector->dev); } void hdmi_connector_irq(struct drm_connector *connector) @@ -431,9 +431,6 @@ struct drm_connector *hdmi_connector_init(struct hdmi *hdmi) DRM_MODE_CONNECTOR_HDMIA); drm_connector_helper_add(connector, _connector_helper_funcs); - connector->polled = DRM_CONNECTOR_POLL_CONNECT | - DRM_CONNECTOR_POLL_DISCONNECT; - connector->interlace_allowed = 1; connector->doublescan_allowed = 0; -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project