[PATCHv2 21/22] drm/bridge: tc358767: add IRQ and HPD support

Andrey Smirnov andrew.smirnov at gmail.com
Tue Apr 2 02:16:14 UTC 2019


On Tue, Mar 26, 2019 at 3:33 AM Tomi Valkeinen <tomi.valkeinen at ti.com> wrote:
>
> Add support for interrupt and hotplug handling. Both are optional.
>
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen at ti.com>
> ---
>  drivers/gpu/drm/bridge/tc358767.c | 157 ++++++++++++++++++++++++++----
>  1 file changed, 139 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c
> index 8606de29c9b2..6978129428a8 100644
> --- a/drivers/gpu/drm/bridge/tc358767.c
> +++ b/drivers/gpu/drm/bridge/tc358767.c
> @@ -71,6 +71,7 @@
>
>  /* System */
>  #define TC_IDREG               0x0500
> +#define SYSSTAT                        0x0508
>  #define SYSCTRL                        0x0510
>  #define DP0_AUDSRC_NO_INPUT            (0 << 3)
>  #define DP0_AUDSRC_I2S_RX              (1 << 3)
> @@ -79,9 +80,16 @@
>  #define DP0_VIDSRC_DPI_RX              (2 << 0)
>  #define DP0_VIDSRC_COLOR_BAR           (3 << 0)
>  #define GPIOM                  0x0540
> +#define GPIOC                  0x0544
> +#define GPIOO                  0x0548
>  #define GPIOI                  0x054c
>  #define INTCTL_G               0x0560
>  #define INTSTS_G               0x0564
> +
> +#define INT_SYSERR             BIT(16)
> +#define INT_GPIO_H(x)          (1 << (x == 0 ? 2 : 10))
> +#define INT_GPIO_LC(x)         (1 << (x == 0 ? 3 : 11))
> +
>  #define INT_GP0_LCNT           0x0584
>  #define INT_GP1_LCNT           0x0588
>
> @@ -219,6 +227,12 @@ struct tc_data {
>         struct gpio_desc        *sd_gpio;
>         struct gpio_desc        *reset_gpio;
>         struct clk              *refclk;
> +
> +       /* do we have IRQ */
> +       bool                    have_irq;
> +
> +       /* HPD pin number (0 or 1) or -ENODEV */
> +       int                     hpd_num;
>  };
>
>  static inline struct tc_data *aux_to_tc(struct drm_dp_aux *a)
> @@ -1095,6 +1109,12 @@ static void tc_bridge_enable(struct drm_bridge *bridge)
>         struct tc_data *tc = bridge_to_tc(bridge);
>         int ret;
>
> +       ret = tc_get_display_props(tc);
> +       if (ret < 0) {
> +               dev_err(tc->dev, "failed to read display props: %d\n", ret);
> +               return;
> +       }
> +
>         ret = tc_main_link_enable(tc);
>         if (ret < 0) {
>                 dev_err(tc->dev, "main link enable error: %d\n", ret);
> @@ -1200,19 +1220,42 @@ static int tc_connector_get_modes(struct drm_connector *connector)
>         return count;
>  }
>
> -static void tc_connector_set_polling(struct tc_data *tc,
> -                                    struct drm_connector *connector)
> -{
> -       /* TODO: add support for HPD */
> -       connector->polled = DRM_CONNECTOR_POLL_CONNECT |
> -                           DRM_CONNECTOR_POLL_DISCONNECT;
> -}
> -
>  static const struct drm_connector_helper_funcs tc_connector_helper_funcs = {
>         .get_modes = tc_connector_get_modes,
>  };
>
> +static enum drm_connector_status tc_connector_detect(struct drm_connector *connector, bool force)
> +{
> +       struct tc_data *tc = connector_to_tc(connector);
> +       bool conn;
> +       u32 val;
> +       int ret;
> +
> +       if (tc->hpd_num < 0) {
> +               if (tc->panel)
> +                       return connector_status_connected;
> +               else
> +                       return connector_status_unknown;
> +       }
> +

The early return above causes tc_get_display_props() to never be
called for eDP case, which in turn result in tc_mode_valid() returning
MODE_BAD for every mode it is given since it depends on tc->link.base
being initialized properly. I had to change this code to:

if (tc->hpd_num < 0) {
    if (!tc->panel)
        return connector_status_unknown;

    conn = true;
} else {
    tc_read(GPIOI, &val);

    conn = val & BIT(tc->hpd_num);
}

to fix the problem.

Thanks,
Andrey Smirnov


More information about the dri-devel mailing list