Skip to content

Commit

Permalink
Merge branch 'msm-next' of git://people.freedesktop.org/~robclark/lin…
Browse files Browse the repository at this point in the history
…ux into drm-next

Now that we have the bits needed for mdp5 atomic, here is the followup
pull request I mentioned.  Main highlights are:

1) mdp5 multiple crtc and public plane support (no more hard-coded mixer setup!)
2) mdp5 atomic conversion
3) couple atomic helper fixes for issues found during mdp5 atomic
debug (reviewed by danvet.. but he didn't plane to send an
atomic-fixes pull request so I agreed to tack them on to mine)

* 'msm-next' of git://people.freedesktop.org/~robclark/linux:
  drm/atomic: shutdown *current* encoder
  drm/atomic: check mode_changed *after* atomic_check
  drm/msm/mdp4: fix mixer setup for multi-crtc + planes
  drm/msm/mdp5: dpms(OFF) cleanups
  drm/msm/mdp5: atomic
  drm/msm: atomic fixes
  drm/msm/mdp5: remove global mdp5_ctl_mgr
  drm/msm/mdp5: don't use void * for opaque types
  drm/msm: add multiple CRTC and overlay support
  drm/msm/mdp5: set rate before enabling clk
  drm/msm/mdp5: introduce mdp5_cfg module
  drm/msm/mdp5: make SMP module dynamically configurable
  drm/msm/hdmi: remove useless kref
  drm/msm/mdp5: get the core clock rate from MDP5 config
  drm/msm/mdp5: use irqdomains
  • Loading branch information
Dave Airlie committed Nov 25, 2014
2 parents ed1e877 + 46df9ad commit 955289c
Show file tree
Hide file tree
Showing 24 changed files with 1,737 additions and 739 deletions.
17 changes: 10 additions & 7 deletions drivers/gpu/drm/drm_atomic_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ mode_fixup(struct drm_atomic_state *state)
}

static int
drm_atomic_helper_check_prepare(struct drm_device *dev,
drm_atomic_helper_check_modeset(struct drm_device *dev,
struct drm_atomic_state *state)
{
int ncrtcs = dev->mode_config.num_crtc;
Expand Down Expand Up @@ -428,10 +428,6 @@ int drm_atomic_helper_check(struct drm_device *dev,
int ncrtcs = dev->mode_config.num_crtc;
int i, ret = 0;

ret = drm_atomic_helper_check_prepare(dev, state);
if (ret)
return ret;

for (i = 0; i < nplanes; i++) {
struct drm_plane_helper_funcs *funcs;
struct drm_plane *plane = state->planes[i];
Expand Down Expand Up @@ -475,6 +471,10 @@ int drm_atomic_helper_check(struct drm_device *dev,
}
}

ret = drm_atomic_helper_check_modeset(dev, state);
if (ret)
return ret;

return ret;
}
EXPORT_SYMBOL(drm_atomic_helper_check);
Expand All @@ -499,9 +499,12 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
if (!old_conn_state || !old_conn_state->crtc)
continue;

encoder = connector->state->best_encoder;
encoder = old_conn_state->best_encoder;

if (!encoder)
/* We shouldn't get this far if we didn't previously have
* an encoder.. but WARN_ON() rather than explode.
*/
if (WARN_ON(!encoder))
continue;

funcs = encoder->helper_private;
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/msm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ msm-y := \
mdp/mdp4/mdp4_irq.o \
mdp/mdp4/mdp4_kms.o \
mdp/mdp4/mdp4_plane.o \
mdp/mdp5/mdp5_cfg.o \
mdp/mdp5/mdp5_ctl.o \
mdp/mdp5/mdp5_crtc.o \
mdp/mdp5/mdp5_encoder.o \
mdp/mdp5/mdp5_irq.o \
Expand Down
57 changes: 26 additions & 31 deletions drivers/gpu/drm/msm/hdmi/hdmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include <linux/of_irq.h>
#include "hdmi.h"

void hdmi_set_mode(struct hdmi *hdmi, bool power_on)
Expand All @@ -39,7 +40,7 @@ void hdmi_set_mode(struct hdmi *hdmi, bool power_on)
power_on ? "Enable" : "Disable", ctrl);
}

irqreturn_t hdmi_irq(int irq, void *dev_id)
static irqreturn_t hdmi_irq(int irq, void *dev_id)
{
struct hdmi *hdmi = dev_id;

Expand All @@ -54,9 +55,8 @@ irqreturn_t hdmi_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}

void hdmi_destroy(struct kref *kref)
static void hdmi_destroy(struct hdmi *hdmi)
{
struct hdmi *hdmi = container_of(kref, struct hdmi, refcount);
struct hdmi_phy *phy = hdmi->phy;

if (phy)
Expand Down Expand Up @@ -84,8 +84,6 @@ static struct hdmi *hdmi_init(struct platform_device *pdev)
goto fail;
}

kref_init(&hdmi->refcount);

hdmi->pdev = pdev;
hdmi->config = config;

Expand Down Expand Up @@ -182,7 +180,7 @@ static struct hdmi *hdmi_init(struct platform_device *pdev)

fail:
if (hdmi)
hdmi_destroy(&hdmi->refcount);
hdmi_destroy(hdmi);

return ERR_PTR(ret);
}
Expand All @@ -200,7 +198,6 @@ int hdmi_modeset_init(struct hdmi *hdmi,
{
struct msm_drm_private *priv = dev->dev_private;
struct platform_device *pdev = hdmi->pdev;
struct hdmi_platform_config *config = pdev->dev.platform_data;
int ret;

hdmi->dev = dev;
Expand All @@ -224,22 +221,20 @@ int hdmi_modeset_init(struct hdmi *hdmi,
goto fail;
}

if (!config->shared_irq) {
hdmi->irq = platform_get_irq(pdev, 0);
if (hdmi->irq < 0) {
ret = hdmi->irq;
dev_err(dev->dev, "failed to get irq: %d\n", ret);
goto fail;
}
hdmi->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
if (hdmi->irq < 0) {
ret = hdmi->irq;
dev_err(dev->dev, "failed to get irq: %d\n", ret);
goto fail;
}

ret = devm_request_threaded_irq(&pdev->dev, hdmi->irq,
NULL, hdmi_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
"hdmi_isr", hdmi);
if (ret < 0) {
dev_err(dev->dev, "failed to request IRQ%u: %d\n",
hdmi->irq, ret);
goto fail;
}
ret = devm_request_irq(&pdev->dev, hdmi->irq,
hdmi_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
"hdmi_isr", hdmi);
if (ret < 0) {
dev_err(dev->dev, "failed to request IRQ%u: %d\n",
hdmi->irq, ret);
goto fail;
}

encoder->bridge = hdmi->bridge;
Expand Down Expand Up @@ -271,12 +266,6 @@ int hdmi_modeset_init(struct hdmi *hdmi,

#include <linux/of_gpio.h>

static void set_hdmi(struct drm_device *dev, struct hdmi *hdmi)
{
struct msm_drm_private *priv = dev->dev_private;
priv->hdmi = hdmi;
}

#ifdef CONFIG_OF
static int get_gpio(struct device *dev, struct device_node *of_node, const char *name)
{
Expand All @@ -297,6 +286,8 @@ static int get_gpio(struct device *dev, struct device_node *of_node, const char

static int hdmi_bind(struct device *dev, struct device *master, void *data)
{
struct drm_device *drm = dev_get_drvdata(master);
struct msm_drm_private *priv = drm->dev_private;
static struct hdmi_platform_config config = {};
struct hdmi *hdmi;
#ifdef CONFIG_OF
Expand All @@ -318,7 +309,6 @@ static int hdmi_bind(struct device *dev, struct device *master, void *data)
config.hpd_clk_cnt = ARRAY_SIZE(hpd_clk_names);
config.pwr_clk_names = pwr_clk_names;
config.pwr_clk_cnt = ARRAY_SIZE(pwr_clk_names);
config.shared_irq = true;
} else if (of_device_is_compatible(of_node, "qcom,hdmi-tx-8960")) {
static const char *hpd_clk_names[] = {"core_clk", "master_iface_clk", "slave_iface_clk"};
static const char *hpd_reg_names[] = {"core-vdda", "hdmi-mux"};
Expand Down Expand Up @@ -392,14 +382,19 @@ 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);
set_hdmi(dev_get_drvdata(master), hdmi);
priv->hdmi = hdmi;
return 0;
}

static void hdmi_unbind(struct device *dev, struct device *master,
void *data)
{
set_hdmi(dev_get_drvdata(master), NULL);
struct drm_device *drm = dev_get_drvdata(master);
struct msm_drm_private *priv = drm->dev_private;
if (priv->hdmi) {
hdmi_destroy(priv->hdmi);
priv->hdmi = NULL;
}
}

static const struct component_ops hdmi_ops = {
Expand Down
17 changes: 0 additions & 17 deletions drivers/gpu/drm/msm/hdmi/hdmi.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ struct hdmi_audio {
};

struct hdmi {
struct kref refcount;

struct drm_device *dev;
struct platform_device *pdev;

Expand Down Expand Up @@ -97,13 +95,9 @@ struct hdmi_platform_config {
/* gpio's: */
int ddc_clk_gpio, ddc_data_gpio, hpd_gpio, mux_en_gpio, mux_sel_gpio;
int mux_lpm_gpio;

/* older devices had their own irq, mdp5+ it is shared w/ mdp: */
bool shared_irq;
};

void hdmi_set_mode(struct hdmi *hdmi, bool power_on);
void hdmi_destroy(struct kref *kref);

static inline void hdmi_write(struct hdmi *hdmi, u32 reg, u32 data)
{
Expand All @@ -115,17 +109,6 @@ static inline u32 hdmi_read(struct hdmi *hdmi, u32 reg)
return msm_readl(hdmi->mmio + reg);
}

static inline struct hdmi * hdmi_reference(struct hdmi *hdmi)
{
kref_get(&hdmi->refcount);
return hdmi;
}

static inline void hdmi_unreference(struct hdmi *hdmi)
{
kref_put(&hdmi->refcount, hdmi_destroy);
}

/*
* The phy appears to be different, for example between 8960 and 8x60,
* so split the phy related functions out and load the correct one at
Expand Down
3 changes: 1 addition & 2 deletions drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ struct hdmi_bridge {
static void hdmi_bridge_destroy(struct drm_bridge *bridge)
{
struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
hdmi_unreference(hdmi_bridge->hdmi);
drm_bridge_cleanup(bridge);
kfree(hdmi_bridge);
}
Expand Down Expand Up @@ -218,7 +217,7 @@ struct drm_bridge *hdmi_bridge_init(struct hdmi *hdmi)
goto fail;
}

hdmi_bridge->hdmi = hdmi_reference(hdmi);
hdmi_bridge->hdmi = hdmi;

bridge = &hdmi_bridge->base;

Expand Down
4 changes: 1 addition & 3 deletions drivers/gpu/drm/msm/hdmi/hdmi_connector.c
Original file line number Diff line number Diff line change
Expand Up @@ -330,8 +330,6 @@ static void hdmi_connector_destroy(struct drm_connector *connector)
drm_connector_unregister(connector);
drm_connector_cleanup(connector);

hdmi_unreference(hdmi_connector->hdmi);

kfree(hdmi_connector);
}

Expand Down Expand Up @@ -425,7 +423,7 @@ struct drm_connector *hdmi_connector_init(struct hdmi *hdmi)
goto fail;
}

hdmi_connector->hdmi = hdmi_reference(hdmi);
hdmi_connector->hdmi = hdmi;
INIT_WORK(&hdmi_connector->hpd_work, hotplug_work);

connector = &hdmi_connector->base;
Expand Down
70 changes: 42 additions & 28 deletions drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,34 +167,54 @@ static bool mdp4_crtc_mode_fixup(struct drm_crtc *crtc,
return true;
}

static void blend_setup(struct drm_crtc *crtc)
/* statically (for now) map planes to mixer stage (z-order): */
static const int idxs[] = {
[VG1] = 1,
[VG2] = 2,
[RGB1] = 0,
[RGB2] = 0,
[RGB3] = 0,
[VG3] = 3,
[VG4] = 4,

};

/* setup mixer config, for which we need to consider all crtc's and
* the planes attached to them
*
* TODO may possibly need some extra locking here
*/
static void setup_mixer(struct mdp4_kms *mdp4_kms)
{
struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
struct mdp4_kms *mdp4_kms = get_kms(crtc);
struct drm_plane *plane;
int i, ovlp = mdp4_crtc->ovlp;
struct drm_mode_config *config = &mdp4_kms->dev->mode_config;
struct drm_crtc *crtc;
uint32_t mixer_cfg = 0;
static const enum mdp_mixer_stage_id stages[] = {
STAGE_BASE, STAGE0, STAGE1, STAGE2, STAGE3,
};
/* statically (for now) map planes to mixer stage (z-order): */
static const int idxs[] = {
[VG1] = 1,
[VG2] = 2,
[RGB1] = 0,
[RGB2] = 0,
[RGB3] = 0,
[VG3] = 3,
[VG4] = 4,

};
bool alpha[4]= { false, false, false, false };
list_for_each_entry(crtc, &config->crtc_list, head) {
struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
struct drm_plane *plane;

/* Don't rely on value read back from hw, but instead use our
* own shadowed value. Possibly disable/reenable looses the
* previous value and goes back to power-on default?
*/
mixer_cfg = mdp4_kms->mixer_cfg;
for_each_plane_on_crtc(crtc, plane) {
enum mdp4_pipe pipe_id = mdp4_plane_pipe(plane);
int idx = idxs[pipe_id];
mixer_cfg = mixercfg(mixer_cfg, mdp4_crtc->mixer,
pipe_id, stages[idx]);
}
}

mdp4_write(mdp4_kms, REG_MDP4_LAYERMIXER_IN_CFG, mixer_cfg);
}

static void blend_setup(struct drm_crtc *crtc)
{
struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
struct mdp4_kms *mdp4_kms = get_kms(crtc);
struct drm_plane *plane;
int i, ovlp = mdp4_crtc->ovlp;
bool alpha[4]= { false, false, false, false };

mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_LOW0(ovlp), 0);
mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_LOW1(ovlp), 0);
Expand All @@ -209,13 +229,8 @@ static void blend_setup(struct drm_crtc *crtc)
to_mdp_format(msm_framebuffer_format(plane->fb));
alpha[idx-1] = format->alpha_enable;
}
mixer_cfg = mixercfg(mixer_cfg, mdp4_crtc->mixer,
pipe_id, stages[idx]);
}

/* this shouldn't happen.. and seems to cause underflow: */
WARN_ON(!mixer_cfg);

for (i = 0; i < 4; i++) {
uint32_t op;

Expand All @@ -238,8 +253,7 @@ static void blend_setup(struct drm_crtc *crtc)
mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_TRANSP_HIGH1(ovlp, i), 0);
}

mdp4_kms->mixer_cfg = mixer_cfg;
mdp4_write(mdp4_kms, REG_MDP4_LAYERMIXER_IN_CFG, mixer_cfg);
setup_mixer(mdp4_kms);
}

static void mdp4_crtc_mode_set_nofb(struct drm_crtc *crtc)
Expand Down
7 changes: 0 additions & 7 deletions drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,6 @@ struct mdp4_kms {

int rev;

/* Shadow value for MDP4_LAYERMIXER_IN_CFG.. since setup for all
* crtcs/encoders is in one shared register, we need to update it
* via read/modify/write. But to avoid getting confused by power-
* on-default values after resume, use this shadow value instead:
*/
uint32_t mixer_cfg;

/* mapper-id used to request GEM buffer mapped for scanout: */
int id;

Expand Down
Loading

0 comments on commit 955289c

Please sign in to comment.