[PATCH 1/2] drm/msm: Initial add eDP support in msm drm driver (V2)

Rob Clark robdclark at gmail.com
Mon Dec 8 10:05:04 PST 2014


On Mon, Dec 8, 2014 at 8:28 AM, Thierry Reding <thierry.reding at gmail.com> wrote:
> On Fri, Dec 05, 2014 at 04:30:00PM -0500, Hai Li wrote:
> [...]
>
>> +     if (IS_ERR(edp))
>> +             return PTR_ERR(edp);
>> +     priv->edp = edp;
>> +
>> +     return 0;
>> +}
>> +
>> +static void edp_unbind(struct device *dev, struct device *master,
>> +             void *data)
>
> We typically align parameters on subsequent lines with the first
> parameter on the first line. But perhaps Rob doesn't care so much.

no, I don't.. and aligned params is kinda annoying if function name or
return type changes make it get out of alignment ;-)

but either way is fine

[snip]

>> +/* 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)
>> +{
>> +     struct platform_device *pdev = edp->pdev;
>> +     struct msm_drm_private *priv = dev->dev_private;
>> +     int ret;
>> +
>> +     edp->encoder = encoder;
>> +     edp->dev = dev;
>> +
>> +     edp->bridge = msm_edp_bridge_init(edp);
>> +     if (IS_ERR(edp->bridge)) {
>> +             ret = PTR_ERR(edp->bridge);
>> +             dev_err(dev->dev, "failed to create eDP bridge: %d\n", ret);
>> +             edp->bridge = NULL;
>> +             goto fail;
>> +     }
>> +
>> +     edp->connector = msm_edp_connector_init(edp);
>> +     if (IS_ERR(edp->connector)) {
>> +             ret = PTR_ERR(edp->connector);
>> +             dev_err(dev->dev, "failed to create eDP connector: %d\n", ret);
>> +             edp->connector = NULL;
>> +             goto fail;
>> +     }
>> +
>> +     edp->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
>
> Why not use the more idiomatic platform_get_irq()?

It may have been a quirk of the downstream 3.10 kernel that I also
have to deal with for some devices, but I couldn't get
platform_get_irq() to work and so used irq_of_parse_and_map() in the
hdmi code.  I assume eDP would have the identical problem.

>> +     if (edp->irq < 0) {
>> +             ret = edp->irq;
>> +             dev_err(dev->dev, "failed to get irq: %d\n", ret);
>
> s/irq/IRQ/
>
>> diff --git a/drivers/gpu/drm/msm/edp/edp.h b/drivers/gpu/drm/msm/edp/edp.h
> [...]
>> +#ifndef __EDP_CONNECTOR_H__
>> +#define __EDP_CONNECTOR_H__
>> +
>> +#include <linux/clk.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/regulator/consumer.h>
>> +#include <linux/of_gpio.h>
>> +#include <linux/pwm.h>
>> +#include <linux/i2c.h>
>
> These should be alphabetically sorted.
>
>> diff --git a/drivers/gpu/drm/msm/edp/edp_aux.c b/drivers/gpu/drm/msm/edp/edp_aux.c
> [...]
>> +#define to_edp_aux(x) container_of(x, struct edp_aux, drm_aux)
>
> Perhaps this should be a static inline function for better type safety.
>

#define is at least consistent w/ rest of drm/msm code (and
obj_to_xyz() in drm core)..  although if misused it probably gives a
more confusing compile error compared to static inline fxn.

I wouldn't reject a patch that converted them all to static inline
fxns, but I think this is ok as-is

[snip]

>
>> +static int edp_sink_power_state(struct edp_ctrl *ctrl, u8 state)
>> +{
>> +     u8 s = state;
>> +
>> +     DBG("%d", s);
>> +
>> +     if (ctrl->dp_link.revision < 0x11)
>> +             return 0;
>> +
>> +     if (drm_dp_dpcd_write(ctrl->drm_aux, DP_SET_POWER, &s, 1) < 1) {
>> +             pr_err("%s: Set power state to panel failed\n", __func__);
>> +             return -ENOLINK;
>> +     }
>> +
>> +     return 0;
>> +}
>
> This is essentially drm_dp_link_power_up()/drm_dp_link_power_down().
> Please use common code where available. And if it's not available yet
> the code is completely generic, please add a core function so that
> other drivers can reuse it.

jfyi, I already have a patch that rips this back out and uses core
functions, once drm_dp_link_power_down() is merged ;-)

[snip]

>> +irqreturn_t msm_edp_ctrl_irq(struct edp_ctrl *ctrl)
>> +{
> [...]
>> +     if (isr1 & EDP_INTERRUPT_REG_1_HPD)
>> +             DBG("edp_hpd");
>
> Don't you want to handle this?
>
>> +
>> +     if (isr2 & EDP_INTERRUPT_REG_2_READY_FOR_VIDEO)
>> +             DBG("edp_video_ready");
>> +
>> +     if (isr2 & EDP_INTERRUPT_REG_2_IDLE_PATTERNs_SENT) {
>
> s/PATTERNs/PATTERNS/? I was going to make that comment to the definition
> of this define, but I can't seem to find it. I suspect that it comes
> from one of the generated headers, but I can't seem to find either the
> generated header nor the XML.

yes, it is generated..

fyi: https://github.com/freedreno/envytools/tree/master/rnndb

>
>> +             DBG("idle_patterns_sent");
>> +             complete(&ctrl->idle_comp);
>> +     }
>> +
>> +     msm_edp_aux_irq(ctrl->aux, isr1);
>> +
>> +     return IRQ_HANDLED;
>> +}
> [...]
>> +bool msm_edp_ctrl_panel_connected(struct edp_ctrl *ctrl)
>> +{
>> +     bool ret;
>
> This is unnecessary, the only place where this is used is to return the
> value of ctrl->edp_connected. You can use that directly instead.
>
> [...]
>> +     ret = ctrl->edp_connected;
>> +     mutex_unlock(&ctrl->dev_mutex);
>> +
>> +     return ret;
>> +}
>> +
>> +int msm_edp_ctrl_get_edid(struct edp_ctrl *ctrl,
>> +             struct drm_connector *connector, struct edid **edid)
>> +{
>> +     int ret = 0;
>> +
>> +     mutex_lock(&ctrl->dev_mutex);
>> +
>> +     if (ctrl->edid) {
>> +             if (edid) {
>> +                     DBG("Just return edid buffer");
>> +                     *edid = ctrl->edid;
>> +             }
>> +             goto unlock_ret;
>> +     }
>
> Is there a way to invalidate an existing EDID?

fwiw, the existing code looks to be enough for fixed eDP panels, but
doesn't really handle unplug (so some of the stale-edid issues
wouldn't crop up yet)..

I am ok will adding full blown DP hot(un)plug as a later patch, but
there are going to be a couple spots where we need to be careful about
stale EDID, etc..


BR,
-R


More information about the dri-devel mailing list