[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