nouveau-fixes 5.6

2020-02-16 Thread Ben Skeggs
Hey,

Nothing major here, another TU1xx modesetting fix, and hooking up
ACR/GR support on TU11x now that NVIDIA have made the firmware
available.

Thanks,
Ben.

The following changes since commit 137c4ba7163ad9d5696b9fde78b1c0898a9c115b:

  drm/nouveau/kms/gv100-: avoid sending a core update until the first
modeset (2020-02-03 21:36:54 +1000)

are available in the Git repository at:

  git://github.com/skeggsb/linux linux-5.6

for you to fetch changes up to f287d3d19769b1d22cba4e51fa0487f2697713c9:

  drm/nouveau/kms/gv100-: Re-set LUT after clearing for modesets
(2020-02-17 17:19:00 +1000)


Ben Skeggs (2):
  drm/nouveau/acr/tu11x: initial support
  drm/nouveau/gr/tu11x: initial support

Lyude Paul (1):
  drm/nouveau/kms/gv100-: Re-set LUT after clearing for modesets

 drivers/gpu/drm/nouveau/dispnv50/wndw.c   |  2 ++
 drivers/gpu/drm/nouveau/nvkm/engine/device/base.c |  4 
 drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c| 26 +++
 drivers/gpu/drm/nouveau/nvkm/subdev/acr/tu102.c   | 14 
 drivers/gpu/drm/nouveau/nvkm/subdev/fb/gv100.c|  2 ++
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


RE: [PATCH 3/3] drm/dp_mst: Remove single tx msg restriction.

2020-02-16 Thread Lin, Wayne
[AMD Public Use]



> -Original Message-
> From: Sean Paul 
> Sent: Saturday, February 15, 2020 12:09 AM
> To: Lin, Wayne 
> Cc: dri-devel@lists.freedesktop.org; ly...@redhat.com; Sean Paul
> ; Maarten Lankhorst
> ; Maxime Ripard ;
> David Airlie 
> Subject: Re: [PATCH 3/3] drm/dp_mst: Remove single tx msg restriction.
> 
> On Fri, Feb 14, 2020 at 12:58 AM Lin, Wayne  wrote:
> >
> > [AMD Public Use]
> >
> > Hi Paul,
> >
> > Thanks for the mail!
> >
> > I tried to solve this problem by having restriction on sending one msg at a
> time due to hub/dock compatibility problems.
> > From my experience, some branch devices don't handle well on
> > interleaved replies (Dock from HP I think)
> 
> Hi Wayne,
> Hmm, that's interesting, do you have a part number of the failing dock so I 
> can
> test it?
> 
Hi Paul,

Sorry but it's been quite a while. I can't exactly tell the part number. 
If I remember correctly, when the specific branch device receives interleaved 
replies,
it just doesn't reply to any requests.

> > As the result of that, correct me if I'm wrong, I remember most gpu vendors
> just send one down request at a time now in windows environment.
> > I would suggest the original solution :)
> 
> I can't really say what happens on the Windows side of the world, but I 
> suppose
> that makes sense if this is a widespread issue with docks. I do worry about 
> the
> performance hit.
> 
> If indeed this is a problem, could we ratelimit per branch device instead of
> globally? Even that would be better than serializing everything.
> 
Since the problem was because some branch devices can't simultaneously handle 
two replies, I'm afraid that we might still encounter the same problem?
 
Thanks!
> Sean
> 
> >
> > Thanks!
> > > -Original Message-
> > > From: Sean Paul 
> > > Sent: Friday, February 14, 2020 5:15 AM
> > > To: dri-devel@lists.freedesktop.org
> > > Cc: ly...@redhat.com; Lin, Wayne ; Sean Paul
> > > ; Maarten Lankhorst
> > > ; Maxime Ripard
> > > ; David Airlie 
> > > Subject: [PATCH 3/3] drm/dp_mst: Remove single tx msg restriction.
> > >
> > > From: Sean Paul 
> > >
> > > Now that we can support multiple simultaneous replies, remove the
> > > restrictions placed on sending new tx msgs.
> > >
> > > This patch essentially just reverts commit
> > >   5a64967a2f3b ("drm/dp_mst: Have DP_Tx send one msg at a time")
> now
> > > that the problem is solved in a different way.
> > >
> > > Cc: Wayne Lin 
> > > Signed-off-by: Sean Paul 
> > > ---
> > >  drivers/gpu/drm/drm_dp_mst_topology.c | 14 ++
> > >  include/drm/drm_dp_mst_helper.h   |  6 --
> > >  2 files changed, 2 insertions(+), 18 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c
> > > b/drivers/gpu/drm/drm_dp_mst_topology.c
> > > index 7e6a82efdfc02..cbf0bb0ddeb84 100644
> > > --- a/drivers/gpu/drm/drm_dp_mst_topology.c
> > > +++ b/drivers/gpu/drm/drm_dp_mst_topology.c
> > > @@ -1203,8 +1203,6 @@ static int drm_dp_mst_wait_tx_reply(struct
> > > drm_dp_mst_branch *mstb,
> > >   txmsg->state == DRM_DP_SIDEBAND_TX_SENT) {
> > >   mstb->tx_slots[txmsg->seqno] = NULL;
> > >   }
> > > - mgr->is_waiting_for_dwn_reply = false;
> > > -
> > >   }
> > >  out:
> > >   if (unlikely(ret == -EIO) && drm_debug_enabled(DRM_UT_DP)) {
> > > @@
> > > -1214,7 +1212,6 @@ static int drm_dp_mst_wait_tx_reply(struct
> > > drm_dp_mst_branch *mstb,
> > >   }
> > >   mutex_unlock(>qlock);
> > >
> > > - drm_dp_mst_kick_tx(mgr);
> > >   return ret;
> > >  }
> > >
> > > @@ -2797,11 +2794,9 @@ static void
> > > process_single_down_tx_qlock(struct
> > > drm_dp_mst_topology_mgr *mgr)
> > >   ret = process_single_tx_qlock(mgr, txmsg, false);
> > >   if (ret == 1) {
> > >   /* txmsg is sent it should be in the slots now */
> > > - mgr->is_waiting_for_dwn_reply = true;
> > >   list_del(>next);
> > >   } else if (ret) {
> > >   DRM_DEBUG_KMS("failed to send msg in q %d\n", ret);
> > > - mgr->is_waiting_for_dwn_reply = false;
> > >   list_del(>next);
> > >   if (txmsg->seqno != -1)
> > >   txmsg->dst->tx_slots[txmsg->seqno] = NULL;
> @@
> > > -2841,8
> > > +2836,7 @@ static void drm_dp_queue_down_tx(struct
> > > drm_dp_mst_topology_mgr *mgr,
> > >   drm_dp_mst_dump_sideband_msg_tx(, txmsg);
> > >   }
> > >
> > > - if (list_is_singular(>tx_msg_downq) &&
> > > - !mgr->is_waiting_for_dwn_reply)
> > > + if (list_is_singular(>tx_msg_downq))
> > >   process_single_down_tx_qlock(mgr);
> > >   mutex_unlock(>qlock);
> > >  }
> > > @@ -3822,7 +3816,6 @@ static int drm_dp_mst_handle_down_rep(struct
> > > drm_dp_mst_topology_mgr *mgr)
> > >   mutex_lock(>qlock);
> > >   txmsg->state = DRM_DP_SIDEBAND_TX_RX;
> > >   mstb->tx_slots[seqno] = NULL;
> > > - mgr->is_waiting_for_dwn_reply = 

Re: [PATCHv4,03/36] drm/gem-fb-helper: Allow drivers to allocate struct drm_framebuffer on their own

2020-02-16 Thread james qian wang (Arm Technology China)
Hi Andrzej:

Good work.

It's a real useful patch, with it seems most vendor-specific fb_create
can be simplified by these helper funcs.

On Fri, Dec 13, 2019 at 04:58:34PM +0100, Andrzej Pietrasiewicz wrote:
> Prepare tools for drivers which need to allocate a struct drm_framebuffer
> (or a container of struct drm_framebuffer) explicitly, before calling
> helpers. In such a case we need new helpers which omit allocating the
> struct drm_framebuffer and this patch provides them. Consequently, they
> are used also inside the helpers themselves.
> 
> The interested drivers will likely need to be able to perform object
> lookups and size checks in separate invocations and this patch provides
> that as well. Helpers themselves are updated, too.
> 
> Signed-off-by: Andrzej Pietrasiewicz 
> ---
>  drivers/gpu/drm/drm_gem_framebuffer_helper.c | 184 ++-
>  include/drm/drm_gem_framebuffer_helper.h |  17 ++
>  2 files changed, 153 insertions(+), 48 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c 
> b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
> index b9bcd310ca2d..787edb9a916b 100644
> --- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c
> +++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
> @@ -54,6 +54,44 @@ struct drm_gem_object *drm_gem_fb_get_obj(struct 
> drm_framebuffer *fb,
>  }
>  EXPORT_SYMBOL_GPL(drm_gem_fb_get_obj);
>  
> +int drm_gem_fb_init_with_funcs(struct drm_framebuffer *fb,
> +struct drm_device *dev,
> +const struct drm_mode_fb_cmd2 *mode_cmd,
> +struct drm_gem_object **obj,
> +unsigned int num_planes,
> +const struct drm_framebuffer_funcs *funcs)
> +{
> + int ret, i;
> +
> + drm_helper_mode_fill_fb_struct(dev, fb, mode_cmd);
> +
> + for (i = 0; i < num_planes; i++)
> + fb->obj[i] = obj[i];
> +
> + ret = drm_framebuffer_init(dev, fb, funcs);
> + if (ret)
> + DRM_DEV_ERROR(dev->dev, "Failed to init framebuffer: %d\n",
> +   ret);
> +
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(drm_gem_fb_init_with_funcs);
> +
> +static const struct drm_framebuffer_funcs drm_gem_fb_funcs = {
> + .destroy= drm_gem_fb_destroy,
> + .create_handle  = drm_gem_fb_create_handle,
> +};
> +
> +int drm_gem_fb_init(struct drm_framebuffer *fb,
> + struct drm_device *dev,
> + const struct drm_mode_fb_cmd2 *mode_cmd,
> + struct drm_gem_object **obj, unsigned int num_planes)
> +{
> + return drm_gem_fb_init_with_funcs(fb, dev, mode_cmd, obj, num_planes,
> +   _gem_fb_funcs);
> +}
> +EXPORT_SYMBOL_GPL(drm_gem_fb_init);
> +
>  static struct drm_framebuffer *
>  drm_gem_fb_alloc(struct drm_device *dev,
>const struct drm_mode_fb_cmd2 *mode_cmd,
> @@ -61,21 +99,15 @@ drm_gem_fb_alloc(struct drm_device *dev,
>const struct drm_framebuffer_funcs *funcs)
>  {
>   struct drm_framebuffer *fb;
> - int ret, i;
> + int ret;
>  
>   fb = kzalloc(sizeof(*fb), GFP_KERNEL);
>   if (!fb)
>   return ERR_PTR(-ENOMEM);
>  
> - drm_helper_mode_fill_fb_struct(dev, fb, mode_cmd);
> -
> - for (i = 0; i < num_planes; i++)
> - fb->obj[i] = obj[i];
> -
> - ret = drm_framebuffer_init(dev, fb, funcs);
> + ret = drm_gem_fb_init_with_funcs(fb, dev, mode_cmd, obj, num_planes,
> +  funcs);
>   if (ret) {
> - DRM_DEV_ERROR(dev->dev, "Failed to init framebuffer: %d\n",
> -   ret);
>   kfree(fb);
>   return ERR_PTR(ret);
>   }
> @@ -124,79 +156,135 @@ int drm_gem_fb_create_handle(struct drm_framebuffer 
> *fb, struct drm_file *file,
>  EXPORT_SYMBOL(drm_gem_fb_create_handle);
>  
>  /**
> - * drm_gem_fb_create_with_funcs() - Helper function for the
> - *  _mode_config_funcs.fb_create
> - *  callback
> + * drm_gem_fb_lookup() - Helper function for use in
> + *_mode_config_funcs.fb_create implementations
>   * @dev: DRM device
>   * @file: DRM file that holds the GEM handle(s) backing the framebuffer
>   * @mode_cmd: Metadata from the userspace framebuffer creation request
> - * @funcs: vtable to be used for the new framebuffer object
>   *
> - * This function can be used to set _framebuffer_funcs for drivers that 
> need
> - * custom framebuffer callbacks. Use drm_gem_fb_create() if you don't need to
> - * change _framebuffer_funcs. The function does buffer size validation.
> + * This function can be used to look up the objects for all planes.
> + * In case an error is returned all the objects are put by the
> + * function before returning.
>   *
>   * Returns:
> - * Pointer to a _framebuffer on success or an error pointer on failure.
> + 

Re: [PATCHv4,02/36] drm/core: Add afbc helper functions

2020-02-16 Thread james qian wang (Arm Technology China)
On Fri, Dec 13, 2019 at 04:58:33PM +0100, Andrzej Pietrasiewicz wrote:
> Add checking if a modifier is afbc and getting afbc block size.
> 
> Signed-off-by: Andrzej Pietrasiewicz 
> ---
>  drivers/gpu/drm/drm_fourcc.c | 53 
>  include/drm/drm_fourcc.h |  4 +++
>  2 files changed, 57 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c
> index b234bfaeda06..d14dd7c86020 100644
> --- a/drivers/gpu/drm/drm_fourcc.c
> +++ b/drivers/gpu/drm/drm_fourcc.c
> @@ -29,6 +29,7 @@
>  
>  #include 
>  #include 
> +#include 
>  
>  static char printable_char(int c)
>  {
> @@ -393,3 +394,55 @@ uint64_t drm_format_info_min_pitch(const struct 
> drm_format_info *info,
>   drm_format_info_block_height(info, plane));
>  }
>  EXPORT_SYMBOL(drm_format_info_min_pitch);
> +
> +/**
> + * drm_is_afbc - test if the modifier describes an afbc buffer
> + * @modifier - modifier to be tested
> + *
> + * Returns: true if the modifier describes an afbc buffer
> + */
> +bool drm_is_afbc(u64 modifier)
> +{
> + /* is it ARM AFBC? */
> + if ((modifier & DRM_FORMAT_MOD_ARM_AFBC(0)) == 0)
> + return false;
> +
> + /* Block size must be known */
> + if ((modifier & AFBC_FORMAT_MOD_BLOCK_SIZE_MASK) == 0)
> + return false;

Do we really need this block size check here ?
Since modifier with ARM AFBC modifier but have no BLOCK_SIZE which
should be an error, but this check returns such error to NONE-AFBC.
And i saw you already have such error check in func
get_superblock_wh(), so I think we can del this size check in this
func.

James.
> +
> + return true;
> +}
> +EXPORT_SYMBOL_GPL(drm_is_afbc);
> +
> +/**
> + * drm_afbc_get_superblock_wh - extract afbc block width/height from modifier
> + * @modifier: the modifier to be looked at
> + * @w: address of a place to store the block width
> + * @h: address of a place to store the block height
> + *
> + * Returns: true if the modifier describes a supported block size
> + */
> +bool drm_afbc_get_superblock_wh(u64 modifier, u32 *w, u32 *h)
> +{
> + switch (modifier & AFBC_FORMAT_MOD_BLOCK_SIZE_MASK) {
> + case AFBC_FORMAT_MOD_BLOCK_SIZE_16x16:
> + *w = 16;
> + *h = 16;
> + break;
> + case AFBC_FORMAT_MOD_BLOCK_SIZE_32x8:
> + *w = 32;
> + *h = 8;
> + break;
> + case AFBC_FORMAT_MOD_BLOCK_SIZE_64x4:
> + /* fall through */
> + case AFBC_FORMAT_MOD_BLOCK_SIZE_32x8_64x4:
> + /* fall through */
> + default:
> + DRM_DEBUG_KMS("Invalid AFBC_FORMAT_MOD_BLOCK_SIZE: %lld.\n",
> +   modifier & AFBC_FORMAT_MOD_BLOCK_SIZE_MASK);
> + return false;
> + }
> + return true;
> +}
> +EXPORT_SYMBOL_GPL(drm_afbc_get_superblock_wh);
> diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h
> index 306d1efeb5e0..7eb23062bf45 100644
> --- a/include/drm/drm_fourcc.h
> +++ b/include/drm/drm_fourcc.h
> @@ -320,4 +320,8 @@ uint64_t drm_format_info_min_pitch(const struct 
> drm_format_info *info,
>  int plane, unsigned int buffer_width);
>  const char *drm_get_format_name(uint32_t format, struct drm_format_name_buf 
> *buf);
>  
> +bool drm_is_afbc(u64 modifier);
> +
> +bool drm_afbc_get_superblock_wh(u64 modifier, u32 *w, u32 *h);
> +
>  #endif /* __DRM_FOURCC_H__ */
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCHv4,01/36] drm/framebuffer: Add optional modifier info

2020-02-16 Thread james qian wang (Arm Technology China)
Hi Andrzej:

Sorry for late due to the outbreak of coronavirus in china.

Reviewed-by: James Qian Wang 

James.

On Fri, Dec 13, 2019 at 04:58:32PM +0100, Andrzej Pietrasiewicz wrote:
> modifier_info is a pointer to an optional modifier-related information.
> Managing the memory needed for that information is the responsibility
> of drivers.
> 
> Signed-off-by: Andrzej Pietrasiewicz 
> ---
>  include/drm/drm_framebuffer.h | 16 
>  1 file changed, 16 insertions(+)
> 
> diff --git a/include/drm/drm_framebuffer.h b/include/drm/drm_framebuffer.h
> index c0e0256e3e98..2b3341b526d7 100644
> --- a/include/drm/drm_framebuffer.h
> +++ b/include/drm/drm_framebuffer.h
> @@ -29,6 +29,7 @@
>  
>  #include 
>  
> +struct drm_afbc;
>  struct drm_clip_rect;
>  struct drm_device;
>  struct drm_file;
> @@ -139,6 +140,21 @@ struct drm_framebuffer {
>* @format: framebuffer format information
>*/
>   const struct drm_format_info *format;
> +
> + union {
> + /**
> +  * @modifier_info: pointer to an optional modifier-related
> +  * information. Managing the memory holding that information
> +  * is driver's responsibility.
> +  */
> + void *modifier_info;
> +
> + /**
> +  * @afbc_info: afbc-specific pointer
> +  */
> + struct drm_afbc *afbc_info;
> + };
> +
>   /**
>* @funcs: framebuffer vfunc table
>*/
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH v2 2/2] drm/mediatek: fix race condition for HDMI jack status reporting

2020-02-16 Thread CK Hu
On Mon, 2020-02-17 at 11:55 +0800, Tzung-Bi Shih wrote:
> On Mon, Feb 17, 2020 at 11:44 AM CK Hu  wrote:
> > On Mon, 2020-02-17 at 11:16 +0800, Tzung-Bi Shih wrote:
> > > Fixes: 5d3c64477392 ("drm/mediatek: support HDMI jack status reporting")
> >
> > This patch looks good to me, but please merge this patch with the patch
> > it fix.
> 
> 5d3c64477392 ("drm/mediatek: support HDMI jack status reporting") has
> applied to ASoC for-next branch.  This is a fixup patch.

I thought a patch need an ack by the maintainer. OK, so I could do is,
for this patch,

Acked-by: CK Hu  
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH v2 2/2] drm/mediatek: fix race condition for HDMI jack status reporting

2020-02-16 Thread CK Hu
Hi, Tzhung-Bi:

On Mon, 2020-02-17 at 11:16 +0800, Tzung-Bi Shih wrote:
> hdmi_conn_detect and mtk_hdmi_audio_hook_plugged_cb would be called
> by different threads.
> 
> Imaging the following calling sequence:
>Thread AThread B
> 
> mtk_hdmi_audio_hook_plugged_cb()
> mtk_cec_hpd_high() -> disconnected
>  hdmi_conn_detect()
>  mtk_cec_hpd_high() -> connected
>  plugged_cb(connected)
> plugged_cb(disconnected)
> 
> The latest disconnected is false reported.  Makes mtk_cec_hpd_high
> and plugged_cb atomic to fix.
> 
> Also uses the same lock to protect read/write of plugged_cb and codec_dev.
> 
> Fixes: 5d3c64477392 ("drm/mediatek: support HDMI jack status reporting")

This patch looks good to me, but please merge this patch with the patch
it fix.

Regards,
CK

> Signed-off-by: Tzung-Bi Shih 
> ---
>  drivers/gpu/drm/mediatek/mtk_hdmi.c | 11 ++-
>  1 file changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c 
> b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> index 03aeb73005ef..d80017e3d84a 100644
> --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> @@ -12,6 +12,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -171,6 +172,7 @@ struct mtk_hdmi {
>   bool enabled;
>   hdmi_codec_plugged_cb plugged_cb;
>   struct device *codec_dev;
> + struct mutex update_plugged_status_lock;
>  };
>  
>  static inline struct mtk_hdmi *hdmi_ctx_from_bridge(struct drm_bridge *b)
> @@ -1199,10 +1201,13 @@ static void mtk_hdmi_clk_disable_audio(struct 
> mtk_hdmi *hdmi)
>  static enum drm_connector_status
>  mtk_hdmi_update_plugged_status(struct mtk_hdmi *hdmi)
>  {
> - bool connected = mtk_cec_hpd_high(hdmi->cec_dev);
> + bool connected;
>  
> + mutex_lock(>update_plugged_status_lock);
> + connected = mtk_cec_hpd_high(hdmi->cec_dev);
>   if (hdmi->plugged_cb && hdmi->codec_dev)
>   hdmi->plugged_cb(hdmi->codec_dev, connected);
> + mutex_unlock(>update_plugged_status_lock);
>  
>   return connected ?
>  connector_status_connected : connector_status_disconnected;
> @@ -1669,8 +1674,11 @@ static int mtk_hdmi_audio_hook_plugged_cb(struct 
> device *dev, void *data,
>  {
>   struct mtk_hdmi *hdmi = data;
>  
> + mutex_lock(>update_plugged_status_lock);
>   hdmi->plugged_cb = fn;
>   hdmi->codec_dev = codec_dev;
> + mutex_unlock(>update_plugged_status_lock);
> +
>   mtk_hdmi_update_plugged_status(hdmi);
>  
>   return 0;
> @@ -1729,6 +1737,7 @@ static int mtk_drm_hdmi_probe(struct platform_device 
> *pdev)
>   return ret;
>   }
>  
> + mutex_init(>update_plugged_status_lock);
>   platform_set_drvdata(pdev, hdmi);
>  
>   ret = mtk_hdmi_output_init(hdmi);

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH] drm/lima: fix recovering from PLBU out of memory

2020-02-16 Thread Qiang Yu
applied to drm-misc-next.

On Mon, Feb 17, 2020 at 9:20 AM Qiang Yu  wrote:
>
> Looks good for me, patch is:
> Reviewed-by: Qiang Yu 
>
> Regards,
> Qiang
>
> On Sat, Feb 15, 2020 at 11:50 AM Vasily Khoruzhick  wrote:
> >
> > It looks like on PLBU_OUT_OF_MEM interrupt we need to resume from where we
> > stopped, i.e. new PLBU heap start is old end. Also update end address
> > in GP frame to grow heap on 2nd and subsequent out of memory interrupts.
> >
> > Fixes: 2081e8dcf1ee ("drm/lima: recover task by enlarging heap buffer")
> > Signed-off-by: Vasily Khoruzhick 
> > ---
> >  drivers/gpu/drm/lima/lima_gp.c | 7 ++-
> >  1 file changed, 6 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/gpu/drm/lima/lima_gp.c b/drivers/gpu/drm/lima/lima_gp.c
> > index d1e7826c2d74..325604262def 100644
> > --- a/drivers/gpu/drm/lima/lima_gp.c
> > +++ b/drivers/gpu/drm/lima/lima_gp.c
> > @@ -224,8 +224,13 @@ static int lima_gp_task_recover(struct lima_sched_pipe 
> > *pipe)
> > }
> >
> > gp_write(LIMA_GP_INT_MASK, LIMA_GP_IRQ_MASK_USED);
> > +   /* Resume from where we stopped, i.e. new start is old end */
> > +   gp_write(LIMA_GP_PLBU_ALLOC_START_ADDR,
> > +f[LIMA_GP_PLBU_ALLOC_END_ADDR >> 2]);
> > +   f[LIMA_GP_PLBU_ALLOC_END_ADDR >> 2] =
> > +   f[LIMA_GP_PLBU_ALLOC_START_ADDR >> 2] + 
> > task->heap->heap_size;
> > gp_write(LIMA_GP_PLBU_ALLOC_END_ADDR,
> > -f[LIMA_GP_PLBU_ALLOC_START_ADDR >> 2] + 
> > task->heap->heap_size);
> > +f[LIMA_GP_PLBU_ALLOC_END_ADDR >> 2]);
> > gp_write(LIMA_GP_CMD, LIMA_GP_CMD_UPDATE_PLBU_ALLOC);
> > return 0;
> >  }
> > --
> > 2.25.0
> >
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH v3 3/7] drm/exynos: Use drm_encoder_mask()

2020-02-16 Thread Inki Dae


20. 2. 12. 오전 1:22에 Ville Syrjala 이(가) 쓴 글:
> From: Ville Syrjälä 
> 
> Replace the hand rolled encoder bitmask thing with drm_encoder_mask()
> 
> Cc: Inki Dae 
> Cc: Joonyoung Shim 
> Cc: Seung-Woo Kim 
> Cc: Kyungmin Park 
> Acked-by: Thomas Zimmermann 
> Signed-off-by: Ville Syrjälä 

Acked-by: Inki Dae 

THanks,
Inki Dae

> ---
>  drivers/gpu/drm/exynos/exynos_drm_drv.c | 5 ++---
>  1 file changed, 2 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c 
> b/drivers/gpu/drm/exynos/exynos_drm_drv.c
> index ba0f868b2477..57defeb44522 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
> @@ -270,7 +270,7 @@ static int exynos_drm_bind(struct device *dev)
>   struct drm_encoder *encoder;
>   struct drm_device *drm;
>   unsigned int clone_mask;
> - int cnt, ret;
> + int ret;
>  
>   drm = drm_dev_alloc(_drm_driver, dev);
>   if (IS_ERR(drm))
> @@ -293,10 +293,9 @@ static int exynos_drm_bind(struct device *dev)
>   exynos_drm_mode_config_init(drm);
>  
>   /* setup possible_clones. */
> - cnt = 0;
>   clone_mask = 0;
>   list_for_each_entry(encoder, >mode_config.encoder_list, head)
> - clone_mask |= (1 << (cnt++));
> + clone_mask |= drm_encoder_mask(encoder);
>  
>   list_for_each_entry(encoder, >mode_config.encoder_list, head)
>   encoder->possible_clones = clone_mask;
> 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH] drm/lima: fix recovering from PLBU out of memory

2020-02-16 Thread Qiang Yu
Looks good for me, patch is:
Reviewed-by: Qiang Yu 

Regards,
Qiang

On Sat, Feb 15, 2020 at 11:50 AM Vasily Khoruzhick  wrote:
>
> It looks like on PLBU_OUT_OF_MEM interrupt we need to resume from where we
> stopped, i.e. new PLBU heap start is old end. Also update end address
> in GP frame to grow heap on 2nd and subsequent out of memory interrupts.
>
> Fixes: 2081e8dcf1ee ("drm/lima: recover task by enlarging heap buffer")
> Signed-off-by: Vasily Khoruzhick 
> ---
>  drivers/gpu/drm/lima/lima_gp.c | 7 ++-
>  1 file changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/lima/lima_gp.c b/drivers/gpu/drm/lima/lima_gp.c
> index d1e7826c2d74..325604262def 100644
> --- a/drivers/gpu/drm/lima/lima_gp.c
> +++ b/drivers/gpu/drm/lima/lima_gp.c
> @@ -224,8 +224,13 @@ static int lima_gp_task_recover(struct lima_sched_pipe 
> *pipe)
> }
>
> gp_write(LIMA_GP_INT_MASK, LIMA_GP_IRQ_MASK_USED);
> +   /* Resume from where we stopped, i.e. new start is old end */
> +   gp_write(LIMA_GP_PLBU_ALLOC_START_ADDR,
> +f[LIMA_GP_PLBU_ALLOC_END_ADDR >> 2]);
> +   f[LIMA_GP_PLBU_ALLOC_END_ADDR >> 2] =
> +   f[LIMA_GP_PLBU_ALLOC_START_ADDR >> 2] + task->heap->heap_size;
> gp_write(LIMA_GP_PLBU_ALLOC_END_ADDR,
> -f[LIMA_GP_PLBU_ALLOC_START_ADDR >> 2] + 
> task->heap->heap_size);
> +f[LIMA_GP_PLBU_ALLOC_END_ADDR >> 2]);
> gp_write(LIMA_GP_CMD, LIMA_GP_CMD_UPDATE_PLBU_ALLOC);
> return 0;
>  }
> --
> 2.25.0
>
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[Bug 200695] Blank screen on RX 580 with amdgpu.dc=1 enabled (no displays detected)

2020-02-16 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=200695

babgozd (babgoz...@outlook.com) changed:

   What|Removed |Added

 CC||babgoz...@outlook.com

--- Comment #38 from babgozd (babgoz...@outlook.com) ---
(In reply to Adam from comment #37)
> As several comments mention different behavior between the different
> connector types I found a spare DVI cable and tried connecting to the same
> monitor via that input and it worked! So once logged in I plugged in the
> HDMI cable and switched input and it worked just fine (monitor was glitchy
> at first but once I disabled DVI output in monitor configuration it worked
> perfectly). To confirm this was indeed working with the DC code path I
> tested audio over HDMI and it worked just fine (and does not work with DC
> disabled, as expected). So I rebooted with both the DVI and HDMI in and the
> output over HDMI worked all through boot. I then disconnected the DVI and
> rebooted and the HDMI continues to work so far. Unfortunately I don't have a
> displayport monitor around to test if that behaves as weirdly. Just to be
> clear, I had tried to make this monitor work for a couple weeks over HDMI
> and the only thing that worked was amdgpu.dc=0 until I plugged in the DVI
> connector so this was not a one off fail.
> 
> I forgot to mention before that when the HDMI output was not working with DC
> my Xorg logs also showed no monitor detected.
> 
> I can attach the two different Xorg logs if that helps?
I am following this thread since it has created. My R9 380 with DVI-I output is
connected to my VGA monitor with DVI-I male to VGA female adapter and I am
getting black/blank screen while booting with amdgpu.dc=1 which is default
since kernel 4.17. It is fine with amdgpu.dc=0. I can provide logs too if any
kernel contributor wants to investigate the problem any further.

-- 
You are receiving this mail because:
You are watching the assignee of the bug.
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v6 41/51] drm/omap: hdmi5: Simplify EDID read

2020-02-16 Thread Laurent Pinchart
Now that the omap_dss_device EDID read operation has been removed,
simplify the bridge-based EDID access by merging multiple functions
together.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
---
 drivers/gpu/drm/omapdrm/dss/hdmi5.c | 86 -
 1 file changed, 35 insertions(+), 51 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
index 6cb709c775d6..4d4c1fabd0a1 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
@@ -307,50 +307,6 @@ static void hdmi_core_disable(struct omap_hdmi *hdmi)
mutex_unlock(>lock);
 }
 
-static struct edid *
-hdmi_do_read_edid(struct omap_hdmi *hdmi,
- struct edid *(*read)(struct omap_hdmi *hdmi,
-  struct drm_connector *connector),
- struct drm_connector *connector)
-{
-   struct edid *edid;
-   bool need_enable;
-   int idlemode;
-   int r;
-
-   need_enable = hdmi->core_enabled == false;
-
-   if (need_enable) {
-   r = hdmi_core_enable(hdmi);
-   if (r)
-   return NULL;
-   }
-
-   mutex_lock(>lock);
-   r = hdmi_runtime_get(hdmi);
-   BUG_ON(r);
-
-   idlemode = REG_GET(hdmi->wp.base, HDMI_WP_SYSCONFIG, 3, 2);
-   /* No-idle mode */
-   REG_FLD_MOD(hdmi->wp.base, HDMI_WP_SYSCONFIG, 1, 3, 2);
-
-   hdmi5_core_ddc_init(>core);
-
-   edid = read(hdmi, connector);
-
-   hdmi5_core_ddc_uninit(>core);
-
-   REG_FLD_MOD(hdmi->wp.base, HDMI_WP_SYSCONFIG, idlemode, 3, 2);
-
-   hdmi_runtime_put(hdmi);
-   mutex_unlock(>lock);
-
-   if (need_enable)
-   hdmi_core_disable(hdmi);
-
-   return (struct edid *)edid;
-}
-
 /* 
-
  * DRM Bridge Operations
  */
@@ -469,18 +425,46 @@ static void hdmi5_bridge_disable(struct drm_bridge 
*bridge,
mutex_unlock(>lock);
 }
 
-static struct edid *hdmi5_bridge_read_edid(struct omap_hdmi *hdmi,
-  struct drm_connector *connector)
-{
-   return drm_do_get_edid(connector, hdmi5_core_ddc_read, >core);
-}
-
 static struct edid *hdmi5_bridge_get_edid(struct drm_bridge *bridge,
  struct drm_connector *connector)
 {
struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
+   struct edid *edid;
+   bool need_enable;
+   int idlemode;
+   int r;
+
+   need_enable = hdmi->core_enabled == false;
+
+   if (need_enable) {
+   r = hdmi_core_enable(hdmi);
+   if (r)
+   return NULL;
+   }
+
+   mutex_lock(>lock);
+   r = hdmi_runtime_get(hdmi);
+   BUG_ON(r);
 
-   return hdmi_do_read_edid(hdmi, hdmi5_bridge_read_edid, connector);
+   idlemode = REG_GET(hdmi->wp.base, HDMI_WP_SYSCONFIG, 3, 2);
+   /* No-idle mode */
+   REG_FLD_MOD(hdmi->wp.base, HDMI_WP_SYSCONFIG, 1, 3, 2);
+
+   hdmi5_core_ddc_init(>core);
+
+   edid = drm_do_get_edid(connector, hdmi5_core_ddc_read, >core);
+
+   hdmi5_core_ddc_uninit(>core);
+
+   REG_FLD_MOD(hdmi->wp.base, HDMI_WP_SYSCONFIG, idlemode, 3, 2);
+
+   hdmi_runtime_put(hdmi);
+   mutex_unlock(>lock);
+
+   if (need_enable)
+   hdmi_core_disable(hdmi);
+
+   return (struct edid *)edid;
 }
 
 static const struct drm_bridge_funcs hdmi5_bridge_funcs = {
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v6 42/51] drm/omap: dpi: Sort includes alphabetically

2020-02-16 Thread Laurent Pinchart
This makes it easier to quickly locate duplicate includes.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
---
 drivers/gpu/drm/omapdrm/dss/dpi.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c 
b/drivers/gpu/drm/omapdrm/dss/dpi.c
index 2d0eb5fcbb5b..f8354271ce6f 100644
--- a/drivers/gpu/drm/omapdrm/dss/dpi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dpi.c
@@ -9,20 +9,20 @@
 
 #define DSS_SUBSYS_NAME "DPI"
 
-#include 
+#include 
 #include 
-#include 
 #include 
 #include 
+#include 
+#include 
+#include 
 #include 
 #include 
 #include 
-#include 
-#include 
 #include 
 
-#include "omapdss.h"
 #include "dss.h"
+#include "omapdss.h"
 
 struct dpi_data {
struct platform_device *pdev;
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v6 38/51] drm/omap: hdmi: Remove omap_dss_device operations

2020-02-16 Thread Laurent Pinchart
Now that the HDMI outputs are driven fully through the drm_bridge API
their omap_dss_device operations are not used anymore. Remove them.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
---
 drivers/gpu/drm/omapdrm/dss/hdmi.h  |  1 -
 drivers/gpu/drm/omapdrm/dss/hdmi4.c | 18 --
 drivers/gpu/drm/omapdrm/dss/hdmi5.c | 18 --
 3 files changed, 37 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi.h 
b/drivers/gpu/drm/omapdrm/dss/hdmi.h
index bd43f6abf27b..3a40833d3368 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi.h
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi.h
@@ -380,7 +380,6 @@ struct omap_hdmi {
bool display_enabled;
 };
 
-#define dssdev_to_hdmi(dssdev) container_of(dssdev, struct omap_hdmi, output)
 #define drm_bridge_to_hdmi(b) container_of(b, struct omap_hdmi, bridge)
 
 #endif
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index b9bcd6e681e8..96ef7bd52199 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -309,18 +309,6 @@ void hdmi4_core_disable(struct hdmi_core_data *core)
mutex_unlock(>lock);
 }
 
-static int hdmi_connect(struct omap_dss_device *src,
-   struct omap_dss_device *dst)
-{
-   return omapdss_device_connect(dst->dss, dst, dst->next);
-}
-
-static void hdmi_disconnect(struct omap_dss_device *src,
-   struct omap_dss_device *dst)
-{
-   omapdss_device_disconnect(dst, dst->next);
-}
-
 static struct edid *
 hdmi_do_read_edid(struct omap_hdmi *hdmi,
  struct edid *(*read)(struct omap_hdmi *hdmi,
@@ -370,11 +358,6 @@ hdmi_do_read_edid(struct omap_hdmi *hdmi,
return edid;
 }
 
-static const struct omap_dss_device_ops hdmi_ops = {
-   .connect= hdmi_connect,
-   .disconnect = hdmi_disconnect,
-};
-
 /* 
-
  * DRM Bridge Operations
  */
@@ -741,7 +724,6 @@ static int hdmi4_init_output(struct omap_hdmi *hdmi)
out->type = OMAP_DISPLAY_TYPE_HDMI;
out->name = "hdmi.0";
out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
-   out->ops = _ops;
out->owner = THIS_MODULE;
out->of_port = 0;
 
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
index effe4a9401ff..6cb709c775d6 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
@@ -307,18 +307,6 @@ static void hdmi_core_disable(struct omap_hdmi *hdmi)
mutex_unlock(>lock);
 }
 
-static int hdmi_connect(struct omap_dss_device *src,
-   struct omap_dss_device *dst)
-{
-   return omapdss_device_connect(dst->dss, dst, dst->next);
-}
-
-static void hdmi_disconnect(struct omap_dss_device *src,
-   struct omap_dss_device *dst)
-{
-   omapdss_device_disconnect(dst, dst->next);
-}
-
 static struct edid *
 hdmi_do_read_edid(struct omap_hdmi *hdmi,
  struct edid *(*read)(struct omap_hdmi *hdmi,
@@ -363,11 +351,6 @@ hdmi_do_read_edid(struct omap_hdmi *hdmi,
return (struct edid *)edid;
 }
 
-static const struct omap_dss_device_ops hdmi_ops = {
-   .connect= hdmi_connect,
-   .disconnect = hdmi_disconnect,
-};
-
 /* 
-
  * DRM Bridge Operations
  */
@@ -715,7 +698,6 @@ static int hdmi5_init_output(struct omap_hdmi *hdmi)
out->type = OMAP_DISPLAY_TYPE_HDMI;
out->name = "hdmi.0";
out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
-   out->ops = _ops;
out->owner = THIS_MODULE;
out->of_port = 0;
 
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v6 43/51] drm/omap: dpi: Reorder functions in sections

2020-02-16 Thread Laurent Pinchart
Group functions based on their purpose and split them in sections to
make the source code easier to navigate.

No functional change is included.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
---
 drivers/gpu/drm/omapdrm/dss/dpi.c | 146 --
 1 file changed, 79 insertions(+), 67 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c 
b/drivers/gpu/drm/omapdrm/dss/dpi.c
index f8354271ce6f..dccf81e4ce64 100644
--- a/drivers/gpu/drm/omapdrm/dss/dpi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dpi.c
@@ -48,6 +48,10 @@ static struct dpi_data *dpi_get_data_from_dssdev(struct 
omap_dss_device *dssdev)
return container_of(dssdev, struct dpi_data, output);
 }
 
+/* 
-
+ * Clock Handling and PLL
+ */
+
 static enum dss_clk_source dpi_get_clk_src_dra7xx(struct dpi_data *dpi,
  enum omap_channel channel)
 {
@@ -366,6 +370,62 @@ static void dpi_config_lcd_manager(struct dpi_data *dpi)
dss_mgr_set_lcd_config(>output, >mgr_config);
 }
 
+static int dpi_verify_pll(struct dss_pll *pll)
+{
+   int r;
+
+   /* do initial setup with the PLL to see if it is operational */
+
+   r = dss_pll_enable(pll);
+   if (r)
+   return r;
+
+   dss_pll_disable(pll);
+
+   return 0;
+}
+
+static void dpi_init_pll(struct dpi_data *dpi)
+{
+   struct dss_pll *pll;
+
+   if (dpi->pll)
+   return;
+
+   dpi->clk_src = dpi_get_clk_src(dpi);
+
+   pll = dss_pll_find_by_src(dpi->dss, dpi->clk_src);
+   if (!pll)
+   return;
+
+   if (dpi_verify_pll(pll)) {
+   DSSWARN("PLL not operational\n");
+   return;
+   }
+
+   dpi->pll = pll;
+}
+
+/* 
-
+ * omap_dss_device Operations
+ */
+
+static int dpi_connect(struct omap_dss_device *src,
+  struct omap_dss_device *dst)
+{
+   struct dpi_data *dpi = dpi_get_data_from_dssdev(dst);
+
+   dpi_init_pll(dpi);
+
+   return omapdss_device_connect(dst->dss, dst, dst->next);
+}
+
+static void dpi_disconnect(struct omap_dss_device *src,
+  struct omap_dss_device *dst)
+{
+   omapdss_device_disconnect(dst, dst->next);
+}
+
 static void dpi_display_enable(struct omap_dss_device *dssdev)
 {
struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
@@ -446,20 +506,6 @@ static void dpi_display_disable(struct omap_dss_device 
*dssdev)
mutex_unlock(>lock);
 }
 
-static void dpi_set_timings(struct omap_dss_device *dssdev,
-   const struct drm_display_mode *mode)
-{
-   struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
-
-   DSSDBG("dpi_set_timings\n");
-
-   mutex_lock(>lock);
-
-   dpi->pixelclock = mode->clock * 1000;
-
-   mutex_unlock(>lock);
-}
-
 static int dpi_check_timings(struct omap_dss_device *dssdev,
 struct drm_display_mode *mode)
 {
@@ -500,41 +546,30 @@ static int dpi_check_timings(struct omap_dss_device 
*dssdev,
return 0;
 }
 
-static int dpi_verify_pll(struct dss_pll *pll)
+static void dpi_set_timings(struct omap_dss_device *dssdev,
+   const struct drm_display_mode *mode)
 {
-   int r;
+   struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
 
-   /* do initial setup with the PLL to see if it is operational */
+   DSSDBG("dpi_set_timings\n");
 
-   r = dss_pll_enable(pll);
-   if (r)
-   return r;
+   mutex_lock(>lock);
 
-   dss_pll_disable(pll);
+   dpi->pixelclock = mode->clock * 1000;
 
-   return 0;
+   mutex_unlock(>lock);
 }
 
-static void dpi_init_pll(struct dpi_data *dpi)
-{
-   struct dss_pll *pll;
-
-   if (dpi->pll)
-   return;
-
-   dpi->clk_src = dpi_get_clk_src(dpi);
-
-   pll = dss_pll_find_by_src(dpi->dss, dpi->clk_src);
-   if (!pll)
-   return;
+static const struct omap_dss_device_ops dpi_ops = {
+   .connect = dpi_connect,
+   .disconnect = dpi_disconnect,
 
-   if (dpi_verify_pll(pll)) {
-   DSSWARN("PLL not operational\n");
-   return;
-   }
+   .enable = dpi_display_enable,
+   .disable = dpi_display_disable,
 
-   dpi->pll = pll;
-}
+   .check_timings = dpi_check_timings,
+   .set_timings = dpi_set_timings,
+};
 
 /*
  * Return a hardcoded channel for the DPI output. This should work for
@@ -572,33 +607,6 @@ static enum omap_channel dpi_get_channel(struct dpi_data 
*dpi)
}
 }
 
-static int dpi_connect(struct omap_dss_device *src,
-  struct omap_dss_device *dst)
-{
-   struct dpi_data *dpi = dpi_get_data_from_dssdev(dst);
-
-   dpi_init_pll(dpi);
-
-   return omapdss_device_connect(dst->dss, dst, dst->next);
-}
-
-static void 

[PATCH v6 50/51] drm/omap: dss: Inline the omapdss_display_get() function

2020-02-16 Thread Laurent Pinchart
Inline the omapdss_display_get() in its only caller to simplify the
code.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
---
 drivers/gpu/drm/omapdrm/dss/display.c | 9 -
 drivers/gpu/drm/omapdrm/dss/omapdss.h | 1 -
 drivers/gpu/drm/omapdrm/omap_drv.c| 7 ---
 3 files changed, 4 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/display.c 
b/drivers/gpu/drm/omapdrm/dss/display.c
index 8a3f61f5825f..3b82158b1bfd 100644
--- a/drivers/gpu/drm/omapdrm/dss/display.c
+++ b/drivers/gpu/drm/omapdrm/dss/display.c
@@ -40,15 +40,6 @@ void omapdss_display_init(struct omap_dss_device *dssdev)
 }
 EXPORT_SYMBOL_GPL(omapdss_display_init);
 
-struct omap_dss_device *omapdss_display_get(struct omap_dss_device *output)
-{
-   while (output->next)
-   output = output->next;
-
-   return omapdss_device_get(output);
-}
-EXPORT_SYMBOL_GPL(omapdss_display_get);
-
 int omapdss_display_get_modes(struct drm_connector *connector,
  const struct videomode *vm)
 {
diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h 
b/drivers/gpu/drm/omapdrm/dss/omapdss.h
index 64aedc50cb0b..6ecbc7273032 100644
--- a/drivers/gpu/drm/omapdrm/dss/omapdss.h
+++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h
@@ -432,7 +432,6 @@ static inline bool omapdss_is_initialized(void)
 }
 
 void omapdss_display_init(struct omap_dss_device *dssdev);
-struct omap_dss_device *omapdss_display_get(struct omap_dss_device *output);
 int omapdss_display_get_modes(struct drm_connector *connector,
  const struct videomode *vm);
 
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c 
b/drivers/gpu/drm/omapdrm/omap_drv.c
index e6a065030523..cdafd7ef1c32 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -207,11 +207,12 @@ static int omap_display_id(struct omap_dss_device *output)
struct device_node *node = NULL;
 
if (output->next) {
-   struct omap_dss_device *display;
+   struct omap_dss_device *display = output;
+
+   while (display->next)
+   display = display->next;
 
-   display = omapdss_display_get(output);
node = display->dev->of_node;
-   omapdss_device_put(display);
} else if (output->bridge) {
struct drm_bridge *bridge = output->bridge;
 
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v6 39/51] drm/omap: venc: Remove omap_dss_device operations

2020-02-16 Thread Laurent Pinchart
Now that the VENC output is driven fully through the drm_bridge API its
omap_dss_device operations are not used anymore. Remove them.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
---
 drivers/gpu/drm/omapdrm/dss/venc.c | 45 --
 1 file changed, 45 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c 
b/drivers/gpu/drm/omapdrm/dss/venc.c
index c8c19967a42f..766553bb2f87 100644
--- a/drivers/gpu/drm/omapdrm/dss/venc.c
+++ b/drivers/gpu/drm/omapdrm/dss/venc.c
@@ -306,7 +306,6 @@ struct venc_device {
struct drm_bridge bridge;
 };
 
-#define dssdev_to_venc(dssdev) container_of(dssdev, struct venc_device, output)
 #define drm_bridge_to_venc(b) container_of(b, struct venc_device, bridge)
 
 static inline void venc_write_reg(struct venc_device *venc, int idx, u32 val)
@@ -479,30 +478,6 @@ static void venc_power_off(struct venc_device *venc)
venc_runtime_put(venc);
 }
 
-static int venc_get_modes(struct omap_dss_device *dssdev,
- struct drm_connector *connector)
-{
-   static const struct drm_display_mode *modes[] = {
-   _dss_pal_mode,
-   _dss_ntsc_mode,
-   };
-   unsigned int i;
-
-   for (i = 0; i < ARRAY_SIZE(modes); ++i) {
-   struct drm_display_mode *mode;
-
-   mode = drm_mode_duplicate(connector->dev, modes[i]);
-   if (!mode)
-   return i;
-
-   mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
-   drm_mode_set_name(mode);
-   drm_mode_probed_add(connector, mode);
-   }
-
-   return ARRAY_SIZE(modes);
-}
-
 static enum venc_videomode venc_get_videomode(const struct drm_display_mode 
*mode)
 {
if (!(mode->flags & DRM_MODE_FLAG_INTERLACE))
@@ -598,25 +573,6 @@ static int venc_get_clocks(struct venc_device *venc)
return 0;
 }
 
-static int venc_connect(struct omap_dss_device *src,
-   struct omap_dss_device *dst)
-{
-   return omapdss_device_connect(dst->dss, dst, dst->next);
-}
-
-static void venc_disconnect(struct omap_dss_device *src,
-   struct omap_dss_device *dst)
-{
-   omapdss_device_disconnect(dst, dst->next);
-}
-
-static const struct omap_dss_device_ops venc_ops = {
-   .connect = venc_connect,
-   .disconnect = venc_disconnect,
-
-   .get_modes = venc_get_modes,
-};
-
 /* 
-
  * DRM Bridge Operations
  */
@@ -816,7 +772,6 @@ static int venc_init_output(struct venc_device *venc)
out->type = OMAP_DISPLAY_TYPE_VENC;
out->name = "venc.0";
out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
-   out->ops = _ops;
out->owner = THIS_MODULE;
out->of_port = 0;
out->ops_flags = OMAP_DSS_DEVICE_OP_MODES;
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v6 32/51] drm/omap: hdmi4: Implement drm_bridge .hpd_notify() operation

2020-02-16 Thread Laurent Pinchart
The HDMI4 encoder is transitioning to the drm_bridge API, implement the
last missing operation.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
---
 drivers/gpu/drm/omapdrm/dss/hdmi4.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index a8d13a081a9a..73f1fab346e9 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -553,6 +553,15 @@ static void hdmi4_bridge_disable(struct drm_bridge *bridge,
mutex_unlock(>lock);
 }
 
+static void hdmi4_bridge_hpd_notify(struct drm_bridge *bridge,
+   enum drm_connector_status status)
+{
+   struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
+
+   if (status == connector_status_disconnected)
+   hdmi4_cec_set_phys_addr(>core, CEC_PHYS_ADDR_INVALID);
+}
+
 static struct edid *hdmi4_bridge_read_edid(struct omap_hdmi *hdmi,
   struct drm_connector *connector)
 {
@@ -575,6 +584,7 @@ static const struct drm_bridge_funcs hdmi4_bridge_funcs = {
.atomic_reset = drm_atomic_helper_bridge_reset,
.atomic_enable = hdmi4_bridge_enable,
.atomic_disable = hdmi4_bridge_disable,
+   .hpd_notify = hdmi4_bridge_hpd_notify,
.get_edid = hdmi4_bridge_get_edid,
 };
 
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v6 35/51] drm/omap: Create connector for bridges

2020-02-16 Thread Laurent Pinchart
Use the drm_bridge_connector helper to create a connector for pipelines
that use drm_bridge. This allows splitting connector operations across
multiple bridges when necessary, instead of having the last bridge in
the chain creating the connector and handling all connector operations
internally.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
---
Changes since v3:

- Remove outdated comment

Changes since v1:

- Squash with patch "drm/omap: Detach from panels at remove time"
---
 drivers/gpu/drm/omapdrm/omap_drv.c | 74 +-
 1 file changed, 62 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c 
b/drivers/gpu/drm/omapdrm/omap_drv.c
index 1df509342b5d..47afa37055b3 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -12,10 +12,12 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -291,9 +293,14 @@ static int omap_modeset_init(struct drm_device *dev)
 
if (pipe->output->bridge) {
ret = drm_bridge_attach(pipe->encoder,
-   pipe->output->bridge, NULL, 0);
-   if (ret < 0)
+   pipe->output->bridge, NULL,
+   DRM_BRIDGE_ATTACH_NO_CONNECTOR);
+   if (ret < 0) {
+   dev_err(priv->dev,
+   "unable to attach bridge %pOF\n",
+   pipe->output->bridge->of_node);
return ret;
+   }
}
 
id = omap_display_id(pipe->output);
@@ -329,8 +336,23 @@ static int omap_modeset_init(struct drm_device *dev)
  encoder);
if (!pipe->connector)
return -ENOMEM;
+   } else {
+   pipe->connector = drm_bridge_connector_init(dev, 
encoder);
+   if (IS_ERR(pipe->connector)) {
+   dev_err(priv->dev,
+   "unable to create bridge connector for 
%s\n",
+   pipe->output->name);
+   return PTR_ERR(pipe->connector);
+   }
+   }
 
-   drm_connector_attach_encoder(pipe->connector, encoder);
+   drm_connector_attach_encoder(pipe->connector, encoder);
+
+   if (pipe->output->panel) {
+   ret = drm_panel_attach(pipe->output->panel,
+  pipe->connector);
+   if (ret < 0)
+   return ret;
}
 
crtc = omap_crtc_init(dev, pipe, priv->planes[i]);
@@ -369,6 +391,23 @@ static int omap_modeset_init(struct drm_device *dev)
return 0;
 }
 
+static void omap_modeset_fini(struct drm_device *ddev)
+{
+   struct omap_drm_private *priv = ddev->dev_private;
+   unsigned int i;
+
+   omap_drm_irq_uninstall(ddev);
+
+   for (i = 0; i < priv->num_pipes; i++) {
+   struct omap_drm_pipeline *pipe = >pipes[i];
+
+   if (pipe->output->panel)
+   drm_panel_detach(pipe->output->panel);
+   }
+
+   drm_mode_config_cleanup(ddev);
+}
+
 /*
  * Enable the HPD in external components if supported
  */
@@ -378,8 +417,15 @@ static void omap_modeset_enable_external_hpd(struct 
drm_device *ddev)
unsigned int i;
 
for (i = 0; i < priv->num_pipes; i++) {
-   if (priv->pipes[i].connector)
-   omap_connector_enable_hpd(priv->pipes[i].connector);
+   struct drm_connector *connector = priv->pipes[i].connector;
+
+   if (!connector)
+   continue;
+
+   if (priv->pipes[i].output->next)
+   omap_connector_enable_hpd(connector);
+   else
+   drm_bridge_connector_enable_hpd(connector);
}
 }
 
@@ -392,8 +438,15 @@ static void omap_modeset_disable_external_hpd(struct 
drm_device *ddev)
unsigned int i;
 
for (i = 0; i < priv->num_pipes; i++) {
-   if (priv->pipes[i].connector)
-   omap_connector_disable_hpd(priv->pipes[i].connector);
+   struct drm_connector *connector = priv->pipes[i].connector;
+
+   if (!connector)
+   continue;
+
+   if (priv->pipes[i].output->next)
+   omap_connector_disable_hpd(connector);
+   else
+   drm_bridge_connector_disable_hpd(connector);
}
 }
 
@@ -616,8 +669,7 @@ static int omapdrm_init(struct 

[PATCH v6 21/51] drm/omap: Use the drm_panel_bridge API

2020-02-16 Thread Laurent Pinchart
Replace the manual panel handling code by a drm_panel_bridge. This
simplifies the driver and allows all components in the display pipeline
to be treated as bridges, paving the way to generic connector handling.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
---
Changes since v1:

- Keep #include 
---
 drivers/gpu/drm/omapdrm/dss/base.c   | 12 -
 drivers/gpu/drm/omapdrm/dss/output.c | 31 +---
 drivers/gpu/drm/omapdrm/omap_connector.c | 10 
 drivers/gpu/drm/omapdrm/omap_drv.c   | 13 --
 drivers/gpu/drm/omapdrm/omap_encoder.c   | 13 --
 5 files changed, 32 insertions(+), 47 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/base.c 
b/drivers/gpu/drm/omapdrm/dss/base.c
index cae5687822e2..80d48936d177 100644
--- a/drivers/gpu/drm/omapdrm/dss/base.c
+++ b/drivers/gpu/drm/omapdrm/dss/base.c
@@ -149,8 +149,7 @@ struct omap_dss_device *omapdss_device_next_output(struct 
omap_dss_device *from)
goto done;
}
 
-   if (dssdev->id &&
-   (dssdev->next || dssdev->bridge || dssdev->panel))
+   if (dssdev->id && (dssdev->next || dssdev->bridge))
goto done;
}
 
@@ -185,11 +184,10 @@ int omapdss_device_connect(struct dss_device *dss,
if (!dst) {
/*
 * The destination is NULL when the source is connected to a
-* bridge or panel instead of a DSS device. Stop here, we will
-* attach the bridge or panel later when we will have a DRM
-* encoder.
+* bridge instead of a DSS device. Stop here, we will attach
+* the bridge later when we will have a DRM encoder.
 */
-   return src && (src->bridge || src->panel) ? 0 : -EINVAL;
+   return src && src->bridge ? 0 : -EINVAL;
}
 
if (omapdss_device_is_connected(dst))
@@ -217,7 +215,7 @@ void omapdss_device_disconnect(struct omap_dss_device *src,
dst ? dev_name(dst->dev) : "NULL");
 
if (!dst) {
-   WARN_ON(!src->bridge && !src->panel);
+   WARN_ON(!src->bridge);
return;
}
 
diff --git a/drivers/gpu/drm/omapdrm/dss/output.c 
b/drivers/gpu/drm/omapdrm/dss/output.c
index 0693d34fca1b..99a253a424c1 100644
--- a/drivers/gpu/drm/omapdrm/dss/output.c
+++ b/drivers/gpu/drm/omapdrm/dss/output.c
@@ -21,6 +21,7 @@
 int omapdss_device_init_output(struct omap_dss_device *out)
 {
struct device_node *remote_node;
+   int ret;
 
remote_node = of_graph_get_remote_node(out->dev->of_node,
   ffs(out->of_ports) - 1, 0);
@@ -39,17 +40,39 @@ int omapdss_device_init_output(struct omap_dss_device *out)
 
if (out->next && out->type != out->next->type) {
dev_err(out->dev, "output type and display type don't match\n");
-   omapdss_device_put(out->next);
-   out->next = NULL;
-   return -EINVAL;
+   ret = -EINVAL;
+   goto error;
}
 
-   return out->next || out->bridge || out->panel ? 0 : -EPROBE_DEFER;
+   if (out->panel) {
+   struct drm_bridge *bridge;
+
+   bridge = drm_panel_bridge_add(out->panel);
+   if (IS_ERR(bridge)) {
+   dev_err(out->dev,
+   "unable to create panel bridge (%ld)\n",
+   PTR_ERR(bridge));
+   ret = PTR_ERR(bridge);
+   goto error;
+   }
+
+   out->bridge = bridge;
+   }
+
+   return out->next || out->bridge ? 0 : -EPROBE_DEFER;
+
+error:
+   omapdss_device_put(out->next);
+   out->next = NULL;
+   return ret;
 }
 EXPORT_SYMBOL(omapdss_device_init_output);
 
 void omapdss_device_cleanup_output(struct omap_dss_device *out)
 {
+   if (out->bridge && out->panel)
+   drm_panel_bridge_remove(out->bridge);
+
if (out->next)
omapdss_device_put(out->next);
 }
diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c 
b/drivers/gpu/drm/omapdrm/omap_connector.c
index 38c7a79c5d4a..b0cb2ecb30ab 100644
--- a/drivers/gpu/drm/omapdrm/omap_connector.c
+++ b/drivers/gpu/drm/omapdrm/omap_connector.c
@@ -6,7 +6,6 @@
 
 #include 
 #include 
-#include 
 #include 
 
 #include "omap_drv.h"
@@ -190,7 +189,6 @@ static int omap_connector_get_modes_edid(struct 
drm_connector *connector,
 
 static int omap_connector_get_modes(struct drm_connector *connector)
 {
-   struct omap_connector *omap_connector = to_omap_connector(connector);
struct omap_dss_device *dssdev;
 
DBG("%s", connector->name);
@@ -213,14 +211,6 @@ static int omap_connector_get_modes(struct drm_connector 
*connector)
if (dssdev)
return dssdev->ops->get_modes(dssdev, connector);
 
-   

[PATCH v6 29/51] drm/omap: hdmi5: Register a drm_bridge for EDID read

2020-02-16 Thread Laurent Pinchart
In order to integrate with a chain of drm_bridge, the internal HDMI5
encoder has to expose the EDID read operation through the drm_bridge
API. Register a bridge at initialisation time to do so.

For the time being make the next bridge in the chain optional as the
HDMI output is still based on omap_dss_device. The create_connector
argument to the bridge attach function is also ignored for the same
reason. This will be changed later when removing the related
omapdrm-specific display drivers.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
---
Changes since v2:

- Unregister bridge if output initialisation fails
---
 drivers/gpu/drm/omapdrm/dss/hdmi5.c | 79 ++---
 1 file changed, 73 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
index 2b02b0a11696..e7fe2a24a3e1 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
@@ -388,8 +388,10 @@ static void hdmi_disconnect(struct omap_dss_device *src,
 
 #define MAX_EDID   512
 
-static struct edid *hdmi_read_edid_data(struct hdmi_core_data *core)
+static struct edid *hdmi_read_edid_data(struct omap_hdmi *hdmi,
+   struct drm_connector *connector)
 {
+   struct hdmi_core_data *core = >core;
int max_ext_blocks = 3;
int r, n, i;
u8 *edid;
@@ -421,9 +423,12 @@ static struct edid *hdmi_read_edid_data(struct 
hdmi_core_data *core)
return NULL;
 }
 
-static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
+static struct edid *
+hdmi_do_read_edid(struct omap_hdmi *hdmi,
+ struct edid *(*read)(struct omap_hdmi *hdmi,
+  struct drm_connector *connector),
+ struct drm_connector *connector)
 {
-   struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
struct edid *edid;
bool need_enable;
int idlemode;
@@ -447,7 +452,7 @@ static struct edid *hdmi_read_edid(struct omap_dss_device 
*dssdev)
 
hdmi5_core_ddc_init(>core);
 
-   edid = hdmi_read_edid_data(>core);
+   edid = read(hdmi, connector);
 
hdmi5_core_ddc_uninit(>core);
 
@@ -462,6 +467,12 @@ static struct edid *hdmi_read_edid(struct omap_dss_device 
*dssdev)
return (struct edid *)edid;
 }
 
+static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
+{
+   return hdmi_do_read_edid(dssdev_to_hdmi(dssdev), hdmi_read_edid_data,
+NULL);
+}
+
 static int hdmi_set_infoframe(struct omap_dss_device *dssdev,
const struct hdmi_avi_infoframe *avi)
 {
@@ -497,6 +508,56 @@ static const struct omap_dss_device_ops hdmi_ops = {
},
 };
 
+/* 
-
+ * DRM Bridge Operations
+ */
+
+static int hdmi5_bridge_attach(struct drm_bridge *bridge,
+  enum drm_bridge_attach_flags flags)
+{
+   struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
+
+   if (!hdmi->output.next_bridge)
+   return 0;
+
+   return drm_bridge_attach(bridge->encoder, hdmi->output.next_bridge,
+bridge, flags);
+}
+
+static struct edid *hdmi5_bridge_read_edid(struct omap_hdmi *hdmi,
+  struct drm_connector *connector)
+{
+   return drm_do_get_edid(connector, hdmi5_core_ddc_read, >core);
+}
+
+static struct edid *hdmi5_bridge_get_edid(struct drm_bridge *bridge,
+ struct drm_connector *connector)
+{
+   struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
+
+   return hdmi_do_read_edid(hdmi, hdmi5_bridge_read_edid, connector);
+}
+
+static const struct drm_bridge_funcs hdmi5_bridge_funcs = {
+   .attach = hdmi5_bridge_attach,
+   .get_edid = hdmi5_bridge_get_edid,
+};
+
+static void hdmi5_bridge_init(struct omap_hdmi *hdmi)
+{
+   hdmi->bridge.funcs = _bridge_funcs;
+   hdmi->bridge.of_node = hdmi->pdev->dev.of_node;
+   hdmi->bridge.ops = DRM_BRIDGE_OP_EDID;
+   hdmi->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
+
+   drm_bridge_add(>bridge);
+}
+
+static void hdmi5_bridge_cleanup(struct omap_hdmi *hdmi)
+{
+   drm_bridge_remove(>bridge);
+}
+
 /* 
-
  * Audio Callbacks
  */
@@ -679,6 +740,8 @@ static int hdmi5_init_output(struct omap_hdmi *hdmi)
struct omap_dss_device *out = >output;
int r;
 
+   hdmi5_bridge_init(hdmi);
+
out->dev = >pdev->dev;
out->id = OMAP_DSS_OUTPUT_HDMI;
out->type = OMAP_DISPLAY_TYPE_HDMI;
@@ -689,9 +752,11 @@ static int hdmi5_init_output(struct omap_hdmi *hdmi)
out->of_port = 0;
out->ops_flags = OMAP_DSS_DEVICE_OP_EDID;
 
-   r = omapdss_device_init_output(out, NULL);
-   if (r < 0)
+   r = omapdss_device_init_output(out, 

[PATCH v6 19/51] drm/omap: Simplify HDMI mode and infoframe configuration

2020-02-16 Thread Laurent Pinchart
Remove the omap_connector_get_hdmi_mode() function as the HDMI mode can
be accessed directly from the connector's display info.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
Acked-by: Sam Ravnborg 
---
 drivers/gpu/drm/omapdrm/omap_connector.c | 11 ---
 drivers/gpu/drm/omapdrm/omap_connector.h |  1 -
 drivers/gpu/drm/omapdrm/omap_encoder.c   |  4 +---
 3 files changed, 1 insertion(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c 
b/drivers/gpu/drm/omapdrm/omap_connector.c
index 94cded387174..88dbf3fa473f 100644
--- a/drivers/gpu/drm/omapdrm/omap_connector.c
+++ b/drivers/gpu/drm/omapdrm/omap_connector.c
@@ -21,7 +21,6 @@ struct omap_connector {
struct drm_connector base;
struct omap_dss_device *output;
struct omap_dss_device *hpd;
-   bool hdmi_mode;
 };
 
 static void omap_connector_hpd_notify(struct drm_connector *connector,
@@ -84,13 +83,6 @@ void omap_connector_disable_hpd(struct drm_connector 
*connector)
hpd->ops->unregister_hpd_cb(hpd);
 }
 
-bool omap_connector_get_hdmi_mode(struct drm_connector *connector)
-{
-   struct omap_connector *omap_connector = to_omap_connector(connector);
-
-   return omap_connector->hdmi_mode;
-}
-
 static struct omap_dss_device *
 omap_connector_find_device(struct drm_connector *connector,
   enum omap_dss_device_ops_flag op)
@@ -167,7 +159,6 @@ static void omap_connector_destroy(struct drm_connector 
*connector)
 static int omap_connector_get_modes_edid(struct drm_connector *connector,
 struct omap_dss_device *dssdev)
 {
-   struct omap_connector *omap_connector = to_omap_connector(connector);
enum drm_connector_status status;
void *edid;
int n;
@@ -189,8 +180,6 @@ static int omap_connector_get_modes_edid(struct 
drm_connector *connector,
drm_connector_update_edid_property(connector, edid);
n = drm_add_edid_modes(connector, edid);
 
-   omap_connector->hdmi_mode = drm_detect_hdmi_monitor(edid);
-
kfree(edid);
return n;
 
diff --git a/drivers/gpu/drm/omapdrm/omap_connector.h 
b/drivers/gpu/drm/omapdrm/omap_connector.h
index 13607bda33d8..4aa5608f4bbe 100644
--- a/drivers/gpu/drm/omapdrm/omap_connector.h
+++ b/drivers/gpu/drm/omapdrm/omap_connector.h
@@ -21,7 +21,6 @@ struct omap_dss_device;
 struct drm_connector *omap_connector_init(struct drm_device *dev,
  struct omap_dss_device *output,
  struct drm_encoder *encoder);
-bool omap_connector_get_hdmi_mode(struct drm_connector *connector);
 void omap_connector_enable_hpd(struct drm_connector *connector);
 void omap_connector_disable_hpd(struct drm_connector *connector);
 enum drm_mode_status omap_connector_mode_fixup(struct omap_dss_device *dssdev,
diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c 
b/drivers/gpu/drm/omapdrm/omap_encoder.c
index 4f2165a37795..cb5aa01d2f87 100644
--- a/drivers/gpu/drm/omapdrm/omap_encoder.c
+++ b/drivers/gpu/drm/omapdrm/omap_encoder.c
@@ -76,9 +76,7 @@ static void omap_encoder_hdmi_mode_set(struct drm_connector 
*connector,
 {
struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
struct omap_dss_device *dssdev = omap_encoder->output;
-   bool hdmi_mode;
-
-   hdmi_mode = omap_connector_get_hdmi_mode(connector);
+   bool hdmi_mode = connector->display_info.is_hdmi;
 
if (dssdev->ops->hdmi.set_hdmi_mode)
dssdev->ops->hdmi.set_hdmi_mode(dssdev, hdmi_mode);
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v6 47/51] drm/omap: sdi: Register a drm_bridge

2020-02-16 Thread Laurent Pinchart
In order to integrate with a chain of drm_bridge, the internal SDI
output has to expose its operations through the drm_bridge API.
Register a bridge at initialisation time to do so and remove the
omap_dss_device operations that are now unused.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
---
Changes since v5:

- Rebased on top of drm_bridge_state

Changes since v3:

- Split dss/base.h and omap_connector.c cleanups to a separate patch

Changes since v2:

- Remove unused omapdss_device_connector_type() function
- Unregister bridge if port initialisation fails
---
 drivers/gpu/drm/omapdrm/dss/sdi.c | 168 +++---
 1 file changed, 109 insertions(+), 59 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/sdi.c 
b/drivers/gpu/drm/omapdrm/dss/sdi.c
index 7dedfcc86922..417a8740ad0a 100644
--- a/drivers/gpu/drm/omapdrm/dss/sdi.c
+++ b/drivers/gpu/drm/omapdrm/dss/sdi.c
@@ -15,6 +15,8 @@
 #include 
 #include 
 
+#include 
+
 #include "dss.h"
 #include "omapdss.h"
 
@@ -30,9 +32,11 @@ struct sdi_device {
int datapairs;
 
struct omap_dss_device output;
+   struct drm_bridge bridge;
 };
 
-#define dssdev_to_sdi(dssdev) container_of(dssdev, struct sdi_device, output)
+#define drm_bridge_to_sdi(bridge) \
+   container_of(bridge, struct sdi_device, bridge)
 
 struct sdi_clk_calc_ctx {
struct sdi_device *sdi;
@@ -118,9 +122,82 @@ static void sdi_config_lcd_manager(struct sdi_device *sdi)
dss_mgr_set_lcd_config(>output, >mgr_config);
 }
 
-static void sdi_display_enable(struct omap_dss_device *dssdev)
+/* 
-
+ * DRM Bridge Operations
+ */
+
+static int sdi_bridge_attach(struct drm_bridge *bridge,
+enum drm_bridge_attach_flags flags)
+{
+   struct sdi_device *sdi = drm_bridge_to_sdi(bridge);
+
+   if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR))
+   return -EINVAL;
+
+   return drm_bridge_attach(bridge->encoder, sdi->output.next_bridge,
+bridge, flags);
+}
+
+static enum drm_mode_status
+sdi_bridge_mode_valid(struct drm_bridge *bridge,
+ const struct drm_display_mode *mode)
+{
+   struct sdi_device *sdi = drm_bridge_to_sdi(bridge);
+   unsigned long pixelclock = mode->clock * 1000;
+   struct dispc_clock_info dispc_cinfo;
+   unsigned long fck;
+   int ret;
+
+   if (pixelclock == 0)
+   return MODE_NOCLOCK;
+
+   ret = sdi_calc_clock_div(sdi, pixelclock, , _cinfo);
+   if (ret < 0)
+   return MODE_CLOCK_RANGE;
+
+   return MODE_OK;
+}
+
+static bool sdi_bridge_mode_fixup(struct drm_bridge *bridge,
+ const struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+   struct sdi_device *sdi = drm_bridge_to_sdi(bridge);
+   unsigned long pixelclock = mode->clock * 1000;
+   struct dispc_clock_info dispc_cinfo;
+   unsigned long fck;
+   unsigned long pck;
+   int ret;
+
+   ret = sdi_calc_clock_div(sdi, pixelclock, , _cinfo);
+   if (ret < 0)
+   return false;
+
+   pck = fck / dispc_cinfo.lck_div / dispc_cinfo.pck_div;
+
+   if (pck != pixelclock)
+   dev_dbg(>pdev->dev,
+   "pixel clock adjusted from %lu Hz to %lu Hz\n",
+   pixelclock, pck);
+
+   adjusted_mode->clock = pck / 1000;
+
+   return true;
+}
+
+static void sdi_bridge_mode_set(struct drm_bridge *bridge,
+   const struct drm_display_mode *mode,
+   const struct drm_display_mode *adjusted_mode)
+{
+   struct sdi_device *sdi = drm_bridge_to_sdi(bridge);
+
+   sdi->pixelclock = adjusted_mode->clock * 1000;
+}
+
+static void sdi_bridge_enable(struct drm_bridge *bridge,
+ struct drm_bridge_state *bridge_state)
 {
-   struct sdi_device *sdi = dssdev_to_sdi(dssdev);
+   struct sdi_device *sdi = drm_bridge_to_sdi(bridge);
struct dispc_clock_info dispc_cinfo;
unsigned long fck;
int r;
@@ -181,9 +258,10 @@ static void sdi_display_enable(struct omap_dss_device 
*dssdev)
regulator_disable(sdi->vdds_sdi_reg);
 }
 
-static void sdi_display_disable(struct omap_dss_device *dssdev)
+static void sdi_bridge_disable(struct drm_bridge *bridge,
+  struct drm_bridge_state *bridge_state)
 {
-   struct sdi_device *sdi = dssdev_to_sdi(dssdev);
+   struct sdi_device *sdi = drm_bridge_to_sdi(bridge);
 
dss_mgr_disable(>output);
 
@@ -194,71 +272,40 @@ static void sdi_display_disable(struct omap_dss_device 
*dssdev)
regulator_disable(sdi->vdds_sdi_reg);
 }
 
-static void sdi_set_timings(struct omap_dss_device *dssdev,
-   const struct drm_display_mode *mode)
-{
-   struct 

[PATCH v6 13/51] drm/bridge: Add driver for the TI TPD12S015 HDMI level shifter

2020-02-16 Thread Laurent Pinchart
The TI TPD12S015 is an HDMI level shifter and ESD protector controlled
through GPIOs. Add a DRM bridge driver for the device.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
Acked-by: Sam Ravnborg 
---
Changes since v2:

- Control CT_CP_HPD GPIO from .hpd_enable() and .hpd_disable()
- Remove unneeded hpd_gpio zero check
- Update copyright notice

Changes since v1:

- Remove empty .hpd_enable() and .hpd_disable() operations
---
 drivers/gpu/drm/bridge/Kconfig|   8 +
 drivers/gpu/drm/bridge/Makefile   |   1 +
 drivers/gpu/drm/bridge/ti-tpd12s015.c | 211 ++
 3 files changed, 220 insertions(+)
 create mode 100644 drivers/gpu/drm/bridge/ti-tpd12s015.c

diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index d63283661850..aaed2347ace9 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -172,6 +172,14 @@ config DRM_TI_SN65DSI86
help
  Texas Instruments SN65DSI86 DSI to eDP Bridge driver
 
+config DRM_TI_TPD12S015
+   tristate "TI TPD12S015 HDMI level shifter and ESD protection"
+   depends on OF
+   select DRM_KMS_HELPER
+   help
+ Texas Instruments TPD12S015 HDMI level shifter and ESD protection
+ driver.
+
 source "drivers/gpu/drm/bridge/analogix/Kconfig"
 
 source "drivers/gpu/drm/bridge/adv7511/Kconfig"
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index 17f1f155e803..6fb062b5b0f0 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_DRM_TOSHIBA_TC358768) += tc358768.o
 obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511/
 obj-$(CONFIG_DRM_TI_SN65DSI86) += ti-sn65dsi86.o
 obj-$(CONFIG_DRM_TI_TFP410) += ti-tfp410.o
+obj-$(CONFIG_DRM_TI_TPD12S015) += ti-tpd12s015.o
 
 obj-y += analogix/
 obj-y += synopsys/
diff --git a/drivers/gpu/drm/bridge/ti-tpd12s015.c 
b/drivers/gpu/drm/bridge/ti-tpd12s015.c
new file mode 100644
index ..514cbf0eac75
--- /dev/null
+++ b/drivers/gpu/drm/bridge/ti-tpd12s015.c
@@ -0,0 +1,211 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * TPD12S015 HDMI ESD protection & level shifter chip driver
+ *
+ * Copyright (C) 2019 Texas Instruments Incorporated
+ *
+ * Based on the omapdrm-specific encoder-opa362 driver
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated
+ * Author: Tomi Valkeinen 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+struct tpd12s015_device {
+   struct drm_bridge bridge;
+
+   struct gpio_desc *ct_cp_hpd_gpio;
+   struct gpio_desc *ls_oe_gpio;
+   struct gpio_desc *hpd_gpio;
+   int hpd_irq;
+
+   struct drm_bridge *next_bridge;
+};
+
+static inline struct tpd12s015_device *to_tpd12s015(struct drm_bridge *bridge)
+{
+   return container_of(bridge, struct tpd12s015_device, bridge);
+}
+
+static int tpd12s015_attach(struct drm_bridge *bridge,
+   enum drm_bridge_attach_flags flags)
+{
+   struct tpd12s015_device *tpd = to_tpd12s015(bridge);
+   int ret;
+
+   if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR))
+   return -EINVAL;
+
+   ret = drm_bridge_attach(bridge->encoder, tpd->next_bridge,
+   bridge, flags);
+   if (ret < 0)
+   return ret;
+
+   gpiod_set_value_cansleep(tpd->ls_oe_gpio, 1);
+
+   /* DC-DC converter needs at max 300us to get to 90% of 5V. */
+   usleep_range(300, 1000);
+
+   return 0;
+}
+
+static void tpd12s015_detach(struct drm_bridge *bridge)
+{
+   struct tpd12s015_device *tpd = to_tpd12s015(bridge);
+
+   gpiod_set_value_cansleep(tpd->ls_oe_gpio, 0);
+}
+
+static enum drm_connector_status tpd12s015_detect(struct drm_bridge *bridge)
+{
+   struct tpd12s015_device *tpd = to_tpd12s015(bridge);
+
+   if (gpiod_get_value_cansleep(tpd->hpd_gpio))
+   return connector_status_connected;
+   else
+   return connector_status_disconnected;
+}
+
+static void tpd12s015_hpd_enable(struct drm_bridge *bridge)
+{
+   struct tpd12s015_device *tpd = to_tpd12s015(bridge);
+
+   gpiod_set_value_cansleep(tpd->ct_cp_hpd_gpio, 1);
+}
+
+static void tpd12s015_hpd_disable(struct drm_bridge *bridge)
+{
+   struct tpd12s015_device *tpd = to_tpd12s015(bridge);
+
+   gpiod_set_value_cansleep(tpd->ct_cp_hpd_gpio, 0);
+}
+
+static const struct drm_bridge_funcs tpd12s015_bridge_funcs = {
+   .attach = tpd12s015_attach,
+   .detach = tpd12s015_detach,
+   .detect = tpd12s015_detect,
+   .hpd_enable = tpd12s015_hpd_enable,
+   .hpd_disable= tpd12s015_hpd_disable,
+};
+
+static irqreturn_t tpd12s015_hpd_isr(int irq, void *data)
+{
+   struct tpd12s015_device *tpd = data;
+   struct drm_bridge *bridge = >bridge;
+
+   drm_bridge_hpd_notify(bridge, tpd12s015_detect(bridge));

[PATCH v6 46/51] drm/omap: sdi: Sort includes alphabetically

2020-02-16 Thread Laurent Pinchart
This makes it easier to quickly locate duplicate includes.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
---
 drivers/gpu/drm/omapdrm/dss/sdi.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/sdi.c 
b/drivers/gpu/drm/omapdrm/dss/sdi.c
index 11aa2f712ff4..7dedfcc86922 100644
--- a/drivers/gpu/drm/omapdrm/dss/sdi.c
+++ b/drivers/gpu/drm/omapdrm/dss/sdi.c
@@ -6,17 +6,17 @@
 
 #define DSS_SUBSYS_NAME "SDI"
 
-#include 
 #include 
 #include 
-#include 
 #include 
+#include 
+#include 
 #include 
+#include 
 #include 
-#include 
 
-#include "omapdss.h"
 #include "dss.h"
+#include "omapdss.h"
 
 struct sdi_device {
struct platform_device *pdev;
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v6 44/51] drm/omap: dpi: Simplify clock setting API

2020-02-16 Thread Laurent Pinchart
The dpi_set_pll_clk() and dpi_set_dispc_clk() return various information
through pointer arguments that are never used by the callers. Remove
them to simplify the clock setting API.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
---
 drivers/gpu/drm/omapdrm/dss/dpi.c | 32 ---
 1 file changed, 8 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c 
b/drivers/gpu/drm/omapdrm/dss/dpi.c
index dccf81e4ce64..c167bd1116ec 100644
--- a/drivers/gpu/drm/omapdrm/dss/dpi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dpi.c
@@ -287,9 +287,7 @@ static bool dpi_dss_clk_calc(struct dpi_data *dpi, unsigned 
long pck,
 
 
 
-static int dpi_set_pll_clk(struct dpi_data *dpi, enum omap_channel channel,
-   unsigned long pck_req, unsigned long *fck, int *lck_div,
-   int *pck_div)
+static int dpi_set_pll_clk(struct dpi_data *dpi, unsigned long pck_req)
 {
struct dpi_clk_calc_ctx ctx;
int r;
@@ -303,19 +301,15 @@ static int dpi_set_pll_clk(struct dpi_data *dpi, enum 
omap_channel channel,
if (r)
return r;
 
-   dss_select_lcd_clk_source(dpi->dss, channel, dpi->clk_src);
+   dss_select_lcd_clk_source(dpi->dss, dpi->output.dispc_channel,
+ dpi->clk_src);
 
dpi->mgr_config.clock_info = ctx.dispc_cinfo;
 
-   *fck = ctx.pll_cinfo.clkout[ctx.clkout_idx];
-   *lck_div = ctx.dispc_cinfo.lck_div;
-   *pck_div = ctx.dispc_cinfo.pck_div;
-
return 0;
 }
 
-static int dpi_set_dispc_clk(struct dpi_data *dpi, unsigned long pck_req,
-   unsigned long *fck, int *lck_div, int *pck_div)
+static int dpi_set_dispc_clk(struct dpi_data *dpi, unsigned long pck_req)
 {
struct dpi_clk_calc_ctx ctx;
int r;
@@ -331,29 +325,19 @@ static int dpi_set_dispc_clk(struct dpi_data *dpi, 
unsigned long pck_req,
 
dpi->mgr_config.clock_info = ctx.dispc_cinfo;
 
-   *fck = ctx.fck;
-   *lck_div = ctx.dispc_cinfo.lck_div;
-   *pck_div = ctx.dispc_cinfo.pck_div;
-
return 0;
 }
 
 static int dpi_set_mode(struct dpi_data *dpi)
 {
-   int lck_div = 0, pck_div = 0;
-   unsigned long fck = 0;
-   int r = 0;
+   int r;
 
if (dpi->pll)
-   r = dpi_set_pll_clk(dpi, dpi->output.dispc_channel,
-   dpi->pixelclock, , _div, _div);
+   r = dpi_set_pll_clk(dpi, dpi->pixelclock);
else
-   r = dpi_set_dispc_clk(dpi, dpi->pixelclock, ,
-   _div, _div);
-   if (r)
-   return r;
+   r = dpi_set_dispc_clk(dpi, dpi->pixelclock);
 
-   return 0;
+   return r;
 }
 
 static void dpi_config_lcd_manager(struct dpi_data *dpi)
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v6 25/51] drm/omap: hdmi: Allocate EDID in the .read_edid() operation

2020-02-16 Thread Laurent Pinchart
Bring the omapdss-specific .read_edid() operation in sync with the
drm_bridge .get_edid() operation to ease code reuse.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
---
Changes since v1:

- Keep MAX_EDID macro
---
 drivers/gpu/drm/omapdrm/dss/hdmi4.c  | 36 
 drivers/gpu/drm/omapdrm/dss/hdmi5.c  | 24 
 drivers/gpu/drm/omapdrm/dss/omapdss.h|  2 +-
 drivers/gpu/drm/omapdrm/omap_connector.c | 12 ++--
 4 files changed, 47 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index dd4a14fe7e59..e15fa3862922 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -405,31 +405,45 @@ static void hdmi_disconnect(struct omap_dss_device *src,
omapdss_device_disconnect(dst, dst->next);
 }
 
-static int hdmi_read_edid(struct omap_dss_device *dssdev,
-   u8 *edid, int len)
+#define MAX_EDID   512
+
+static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
 {
struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
bool need_enable;
+   u8 *edid;
int r;
 
+   edid = kzalloc(MAX_EDID, GFP_KERNEL);
+   if (!edid)
+   return NULL;
+
need_enable = hdmi->core_enabled == false;
 
if (need_enable) {
r = hdmi4_core_enable(>core);
-   if (r)
-   return r;
+   if (r) {
+   kfree(edid);
+   return NULL;
+   }
+   }
+
+   r = read_edid(hdmi, edid, MAX_EDID);
+   if (r < 0) {
+   kfree(edid);
+   edid = NULL;
+   } else {
+   unsigned int cec_addr;
+
+   cec_addr = r >= 256 ? cec_get_edid_phys_addr(edid, r, NULL)
+: CEC_PHYS_ADDR_INVALID;
+   hdmi4_cec_set_phys_addr(>core, cec_addr);
}
 
-   r = read_edid(hdmi, edid, len);
-   if (r >= 256)
-   hdmi4_cec_set_phys_addr(>core,
-   cec_get_edid_phys_addr(edid, r, NULL));
-   else
-   hdmi4_cec_set_phys_addr(>core, CEC_PHYS_ADDR_INVALID);
if (need_enable)
hdmi4_core_disable(>core);
 
-   return r;
+   return (struct edid *)edid;
 }
 
 static void hdmi_lost_hotplug(struct omap_dss_device *dssdev)
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
index 8e3790dd8b98..99720dfc5769 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
@@ -410,27 +410,39 @@ static void hdmi_disconnect(struct omap_dss_device *src,
omapdss_device_disconnect(dst, dst->next);
 }
 
-static int hdmi_read_edid(struct omap_dss_device *dssdev,
-   u8 *edid, int len)
+#define MAX_EDID   512
+
+static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
 {
struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
bool need_enable;
+   u8 *edid;
int r;
 
+   edid = kzalloc(MAX_EDID, GFP_KERNEL);
+   if (!edid)
+   return NULL;
+
need_enable = hdmi->core_enabled == false;
 
if (need_enable) {
r = hdmi_core_enable(hdmi);
-   if (r)
-   return r;
+   if (r) {
+   kfree(edid);
+   return NULL;
+   }
}
 
-   r = read_edid(hdmi, edid, len);
+   r = read_edid(hdmi, edid, MAX_EDID);
+   if (r < 0) {
+   kfree(edid);
+   edid = NULL;
+   }
 
if (need_enable)
hdmi_core_disable(hdmi);
 
-   return r;
+   return (struct edid *)edid;
 }
 
 static int hdmi_set_infoframe(struct omap_dss_device *dssdev,
diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h 
b/drivers/gpu/drm/omapdrm/dss/omapdss.h
index 82e9bfa5530a..269e143d57be 100644
--- a/drivers/gpu/drm/omapdrm/dss/omapdss.h
+++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h
@@ -367,7 +367,7 @@ struct omap_dss_device_ops {
void *cb_data);
void (*unregister_hpd_cb)(struct omap_dss_device *dssdev);
 
-   int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len);
+   struct edid *(*read_edid)(struct omap_dss_device *dssdev);
 
int (*get_modes)(struct omap_dss_device *dssdev,
 struct drm_connector *connector);
diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c 
b/drivers/gpu/drm/omapdrm/omap_connector.c
index a24cec4b0bb9..c636ae228130 100644
--- a/drivers/gpu/drm/omapdrm/omap_connector.c
+++ b/drivers/gpu/drm/omapdrm/omap_connector.c
@@ -153,25 +153,19 @@ static void omap_connector_destroy(struct drm_connector 
*connector)
kfree(omap_connector);
 }
 
-#define MAX_EDID  512
-
 static int omap_connector_get_modes_edid(struct drm_connector *connector,
   

[PATCH v6 16/51] drm/bridge: tfp410: Allow operation without drm_connector

2020-02-16 Thread Laurent Pinchart
The tfp410 driver can operate as part of a pipeline where the
drm_connector is created by the display controller. Enable this mode of
operation by skipping creation of a drm_connector internally.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Boris Brezillon 
Acked-by: Sam Ravnborg 
---
 drivers/gpu/drm/bridge/ti-tfp410.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c 
b/drivers/gpu/drm/bridge/ti-tfp410.c
index 2b8741ebc696..40c4d4a5517b 100644
--- a/drivers/gpu/drm/bridge/ti-tfp410.c
+++ b/drivers/gpu/drm/bridge/ti-tfp410.c
@@ -124,10 +124,8 @@ static int tfp410_attach(struct drm_bridge *bridge,
if (ret < 0)
return ret;
 
-   if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) {
-   DRM_ERROR("Fix bridge driver to make connector optional!");
-   return -EINVAL;
-   }
+   if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
+   return 0;
 
if (!bridge->encoder) {
dev_err(dvi->dev, "Missing encoder\n");
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v6 51/51] drm/omap: dss: Remove unused omapdss_of_find_connected_device() function

2020-02-16 Thread Laurent Pinchart
The omapdss_of_find_connected_device() function isn't used anymore,
remove it.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
---
 drivers/gpu/drm/omapdrm/dss/Makefile  |  2 +-
 drivers/gpu/drm/omapdrm/dss/dss-of.c  | 28 ---
 drivers/gpu/drm/omapdrm/dss/omapdss.h |  3 ---
 3 files changed, 1 insertion(+), 32 deletions(-)
 delete mode 100644 drivers/gpu/drm/omapdrm/dss/dss-of.c

diff --git a/drivers/gpu/drm/omapdrm/dss/Makefile 
b/drivers/gpu/drm/omapdrm/dss/Makefile
index 5950c3f52c2e..f967e6948f2e 100644
--- a/drivers/gpu/drm/omapdrm/dss/Makefile
+++ b/drivers/gpu/drm/omapdrm/dss/Makefile
@@ -2,7 +2,7 @@
 obj-$(CONFIG_OMAP2_DSS_INIT) += omapdss-boot-init.o
 
 obj-$(CONFIG_OMAP_DSS_BASE) += omapdss-base.o
-omapdss-base-y := base.o display.o dss-of.o output.o
+omapdss-base-y := base.o display.o output.o
 
 obj-$(CONFIG_OMAP2_DSS) += omapdss.o
 # Core DSS files
diff --git a/drivers/gpu/drm/omapdrm/dss/dss-of.c 
b/drivers/gpu/drm/omapdrm/dss/dss-of.c
deleted file mode 100644
index b7981f3b80ad..
--- a/drivers/gpu/drm/omapdrm/dss/dss-of.c
+++ /dev/null
@@ -1,28 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
- * Author: Tomi Valkeinen 
- */
-
-#include 
-#include 
-#include 
-
-#include "omapdss.h"
-
-struct omap_dss_device *
-omapdss_of_find_connected_device(struct device_node *node, unsigned int port)
-{
-   struct device_node *remote_node;
-   struct omap_dss_device *dssdev;
-
-   remote_node = of_graph_get_remote_node(node, port, 0);
-   if (!remote_node)
-   return NULL;
-
-   dssdev = omapdss_find_device_by_node(remote_node);
-   of_node_put(remote_node);
-
-   return dssdev ? dssdev : ERR_PTR(-EPROBE_DEFER);
-}
-EXPORT_SYMBOL_GPL(omapdss_of_find_connected_device);
diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h 
b/drivers/gpu/drm/omapdrm/dss/omapdss.h
index 6ecbc7273032..ab19d4af8de7 100644
--- a/drivers/gpu/drm/omapdrm/dss/omapdss.h
+++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h
@@ -471,9 +471,6 @@ static inline bool omapdss_device_is_enabled(struct 
omap_dss_device *dssdev)
return dssdev->state == OMAP_DSS_DISPLAY_ACTIVE;
 }
 
-struct omap_dss_device *
-omapdss_of_find_connected_device(struct device_node *node, unsigned int port);
-
 enum dss_writeback_channel {
DSS_WB_LCD1_MGR =   0,
DSS_WB_LCD2_MGR =   1,
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v6 18/51] drm/omap: dss: Cleanup DSS ports on initialisation failure

2020-02-16 Thread Laurent Pinchart
When the DSS initialises its output DPI and SDI ports, failures don't
clean up previous successfully initialised ports. This can lead to
resource leak or memory corruption. Fix it.

Reported-by: Hans Verkuil 
Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
Acked-by: Sam Ravnborg 
---
 drivers/gpu/drm/omapdrm/dss/dss.c | 43 +++
 1 file changed, 26 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dss.c 
b/drivers/gpu/drm/omapdrm/dss/dss.c
index 225ec808b01a..67b92b5d8dd7 100644
--- a/drivers/gpu/drm/omapdrm/dss/dss.c
+++ b/drivers/gpu/drm/omapdrm/dss/dss.c
@@ -1151,46 +1151,38 @@ static const struct dss_features dra7xx_dss_feats = {
.has_lcd_clk_src=   true,
 };
 
-static int dss_init_ports(struct dss_device *dss)
+static void __dss_uninit_ports(struct dss_device *dss, unsigned int num_ports)
 {
struct platform_device *pdev = dss->pdev;
struct device_node *parent = pdev->dev.of_node;
struct device_node *port;
unsigned int i;
-   int r;
 
-   for (i = 0; i < dss->feat->num_ports; i++) {
+   for (i = 0; i < num_ports; i++) {
port = of_graph_get_port_by_id(parent, i);
if (!port)
continue;
 
switch (dss->feat->ports[i]) {
case OMAP_DISPLAY_TYPE_DPI:
-   r = dpi_init_port(dss, pdev, port, dss->feat->model);
-   if (r)
-   return r;
+   dpi_uninit_port(port);
break;
-
case OMAP_DISPLAY_TYPE_SDI:
-   r = sdi_init_port(dss, pdev, port);
-   if (r)
-   return r;
+   sdi_uninit_port(port);
break;
-
default:
break;
}
}
-
-   return 0;
 }
 
-static void dss_uninit_ports(struct dss_device *dss)
+static int dss_init_ports(struct dss_device *dss)
 {
struct platform_device *pdev = dss->pdev;
struct device_node *parent = pdev->dev.of_node;
struct device_node *port;
-   int i;
+   unsigned int i;
+   int r;
 
for (i = 0; i < dss->feat->num_ports; i++) {
port = of_graph_get_port_by_id(parent, i);
@@ -1199,15 +1191,32 @@ static void dss_uninit_ports(struct dss_device *dss)
 
switch (dss->feat->ports[i]) {
case OMAP_DISPLAY_TYPE_DPI:
-   dpi_uninit_port(port);
+   r = dpi_init_port(dss, pdev, port, dss->feat->model);
+   if (r)
+   goto error;
break;
+
case OMAP_DISPLAY_TYPE_SDI:
-   sdi_uninit_port(port);
+   r = sdi_init_port(dss, pdev, port);
+   if (r)
+   goto error;
break;
+
default:
break;
}
}
+
+   return 0;
+
+error:
+   __dss_uninit_ports(dss, i);
+   return r;
+}
+
+static void dss_uninit_ports(struct dss_device *dss)
+{
+   __dss_uninit_ports(dss, dss->feat->num_ports);
 }
 
 static int dss_video_pll_probe(struct dss_device *dss)
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v6 37/51] drm/omap: Remove HPD, detect and EDID omapdss operations

2020-02-16 Thread Laurent Pinchart
Due to the removal of several omapdrm display drivers, the omapdss HPD,
detected and EDID operations are not used anymore. Remove them and all
related code.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
---
 drivers/gpu/drm/omapdrm/dss/hdmi4.c  |  61 
 drivers/gpu/drm/omapdrm/dss/hdmi5.c  |  46 --
 drivers/gpu/drm/omapdrm/dss/omapdss.h|  25 +--
 drivers/gpu/drm/omapdrm/omap_connector.c | 190 +++
 drivers/gpu/drm/omapdrm/omap_connector.h |   2 -
 drivers/gpu/drm/omapdrm/omap_drv.c   |   8 +-
 6 files changed, 22 insertions(+), 310 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index 52daae36935a..b9bcd6e681e8 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -321,47 +321,6 @@ static void hdmi_disconnect(struct omap_dss_device *src,
omapdss_device_disconnect(dst, dst->next);
 }
 
-#define MAX_EDID   512
-
-static struct edid *hdmi_read_edid_data(struct omap_hdmi *hdmi,
-   struct drm_connector *connector)
-{
-   u8 *edid;
-   int r;
-
-   edid = kzalloc(MAX_EDID, GFP_KERNEL);
-   if (!edid)
-   return NULL;
-
-   r = hdmi4_core_ddc_read(>core, edid, 0, EDID_LENGTH);
-   if (r)
-   goto error;
-
-   if (edid[0x7e] > 0) {
-   char checksum = 0;
-   unsigned int i;
-
-   r = hdmi4_core_ddc_read(>core, edid + EDID_LENGTH, 1,
-   EDID_LENGTH);
-   if (r)
-   goto error;
-
-   for (i = 0; i < EDID_LENGTH; ++i)
-   checksum += edid[EDID_LENGTH + i];
-
-   if (checksum != 0) {
-   DSSERR("E-EDID checksum failed!!\n");
-   goto error;
-   }
-   }
-
-   return (struct edid *)edid;
-
-error:
-   kfree(edid);
-   return NULL;
-}
-
 static struct edid *
 hdmi_do_read_edid(struct omap_hdmi *hdmi,
  struct edid *(*read)(struct omap_hdmi *hdmi,
@@ -411,28 +370,9 @@ hdmi_do_read_edid(struct omap_hdmi *hdmi,
return edid;
 }
 
-static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
-{
-   return hdmi_do_read_edid(dssdev_to_hdmi(dssdev), hdmi_read_edid_data,
-NULL);
-}
-
-static void hdmi_lost_hotplug(struct omap_dss_device *dssdev)
-{
-   struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-
-   hdmi4_cec_set_phys_addr(>core, CEC_PHYS_ADDR_INVALID);
-}
-
 static const struct omap_dss_device_ops hdmi_ops = {
.connect= hdmi_connect,
.disconnect = hdmi_disconnect,
-
-   .read_edid  = hdmi_read_edid,
-
-   .hdmi = {
-   .lost_hotplug   = hdmi_lost_hotplug,
-   },
 };
 
 /* 
-
@@ -804,7 +744,6 @@ static int hdmi4_init_output(struct omap_hdmi *hdmi)
out->ops = _ops;
out->owner = THIS_MODULE;
out->of_port = 0;
-   out->ops_flags = OMAP_DSS_DEVICE_OP_EDID;
 
r = omapdss_device_init_output(out, >bridge);
if (r < 0) {
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
index f07fd5c6dc39..effe4a9401ff 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
@@ -319,43 +319,6 @@ static void hdmi_disconnect(struct omap_dss_device *src,
omapdss_device_disconnect(dst, dst->next);
 }
 
-#define MAX_EDID   512
-
-static struct edid *hdmi_read_edid_data(struct omap_hdmi *hdmi,
-   struct drm_connector *connector)
-{
-   struct hdmi_core_data *core = >core;
-   int max_ext_blocks = 3;
-   int r, n, i;
-   u8 *edid;
-
-   edid = kzalloc(MAX_EDID, GFP_KERNEL);
-   if (!edid)
-   return NULL;
-
-   r = hdmi5_core_ddc_read(core, edid, 0, EDID_LENGTH);
-   if (r)
-   goto error;
-
-   n = edid[0x7e];
-
-   if (n > max_ext_blocks)
-   n = max_ext_blocks;
-
-   for (i = 1; i <= n; i++) {
-   r = hdmi5_core_ddc_read(core, edid + i * EDID_LENGTH, i,
-   EDID_LENGTH);
-   if (r)
-   goto error;
-   }
-
-   return (struct edid *)edid;
-
-error:
-   kfree(edid);
-   return NULL;
-}
-
 static struct edid *
 hdmi_do_read_edid(struct omap_hdmi *hdmi,
  struct edid *(*read)(struct omap_hdmi *hdmi,
@@ -400,17 +363,9 @@ hdmi_do_read_edid(struct omap_hdmi *hdmi,
return (struct edid *)edid;
 }
 
-static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
-{
-   return hdmi_do_read_edid(dssdev_to_hdmi(dssdev), hdmi_read_edid_data,
-NULL);
-}
-
 static const 

[PATCH v6 26/51] drm/omap: hdmi4: Rework EDID read to isolate data read

2020-02-16 Thread Laurent Pinchart
In preparation of adding DRM bridge support to the hdmi4 encoder code,
rework the EDID read to isolate data read.

The hdmi_read_edid() function is the main entry point. It performs all
initialisation steps required prior to reading the EDID (such as
ensuring the device is powered on), as well as corresponding cleanup
steps afterwards. EDID read itself is handled by hdmi_read_edid_data()
that calls the hdmi4_core_ddc_read() function to read individual blocks.

This new code architecture will allow reusing hdmi_read_edid() and
hdmi4_core_ddc_read() for the drm_bridge EDID read implementation, while
swapping out hdmi_read_edid_data() for the DRM drm_do_get_edid()
function.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
---
Changes since v2:

- Expand commit message
---
 drivers/gpu/drm/omapdrm/dss/hdmi4.c  | 94 +++-
 drivers/gpu/drm/omapdrm/dss/hdmi4_core.c | 59 +++
 drivers/gpu/drm/omapdrm/dss/hdmi4_core.h |  4 +-
 3 files changed, 73 insertions(+), 84 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index e15fa3862922..37536b9f3114 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -272,23 +272,6 @@ static int hdmi_dump_regs(struct seq_file *s, void *p)
return 0;
 }
 
-static int read_edid(struct omap_hdmi *hdmi, u8 *buf, int len)
-{
-   int r;
-
-   mutex_lock(>lock);
-
-   r = hdmi_runtime_get(hdmi);
-   BUG_ON(r);
-
-   r = hdmi4_read_edid(>core,  buf, len);
-
-   hdmi_runtime_put(hdmi);
-   mutex_unlock(>lock);
-
-   return r;
-}
-
 static void hdmi_start_audio_stream(struct omap_hdmi *hd)
 {
hdmi_wp_audio_enable(>wp, true);
@@ -407,10 +390,8 @@ static void hdmi_disconnect(struct omap_dss_device *src,
 
 #define MAX_EDID   512
 
-static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
+static struct edid *hdmi_read_edid_data(struct omap_hdmi *hdmi)
 {
-   struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-   bool need_enable;
u8 *edid;
int r;
 
@@ -418,32 +399,79 @@ static struct edid *hdmi_read_edid(struct omap_dss_device 
*dssdev)
if (!edid)
return NULL;
 
+   r = hdmi4_core_ddc_read(>core, edid, 0, EDID_LENGTH);
+   if (r)
+   goto error;
+
+   if (edid[0x7e] > 0) {
+   char checksum = 0;
+   unsigned int i;
+
+   r = hdmi4_core_ddc_read(>core, edid + EDID_LENGTH, 1,
+   EDID_LENGTH);
+   if (r)
+   goto error;
+
+   for (i = 0; i < EDID_LENGTH; ++i)
+   checksum += edid[EDID_LENGTH + i];
+
+   if (checksum != 0) {
+   DSSERR("E-EDID checksum failed!!\n");
+   goto error;
+   }
+   }
+
+   return (struct edid *)edid;
+
+error:
+   kfree(edid);
+   return NULL;
+}
+
+static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
+{
+   struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
+   struct edid *edid = NULL;
+   unsigned int cec_addr;
+   bool need_enable;
+   int r;
+
need_enable = hdmi->core_enabled == false;
 
if (need_enable) {
r = hdmi4_core_enable(>core);
-   if (r) {
-   kfree(edid);
+   if (r)
return NULL;
-   }
}
 
-   r = read_edid(hdmi, edid, MAX_EDID);
-   if (r < 0) {
-   kfree(edid);
-   edid = NULL;
-   } else {
-   unsigned int cec_addr;
+   mutex_lock(>lock);
+   r = hdmi_runtime_get(hdmi);
+   BUG_ON(r);
+
+   r = hdmi4_core_ddc_init(>core);
+   if (r)
+   goto done;
 
-   cec_addr = r >= 256 ? cec_get_edid_phys_addr(edid, r, NULL)
-: CEC_PHYS_ADDR_INVALID;
-   hdmi4_cec_set_phys_addr(>core, cec_addr);
+   edid = hdmi_read_edid_data(hdmi);
+
+done:
+   hdmi_runtime_put(hdmi);
+   mutex_unlock(>lock);
+
+   if (edid && edid->extensions) {
+   unsigned int len = (edid->extensions + 1) * EDID_LENGTH;
+
+   cec_addr = cec_get_edid_phys_addr((u8 *)edid, len, NULL);
+   } else {
+   cec_addr = CEC_PHYS_ADDR_INVALID;
}
 
+   hdmi4_cec_set_phys_addr(>core, cec_addr);
+
if (need_enable)
hdmi4_core_disable(>core);
 
-   return (struct edid *)edid;
+   return edid;
 }
 
 static void hdmi_lost_hotplug(struct omap_dss_device *dssdev)
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c
index ea5d5c228534..751985a2679a 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c
@@ -32,7 +32,7 @@ static inline void __iomem *hdmi_av_base(struct 

[PATCH v6 10/51] drm/bridge: simple-bridge: Add support for enable GPIO

2020-02-16 Thread Laurent Pinchart
If an enable GPIO is declared in the firmware, assert it when enabling
the bridge and deassert it when disabling it.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Andrzej Hajda 
Reviewed-by: Stefan Agner 
Reviewed-by: Boris Brezillon 
Reviewed-by: Maxime Ripard 
Acked-by: Sam Ravnborg 
---
 drivers/gpu/drm/bridge/simple-bridge.c | 22 ++
 1 file changed, 18 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/bridge/simple-bridge.c 
b/drivers/gpu/drm/bridge/simple-bridge.c
index 20866c1230de..70e6092bdf6c 100644
--- a/drivers/gpu/drm/bridge/simple-bridge.c
+++ b/drivers/gpu/drm/bridge/simple-bridge.c
@@ -6,6 +6,7 @@
  * Maxime Ripard 
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -30,6 +31,7 @@ struct simple_bridge {
 
struct i2c_adapter  *ddc;
struct regulator*vdd;
+   struct gpio_desc*enable;
 };
 
 static inline struct simple_bridge *
@@ -143,19 +145,23 @@ static int simple_bridge_attach(struct drm_bridge *bridge,
 static void simple_bridge_enable(struct drm_bridge *bridge)
 {
struct simple_bridge *sbridge = drm_bridge_to_simple_bridge(bridge);
-   int ret = 0;
+   int ret;
 
-   if (sbridge->vdd)
+   if (sbridge->vdd) {
ret = regulator_enable(sbridge->vdd);
+   if (ret)
+   DRM_ERROR("Failed to enable vdd regulator: %d\n", ret);
+   }
 
-   if (ret)
-   DRM_ERROR("Failed to enable vdd regulator: %d\n", ret);
+   gpiod_set_value_cansleep(sbridge->enable, 1);
 }
 
 static void simple_bridge_disable(struct drm_bridge *bridge)
 {
struct simple_bridge *sbridge = drm_bridge_to_simple_bridge(bridge);
 
+   gpiod_set_value_cansleep(sbridge->enable, 0);
+
if (sbridge->vdd)
regulator_disable(sbridge->vdd);
 }
@@ -208,6 +214,14 @@ static int simple_bridge_probe(struct platform_device 
*pdev)
dev_dbg(>dev, "No vdd regulator found: %d\n", ret);
}
 
+   sbridge->enable = devm_gpiod_get_optional(>dev, "enable",
+ GPIOD_OUT_LOW);
+   if (IS_ERR(sbridge->enable)) {
+   if (PTR_ERR(sbridge->enable) != -EPROBE_DEFER)
+   dev_err(>dev, "Unable to retrieve enable GPIO\n");
+   return PTR_ERR(sbridge->enable);
+   }
+
sbridge->ddc = simple_bridge_retrieve_ddc(>dev);
if (IS_ERR(sbridge->ddc)) {
if (PTR_ERR(sbridge->ddc) == -ENODEV) {
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v6 48/51] drm/omap: Hardcode omap_connector type to DSI

2020-02-16 Thread Laurent Pinchart
The omap_connector implementation is now used for DSI only. Hardcode its
type and drop unused code.

Signed-off-by: Laurent Pinchart 
---
 drivers/gpu/drm/omapdrm/dss/base.c   | 23 --
 drivers/gpu/drm/omapdrm/dss/omapdss.h|  1 -
 drivers/gpu/drm/omapdrm/omap_connector.c | 31 ++--
 3 files changed, 2 insertions(+), 53 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/base.c 
b/drivers/gpu/drm/omapdrm/dss/base.c
index 2db3bd2f19db..455b410f7401 100644
--- a/drivers/gpu/drm/omapdrm/dss/base.c
+++ b/drivers/gpu/drm/omapdrm/dss/base.c
@@ -286,29 +286,6 @@ void omapdss_device_post_disable(struct omap_dss_device 
*dssdev)
 }
 EXPORT_SYMBOL_GPL(omapdss_device_post_disable);
 
-unsigned int omapdss_device_connector_type(enum omap_display_type type)
-{
-   switch (type) {
-   case OMAP_DISPLAY_TYPE_HDMI:
-   return DRM_MODE_CONNECTOR_HDMIA;
-   case OMAP_DISPLAY_TYPE_DVI:
-   return DRM_MODE_CONNECTOR_DVID;
-   case OMAP_DISPLAY_TYPE_DSI:
-   return DRM_MODE_CONNECTOR_DSI;
-   case OMAP_DISPLAY_TYPE_DPI:
-   case OMAP_DISPLAY_TYPE_DBI:
-   return DRM_MODE_CONNECTOR_DPI;
-   case OMAP_DISPLAY_TYPE_VENC:
-   /* TODO: This could also be composite */
-   return DRM_MODE_CONNECTOR_SVIDEO;
-   case OMAP_DISPLAY_TYPE_SDI:
-   return DRM_MODE_CONNECTOR_LVDS;
-   default:
-   return DRM_MODE_CONNECTOR_Unknown;
-   }
-}
-EXPORT_SYMBOL_GPL(omapdss_device_connector_type);
-
 /* 
-
  * Components Handling
  */
diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h 
b/drivers/gpu/drm/omapdrm/dss/omapdss.h
index cb79e05c902d..2e5453df2293 100644
--- a/drivers/gpu/drm/omapdrm/dss/omapdss.h
+++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h
@@ -454,7 +454,6 @@ void omapdss_device_pre_enable(struct omap_dss_device 
*dssdev);
 void omapdss_device_enable(struct omap_dss_device *dssdev);
 void omapdss_device_disable(struct omap_dss_device *dssdev);
 void omapdss_device_post_disable(struct omap_dss_device *dssdev);
-unsigned int omapdss_device_connector_type(enum omap_display_type type);
 
 int omap_dss_get_num_overlay_managers(void);
 
diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c 
b/drivers/gpu/drm/omapdrm/omap_connector.c
index baa31ed1f993..528764566b17 100644
--- a/drivers/gpu/drm/omapdrm/omap_connector.c
+++ b/drivers/gpu/drm/omapdrm/omap_connector.c
@@ -24,22 +24,7 @@ struct omap_connector {
 static enum drm_connector_status omap_connector_detect(
struct drm_connector *connector, bool force)
 {
-   enum drm_connector_status status;
-
-   switch (connector->connector_type) {
-   case DRM_MODE_CONNECTOR_DPI:
-   case DRM_MODE_CONNECTOR_LVDS:
-   case DRM_MODE_CONNECTOR_DSI:
-   status = connector_status_connected;
-   break;
-   default:
-   status = connector_status_unknown;
-   break;
-   }
-
-   VERB("%s: %d (force=%d)", connector->name, status, force);
-
-   return status;
+   return connector_status_connected;
 }
 
 static void omap_connector_destroy(struct drm_connector *connector)
@@ -138,18 +123,6 @@ static const struct drm_connector_helper_funcs 
omap_connector_helper_funcs = {
.mode_valid = omap_connector_mode_valid,
 };
 
-static int omap_connector_get_type(struct omap_dss_device *output)
-{
-   struct omap_dss_device *display;
-   enum omap_display_type type;
-
-   display = omapdss_display_get(output);
-   type = display->type;
-   omapdss_device_put(display);
-
-   return omapdss_device_connector_type(type);
-}
-
 /* initialize connector */
 struct drm_connector *omap_connector_init(struct drm_device *dev,
  struct omap_dss_device *output,
@@ -171,7 +144,7 @@ struct drm_connector *omap_connector_init(struct drm_device 
*dev,
connector->doublescan_allowed = 0;
 
drm_connector_init(dev, connector, _connector_funcs,
-  omap_connector_get_type(output));
+  DRM_MODE_CONNECTOR_DSI);
drm_connector_helper_add(connector, _connector_helper_funcs);
 
return connector;
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v6 11/51] drm/bridge: simple-bridge: Add support for the TI OPA362

2020-02-16 Thread Laurent Pinchart
The TI OPA362 is an analog video amplifier controlled through a GPIO. Add
support for it to the simple-bridge driver.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Andrzej Hajda 
Reviewed-by: Boris Brezillon 
Reviewed-by: Maxime Ripard 
Reviewed-by: Tomi Valkeinen 
Acked-by: Sam Ravnborg 
---
Changes since v3:

- Fix device name in commit message
---
 drivers/gpu/drm/bridge/simple-bridge.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/bridge/simple-bridge.c 
b/drivers/gpu/drm/bridge/simple-bridge.c
index 70e6092bdf6c..a2dca7a3ef03 100644
--- a/drivers/gpu/drm/bridge/simple-bridge.c
+++ b/drivers/gpu/drm/bridge/simple-bridge.c
@@ -305,6 +305,11 @@ static const struct of_device_id simple_bridge_match[] = {
.timings = _bridge_timings,
.connector_type = DRM_MODE_CONNECTOR_VGA,
},
+   }, {
+   .compatible = "ti,opa362",
+   .data = &(const struct simple_bridge_info) {
+   .connector_type = DRM_MODE_CONNECTOR_Composite,
+   },
}, {
.compatible = "ti,ths8135",
.data = &(const struct simple_bridge_info) {
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v6 27/51] drm/omap: hdmi5: Rework EDID read to isolate data read

2020-02-16 Thread Laurent Pinchart
In preparation of adding DRM bridge support to the hdmi5 encoder code,
rework the EDID read to isolate data read.

The hdmi_read_edid() function is the main entry point. It performs all
initialisation steps required prior to reading the EDID (such as
ensuring the device is powered on), as well as corresponding cleanup
steps afterwards. EDID read itself is handled by hdmi_read_edid_data()
that calls the hdmi5_core_ddc_read() function to read individual blocks.

This new code architecture will allow reusing hdmi_read_edid() and
hdmi5_core_ddc_read() for the drm_bridge EDID read implementation, while
swapping out hdmi_read_edid_data() for the DRM drm_do_get_edid()
function.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
---
Changes since v2:

- Expand commit message
---
 drivers/gpu/drm/omapdrm/dss/hdmi5.c  | 89 ++--
 drivers/gpu/drm/omapdrm/dss/hdmi5_core.c | 48 +++--
 drivers/gpu/drm/omapdrm/dss/hdmi5_core.h |  5 +-
 3 files changed, 65 insertions(+), 77 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
index 99720dfc5769..2b02b0a11696 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
@@ -271,30 +271,6 @@ static int hdmi_dump_regs(struct seq_file *s, void *p)
return 0;
 }
 
-static int read_edid(struct omap_hdmi *hdmi, u8 *buf, int len)
-{
-   int r;
-   int idlemode;
-
-   mutex_lock(>lock);
-
-   r = hdmi_runtime_get(hdmi);
-   BUG_ON(r);
-
-   idlemode = REG_GET(hdmi->wp.base, HDMI_WP_SYSCONFIG, 3, 2);
-   /* No-idle mode */
-   REG_FLD_MOD(hdmi->wp.base, HDMI_WP_SYSCONFIG, 1, 3, 2);
-
-   r = hdmi5_read_edid(>core,  buf, len);
-
-   REG_FLD_MOD(hdmi->wp.base, HDMI_WP_SYSCONFIG, idlemode, 3, 2);
-
-   hdmi_runtime_put(hdmi);
-   mutex_unlock(>lock);
-
-   return r;
-}
-
 static void hdmi_start_audio_stream(struct omap_hdmi *hd)
 {
REG_FLD_MOD(hd->wp.base, HDMI_WP_SYSCONFIG, 1, 3, 2);
@@ -412,32 +388,73 @@ static void hdmi_disconnect(struct omap_dss_device *src,
 
 #define MAX_EDID   512
 
-static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
+static struct edid *hdmi_read_edid_data(struct hdmi_core_data *core)
 {
-   struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-   bool need_enable;
+   int max_ext_blocks = 3;
+   int r, n, i;
u8 *edid;
-   int r;
 
edid = kzalloc(MAX_EDID, GFP_KERNEL);
if (!edid)
return NULL;
 
+   r = hdmi5_core_ddc_read(core, edid, 0, EDID_LENGTH);
+   if (r)
+   goto error;
+
+   n = edid[0x7e];
+
+   if (n > max_ext_blocks)
+   n = max_ext_blocks;
+
+   for (i = 1; i <= n; i++) {
+   r = hdmi5_core_ddc_read(core, edid + i * EDID_LENGTH, i,
+   EDID_LENGTH);
+   if (r)
+   goto error;
+   }
+
+   return (struct edid *)edid;
+
+error:
+   kfree(edid);
+   return NULL;
+}
+
+static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
+{
+   struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
+   struct edid *edid;
+   bool need_enable;
+   int idlemode;
+   int r;
+
need_enable = hdmi->core_enabled == false;
 
if (need_enable) {
r = hdmi_core_enable(hdmi);
-   if (r) {
-   kfree(edid);
+   if (r)
return NULL;
-   }
}
 
-   r = read_edid(hdmi, edid, MAX_EDID);
-   if (r < 0) {
-   kfree(edid);
-   edid = NULL;
-   }
+   mutex_lock(>lock);
+   r = hdmi_runtime_get(hdmi);
+   BUG_ON(r);
+
+   idlemode = REG_GET(hdmi->wp.base, HDMI_WP_SYSCONFIG, 3, 2);
+   /* No-idle mode */
+   REG_FLD_MOD(hdmi->wp.base, HDMI_WP_SYSCONFIG, 1, 3, 2);
+
+   hdmi5_core_ddc_init(>core);
+
+   edid = hdmi_read_edid_data(>core);
+
+   hdmi5_core_ddc_uninit(>core);
+
+   REG_FLD_MOD(hdmi->wp.base, HDMI_WP_SYSCONFIG, idlemode, 3, 2);
+
+   hdmi_runtime_put(hdmi);
+   mutex_unlock(>lock);
 
if (need_enable)
hdmi_core_disable(hdmi);
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c
index ff4d35c8771f..7dd587035160 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c
@@ -23,7 +23,7 @@
 
 #include "hdmi5_core.h"
 
-static void hdmi_core_ddc_init(struct hdmi_core_data *core)
+void hdmi5_core_ddc_init(struct hdmi_core_data *core)
 {
void __iomem *base = core->base;
const unsigned long long iclk = 26600;  /* DSS L3 ICLK */
@@ -102,7 +102,7 @@ static void hdmi_core_ddc_init(struct hdmi_core_data *core)
REG_FLD_MOD(base, HDMI_CORE_I2CM_INT, 0x0, 2, 2);
 }
 
-static void hdmi_core_ddc_uninit(struct hdmi_core_data *core)
+void 

[PATCH v6 24/51] drm/omap: dss: Make omap_dss_device_ops optional

2020-02-16 Thread Laurent Pinchart
As part of the move to drm_bridge ops, the dssdev ops will become empty
for some of the internal encoders. Make them optional in the driver to
allow them to be removed completely, easing the transition.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
---
 drivers/gpu/drm/omapdrm/dss/base.c   | 21 -
 drivers/gpu/drm/omapdrm/dss/dss.c|  3 ++-
 drivers/gpu/drm/omapdrm/omap_connector.c |  2 +-
 drivers/gpu/drm/omapdrm/omap_encoder.c   | 12 +++-
 4 files changed, 22 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/base.c 
b/drivers/gpu/drm/omapdrm/dss/base.c
index 80d48936d177..2db3bd2f19db 100644
--- a/drivers/gpu/drm/omapdrm/dss/base.c
+++ b/drivers/gpu/drm/omapdrm/dss/base.c
@@ -195,10 +195,12 @@ int omapdss_device_connect(struct dss_device *dss,
 
dst->dss = dss;
 
-   ret = dst->ops->connect(src, dst);
-   if (ret < 0) {
-   dst->dss = NULL;
-   return ret;
+   if (dst->ops && dst->ops->connect) {
+   ret = dst->ops->connect(src, dst);
+   if (ret < 0) {
+   dst->dss = NULL;
+   return ret;
+   }
}
 
return 0;
@@ -226,7 +228,8 @@ void omapdss_device_disconnect(struct omap_dss_device *src,
 
WARN_ON(dst->state != OMAP_DSS_DISPLAY_DISABLED);
 
-   dst->ops->disconnect(src, dst);
+   if (dst->ops && dst->ops->disconnect)
+   dst->ops->disconnect(src, dst);
dst->dss = NULL;
 }
 EXPORT_SYMBOL_GPL(omapdss_device_disconnect);
@@ -238,7 +241,7 @@ void omapdss_device_pre_enable(struct omap_dss_device 
*dssdev)
 
omapdss_device_pre_enable(dssdev->next);
 
-   if (dssdev->ops->pre_enable)
+   if (dssdev->ops && dssdev->ops->pre_enable)
dssdev->ops->pre_enable(dssdev);
 }
 EXPORT_SYMBOL_GPL(omapdss_device_pre_enable);
@@ -248,7 +251,7 @@ void omapdss_device_enable(struct omap_dss_device *dssdev)
if (!dssdev)
return;
 
-   if (dssdev->ops->enable)
+   if (dssdev->ops && dssdev->ops->enable)
dssdev->ops->enable(dssdev);
 
omapdss_device_enable(dssdev->next);
@@ -264,7 +267,7 @@ void omapdss_device_disable(struct omap_dss_device *dssdev)
 
omapdss_device_disable(dssdev->next);
 
-   if (dssdev->ops->disable)
+   if (dssdev->ops && dssdev->ops->disable)
dssdev->ops->disable(dssdev);
 }
 EXPORT_SYMBOL_GPL(omapdss_device_disable);
@@ -274,7 +277,7 @@ void omapdss_device_post_disable(struct omap_dss_device 
*dssdev)
if (!dssdev)
return;
 
-   if (dssdev->ops->post_disable)
+   if (dssdev->ops && dssdev->ops->post_disable)
dssdev->ops->post_disable(dssdev);
 
omapdss_device_post_disable(dssdev->next);
diff --git a/drivers/gpu/drm/omapdrm/dss/dss.c 
b/drivers/gpu/drm/omapdrm/dss/dss.c
index 67b92b5d8dd7..b76fc2b56227 100644
--- a/drivers/gpu/drm/omapdrm/dss/dss.c
+++ b/drivers/gpu/drm/omapdrm/dss/dss.c
@@ -1552,7 +1552,8 @@ static void dss_shutdown(struct platform_device *pdev)
DSSDBG("shutdown\n");
 
for_each_dss_output(dssdev) {
-   if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
+   if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE &&
+   dssdev->ops && dssdev->ops->disable)
dssdev->ops->disable(dssdev);
}
 }
diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c 
b/drivers/gpu/drm/omapdrm/omap_connector.c
index b0cb2ecb30ab..a24cec4b0bb9 100644
--- a/drivers/gpu/drm/omapdrm/omap_connector.c
+++ b/drivers/gpu/drm/omapdrm/omap_connector.c
@@ -228,7 +228,7 @@ enum drm_mode_status omap_connector_mode_fixup(struct 
omap_dss_device *dssdev,
drm_mode_copy(adjusted_mode, mode);
 
for (; dssdev; dssdev = dssdev->next) {
-   if (!dssdev->ops->check_timings)
+   if (!dssdev->ops || !dssdev->ops->check_timings)
continue;
 
ret = dssdev->ops->check_timings(dssdev, adjusted_mode);
diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c 
b/drivers/gpu/drm/omapdrm/omap_encoder.c
index a270173a2411..b232acd3bc3d 100644
--- a/drivers/gpu/drm/omapdrm/omap_encoder.c
+++ b/drivers/gpu/drm/omapdrm/omap_encoder.c
@@ -77,10 +77,10 @@ static void omap_encoder_hdmi_mode_set(struct drm_connector 
*connector,
struct omap_dss_device *dssdev = omap_encoder->output;
bool hdmi_mode = connector->display_info.is_hdmi;
 
-   if (dssdev->ops->hdmi.set_hdmi_mode)
+   if (dssdev->ops && dssdev->ops->hdmi.set_hdmi_mode)
dssdev->ops->hdmi.set_hdmi_mode(dssdev, hdmi_mode);
 
-   if (hdmi_mode && dssdev->ops->hdmi.set_infoframe) {
+   if (hdmi_mode && dssdev->ops && dssdev->ops->hdmi.set_infoframe) {
struct hdmi_avi_infoframe avi;
int r;
 
@@ -139,7 +139,7 @@ static void omap_encoder_mode_set(struct drm_encoder 

[PATCH v6 15/51] drm/bridge: tfp410: Replace manual connector handling with bridge

2020-02-16 Thread Laurent Pinchart
Now that a driver is available for display connectors, replace the
manual connector handling code with usage of the DRM bridge API. The
tfp410 driver doesn't deal with the display connector directly anymore,
but still delegates drm_connector operations to the next bridge. This
brings us one step closer to having the tfp410 driver handling the
TFP410 only.

Signed-off-by: Laurent Pinchart 
Acked-by: Sam Ravnborg 
---
Changes since v2:

- Use drm_bridge_get_edid() and drm_bridge_detect() helpers
---
 drivers/gpu/drm/bridge/ti-tfp410.c | 216 ++---
 1 file changed, 75 insertions(+), 141 deletions(-)

diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c 
b/drivers/gpu/drm/bridge/ti-tfp410.c
index 193c9368f664..2b8741ebc696 100644
--- a/drivers/gpu/drm/bridge/ti-tfp410.c
+++ b/drivers/gpu/drm/bridge/ti-tfp410.c
@@ -4,14 +4,12 @@
  * Author: Jyri Sarha 
  */
 
-#include 
-#include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -24,16 +22,13 @@
 struct tfp410 {
struct drm_bridge   bridge;
struct drm_connectorconnector;
-   unsigned intconnector_type;
 
u32 bus_format;
-   struct i2c_adapter  *ddc;
-   struct gpio_desc*hpd;
-   int hpd_irq;
struct delayed_work hpd_work;
struct gpio_desc*powerdown;
 
struct drm_bridge_timings timings;
+   struct drm_bridge   *next_bridge;
 
struct device *dev;
 };
@@ -56,13 +51,18 @@ static int tfp410_get_modes(struct drm_connector *connector)
struct edid *edid;
int ret;
 
-   if (!dvi->ddc)
-   goto fallback;
+   edid = drm_bridge_get_edid(dvi->next_bridge, connector);
+   if (IS_ERR_OR_NULL(edid)) {
+   if (edid != ERR_PTR(-ENOTSUPP))
+   DRM_INFO("EDID read failed. Fallback to standard 
modes\n");
 
-   edid = drm_get_edid(connector, dvi->ddc);
-   if (!edid) {
-   DRM_INFO("EDID read failed. Fallback to standard modes\n");
-   goto fallback;
+   /*
+* No EDID, fallback on the XGA standard modes and prefer a mode
+* pretty much anything can handle.
+*/
+   ret = drm_add_modes_noedid(connector, 1920, 1200);
+   drm_set_preferred_mode(connector, 1024, 768);
+   return ret;
}
 
drm_connector_update_edid_property(connector, edid);
@@ -71,15 +71,6 @@ static int tfp410_get_modes(struct drm_connector *connector)
 
kfree(edid);
 
-   return ret;
-
-fallback:
-   /* No EDID, fallback on the XGA standard modes */
-   ret = drm_add_modes_noedid(connector, 1920, 1200);
-
-   /* And prefer a mode pretty much anything can handle */
-   drm_set_preferred_mode(connector, 1024, 768);
-
return ret;
 }
 
@@ -92,21 +83,7 @@ tfp410_connector_detect(struct drm_connector *connector, 
bool force)
 {
struct tfp410 *dvi = drm_connector_to_tfp410(connector);
 
-   if (dvi->hpd) {
-   if (gpiod_get_value_cansleep(dvi->hpd))
-   return connector_status_connected;
-   else
-   return connector_status_disconnected;
-   }
-
-   if (dvi->ddc) {
-   if (drm_probe_ddc(dvi->ddc))
-   return connector_status_connected;
-   else
-   return connector_status_disconnected;
-   }
-
-   return connector_status_unknown;
+   return drm_bridge_detect(dvi->next_bridge);
 }
 
 static const struct drm_connector_funcs tfp410_con_funcs = {
@@ -118,12 +95,35 @@ static const struct drm_connector_funcs tfp410_con_funcs = 
{
.atomic_destroy_state   = drm_atomic_helper_connector_destroy_state,
 };
 
+static void tfp410_hpd_work_func(struct work_struct *work)
+{
+   struct tfp410 *dvi;
+
+   dvi = container_of(work, struct tfp410, hpd_work.work);
+
+   if (dvi->bridge.dev)
+   drm_helper_hpd_irq_event(dvi->bridge.dev);
+}
+
+static void tfp410_hpd_callback(void *arg, enum drm_connector_status status)
+{
+   struct tfp410 *dvi = arg;
+
+   mod_delayed_work(system_wq, >hpd_work,
+msecs_to_jiffies(HOTPLUG_DEBOUNCE_MS));
+}
+
 static int tfp410_attach(struct drm_bridge *bridge,
 enum drm_bridge_attach_flags flags)
 {
struct tfp410 *dvi = drm_bridge_to_tfp410(bridge);
int ret;
 
+   ret = drm_bridge_attach(bridge->encoder, dvi->next_bridge, bridge,
+   DRM_BRIDGE_ATTACH_NO_CONNECTOR);
+   if (ret < 0)
+   return ret;
+
if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) {
DRM_ERROR("Fix bridge driver to make connector optional!");
return -EINVAL;
@@ -134,17 +134,23 @@ static int tfp410_attach(struct drm_bridge *bridge,

[PATCH v6 33/51] drm/omap: dss: Remove .set_hdmi_mode() and .set_infoframe() operations

2020-02-16 Thread Laurent Pinchart
The omapdss_hdmi_ops .set_hdmi_mode() and .set_infoframe() operations
operations are not used anymore, remove them.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
---
 drivers/gpu/drm/omapdrm/dss/omapdss.h  |  3 ---
 drivers/gpu/drm/omapdrm/omap_encoder.c | 26 --
 2 files changed, 29 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h 
b/drivers/gpu/drm/omapdrm/dss/omapdss.h
index 269e143d57be..30a12cf91cbb 100644
--- a/drivers/gpu/drm/omapdrm/dss/omapdss.h
+++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h
@@ -287,9 +287,6 @@ struct omap_dss_writeback_info {
 
 struct omapdss_hdmi_ops {
void (*lost_hotplug)(struct omap_dss_device *dssdev);
-   int (*set_hdmi_mode)(struct omap_dss_device *dssdev, bool hdmi_mode);
-   int (*set_infoframe)(struct omap_dss_device *dssdev,
-   const struct hdmi_avi_infoframe *avi);
 };
 
 struct omapdss_dsi_ops {
diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c 
b/drivers/gpu/drm/omapdrm/omap_encoder.c
index b232acd3bc3d..18a79dde6815 100644
--- a/drivers/gpu/drm/omapdrm/omap_encoder.c
+++ b/drivers/gpu/drm/omapdrm/omap_encoder.c
@@ -69,28 +69,6 @@ static void omap_encoder_update_videomode_flags(struct 
videomode *vm,
}
 }
 
-static void omap_encoder_hdmi_mode_set(struct drm_connector *connector,
-  struct drm_encoder *encoder,
-  struct drm_display_mode *adjusted_mode)
-{
-   struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
-   struct omap_dss_device *dssdev = omap_encoder->output;
-   bool hdmi_mode = connector->display_info.is_hdmi;
-
-   if (dssdev->ops && dssdev->ops->hdmi.set_hdmi_mode)
-   dssdev->ops->hdmi.set_hdmi_mode(dssdev, hdmi_mode);
-
-   if (hdmi_mode && dssdev->ops && dssdev->ops->hdmi.set_infoframe) {
-   struct hdmi_avi_infoframe avi;
-   int r;
-
-   r = drm_hdmi_avi_infoframe_from_display_mode(, connector,
-adjusted_mode);
-   if (r == 0)
-   dssdev->ops->hdmi.set_infoframe(dssdev, );
-   }
-}
-
 static void omap_encoder_mode_set(struct drm_encoder *encoder,
  struct drm_display_mode *mode,
  struct drm_display_mode *adjusted_mode)
@@ -142,10 +120,6 @@ static void omap_encoder_mode_set(struct drm_encoder 
*encoder,
if (dssdev->ops && dssdev->ops->set_timings)
dssdev->ops->set_timings(dssdev, adjusted_mode);
}
-
-   /* Set the HDMI mode and HDMI infoframe if applicable. */
-   if (output->type == OMAP_DISPLAY_TYPE_HDMI)
-   omap_encoder_hdmi_mode_set(connector, encoder, adjusted_mode);
 }
 
 static void omap_encoder_disable(struct drm_encoder *encoder)
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v6 30/51] drm/omap: hdmi4: Move mode set, enable and disable operations to bridge

2020-02-16 Thread Laurent Pinchart
Move the omap_dss_device .set_timings(), .enable() and .disable()
operations to the drm_bridge functions. As the drm_bridge for the HDMI
encoder is unconditionally registered and attached, those operations
will be called at the appropriate time.

The omapdss device .set_infoframe() and .set_hdmi_mode() operations have
no equivalent in drm_bridge. Thir content is thus moved to the bridge
.enable() operation as the data they store is not needed before the HDMI
encoder gets enabled.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
---
Changes since v5:

- Rebased on top of drm_bridge_state

Changes since v2:

- Detail .set_infoframe() and .set_hdmi_mode() handling in the commit
  message
---
 drivers/gpu/drm/omapdrm/dss/hdmi4.c | 206 +++-
 1 file changed, 111 insertions(+), 95 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index 67994287447b..a8d13a081a9a 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -28,6 +28,9 @@
 #include 
 #include 
 
+#include 
+#include 
+
 #include "omapdss.h"
 #include "hdmi4_core.h"
 #include "hdmi4_cec.h"
@@ -237,20 +240,6 @@ static void hdmi_power_off_full(struct omap_hdmi *hdmi)
hdmi_power_off_core(hdmi);
 }
 
-static void hdmi_display_set_timings(struct omap_dss_device *dssdev,
-const struct drm_display_mode *mode)
-{
-   struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-
-   mutex_lock(>lock);
-
-   drm_display_mode_to_videomode(mode, >cfg.vm);
-
-   dispc_set_tv_pclk(hdmi->dss->dispc, mode->clock * 1000);
-
-   mutex_unlock(>lock);
-}
-
 static int hdmi_dump_regs(struct seq_file *s, void *p)
 {
struct omap_hdmi *hdmi = s->private;
@@ -284,62 +273,6 @@ static void hdmi_stop_audio_stream(struct omap_hdmi *hd)
hdmi_wp_audio_enable(>wp, false);
 }
 
-static void hdmi_display_enable(struct omap_dss_device *dssdev)
-{
-   struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-   unsigned long flags;
-   int r;
-
-   DSSDBG("ENTER hdmi_display_enable\n");
-
-   mutex_lock(>lock);
-
-   r = hdmi_power_on_full(hdmi);
-   if (r) {
-   DSSERR("failed to power on device\n");
-   goto done;
-   }
-
-   if (hdmi->audio_configured) {
-   r = hdmi4_audio_config(>core, >wp,
-  >audio_config,
-  hdmi->cfg.vm.pixelclock);
-   if (r) {
-   DSSERR("Error restoring audio configuration: %d", r);
-   hdmi->audio_abort_cb(>pdev->dev);
-   hdmi->audio_configured = false;
-   }
-   }
-
-   spin_lock_irqsave(>audio_playing_lock, flags);
-   if (hdmi->audio_configured && hdmi->audio_playing)
-   hdmi_start_audio_stream(hdmi);
-   hdmi->display_enabled = true;
-   spin_unlock_irqrestore(>audio_playing_lock, flags);
-
-done:
-   mutex_unlock(>lock);
-}
-
-static void hdmi_display_disable(struct omap_dss_device *dssdev)
-{
-   struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-   unsigned long flags;
-
-   DSSDBG("Enter hdmi_display_disable\n");
-
-   mutex_lock(>lock);
-
-   spin_lock_irqsave(>audio_playing_lock, flags);
-   hdmi_stop_audio_stream(hdmi);
-   hdmi->display_enabled = false;
-   spin_unlock_irqrestore(>audio_playing_lock, flags);
-
-   hdmi_power_off_full(hdmi);
-
-   mutex_unlock(>lock);
-}
-
 int hdmi4_core_enable(struct hdmi_core_data *core)
 {
struct omap_hdmi *hdmi = container_of(core, struct omap_hdmi, core);
@@ -491,39 +424,14 @@ static void hdmi_lost_hotplug(struct omap_dss_device 
*dssdev)
hdmi4_cec_set_phys_addr(>core, CEC_PHYS_ADDR_INVALID);
 }
 
-static int hdmi_set_infoframe(struct omap_dss_device *dssdev,
-   const struct hdmi_avi_infoframe *avi)
-{
-   struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-
-   hdmi->cfg.infoframe = *avi;
-   return 0;
-}
-
-static int hdmi_set_hdmi_mode(struct omap_dss_device *dssdev,
-   bool hdmi_mode)
-{
-   struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-
-   hdmi->cfg.hdmi_dvi_mode = hdmi_mode ? HDMI_HDMI : HDMI_DVI;
-   return 0;
-}
-
 static const struct omap_dss_device_ops hdmi_ops = {
.connect= hdmi_connect,
.disconnect = hdmi_disconnect,
 
-   .enable = hdmi_display_enable,
-   .disable= hdmi_display_disable,
-
-   .set_timings= hdmi_display_set_timings,
-
.read_edid  = hdmi_read_edid,
 
.hdmi = {
.lost_hotplug   = hdmi_lost_hotplug,
-   .set_infoframe  = hdmi_set_infoframe,
-   .set_hdmi_mode  = hdmi_set_hdmi_mode,
},
 };
 
@@ -543,6 +451,108 @@ static int 

[PATCH v6 49/51] drm/omap: dss: Remove unused omap_dss_device operations

2020-02-16 Thread Laurent Pinchart
The omap_dss_device .pre_enable(), .post_disable() and .set_timings()
are not used anymore. Remove them.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
---
 drivers/gpu/drm/omapdrm/dss/base.c | 26 ---
 drivers/gpu/drm/omapdrm/dss/omapdss.h  |  6 
 drivers/gpu/drm/omapdrm/omap_encoder.c | 44 +++---
 3 files changed, 5 insertions(+), 71 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/base.c 
b/drivers/gpu/drm/omapdrm/dss/base.c
index 455b410f7401..c7650a7c155d 100644
--- a/drivers/gpu/drm/omapdrm/dss/base.c
+++ b/drivers/gpu/drm/omapdrm/dss/base.c
@@ -234,18 +234,6 @@ void omapdss_device_disconnect(struct omap_dss_device *src,
 }
 EXPORT_SYMBOL_GPL(omapdss_device_disconnect);
 
-void omapdss_device_pre_enable(struct omap_dss_device *dssdev)
-{
-   if (!dssdev)
-   return;
-
-   omapdss_device_pre_enable(dssdev->next);
-
-   if (dssdev->ops && dssdev->ops->pre_enable)
-   dssdev->ops->pre_enable(dssdev);
-}
-EXPORT_SYMBOL_GPL(omapdss_device_pre_enable);
-
 void omapdss_device_enable(struct omap_dss_device *dssdev)
 {
if (!dssdev)
@@ -272,20 +260,6 @@ void omapdss_device_disable(struct omap_dss_device *dssdev)
 }
 EXPORT_SYMBOL_GPL(omapdss_device_disable);
 
-void omapdss_device_post_disable(struct omap_dss_device *dssdev)
-{
-   if (!dssdev)
-   return;
-
-   if (dssdev->ops && dssdev->ops->post_disable)
-   dssdev->ops->post_disable(dssdev);
-
-   omapdss_device_post_disable(dssdev->next);
-
-   dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-}
-EXPORT_SYMBOL_GPL(omapdss_device_post_disable);
-
 /* 
-
  * Components Handling
  */
diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h 
b/drivers/gpu/drm/omapdrm/dss/omapdss.h
index 2e5453df2293..64aedc50cb0b 100644
--- a/drivers/gpu/drm/omapdrm/dss/omapdss.h
+++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h
@@ -342,15 +342,11 @@ struct omap_dss_device_ops {
void (*disconnect)(struct omap_dss_device *dssdev,
struct omap_dss_device *dst);
 
-   void (*pre_enable)(struct omap_dss_device *dssdev);
void (*enable)(struct omap_dss_device *dssdev);
void (*disable)(struct omap_dss_device *dssdev);
-   void (*post_disable)(struct omap_dss_device *dssdev);
 
int (*check_timings)(struct omap_dss_device *dssdev,
 struct drm_display_mode *mode);
-   void (*set_timings)(struct omap_dss_device *dssdev,
-   const struct drm_display_mode *mode);
 
int (*get_modes)(struct omap_dss_device *dssdev,
 struct drm_connector *connector);
@@ -450,10 +446,8 @@ int omapdss_device_connect(struct dss_device *dss,
   struct omap_dss_device *dst);
 void omapdss_device_disconnect(struct omap_dss_device *src,
   struct omap_dss_device *dst);
-void omapdss_device_pre_enable(struct omap_dss_device *dssdev);
 void omapdss_device_enable(struct omap_dss_device *dssdev);
 void omapdss_device_disable(struct omap_dss_device *dssdev);
-void omapdss_device_post_disable(struct omap_dss_device *dssdev);
 
 int omap_dss_get_num_overlay_managers(void);
 
diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c 
b/drivers/gpu/drm/omapdrm/omap_encoder.c
index 18a79dde6815..ae4b867a67a3 100644
--- a/drivers/gpu/drm/omapdrm/omap_encoder.c
+++ b/drivers/gpu/drm/omapdrm/omap_encoder.c
@@ -113,13 +113,8 @@ static void omap_encoder_mode_set(struct drm_encoder 
*encoder,
bus_flags = connector->display_info.bus_flags;
omap_encoder_update_videomode_flags(, bus_flags);
 
-   /* Set timings for all devices in the display pipeline. */
+   /* Set timings for the dss manager. */
dss_mgr_set_timings(output, );
-
-   for (dssdev = output; dssdev; dssdev = dssdev->next) {
-   if (dssdev->ops && dssdev->ops->set_timings)
-   dssdev->ops->set_timings(dssdev, adjusted_mode);
-   }
 }
 
 static void omap_encoder_disable(struct drm_encoder *encoder)
@@ -132,26 +127,10 @@ static void omap_encoder_disable(struct drm_encoder 
*encoder)
 
/*
 * Disable the chain of external devices, starting at the one at the
-* internal encoder's output.
+* internal encoder's output. This is used for DSI outputs only, as
+* dssdev->next is NULL for all other outputs.
 */
omapdss_device_disable(dssdev->next);
-
-   /*
-* Disable the internal encoder. This will disable the DSS output. The
-* DSI is treated as an exception as DSI pipelines still use the legacy
-* flow where the pipeline output controls the encoder.
-*/
-   if (dssdev->type != OMAP_DISPLAY_TYPE_DSI) {
-   if (dssdev->ops && dssdev->ops->disable)
-   dssdev->ops->disable(dssdev);
-

[PATCH v6 17/51] drm: Add helper to create a connector for a chain of bridges

2020-02-16 Thread Laurent Pinchart
Most bridge drivers create a DRM connector to model the connector at the
output of the bridge. This model is historical and has worked pretty
well so far, but causes several issues:

- It prevents supporting more complex display pipelines where DRM
connector operations are split over multiple components. For instance a
pipeline with a bridge connected to the DDC signals to read EDID data,
and another one connected to the HPD signal to detect connection and
disconnection, will not be possible to support through this model.

- It requires every bridge driver to implement similar connector
handling code, resulting in code duplication.

- It assumes that a bridge will either be wired to a connector or to
another bridge, but doesn't support bridges that can be used in both
positions very well (although there is some ad-hoc support for this in
the analogix_dp bridge driver).

In order to solve these issues, ownership of the connector needs to be
moved to the display controller driver.

To avoid code duplication in display controller drivers, add a new
helper to create and manage a DRM connector backed by a chain of
bridges. All connector operations are delegating to the appropriate
bridge in the chain.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Boris Brezillon 
Acked-by: Sam Ravnborg 
---
Changes since v5:

- Fix the interlace_allowed flag logic

Changes since v4:

- Set the connector interlace_allowed flag based on interlaced support
  in bridges

Changes since v2:

- Fixed typo in documentation
- Rebased on top of Boris' drm_bridge chaining rework
- Pass drm_encoder instead of brm_bridge to drm_bridge_connector_init()

Changes since v1:

- Removed the unused MAX_EDID macro
- Removed the unused drm_bridge_connector.hdmi_mode field
- Use drm_connector_init_with_ddc()
---
 drivers/gpu/drm/Makefile   |   3 +-
 drivers/gpu/drm/drm_bridge_connector.c | 378 +
 include/drm/drm_bridge_connector.h |  18 ++
 3 files changed, 398 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/drm_bridge_connector.c
 create mode 100644 include/drm/drm_bridge_connector.h

diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index ca0ca775d37f..7f72ef5e7811 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -39,7 +39,8 @@ obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o
 drm_ttm_helper-y := drm_gem_ttm_helper.o
 obj-$(CONFIG_DRM_TTM_HELPER) += drm_ttm_helper.o
 
-drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_dsc.o 
drm_probe_helper.o \
+drm_kms_helper-y := drm_bridge_connector.o drm_crtc_helper.o drm_dp_helper.o \
+   drm_dsc.o drm_probe_helper.o \
drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \
drm_kms_helper_common.o drm_dp_dual_mode_helper.o \
drm_simple_kms_helper.o drm_modeset_helper.o \
diff --git a/drivers/gpu/drm/drm_bridge_connector.c 
b/drivers/gpu/drm/drm_bridge_connector.c
new file mode 100644
index ..a102755afde8
--- /dev/null
+++ b/drivers/gpu/drm/drm_bridge_connector.c
@@ -0,0 +1,378 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Laurent Pinchart 
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/**
+ * DOC: overview
+ *
+ * The DRM bridge connector helper object provides a DRM connector
+ * implementation that wraps a chain of  drm_bridge. The connector
+ * operations are fully implemented based on the operations of the bridges in
+ * the chain, and don't require any intervention from the display controller
+ * driver at runtime.
+ *
+ * To use the helper, display controller drivers create a bridge connector with
+ * a call to drm_bridge_connector_init(). This associates the newly created
+ * connector with the chain of bridges passed to the function and registers it
+ * with the DRM device. At that point the connector becomes fully usable, no
+ * further operation is needed.
+ *
+ * The DRM bridge connector operations are implemented based on the operations
+ * provided by the bridges in the chain. Each connector operation is delegated
+ * to the bridge closest to the connector (at the end of the chain) that
+ * provides the relevant functionality.
+ *
+ * To make use of this helper, all bridges in the chain shall report bridge
+ * operation flags (_bridge->ops) and bridge output type
+ * (_bridge->type), and none of them may create a DRM connector directly.
+ */
+
+/**
+ * struct drm_bridge_connector - A connector backed by a chain of bridges
+ */
+struct drm_bridge_connector {
+   /**
+* @base: The base DRM connector
+*/
+   struct drm_connector base;
+   /**
+* @encoder:
+*
+* The encoder at the start of the bridges chain.
+*/
+   struct drm_encoder *encoder;
+   /**
+* @bridge_edid:
+*
+* The last bridge in the chain (closest to the 

[PATCH v6 45/51] drm/omap: dpi: Register a drm_bridge

2020-02-16 Thread Laurent Pinchart
In order to integrate with a chain of drm_bridge, the internal DPI
output has to expose its operations through the drm_bridge API.
Register a bridge at initialisation time to do so and remove the
omap_dss_device operations that are now unused.

Signed-off-by: Laurent Pinchart 
---
Changes since v5:

- Rebased on top of drm_bridge_state

Changes since v3:

- Drop unneeded lock

Changes since v2:

- Unregister bridge if port initialisation fails
---
 drivers/gpu/drm/omapdrm/dss/dpi.c | 209 +-
 1 file changed, 116 insertions(+), 93 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c 
b/drivers/gpu/drm/omapdrm/dss/dpi.c
index c167bd1116ec..5110acb0c6c1 100644
--- a/drivers/gpu/drm/omapdrm/dss/dpi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dpi.c
@@ -21,6 +21,8 @@
 #include 
 #include 
 
+#include 
+
 #include "dss.h"
 #include "omapdss.h"
 
@@ -34,19 +36,15 @@ struct dpi_data {
enum dss_clk_source clk_src;
struct dss_pll *pll;
 
-   struct mutex lock;
-
struct dss_lcd_mgr_config mgr_config;
unsigned long pixelclock;
int data_lines;
 
struct omap_dss_device output;
+   struct drm_bridge bridge;
 };
 
-static struct dpi_data *dpi_get_data_from_dssdev(struct omap_dss_device 
*dssdev)
-{
-   return container_of(dssdev, struct dpi_data, output);
-}
+#define drm_bridge_to_dpi(bridge) container_of(bridge, struct dpi_data, bridge)
 
 /* 
-
  * Clock Handling and PLL
@@ -354,6 +352,32 @@ static void dpi_config_lcd_manager(struct dpi_data *dpi)
dss_mgr_set_lcd_config(>output, >mgr_config);
 }
 
+static int dpi_clock_update(struct dpi_data *dpi, unsigned long *clock)
+{
+   int lck_div, pck_div;
+   unsigned long fck;
+   struct dpi_clk_calc_ctx ctx;
+
+   if (dpi->pll) {
+   if (!dpi_pll_clk_calc(dpi, *clock, ))
+   return -EINVAL;
+
+   fck = ctx.pll_cinfo.clkout[ctx.clkout_idx];
+   } else {
+   if (!dpi_dss_clk_calc(dpi, *clock, ))
+   return -EINVAL;
+
+   fck = ctx.fck;
+   }
+
+   lck_div = ctx.dispc_cinfo.lck_div;
+   pck_div = ctx.dispc_cinfo.pck_div;
+
+   *clock = fck / lck_div / pck_div;
+
+   return 0;
+}
+
 static int dpi_verify_pll(struct dss_pll *pll)
 {
int r;
@@ -391,44 +415,86 @@ static void dpi_init_pll(struct dpi_data *dpi)
 }
 
 /* 
-
- * omap_dss_device Operations
+ * DRM Bridge Operations
  */
 
-static int dpi_connect(struct omap_dss_device *src,
-  struct omap_dss_device *dst)
+static int dpi_bridge_attach(struct drm_bridge *bridge,
+enum drm_bridge_attach_flags flags)
 {
-   struct dpi_data *dpi = dpi_get_data_from_dssdev(dst);
+   struct dpi_data *dpi = drm_bridge_to_dpi(bridge);
+
+   if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR))
+   return -EINVAL;
 
dpi_init_pll(dpi);
 
-   return omapdss_device_connect(dst->dss, dst, dst->next);
+   return drm_bridge_attach(bridge->encoder, dpi->output.next_bridge,
+bridge, flags);
 }
 
-static void dpi_disconnect(struct omap_dss_device *src,
-  struct omap_dss_device *dst)
+static enum drm_mode_status
+dpi_bridge_mode_valid(struct drm_bridge *bridge,
+  const struct drm_display_mode *mode)
 {
-   omapdss_device_disconnect(dst, dst->next);
+   struct dpi_data *dpi = drm_bridge_to_dpi(bridge);
+   unsigned long clock = mode->clock * 1000;
+   int ret;
+
+   if (mode->hdisplay % 8 != 0)
+   return MODE_BAD_WIDTH;
+
+   if (mode->clock == 0)
+   return MODE_NOCLOCK;
+
+   ret = dpi_clock_update(dpi, );
+   if (ret < 0)
+   return MODE_CLOCK_RANGE;
+
+   return MODE_OK;
 }
 
-static void dpi_display_enable(struct omap_dss_device *dssdev)
+static bool dpi_bridge_mode_fixup(struct drm_bridge *bridge,
+  const struct drm_display_mode *mode,
+  struct drm_display_mode *adjusted_mode)
 {
-   struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
-   struct omap_dss_device *out = >output;
-   int r;
+   struct dpi_data *dpi = drm_bridge_to_dpi(bridge);
+   unsigned long clock = mode->clock * 1000;
+   int ret;
+
+   ret = dpi_clock_update(dpi, );
+   if (ret < 0)
+   return false;
+
+   adjusted_mode->clock = clock / 1000;
+
+   return true;
+}
 
-   mutex_lock(>lock);
+static void dpi_bridge_mode_set(struct drm_bridge *bridge,
+const struct drm_display_mode *mode,
+const struct drm_display_mode *adjusted_mode)
+{
+   struct dpi_data *dpi = drm_bridge_to_dpi(bridge);
+

[PATCH v6 09/51] drm/bridge: simple-bridge: Add support for non-VGA bridges

2020-02-16 Thread Laurent Pinchart
Create a new simple_bridge_info structure that stores information about
the bridge model, and store the bridge timings in there, along with the
connector type. Use that new structure for of_device_id data. This
enables support for non-VGA bridges.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Andrzej Hajda 
Reviewed-by: Stefan Agner 
Reviewed-by: Boris Brezillon 
Reviewed-by: Maxime Ripard 
Acked-by: Sam Ravnborg 
---
Changes since v1:

- Renamed simple_bridge_info.type field to connector_type
---
 drivers/gpu/drm/bridge/simple-bridge.c | 41 ++
 1 file changed, 29 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/bridge/simple-bridge.c 
b/drivers/gpu/drm/bridge/simple-bridge.c
index 00d810c99193..20866c1230de 100644
--- a/drivers/gpu/drm/bridge/simple-bridge.c
+++ b/drivers/gpu/drm/bridge/simple-bridge.c
@@ -17,10 +17,17 @@
 #include 
 #include 
 
+struct simple_bridge_info {
+   const struct drm_bridge_timings *timings;
+   unsigned int connector_type;
+};
+
 struct simple_bridge {
struct drm_bridge   bridge;
struct drm_connectorconnector;
 
+   const struct simple_bridge_info *info;
+
struct i2c_adapter  *ddc;
struct regulator*vdd;
 };
@@ -120,7 +127,7 @@ static int simple_bridge_attach(struct drm_bridge *bridge,
 _bridge_con_helper_funcs);
ret = drm_connector_init_with_ddc(bridge->dev, >connector,
  _bridge_con_funcs,
- DRM_MODE_CONNECTOR_VGA,
+ sbridge->info->connector_type,
  sbridge->ddc);
if (ret) {
DRM_ERROR("Failed to initialize connector\n");
@@ -190,6 +197,8 @@ static int simple_bridge_probe(struct platform_device *pdev)
return -ENOMEM;
platform_set_drvdata(pdev, sbridge);
 
+   sbridge->info = of_device_get_match_data(>dev);
+
sbridge->vdd = devm_regulator_get_optional(>dev, "vdd");
if (IS_ERR(sbridge->vdd)) {
int ret = PTR_ERR(sbridge->vdd);
@@ -213,7 +222,7 @@ static int simple_bridge_probe(struct platform_device *pdev)
 
sbridge->bridge.funcs = _bridge_bridge_funcs;
sbridge->bridge.of_node = pdev->dev.of_node;
-   sbridge->bridge.timings = of_device_get_match_data(>dev);
+   sbridge->bridge.timings = sbridge->info->timings;
 
drm_bridge_add(>bridge);
 
@@ -273,19 +282,27 @@ static const struct drm_bridge_timings 
ti_ths8135_bridge_timings = {
 static const struct of_device_id simple_bridge_match[] = {
{
.compatible = "dumb-vga-dac",
-   .data = NULL,
-   },
-   {
+   .data = &(const struct simple_bridge_info) {
+   .connector_type = DRM_MODE_CONNECTOR_VGA,
+   },
+   }, {
.compatible = "adi,adv7123",
-   .data = _bridge_timings,
-   },
-   {
+   .data = &(const struct simple_bridge_info) {
+   .timings = _bridge_timings,
+   .connector_type = DRM_MODE_CONNECTOR_VGA,
+   },
+   }, {
.compatible = "ti,ths8135",
-   .data = _ths8135_bridge_timings,
-   },
-   {
+   .data = &(const struct simple_bridge_info) {
+   .timings = _ths8135_bridge_timings,
+   .connector_type = DRM_MODE_CONNECTOR_VGA,
+   },
+   }, {
.compatible = "ti,ths8134",
-   .data = _ths8134_bridge_timings,
+   .data = &(const struct simple_bridge_info) {
+   .timings = _ths8134_bridge_timings,
+   .connector_type = DRM_MODE_CONNECTOR_VGA,
+   },
},
{},
 };
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v6 31/51] drm/omap: hdmi5: Move mode set, enable and disable operations to bridge

2020-02-16 Thread Laurent Pinchart
Move the omap_dss_device .set_timings(), .enable() and .disable()
operations to the drm_bridge functions. As the drm_bridge for the HDMI
encoder is unconditionally registered and attached, those operations
will be called at the appropriate time.

The omapdss device .set_infoframe() and .set_hdmi_mode() operations have
no equivalent in drm_bridge. Thir content is thus moved to the bridge
.enable() operation as the data they store is not needed before the HDMI
encoder gets enabled.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
---
Changes since v5:

- Rebased on top of drm_bridge_state

Changes since v2:

- Detail .set_infoframe() and .set_hdmi_mode() handling in the commit
  message
---
 drivers/gpu/drm/omapdrm/dss/hdmi5.c | 209 +++-
 1 file changed, 111 insertions(+), 98 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
index e7fe2a24a3e1..52184797c858 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
@@ -31,6 +31,9 @@
 #include 
 #include 
 
+#include 
+#include 
+
 #include "omapdss.h"
 #include "hdmi5_core.h"
 #include "dss.h"
@@ -236,20 +239,6 @@ static void hdmi_power_off_full(struct omap_hdmi *hdmi)
hdmi_power_off_core(hdmi);
 }
 
-static void hdmi_display_set_timings(struct omap_dss_device *dssdev,
-const struct drm_display_mode *mode)
-{
-   struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-
-   mutex_lock(>lock);
-
-   drm_display_mode_to_videomode(mode, >cfg.vm);
-
-   dispc_set_tv_pclk(hdmi->dss->dispc, mode->clock * 1000);
-
-   mutex_unlock(>lock);
-}
-
 static int hdmi_dump_regs(struct seq_file *s, void *p)
 {
struct omap_hdmi *hdmi = s->private;
@@ -285,62 +274,6 @@ static void hdmi_stop_audio_stream(struct omap_hdmi *hd)
REG_FLD_MOD(hd->wp.base, HDMI_WP_SYSCONFIG, hd->wp_idlemode, 3, 2);
 }
 
-static void hdmi_display_enable(struct omap_dss_device *dssdev)
-{
-   struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-   unsigned long flags;
-   int r;
-
-   DSSDBG("ENTER hdmi_display_enable\n");
-
-   mutex_lock(>lock);
-
-   r = hdmi_power_on_full(hdmi);
-   if (r) {
-   DSSERR("failed to power on device\n");
-   goto done;
-   }
-
-   if (hdmi->audio_configured) {
-   r = hdmi5_audio_config(>core, >wp,
-  >audio_config,
-  hdmi->cfg.vm.pixelclock);
-   if (r) {
-   DSSERR("Error restoring audio configuration: %d", r);
-   hdmi->audio_abort_cb(>pdev->dev);
-   hdmi->audio_configured = false;
-   }
-   }
-
-   spin_lock_irqsave(>audio_playing_lock, flags);
-   if (hdmi->audio_configured && hdmi->audio_playing)
-   hdmi_start_audio_stream(hdmi);
-   hdmi->display_enabled = true;
-   spin_unlock_irqrestore(>audio_playing_lock, flags);
-
-done:
-   mutex_unlock(>lock);
-}
-
-static void hdmi_display_disable(struct omap_dss_device *dssdev)
-{
-   struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-   unsigned long flags;
-
-   DSSDBG("Enter hdmi_display_disable\n");
-
-   mutex_lock(>lock);
-
-   spin_lock_irqsave(>audio_playing_lock, flags);
-   hdmi_stop_audio_stream(hdmi);
-   hdmi->display_enabled = false;
-   spin_unlock_irqrestore(>audio_playing_lock, flags);
-
-   hdmi_power_off_full(hdmi);
-
-   mutex_unlock(>lock);
-}
-
 static int hdmi_core_enable(struct omap_hdmi *hdmi)
 {
int r = 0;
@@ -473,39 +406,11 @@ static struct edid *hdmi_read_edid(struct omap_dss_device 
*dssdev)
 NULL);
 }
 
-static int hdmi_set_infoframe(struct omap_dss_device *dssdev,
-   const struct hdmi_avi_infoframe *avi)
-{
-   struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-
-   hdmi->cfg.infoframe = *avi;
-   return 0;
-}
-
-static int hdmi_set_hdmi_mode(struct omap_dss_device *dssdev,
-   bool hdmi_mode)
-{
-   struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-
-   hdmi->cfg.hdmi_dvi_mode = hdmi_mode ? HDMI_HDMI : HDMI_DVI;
-   return 0;
-}
-
 static const struct omap_dss_device_ops hdmi_ops = {
.connect= hdmi_connect,
.disconnect = hdmi_disconnect,
 
-   .enable = hdmi_display_enable,
-   .disable= hdmi_display_disable,
-
-   .set_timings= hdmi_display_set_timings,
-
.read_edid  = hdmi_read_edid,
-
-   .hdmi = {
-   .set_infoframe  = hdmi_set_infoframe,
-   .set_hdmi_mode  = hdmi_set_hdmi_mode,
-   },
 };
 
 /* 
-
@@ -524,6 +429,108 @@ static int hdmi5_bridge_attach(struct drm_bridge 

[PATCH v6 07/51] drm/bridge: dumb-vga-dac: Rename internal symbols to simple-bridge

2020-02-16 Thread Laurent Pinchart
The dumb-vga-dac driver is a simple DRM bridge driver for simple VGA
DACs that don't require configuration. Other non-VGA bridges fall in a
similar category, and would benefit from a common driver. Prepare for
this by renaming the internal symbols from dumb-vga-dac to
simple-bridge.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Andrzej Hajda 
Reviewed-by: Boris Brezillon 
Reviewed-by: Maxime Ripard 
Acked-by: Sam Ravnborg 
---
 drivers/gpu/drm/bridge/dumb-vga-dac.c | 154 +-
 1 file changed, 77 insertions(+), 77 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c 
b/drivers/gpu/drm/bridge/dumb-vga-dac.c
index ad5b5a849e43..7287be2d3220 100644
--- a/drivers/gpu/drm/bridge/dumb-vga-dac.c
+++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c
@@ -17,7 +17,7 @@
 #include 
 #include 
 
-struct dumb_vga {
+struct simple_bridge {
struct drm_bridge   bridge;
struct drm_connectorconnector;
 
@@ -25,28 +25,28 @@ struct dumb_vga {
struct regulator*vdd;
 };
 
-static inline struct dumb_vga *
-drm_bridge_to_dumb_vga(struct drm_bridge *bridge)
+static inline struct simple_bridge *
+drm_bridge_to_simple_bridge(struct drm_bridge *bridge)
 {
-   return container_of(bridge, struct dumb_vga, bridge);
+   return container_of(bridge, struct simple_bridge, bridge);
 }
 
-static inline struct dumb_vga *
-drm_connector_to_dumb_vga(struct drm_connector *connector)
+static inline struct simple_bridge *
+drm_connector_to_simple_bridge(struct drm_connector *connector)
 {
-   return container_of(connector, struct dumb_vga, connector);
+   return container_of(connector, struct simple_bridge, connector);
 }
 
-static int dumb_vga_get_modes(struct drm_connector *connector)
+static int simple_bridge_get_modes(struct drm_connector *connector)
 {
-   struct dumb_vga *vga = drm_connector_to_dumb_vga(connector);
+   struct simple_bridge *sbridge = 
drm_connector_to_simple_bridge(connector);
struct edid *edid;
int ret;
 
-   if (!vga->ddc)
+   if (!sbridge->ddc)
goto fallback;
 
-   edid = drm_get_edid(connector, vga->ddc);
+   edid = drm_get_edid(connector, sbridge->ddc);
if (!edid) {
DRM_INFO("EDID readout failed, falling back to standard 
modes\n");
goto fallback;
@@ -70,14 +70,14 @@ static int dumb_vga_get_modes(struct drm_connector 
*connector)
return ret;
 }
 
-static const struct drm_connector_helper_funcs dumb_vga_con_helper_funcs = {
-   .get_modes  = dumb_vga_get_modes,
+static const struct drm_connector_helper_funcs simple_bridge_con_helper_funcs 
= {
+   .get_modes  = simple_bridge_get_modes,
 };
 
 static enum drm_connector_status
-dumb_vga_connector_detect(struct drm_connector *connector, bool force)
+simple_bridge_connector_detect(struct drm_connector *connector, bool force)
 {
-   struct dumb_vga *vga = drm_connector_to_dumb_vga(connector);
+   struct simple_bridge *sbridge = 
drm_connector_to_simple_bridge(connector);
 
/*
 * Even if we have an I2C bus, we can't assume that the cable
@@ -85,14 +85,14 @@ dumb_vga_connector_detect(struct drm_connector *connector, 
bool force)
 * wire the DDC pins, or the I2C bus might not be working at
 * all.
 */
-   if (vga->ddc && drm_probe_ddc(vga->ddc))
+   if (sbridge->ddc && drm_probe_ddc(sbridge->ddc))
return connector_status_connected;
 
return connector_status_unknown;
 }
 
-static const struct drm_connector_funcs dumb_vga_con_funcs = {
-   .detect = dumb_vga_connector_detect,
+static const struct drm_connector_funcs simple_bridge_con_funcs = {
+   .detect = simple_bridge_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy= drm_connector_cleanup,
.reset  = drm_atomic_helper_connector_reset,
@@ -100,10 +100,10 @@ static const struct drm_connector_funcs 
dumb_vga_con_funcs = {
.atomic_destroy_state   = drm_atomic_helper_connector_destroy_state,
 };
 
-static int dumb_vga_attach(struct drm_bridge *bridge,
-  enum drm_bridge_attach_flags flags)
+static int simple_bridge_attach(struct drm_bridge *bridge,
+   enum drm_bridge_attach_flags flags)
 {
-   struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
+   struct simple_bridge *sbridge = drm_bridge_to_simple_bridge(bridge);
int ret;
 
if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) {
@@ -116,50 +116,50 @@ static int dumb_vga_attach(struct drm_bridge *bridge,
return -ENODEV;
}
 
-   drm_connector_helper_add(>connector,
-_vga_con_helper_funcs);
-   ret = drm_connector_init_with_ddc(bridge->dev, >connector,
- _vga_con_funcs,
+   

[PATCH v6 40/51] drm/omap: hdmi4: Simplify EDID read

2020-02-16 Thread Laurent Pinchart
Now that the omap_dss_device EDID read operation has been removed,
simplify the bridge-based EDID access by merging multiple functions
together.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
---
 drivers/gpu/drm/omapdrm/dss/hdmi4.c | 96 -
 1 file changed, 40 insertions(+), 56 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index 96ef7bd52199..2578c95570f6 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -309,55 +309,6 @@ void hdmi4_core_disable(struct hdmi_core_data *core)
mutex_unlock(>lock);
 }
 
-static struct edid *
-hdmi_do_read_edid(struct omap_hdmi *hdmi,
- struct edid *(*read)(struct omap_hdmi *hdmi,
-  struct drm_connector *connector),
- struct drm_connector *connector)
-{
-   struct edid *edid = NULL;
-   unsigned int cec_addr;
-   bool need_enable;
-   int r;
-
-   need_enable = hdmi->core_enabled == false;
-
-   if (need_enable) {
-   r = hdmi4_core_enable(>core);
-   if (r)
-   return NULL;
-   }
-
-   mutex_lock(>lock);
-   r = hdmi_runtime_get(hdmi);
-   BUG_ON(r);
-
-   r = hdmi4_core_ddc_init(>core);
-   if (r)
-   goto done;
-
-   edid = read(hdmi, connector);
-
-done:
-   hdmi_runtime_put(hdmi);
-   mutex_unlock(>lock);
-
-   if (edid && edid->extensions) {
-   unsigned int len = (edid->extensions + 1) * EDID_LENGTH;
-
-   cec_addr = cec_get_edid_phys_addr((u8 *)edid, len, NULL);
-   } else {
-   cec_addr = CEC_PHYS_ADDR_INVALID;
-   }
-
-   hdmi4_cec_set_phys_addr(>core, cec_addr);
-
-   if (need_enable)
-   hdmi4_core_disable(>core);
-
-   return edid;
-}
-
 /* 
-
  * DRM Bridge Operations
  */
@@ -485,18 +436,51 @@ static void hdmi4_bridge_hpd_notify(struct drm_bridge 
*bridge,
hdmi4_cec_set_phys_addr(>core, CEC_PHYS_ADDR_INVALID);
 }
 
-static struct edid *hdmi4_bridge_read_edid(struct omap_hdmi *hdmi,
-  struct drm_connector *connector)
-{
-   return drm_do_get_edid(connector, hdmi4_core_ddc_read, >core);
-}
-
 static struct edid *hdmi4_bridge_get_edid(struct drm_bridge *bridge,
  struct drm_connector *connector)
 {
struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
+   struct edid *edid = NULL;
+   unsigned int cec_addr;
+   bool need_enable;
+   int r;
+
+   need_enable = hdmi->core_enabled == false;
+
+   if (need_enable) {
+   r = hdmi4_core_enable(>core);
+   if (r)
+   return NULL;
+   }
+
+   mutex_lock(>lock);
+   r = hdmi_runtime_get(hdmi);
+   BUG_ON(r);
+
+   r = hdmi4_core_ddc_init(>core);
+   if (r)
+   goto done;
+
+   edid = drm_do_get_edid(connector, hdmi4_core_ddc_read, >core);
 
-   return hdmi_do_read_edid(hdmi, hdmi4_bridge_read_edid, connector);
+done:
+   hdmi_runtime_put(hdmi);
+   mutex_unlock(>lock);
+
+   if (edid && edid->extensions) {
+   unsigned int len = (edid->extensions + 1) * EDID_LENGTH;
+
+   cec_addr = cec_get_edid_phys_addr((u8 *)edid, len, NULL);
+   } else {
+   cec_addr = CEC_PHYS_ADDR_INVALID;
+   }
+
+   hdmi4_cec_set_phys_addr(>core, cec_addr);
+
+   if (need_enable)
+   hdmi4_core_disable(>core);
+
+   return edid;
 }
 
 static const struct drm_bridge_funcs hdmi4_bridge_funcs = {
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v6 28/51] drm/omap: hdmi4: Register a drm_bridge for EDID read

2020-02-16 Thread Laurent Pinchart
In order to integrate with a chain of drm_bridge, the internal HDMI4
encoder has to expose the EDID read operation through the drm_bridge
API. Register a bridge at initialisation time to do so.

For the time being make the next bridge in the chain optional as the
HDMI output is still based on omap_dss_device. The create_connector
argument to the bridge attach function is also ignored for the same
reason. This will be changed later when removing the related
omapdrm-specific display drivers.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
---
Changes since v2:

- Unregister bridge if output initialisation fails
---
 drivers/gpu/drm/omapdrm/dss/hdmi.h  |  3 ++
 drivers/gpu/drm/omapdrm/dss/hdmi4.c | 78 ++---
 2 files changed, 75 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi.h 
b/drivers/gpu/drm/omapdrm/dss/hdmi.h
index c867552c925c..bd43f6abf27b 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi.h
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi.h
@@ -14,6 +14,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "omapdss.h"
 #include "dss.h"
@@ -364,6 +365,7 @@ struct omap_hdmi {
bool core_enabled;
 
struct omap_dss_device output;
+   struct drm_bridge bridge;
 
struct platform_device *audio_pdev;
void (*audio_abort_cb)(struct device *dev);
@@ -379,5 +381,6 @@ struct omap_hdmi {
 };
 
 #define dssdev_to_hdmi(dssdev) container_of(dssdev, struct omap_hdmi, output)
+#define drm_bridge_to_hdmi(b) container_of(b, struct omap_hdmi, bridge)
 
 #endif
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index 37536b9f3114..67994287447b 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -390,7 +390,8 @@ static void hdmi_disconnect(struct omap_dss_device *src,
 
 #define MAX_EDID   512
 
-static struct edid *hdmi_read_edid_data(struct omap_hdmi *hdmi)
+static struct edid *hdmi_read_edid_data(struct omap_hdmi *hdmi,
+   struct drm_connector *connector)
 {
u8 *edid;
int r;
@@ -428,9 +429,12 @@ static struct edid *hdmi_read_edid_data(struct omap_hdmi 
*hdmi)
return NULL;
 }
 
-static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
+static struct edid *
+hdmi_do_read_edid(struct omap_hdmi *hdmi,
+ struct edid *(*read)(struct omap_hdmi *hdmi,
+  struct drm_connector *connector),
+ struct drm_connector *connector)
 {
-   struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
struct edid *edid = NULL;
unsigned int cec_addr;
bool need_enable;
@@ -452,7 +456,7 @@ static struct edid *hdmi_read_edid(struct omap_dss_device 
*dssdev)
if (r)
goto done;
 
-   edid = hdmi_read_edid_data(hdmi);
+   edid = read(hdmi, connector);
 
 done:
hdmi_runtime_put(hdmi);
@@ -474,6 +478,12 @@ static struct edid *hdmi_read_edid(struct omap_dss_device 
*dssdev)
return edid;
 }
 
+static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
+{
+   return hdmi_do_read_edid(dssdev_to_hdmi(dssdev), hdmi_read_edid_data,
+NULL);
+}
+
 static void hdmi_lost_hotplug(struct omap_dss_device *dssdev)
 {
struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
@@ -517,6 +527,56 @@ static const struct omap_dss_device_ops hdmi_ops = {
},
 };
 
+/* 
-
+ * DRM Bridge Operations
+ */
+
+static int hdmi4_bridge_attach(struct drm_bridge *bridge,
+  enum drm_bridge_attach_flags flags)
+{
+   struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
+
+   if (!hdmi->output.next_bridge)
+   return 0;
+
+   return drm_bridge_attach(bridge->encoder, hdmi->output.next_bridge,
+bridge, flags);
+}
+
+static struct edid *hdmi4_bridge_read_edid(struct omap_hdmi *hdmi,
+  struct drm_connector *connector)
+{
+   return drm_do_get_edid(connector, hdmi4_core_ddc_read, >core);
+}
+
+static struct edid *hdmi4_bridge_get_edid(struct drm_bridge *bridge,
+ struct drm_connector *connector)
+{
+   struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
+
+   return hdmi_do_read_edid(hdmi, hdmi4_bridge_read_edid, connector);
+}
+
+static const struct drm_bridge_funcs hdmi4_bridge_funcs = {
+   .attach = hdmi4_bridge_attach,
+   .get_edid = hdmi4_bridge_get_edid,
+};
+
+static void hdmi4_bridge_init(struct omap_hdmi *hdmi)
+{
+   hdmi->bridge.funcs = _bridge_funcs;
+   hdmi->bridge.of_node = hdmi->pdev->dev.of_node;
+   hdmi->bridge.ops = DRM_BRIDGE_OP_EDID;
+   hdmi->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
+
+   drm_bridge_add(>bridge);
+}
+
+static void hdmi4_bridge_cleanup(struct 

[PATCH v6 34/51] drm/omap: venc: Register a drm_bridge

2020-02-16 Thread Laurent Pinchart
In order to integrate with a chain of drm_bridge, the internal VENC
encoder has to expose the mode valid, fixup and set, the enable and
disable and the get modes operations through the drm_bridge API.
Register a bridge at initialisation time to do so.

Most of those operations are removed from the omap_dss_device as they
are now called through the drm_bridge API by the DRM atomic helpers. The
only exception is the .get_modes() operation that is still invoked
through the omap_dss_device-based pipeline.

For the time being make the next bridge in the chain optional as the
VENC output is still based on omap_dss_device. The create_connector
argument to the bridge attach function is also ignored for the same
reason. This will be changed later when removing the related
omapdrm-specific display drivers.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
---
Changes since v5:

- Rebased on top of drm_bridge_state

Changes since v4:

- Set bridge interlace_allowed flag

Changes since v3:

- Drop unneeded venc_lock

Changes since v2:

- Unregister bridge if output initialisation fails
---
 drivers/gpu/drm/omapdrm/dss/venc.c | 242 ++---
 1 file changed, 154 insertions(+), 88 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c 
b/drivers/gpu/drm/omapdrm/dss/venc.c
index 977d8d525b43..cb9a689ed612 100644
--- a/drivers/gpu/drm/omapdrm/dss/venc.c
+++ b/drivers/gpu/drm/omapdrm/dss/venc.c
@@ -13,7 +13,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -26,6 +25,8 @@
 #include 
 #include 
 
+#include 
+
 #include "omapdss.h"
 #include "dss.h"
 
@@ -289,7 +290,6 @@ static const struct drm_display_mode omap_dss_ntsc_mode = {
 struct venc_device {
struct platform_device *pdev;
void __iomem *base;
-   struct mutex venc_lock;
struct regulator *vdda_dac_reg;
struct dss_device *dss;
 
@@ -303,9 +303,11 @@ struct venc_device {
bool requires_tv_dac_clk;
 
struct omap_dss_device output;
+   struct drm_bridge bridge;
 };
 
 #define dssdev_to_venc(dssdev) container_of(dssdev, struct venc_device, output)
+#define drm_bridge_to_venc(b) container_of(b, struct venc_device, bridge)
 
 static inline void venc_write_reg(struct venc_device *venc, int idx, u32 val)
 {
@@ -477,32 +479,6 @@ static void venc_power_off(struct venc_device *venc)
venc_runtime_put(venc);
 }
 
-static void venc_display_enable(struct omap_dss_device *dssdev)
-{
-   struct venc_device *venc = dssdev_to_venc(dssdev);
-
-   DSSDBG("venc_display_enable\n");
-
-   mutex_lock(>venc_lock);
-
-   venc_power_on(venc);
-
-   mutex_unlock(>venc_lock);
-}
-
-static void venc_display_disable(struct omap_dss_device *dssdev)
-{
-   struct venc_device *venc = dssdev_to_venc(dssdev);
-
-   DSSDBG("venc_display_disable\n");
-
-   mutex_lock(>venc_lock);
-
-   venc_power_off(venc);
-
-   mutex_unlock(>venc_lock);
-}
-
 static int venc_get_modes(struct omap_dss_device *dssdev,
  struct drm_connector *connector)
 {
@@ -545,57 +521,6 @@ static enum venc_videomode venc_get_videomode(const struct 
drm_display_mode *mod
return VENC_MODE_UNKNOWN;
 }
 
-static void venc_set_timings(struct omap_dss_device *dssdev,
-const struct drm_display_mode *mode)
-{
-   struct venc_device *venc = dssdev_to_venc(dssdev);
-   enum venc_videomode venc_mode = venc_get_videomode(mode);
-
-   DSSDBG("venc_set_timings\n");
-
-   mutex_lock(>venc_lock);
-
-   switch (venc_mode) {
-   default:
-   WARN_ON_ONCE(1);
-   /* Fall-through */
-   case VENC_MODE_PAL:
-   venc->config = _config_pal_trm;
-   break;
-
-   case VENC_MODE_NTSC:
-   venc->config = _config_ntsc_trm;
-   break;
-   }
-
-   dispc_set_tv_pclk(venc->dss->dispc, 1350);
-
-   mutex_unlock(>venc_lock);
-}
-
-static int venc_check_timings(struct omap_dss_device *dssdev,
- struct drm_display_mode *mode)
-{
-   DSSDBG("venc_check_timings\n");
-
-   switch (venc_get_videomode(mode)) {
-   case VENC_MODE_PAL:
-   drm_mode_copy(mode, _dss_pal_mode);
-   break;
-
-   case VENC_MODE_NTSC:
-   drm_mode_copy(mode, _dss_ntsc_mode);
-   break;
-
-   default:
-   return -EINVAL;
-   }
-
-   drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
-   drm_mode_set_name(mode);
-   return 0;
-}
-
 static int venc_dump_regs(struct seq_file *s, void *p)
 {
struct venc_device *venc = s->private;
@@ -689,15 +614,152 @@ static const struct omap_dss_device_ops venc_ops = {
.connect = venc_connect,
.disconnect = venc_disconnect,
 
-   .enable = venc_display_enable,
-   .disable = venc_display_disable,
+   .get_modes = venc_get_modes,
+};
 
-   .check_timings = 

[PATCH v6 20/51] drm/omap: Factor out display type to connector type conversion

2020-02-16 Thread Laurent Pinchart
Move the code that computes the DRM connector type for the
omapdss_device display type to a new omapdss_device_connector_type()
function for later reuse.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
Acked-by: Sam Ravnborg 
---
 drivers/gpu/drm/omapdrm/dss/base.c   | 23 +++
 drivers/gpu/drm/omapdrm/dss/omapdss.h|  1 +
 drivers/gpu/drm/omapdrm/omap_connector.c | 19 +--
 3 files changed, 25 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/base.c 
b/drivers/gpu/drm/omapdrm/dss/base.c
index a1970b9db6ab..cae5687822e2 100644
--- a/drivers/gpu/drm/omapdrm/dss/base.c
+++ b/drivers/gpu/drm/omapdrm/dss/base.c
@@ -285,6 +285,29 @@ void omapdss_device_post_disable(struct omap_dss_device 
*dssdev)
 }
 EXPORT_SYMBOL_GPL(omapdss_device_post_disable);
 
+unsigned int omapdss_device_connector_type(enum omap_display_type type)
+{
+   switch (type) {
+   case OMAP_DISPLAY_TYPE_HDMI:
+   return DRM_MODE_CONNECTOR_HDMIA;
+   case OMAP_DISPLAY_TYPE_DVI:
+   return DRM_MODE_CONNECTOR_DVID;
+   case OMAP_DISPLAY_TYPE_DSI:
+   return DRM_MODE_CONNECTOR_DSI;
+   case OMAP_DISPLAY_TYPE_DPI:
+   case OMAP_DISPLAY_TYPE_DBI:
+   return DRM_MODE_CONNECTOR_DPI;
+   case OMAP_DISPLAY_TYPE_VENC:
+   /* TODO: This could also be composite */
+   return DRM_MODE_CONNECTOR_SVIDEO;
+   case OMAP_DISPLAY_TYPE_SDI:
+   return DRM_MODE_CONNECTOR_LVDS;
+   default:
+   return DRM_MODE_CONNECTOR_Unknown;
+   }
+}
+EXPORT_SYMBOL_GPL(omapdss_device_connector_type);
+
 /* 
-
  * Components Handling
  */
diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h 
b/drivers/gpu/drm/omapdrm/dss/omapdss.h
index 79f6b195c7cf..c5672e5174c5 100644
--- a/drivers/gpu/drm/omapdrm/dss/omapdss.h
+++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h
@@ -479,6 +479,7 @@ void omapdss_device_pre_enable(struct omap_dss_device 
*dssdev);
 void omapdss_device_enable(struct omap_dss_device *dssdev);
 void omapdss_device_disable(struct omap_dss_device *dssdev);
 void omapdss_device_post_disable(struct omap_dss_device *dssdev);
+unsigned int omapdss_device_connector_type(enum omap_display_type type);
 
 int omap_dss_get_num_overlay_managers(void);
 
diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c 
b/drivers/gpu/drm/omapdrm/omap_connector.c
index 88dbf3fa473f..38c7a79c5d4a 100644
--- a/drivers/gpu/drm/omapdrm/omap_connector.c
+++ b/drivers/gpu/drm/omapdrm/omap_connector.c
@@ -296,24 +296,7 @@ static int omap_connector_get_type(struct omap_dss_device 
*output)
type = display->type;
omapdss_device_put(display);
 
-   switch (type) {
-   case OMAP_DISPLAY_TYPE_HDMI:
-   return DRM_MODE_CONNECTOR_HDMIA;
-   case OMAP_DISPLAY_TYPE_DVI:
-   return DRM_MODE_CONNECTOR_DVID;
-   case OMAP_DISPLAY_TYPE_DSI:
-   return DRM_MODE_CONNECTOR_DSI;
-   case OMAP_DISPLAY_TYPE_DPI:
-   case OMAP_DISPLAY_TYPE_DBI:
-   return DRM_MODE_CONNECTOR_DPI;
-   case OMAP_DISPLAY_TYPE_VENC:
-   /* TODO: This could also be composite */
-   return DRM_MODE_CONNECTOR_SVIDEO;
-   case OMAP_DISPLAY_TYPE_SDI:
-   return DRM_MODE_CONNECTOR_LVDS;
-   default:
-   return DRM_MODE_CONNECTOR_Unknown;
-   }
+   return omapdss_device_connector_type(type);
 }
 
 /* initialize connector */
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v6 23/51] drm/omap: Add infrastructure to support drm_bridge local to DSS outputs

2020-02-16 Thread Laurent Pinchart
In order to support drm_bridge-based pipeline, the internal HDMI
encoders will need to expose the EDID read operation through the
drm_bridge API, and thus to expose a drm_bridge instance corresponding
to the encoder. The HDMI encoders are however handled as omap_dss_device
instances, which conflicts with this requirement.

In order to move forward with the drm_bridge transition, add support for
creating drm_bridge instances local to DSS outputs. If a local bridge is
passed to the omapdss_device_init_output() function, it is used as the
first bridge in the chain, and the omap_dss_device.next_bridge field is
set to the next bridge for the use of the internal encoders' bridges.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
---
 drivers/gpu/drm/omapdrm/dss/dpi.c |  2 +-
 drivers/gpu/drm/omapdrm/dss/dsi.c |  2 +-
 drivers/gpu/drm/omapdrm/dss/hdmi4.c   |  2 +-
 drivers/gpu/drm/omapdrm/dss/hdmi5.c   |  2 +-
 drivers/gpu/drm/omapdrm/dss/omapdss.h |  4 +++-
 drivers/gpu/drm/omapdrm/dss/output.c  | 20 
 drivers/gpu/drm/omapdrm/dss/sdi.c |  2 +-
 drivers/gpu/drm/omapdrm/dss/venc.c|  2 +-
 drivers/gpu/drm/omapdrm/omap_drv.c|  2 +-
 9 files changed, 26 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c 
b/drivers/gpu/drm/omapdrm/dss/dpi.c
index 462ed6f3118a..2d0eb5fcbb5b 100644
--- a/drivers/gpu/drm/omapdrm/dss/dpi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dpi.c
@@ -629,7 +629,7 @@ static int dpi_init_output_port(struct dpi_data *dpi, 
struct device_node *port)
out->ops = _ops;
out->owner = THIS_MODULE;
 
-   r = omapdss_device_init_output(out);
+   r = omapdss_device_init_output(out, NULL);
if (r < 0)
return r;
 
diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c 
b/drivers/gpu/drm/omapdrm/dss/dsi.c
index 6379eea124d1..79ddfbfd1b58 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -5121,7 +5121,7 @@ static int dsi_init_output(struct dsi_data *dsi)
   | DRM_BUS_FLAG_DE_HIGH
   | DRM_BUS_FLAG_SYNC_DRIVE_NEGEDGE;
 
-   r = omapdss_device_init_output(out);
+   r = omapdss_device_init_output(out, NULL);
if (r < 0)
return r;
 
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index 44075718407b..dd4a14fe7e59 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -676,7 +676,7 @@ static int hdmi4_init_output(struct omap_hdmi *hdmi)
out->of_port = 0;
out->ops_flags = OMAP_DSS_DEVICE_OP_EDID;
 
-   r = omapdss_device_init_output(out);
+   r = omapdss_device_init_output(out, NULL);
if (r < 0)
return r;
 
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c 
b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
index 1b5bd44ee09d..8e3790dd8b98 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
@@ -660,7 +660,7 @@ static int hdmi5_init_output(struct omap_hdmi *hdmi)
out->of_port = 0;
out->ops_flags = OMAP_DSS_DEVICE_OP_EDID;
 
-   r = omapdss_device_init_output(out);
+   r = omapdss_device_init_output(out, NULL);
if (r < 0)
return r;
 
diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h 
b/drivers/gpu/drm/omapdrm/dss/omapdss.h
index b48a51d11310..82e9bfa5530a 100644
--- a/drivers/gpu/drm/omapdrm/dss/omapdss.h
+++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h
@@ -400,6 +400,7 @@ struct omap_dss_device {
struct dss_device *dss;
struct omap_dss_device *next;
struct drm_bridge *bridge;
+   struct drm_bridge *next_bridge;
struct drm_panel *panel;
 
struct list_head list;
@@ -488,7 +489,8 @@ int omap_dss_get_num_overlays(void);
 #define for_each_dss_output(d) \
while ((d = omapdss_device_next_output(d)) != NULL)
 struct omap_dss_device *omapdss_device_next_output(struct omap_dss_device 
*from);
-int omapdss_device_init_output(struct omap_dss_device *out);
+int omapdss_device_init_output(struct omap_dss_device *out,
+  struct drm_bridge *local_bridge);
 void omapdss_device_cleanup_output(struct omap_dss_device *out);
 
 typedef void (*omap_dispc_isr_t) (void *arg, u32 mask);
diff --git a/drivers/gpu/drm/omapdrm/dss/output.c 
b/drivers/gpu/drm/omapdrm/dss/output.c
index c1ec9d343e53..9ba7cc8539a1 100644
--- a/drivers/gpu/drm/omapdrm/dss/output.c
+++ b/drivers/gpu/drm/omapdrm/dss/output.c
@@ -17,7 +17,8 @@
 #include "dss.h"
 #include "omapdss.h"
 
-int omapdss_device_init_output(struct omap_dss_device *out)
+int omapdss_device_init_output(struct omap_dss_device *out,
+  struct drm_bridge *local_bridge)
 {
struct device_node *remote_node;
int ret;
@@ -58,10 +59,20 @@ int omapdss_device_init_output(struct omap_dss_device *out)
out->bridge = bridge;
}
 
-   return out->next || 

[PATCH v6 36/51] drm/omap: Switch the HDMI and VENC outputs to drm_bridge

2020-02-16 Thread Laurent Pinchart
The TPD12S015, OPA362 and analog and HDMI connectors are now supported
by DRM bridge drivers, and the omapdrm HDMI and VENC outputs can be
handled through the drm_bridge API. Switch the outputs to drm_bridge by
making the next bridge mandatory and removing the related
omapdrm-specific display drivers.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
---
Changes since v3:

- Update arch/arm/configs/omap2plus_defconfig
---
 arch/arm/configs/omap2plus_defconfig  |   7 +-
 drivers/gpu/drm/omapdrm/displays/Kconfig  |  22 --
 drivers/gpu/drm/omapdrm/displays/Makefile |   4 -
 .../omapdrm/displays/connector-analog-tv.c|  97 
 .../gpu/drm/omapdrm/displays/connector-hdmi.c | 183 ---
 .../gpu/drm/omapdrm/displays/encoder-opa362.c | 137 ---
 .../drm/omapdrm/displays/encoder-tpd12s015.c  | 217 --
 drivers/gpu/drm/omapdrm/dss/hdmi4.c   |   4 +-
 drivers/gpu/drm/omapdrm/dss/hdmi5.c   |   4 +-
 .../gpu/drm/omapdrm/dss/omapdss-boot-init.c   |   5 -
 drivers/gpu/drm/omapdrm/dss/output.c  |   5 +
 drivers/gpu/drm/omapdrm/dss/venc.c|   4 +-
 12 files changed, 14 insertions(+), 675 deletions(-)
 delete mode 100644 drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c
 delete mode 100644 drivers/gpu/drm/omapdrm/displays/connector-hdmi.c
 delete mode 100644 drivers/gpu/drm/omapdrm/displays/encoder-opa362.c
 delete mode 100644 drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c

diff --git a/arch/arm/configs/omap2plus_defconfig 
b/arch/arm/configs/omap2plus_defconfig
index 8c37cc8ab6f2..a74abf4ac468 100644
--- a/arch/arm/configs/omap2plus_defconfig
+++ b/arch/arm/configs/omap2plus_defconfig
@@ -348,14 +348,13 @@ CONFIG_DRM_OMAP=m
 CONFIG_OMAP5_DSS_HDMI=y
 CONFIG_OMAP2_DSS_SDI=y
 CONFIG_OMAP2_DSS_DSI=y
-CONFIG_DRM_OMAP_ENCODER_OPA362=m
-CONFIG_DRM_OMAP_ENCODER_TPD12S015=m
-CONFIG_DRM_OMAP_CONNECTOR_HDMI=m
-CONFIG_DRM_OMAP_CONNECTOR_ANALOG_TV=m
 CONFIG_DRM_OMAP_PANEL_DSI_CM=m
 CONFIG_DRM_TILCDC=m
 CONFIG_DRM_PANEL_SIMPLE=m
+CONFIG_DRM_DISPLAY_CONNECTOR=m
+CONFIG_DRM_SIMPLE_BRIDGE=m
 CONFIG_DRM_TI_TFP410=m
+CONFIG_DRM_TI_TPD12S015=m
 CONFIG_DRM_PANEL_LG_LB035Q02=m
 CONFIG_DRM_PANEL_NEC_NL8048HL11=m
 CONFIG_DRM_PANEL_SHARP_LS037V7DW01=m
diff --git a/drivers/gpu/drm/omapdrm/displays/Kconfig 
b/drivers/gpu/drm/omapdrm/displays/Kconfig
index b562a8cd61bf..f2be594c7eff 100644
--- a/drivers/gpu/drm/omapdrm/displays/Kconfig
+++ b/drivers/gpu/drm/omapdrm/displays/Kconfig
@@ -1,28 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
 menu "OMAPDRM External Display Device Drivers"
 
-config DRM_OMAP_ENCODER_OPA362
-   tristate "OPA362 external analog amplifier"
-   help
- Driver for OPA362 external analog TV amplifier controlled
- through a GPIO.
-
-config DRM_OMAP_ENCODER_TPD12S015
-   tristate "TPD12S015 HDMI ESD protection and level shifter"
-   help
- Driver for TPD12S015, which offers HDMI ESD protection and level
- shifting.
-
-config DRM_OMAP_CONNECTOR_HDMI
-   tristate "HDMI Connector"
-   help
- Driver for a generic HDMI connector.
-
-config DRM_OMAP_CONNECTOR_ANALOG_TV
-   tristate "Analog TV Connector"
-   help
- Driver for a generic analog TV connector.
-
 config DRM_OMAP_PANEL_DSI_CM
tristate "Generic DSI Command Mode Panel"
depends on BACKLIGHT_CLASS_DEVICE
diff --git a/drivers/gpu/drm/omapdrm/displays/Makefile 
b/drivers/gpu/drm/omapdrm/displays/Makefile
index cb76859dc574..488ddf153613 100644
--- a/drivers/gpu/drm/omapdrm/displays/Makefile
+++ b/drivers/gpu/drm/omapdrm/displays/Makefile
@@ -1,6 +1,2 @@
 # SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_DRM_OMAP_ENCODER_OPA362) += encoder-opa362.o
-obj-$(CONFIG_DRM_OMAP_ENCODER_TPD12S015) += encoder-tpd12s015.o
-obj-$(CONFIG_DRM_OMAP_CONNECTOR_HDMI) += connector-hdmi.o
-obj-$(CONFIG_DRM_OMAP_CONNECTOR_ANALOG_TV) += connector-analog-tv.o
 obj-$(CONFIG_DRM_OMAP_PANEL_DSI_CM) += panel-dsi-cm.o
diff --git a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c 
b/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c
deleted file mode 100644
index f36aa1885d39..
--- a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c
+++ /dev/null
@@ -1,97 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Analog TV Connector driver
- *
- * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
- * Author: Tomi Valkeinen 
- */
-
-#include 
-#include 
-#include 
-#include 
-
-#include "../dss/omapdss.h"
-
-struct panel_drv_data {
-   struct omap_dss_device dssdev;
-
-   struct device *dev;
-};
-
-#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
-
-static int tvc_connect(struct omap_dss_device *src,
-  struct omap_dss_device *dst)
-{
-   return 0;
-}
-
-static void tvc_disconnect(struct omap_dss_device *src,
-  struct omap_dss_device *dst)
-{
-}
-
-static const struct 

[PATCH v6 04/51] drm/bridge: Add connector-related bridge operations and data

2020-02-16 Thread Laurent Pinchart
To support implementation of DRM connectors on top of DRM bridges
instead of by bridges, the drm_bridge needs to expose new operations and
data:

- Output detection, hot-plug notification, mode retrieval and EDID
  retrieval operations
- Bitmask of supported operations
- Bridge output type
- I2C adapter for DDC access

Add and document these.

Three new bridge helper functions are also added to handle hot plug
notification in a way that is as transparent as possible for the
bridges.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Boris Brezillon 
Reviewed-by: Sam Ravnborg 
---
Changes since v3:

- Fix typos

Changes since v2:

- Add wrappers around the .detect(), .get_modes() and .get_edid()
  operations
- Warn bridge drivers about valid usage of the connector argument to
  .get_modes() and .get_edid()

Changes since v1:

- Make .hpd_enable() and .hpd_disable() optional
- Rename .lost_hotplug() to .hpd_notify()
- Add ddc field to drm_bridge
---
 drivers/gpu/drm/drm_bridge.c | 162 +
 include/drm/drm_bridge.h | 192 ++-
 2 files changed, 353 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 68ab933ee430..78d26a9a3ee6 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -71,6 +71,8 @@ static LIST_HEAD(bridge_list);
  */
 void drm_bridge_add(struct drm_bridge *bridge)
 {
+   mutex_init(>hpd_mutex);
+
mutex_lock(_lock);
list_add_tail(>list, _list);
mutex_unlock(_lock);
@@ -87,6 +89,8 @@ void drm_bridge_remove(struct drm_bridge *bridge)
mutex_lock(_lock);
list_del_init(>list);
mutex_unlock(_lock);
+
+   mutex_destroy(>hpd_mutex);
 }
 EXPORT_SYMBOL(drm_bridge_remove);
 
@@ -919,6 +923,164 @@ int drm_atomic_bridge_chain_check(struct drm_bridge 
*bridge,
 }
 EXPORT_SYMBOL(drm_atomic_bridge_chain_check);
 
+/**
+ * drm_bridge_detect - check if anything is attached to the bridge output
+ * @bridge: bridge control structure
+ *
+ * If the bridge supports output detection, as reported by the
+ * DRM_BRIDGE_OP_DETECT bridge ops flag, call _bridge_funcs.detect for the
+ * bridge and return the connection status. Otherwise return
+ * connector_status_unknown.
+ *
+ * RETURNS:
+ * The detection status on success, or connector_status_unknown if the bridge
+ * doesn't support output detection.
+ */
+enum drm_connector_status drm_bridge_detect(struct drm_bridge *bridge)
+{
+   if (!(bridge->ops & DRM_BRIDGE_OP_DETECT))
+   return connector_status_unknown;
+
+   return bridge->funcs->detect(bridge);
+}
+EXPORT_SYMBOL_GPL(drm_bridge_detect);
+
+/**
+ * drm_bridge_get_modes - fill all modes currently valid for the sink into the
+ * @connector
+ * @bridge: bridge control structure
+ * @connector: the connector to fill with modes
+ *
+ * If the bridge supports output modes retrieval, as reported by the
+ * DRM_BRIDGE_OP_MODES bridge ops flag, call _bridge_funcs.get_modes to
+ * fill the connector with all valid modes and return the number of modes
+ * added. Otherwise return 0.
+ *
+ * RETURNS:
+ * The number of modes added to the connector.
+ */
+int drm_bridge_get_modes(struct drm_bridge *bridge,
+struct drm_connector *connector)
+{
+   if (!(bridge->ops & DRM_BRIDGE_OP_MODES))
+   return 0;
+
+   return bridge->funcs->get_modes(bridge, connector);
+}
+EXPORT_SYMBOL_GPL(drm_bridge_get_modes);
+
+/**
+ * drm_bridge_get_edid - get the EDID data of the connected display
+ * @bridge: bridge control structure
+ * @connector: the connector to read EDID for
+ *
+ * If the bridge supports output EDID retrieval, as reported by the
+ * DRM_BRIDGE_OP_EDID bridge ops flag, call _bridge_funcs.get_edid to
+ * get the EDID and return it. Otherwise return ERR_PTR(-ENOTSUPP).
+ *
+ * RETURNS:
+ * The retrieved EDID on success, or an error pointer otherwise.
+ */
+struct edid *drm_bridge_get_edid(struct drm_bridge *bridge,
+struct drm_connector *connector)
+{
+   if (!(bridge->ops & DRM_BRIDGE_OP_EDID))
+   return ERR_PTR(-ENOTSUPP);
+
+   return bridge->funcs->get_edid(bridge, connector);
+}
+EXPORT_SYMBOL_GPL(drm_bridge_get_edid);
+
+/**
+ * drm_bridge_hpd_enable - enable hot plug detection for the bridge
+ * @bridge: bridge control structure
+ * @cb: hot-plug detection callback
+ * @data: data to be passed to the hot-plug detection callback
+ *
+ * Call _bridge_funcs.hpd_enable if implemented and register the given @cb
+ * and @data as hot plug notification callback. From now on the @cb will be
+ * called with @data when an output status change is detected by the bridge,
+ * until hot plug notification gets disabled with drm_bridge_hpd_disable().
+ *
+ * Hot plug detection is supported only if the DRM_BRIDGE_OP_HPD flag is set in
+ * bridge->ops. This function shall not be called when the flag is not set.
+ *
+ * Only one hot 

[PATCH v6 08/51] drm/bridge: dumb-vga-dac: Rename driver to simple-bridge

2020-02-16 Thread Laurent Pinchart
The dumb-vga-dac driver can support simple DRM bridges without being
limited to VGA DACs. Rename it to simple-bridge.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Andrzej Hajda 
Reviewed-by: Boris Brezillon 
Acked-by: Maxime Ripard 
Acked-by: Sam Ravnborg 
---
 arch/arm/configs/davinci_all_defconfig   |  2 +-
 arch/arm/configs/integrator_defconfig|  2 +-
 arch/arm/configs/multi_v7_defconfig  |  2 +-
 arch/arm/configs/shmobile_defconfig  |  2 +-
 arch/arm/configs/sunxi_defconfig |  2 +-
 arch/arm/configs/versatile_defconfig |  2 +-
 drivers/gpu/drm/bridge/Kconfig   | 16 
 drivers/gpu/drm/bridge/Makefile  |  2 +-
 .../bridge/{dumb-vga-dac.c => simple-bridge.c}   |  2 +-
 9 files changed, 16 insertions(+), 16 deletions(-)
 rename drivers/gpu/drm/bridge/{dumb-vga-dac.c => simple-bridge.c} (99%)

diff --git a/arch/arm/configs/davinci_all_defconfig 
b/arch/arm/configs/davinci_all_defconfig
index 231f8973bbb2..b370958b0579 100644
--- a/arch/arm/configs/davinci_all_defconfig
+++ b/arch/arm/configs/davinci_all_defconfig
@@ -160,7 +160,7 @@ CONFIG_VIDEO_TVP514X=m
 CONFIG_VIDEO_ADV7343=m
 CONFIG_DRM=m
 CONFIG_DRM_TILCDC=m
-CONFIG_DRM_DUMB_VGA_DAC=m
+CONFIG_DRM_SIMPLE_BRIDGE=m
 CONFIG_DRM_TINYDRM=m
 CONFIG_TINYDRM_ST7586=m
 CONFIG_FB=y
diff --git a/arch/arm/configs/integrator_defconfig 
b/arch/arm/configs/integrator_defconfig
index 2f0a762dc3a0..a9755c501bec 100644
--- a/arch/arm/configs/integrator_defconfig
+++ b/arch/arm/configs/integrator_defconfig
@@ -55,7 +55,7 @@ CONFIG_SMC91X=y
 # CONFIG_KEYBOARD_ATKBD is not set
 # CONFIG_SERIO_SERPORT is not set
 CONFIG_DRM=y
-CONFIG_DRM_DUMB_VGA_DAC=y
+CONFIG_DRM_SIMPLE_BRIDGE=y
 CONFIG_DRM_PL111=y
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_MATROX=y
diff --git a/arch/arm/configs/multi_v7_defconfig 
b/arch/arm/configs/multi_v7_defconfig
index 3f1b96dc7faa..59321917d035 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -667,11 +667,11 @@ CONFIG_DRM_PANEL_ORISETECH_OTM8009A=m
 CONFIG_DRM_PANEL_RAYDIUM_RM68200=m
 CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03=m
 CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0=m
-CONFIG_DRM_DUMB_VGA_DAC=m
 CONFIG_DRM_NXP_PTN3460=m
 CONFIG_DRM_PARADE_PS8622=m
 CONFIG_DRM_SII902X=m
 CONFIG_DRM_SII9234=m
+CONFIG_DRM_SIMPLE_BRIDGE=m
 CONFIG_DRM_TOSHIBA_TC358764=m
 CONFIG_DRM_I2C_ADV7511=m
 CONFIG_DRM_I2C_ADV7511_AUDIO=y
diff --git a/arch/arm/configs/shmobile_defconfig 
b/arch/arm/configs/shmobile_defconfig
index bda57cafa2bc..3d7e9a6ca85d 100644
--- a/arch/arm/configs/shmobile_defconfig
+++ b/arch/arm/configs/shmobile_defconfig
@@ -123,8 +123,8 @@ CONFIG_VIDEO_ADV7604=y
 CONFIG_VIDEO_ML86V7667=y
 CONFIG_DRM=y
 CONFIG_DRM_RCAR_DU=y
-CONFIG_DRM_DUMB_VGA_DAC=y
 CONFIG_DRM_SII902X=y
+CONFIG_DRM_SIMPLE_BRIDGE=y
 CONFIG_DRM_I2C_ADV7511=y
 CONFIG_DRM_I2C_ADV7511_AUDIO=y
 CONFIG_FB_SH_MOBILE_LCDC=y
diff --git a/arch/arm/configs/sunxi_defconfig b/arch/arm/configs/sunxi_defconfig
index 3f5d727efc41..17958ff4a2e2 100644
--- a/arch/arm/configs/sunxi_defconfig
+++ b/arch/arm/configs/sunxi_defconfig
@@ -100,7 +100,7 @@ CONFIG_RC_DEVICES=y
 CONFIG_IR_SUNXI=y
 CONFIG_DRM=y
 CONFIG_DRM_SUN4I=y
-CONFIG_DRM_DUMB_VGA_DAC=y
+CONFIG_DRM_SIMPLE_BRIDGE=y
 CONFIG_FB_SIMPLE=y
 CONFIG_SOUND=y
 CONFIG_SND=y
diff --git a/arch/arm/configs/versatile_defconfig 
b/arch/arm/configs/versatile_defconfig
index fe4d4b596585..767935337413 100644
--- a/arch/arm/configs/versatile_defconfig
+++ b/arch/arm/configs/versatile_defconfig
@@ -59,7 +59,7 @@ CONFIG_GPIO_PL061=y
 CONFIG_DRM=y
 CONFIG_DRM_PANEL_ARM_VERSATILE=y
 CONFIG_DRM_PANEL_SIMPLE=y
-CONFIG_DRM_DUMB_VGA_DAC=y
+CONFIG_DRM_SIMPLE_BRIDGE=y
 CONFIG_DRM_PL111=y
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 20a439199cb8..10073ad88283 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -27,14 +27,6 @@ config DRM_CDNS_DSI
  Support Cadence DPI to DSI bridge. This is an internal
  bridge and is meant to be directly embedded in a SoC.
 
-config DRM_DUMB_VGA_DAC
-   tristate "Dumb VGA DAC Bridge support"
-   depends on OF
-   select DRM_KMS_HELPER
-   help
- Support for non-programmable RGB to VGA DAC bridges, such as ADI
- ADV7123, TI THS8134 and THS8135 or passive resistor ladder DACs.
-
 config DRM_LVDS_CODEC
tristate "Transparent LVDS encoders and decoders support"
depends on OF
@@ -110,6 +102,14 @@ config DRM_SII9234
  It is an I2C driver, that detects connection of MHL bridge
  and starts encapsulation of HDMI signal.
 
+config DRM_SIMPLE_BRIDGE
+   tristate "Simple DRM bridge support"
+   depends on OF
+   select DRM_KMS_HELPER
+   help
+ Support for non-programmable DRM bridges, such as ADI ADV7123, TI
+ THS8134 and THS8135 or passive resistor ladder DACs.
+
 config 

[PATCH v6 22/51] drm/omap: dss: Fix output next device lookup in DT

2020-02-16 Thread Laurent Pinchart
The DSS core looks up the next device connected to an output by
traversing the OF graph. It currently hardcodes the local port number to
0, which breaks any output with a different port number (SDI on OMAP3
and any DPI output but the first one). Fix this by repurposing the
currently unused of_ports bitmask in omap_dss_device with an of_port
output port number, and use it to traverse the OF graph.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
---
 drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c | 2 +-
 drivers/gpu/drm/omapdrm/displays/connector-hdmi.c  | 2 +-
 drivers/gpu/drm/omapdrm/displays/encoder-opa362.c  | 2 +-
 drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c   | 2 +-
 drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c| 2 +-
 drivers/gpu/drm/omapdrm/dss/dpi.c  | 2 +-
 drivers/gpu/drm/omapdrm/dss/dsi.c  | 2 +-
 drivers/gpu/drm/omapdrm/dss/hdmi4.c| 2 +-
 drivers/gpu/drm/omapdrm/dss/hdmi5.c| 2 +-
 drivers/gpu/drm/omapdrm/dss/omapdss.h  | 4 ++--
 drivers/gpu/drm/omapdrm/dss/output.c   | 3 +--
 drivers/gpu/drm/omapdrm/dss/sdi.c  | 2 +-
 drivers/gpu/drm/omapdrm/dss/venc.c | 2 +-
 13 files changed, 14 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c 
b/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c
index 0d20fab605d7..f36aa1885d39 100644
--- a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c
+++ b/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c
@@ -55,7 +55,7 @@ static int tvc_probe(struct platform_device *pdev)
dssdev->type = OMAP_DISPLAY_TYPE_VENC;
dssdev->display = true;
dssdev->owner = THIS_MODULE;
-   dssdev->of_ports = BIT(0);
+   dssdev->of_port = 0;
 
omapdss_display_init(dssdev);
omapdss_device_register(dssdev);
diff --git a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c 
b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c
index f5d69d810bb8..37c212491cd3 100644
--- a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c
+++ b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c
@@ -139,7 +139,7 @@ static int hdmic_probe(struct platform_device *pdev)
dssdev->type = OMAP_DISPLAY_TYPE_HDMI;
dssdev->display = true;
dssdev->owner = THIS_MODULE;
-   dssdev->of_ports = BIT(0);
+   dssdev->of_port = 0;
dssdev->ops_flags = ddata->hpd_gpio
  ? OMAP_DSS_DEVICE_OP_DETECT | OMAP_DSS_DEVICE_OP_HPD
  : 0;
diff --git a/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c 
b/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c
index b992387ed674..252705222ef1 100644
--- a/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c
+++ b/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c
@@ -86,7 +86,7 @@ static int opa362_probe(struct platform_device *pdev)
dssdev->dev = >dev;
dssdev->type = OMAP_DISPLAY_TYPE_VENC;
dssdev->owner = THIS_MODULE;
-   dssdev->of_ports = BIT(1) | BIT(0);
+   dssdev->of_port = 1;
 
dssdev->next = omapdss_of_find_connected_device(pdev->dev.of_node, 1);
if (IS_ERR(dssdev->next)) {
diff --git a/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c 
b/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c
index 089105c5aa0a..857ae84cd7d1 100644
--- a/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c
+++ b/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c
@@ -165,7 +165,7 @@ static int tpd_probe(struct platform_device *pdev)
dssdev->dev = >dev;
dssdev->type = OMAP_DISPLAY_TYPE_HDMI;
dssdev->owner = THIS_MODULE;
-   dssdev->of_ports = BIT(1) | BIT(0);
+   dssdev->of_port = 1;
dssdev->ops_flags = OMAP_DSS_DEVICE_OP_DETECT
  | OMAP_DSS_DEVICE_OP_HPD;
 
diff --git a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c 
b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
index 3ec6a55e932a..3484b5d4a91c 100644
--- a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
+++ b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
@@ -1265,7 +1265,7 @@ static int dsicm_probe(struct platform_device *pdev)
dssdev->type = OMAP_DISPLAY_TYPE_DSI;
dssdev->display = true;
dssdev->owner = THIS_MODULE;
-   dssdev->of_ports = BIT(0);
+   dssdev->of_port = 0;
dssdev->ops_flags = OMAP_DSS_DEVICE_OP_MODES;
 
dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c 
b/drivers/gpu/drm/omapdrm/dss/dpi.c
index 95147437b990..462ed6f3118a 100644
--- a/drivers/gpu/drm/omapdrm/dss/dpi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dpi.c
@@ -625,7 +625,7 @@ static int dpi_init_output_port(struct dpi_data *dpi, 
struct device_node *port)
out->id = OMAP_DSS_OUTPUT_DPI;
out->type = OMAP_DISPLAY_TYPE_DPI;
out->dispc_channel = dpi_get_channel(dpi);
-   

[PATCH v6 03/51] drm/edid: Add flag to drm_display_info to identify HDMI sinks

2020-02-16 Thread Laurent Pinchart
The drm_display_info structure contains many fields related to HDMI
sinks, but none that identifies if a sink compliant with CEA-861 (EDID)
shall be treated as an HDMI sink or a DVI sink. Add such a flag, and
populate it according to section 8.3.3 ("DVI/HDMI Device
Discrimination") of the HDMI v1.3 specification.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Andrzej Hajda 
Reviewed-by: Ville Syrjälä 
Reviewed-by: Daniel Vetter 
Reviewed-by: Boris Brezillon 
Acked-by: Sam Ravnborg 
---
Changes since v1:

- Link the is_hdmi field doc with drm_detect_hdmi_monitor()
- Add a conversion task in todo.rst
---
 Documentation/gpu/todo.rst  | 14 ++
 drivers/gpu/drm/drm_edid.c  |  6 ++
 include/drm/drm_connector.h |  8 
 3 files changed, 28 insertions(+)

diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst
index 370ac678106e..ccf5e8e34222 100644
--- a/Documentation/gpu/todo.rst
+++ b/Documentation/gpu/todo.rst
@@ -407,6 +407,20 @@ Contact: Daniel Vetter
 
 Level: Intermediate
 
+Replace drm_detect_hdmi_monitor() with drm_display_info.is_hdmi
+---
+
+Once EDID is parsed, the monitor HDMI support information is available through
+drm_display_info.is_hdmi. Many drivers still call drm_detect_hdmi_monitor() to
+retrieve the same information, which is less efficient.
+
+Audit each individual driver calling drm_detect_hdmi_monitor() and switch to
+drm_display_info.is_hdmi if applicable.
+
+Contact: Laurent Pinchart, respective driver maintainers
+
+Level: Intermediate
+
 Core refactorings
 =
 
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 8f2d5022d0bc..6a2fcfdc7272 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -4647,6 +4647,9 @@ EXPORT_SYMBOL(drm_av_sync_delay);
  *
  * Parse the CEA extension according to CEA-861-B.
  *
+ * Drivers that have added the modes parsed from EDID to drm_display_info
+ * should use _display_info.is_hdmi instead of calling this function.
+ *
  * Return: True if the monitor is HDMI, false if not or unknown.
  */
 bool drm_detect_hdmi_monitor(struct edid *edid)
@@ -4881,6 +4884,8 @@ drm_parse_hdmi_vsdb_video(struct drm_connector 
*connector, const u8 *db)
struct drm_display_info *info = >display_info;
u8 len = cea_db_payload_len(db);
 
+   info->is_hdmi = true;
+
if (len >= 6)
info->dvi_dual = db[6] & 1;
if (len >= 7)
@@ -4949,6 +4954,7 @@ drm_reset_display_info(struct drm_connector *connector)
info->cea_rev = 0;
info->max_tmds_clock = 0;
info->dvi_dual = false;
+   info->is_hdmi = false;
info->has_hdmi_infoframe = false;
info->rgb_quant_range_selectable = false;
memset(>hdmi, 0, sizeof(info->hdmi));
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index c3bd5262db9c..0df7a95ca5d9 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -434,6 +434,14 @@ struct drm_display_info {
 */
bool dvi_dual;
 
+   /**
+* @is_hdmi: True if the sink is an HDMI device.
+*
+* This field shall be used instead of calling
+* drm_detect_hdmi_monitor() when possible.
+*/
+   bool is_hdmi;
+
/**
 * @has_hdmi_infoframe: Does the sink support the HDMI infoframe?
 */
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v6 02/51] drm/connector: Add helper to get a connector type name

2020-02-16 Thread Laurent Pinchart
drm_connector.c contains a map of connector types (DRM_MODE_CONNECTOR_*)
to name strings, but doesn't expose it. This leads to drivers having to
store a similar map.

Add a new drm_get_connector_type_name() helper function that return a
name string for a connector type.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Boris Brezillon 
Reviewed-by: Sam Ravnborg 
---
 drivers/gpu/drm/drm_connector.c | 15 +++
 include/drm/drm_connector.h |  1 +
 2 files changed, 16 insertions(+)

diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index f632ca05960e..644f0ad10671 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -111,6 +111,21 @@ void drm_connector_ida_destroy(void)
ida_destroy(_connector_enum_list[i].ida);
 }
 
+/**
+ * drm_get_connector_type_name - return a string for connector type
+ * @type: The connector type (DRM_MODE_CONNECTOR_*)
+ *
+ * Returns: the name of the connector type, or NULL if the type is not valid.
+ */
+const char *drm_get_connector_type_name(unsigned int type)
+{
+   if (type < ARRAY_SIZE(drm_connector_enum_list))
+   return drm_connector_enum_list[type].name;
+
+   return NULL;
+}
+EXPORT_SYMBOL(drm_get_connector_type_name);
+
 /**
  * drm_connector_get_cmdline_mode - reads the user's cmdline mode
  * @connector: connector to quwery
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index b3815371c271..c3bd5262db9c 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -1518,6 +1518,7 @@ drm_connector_is_unregistered(struct drm_connector 
*connector)
DRM_CONNECTOR_UNREGISTERED;
 }
 
+const char *drm_get_connector_type_name(unsigned int connector_type);
 const char *drm_get_connector_status_name(enum drm_connector_status status);
 const char *drm_get_subpixel_order_name(enum subpixel_order order);
 const char *drm_get_dpms_name(int val);
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v6 06/51] drm/bridge: Extend bridge API to disable connector creation

2020-02-16 Thread Laurent Pinchart
Most bridge drivers create a DRM connector to model the connector at the
output of the bridge. This model is historical and has worked pretty
well so far, but causes several issues:

- It prevents supporting more complex display pipelines where DRM
connector operations are split over multiple components. For instance a
pipeline with a bridge connected to the DDC signals to read EDID data,
and another one connected to the HPD signal to detect connection and
disconnection, will not be possible to support through this model.

- It requires every bridge driver to implement similar connector
handling code, resulting in code duplication.

- It assumes that a bridge will either be wired to a connector or to
another bridge, but doesn't support bridges that can be used in both
positions very well (although there is some ad-hoc support for this in
the analogix_dp bridge driver).

In order to solve these issues, ownership of the connector should be
moved to the display controller driver (where it can be implemented
using helpers provided by the core).

Extend the bridge API to allow disabling connector creation in bridge
drivers as a first step towards the new model. The new flags argument to
the bridge .attach() operation allows instructing the bridge driver to
skip creating a connector. Unconditionally set the new flags argument to
0 for now to keep the existing behaviour, and modify all existing bridge
drivers to return an error when connector creation is not requested as
they don't support this feature yet.

The change is based on the following semantic patch, with manual review
and edits.

@ rule1 @
identifier funcs;
identifier fn;
@@
 struct drm_bridge_funcs funcs = {
...,
.attach = fn
 };

@ depends on rule1 @
identifier rule1.fn;
identifier bridge;
statement S, S1;
@@
 int fn(
struct drm_bridge *bridge
+   , enum drm_bridge_attach_flags flags
 )
 {
... when != S
+   if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) {
+   DRM_ERROR("Fix bridge driver to make connector optional!");
+   return -EINVAL;
+   }
+
S1
...
 }

@ depends on rule1 @
identifier rule1.fn;
identifier bridge, flags;
expression E1, E2, E3;
@@
 int fn(
struct drm_bridge *bridge,
enum drm_bridge_attach_flags flags
 ) {
 <...
 drm_bridge_attach(E1, E2, E3
+   , flags
 )
 ...>
 }

@@
expression E1, E2, E3;
@@
 drm_bridge_attach(E1, E2, E3
+   , 0
 )

Signed-off-by: Laurent Pinchart 
Reviewed-by: Boris Brezillon 
Acked-by: Sam Ravnborg 
Reviewed-by: Tomi Valkeinen 
---
Changes since v5:

- Handle parade-ps8640, tc358768 and tidss

Changes since v3:

- Print error message when DRM_BRIDGE_ATTACH_NO_CONNECTOR can't be
  honoured
- Fix semantic patch to correctly handle drm_bridge_attach() calls from
  within a bridge .attach() handler
- Include drm_print.h in tc358767.c and rcar_lvds.c

Changes since v2:

- Update commit message to the new flags argument
- Replace a leftover 'true' with 0
- Update msm edp and hdmi

Changes since v1:

- Replace the create_connector boolean with a flags bitmask
- Update ingenic driver
- Add semantic patch to commit message
---
 drivers/gpu/drm/arc/arcpgu_hdmi.c |  2 +-
 .../gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c  |  2 +-
 drivers/gpu/drm/bridge/adv7511/adv7511_drv.c  |  8 +++-
 .../drm/bridge/analogix/analogix-anx6345.c|  8 +++-
 .../drm/bridge/analogix/analogix-anx78xx.c|  8 +++-
 .../drm/bridge/analogix/analogix_dp_core.c| 10 --
 drivers/gpu/drm/bridge/cdns-dsi.c |  6 --
 drivers/gpu/drm/bridge/dumb-vga-dac.c |  8 +++-
 drivers/gpu/drm/bridge/lvds-codec.c   |  5 +++--
 .../bridge/megachips-stdp-ge-b850v3-fw.c  |  8 +++-
 drivers/gpu/drm/bridge/nxp-ptn3460.c  |  8 +++-
 drivers/gpu/drm/bridge/panel.c|  8 +++-
 drivers/gpu/drm/bridge/parade-ps8622.c|  8 +++-
 drivers/gpu/drm/bridge/parade-ps8640.c|  5 +++--
 drivers/gpu/drm/bridge/sii902x.c  |  8 +++-
 drivers/gpu/drm/bridge/sil-sii8620.c  |  3 ++-
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 10 --
 drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c |  8 +---
 drivers/gpu/drm/bridge/tc358764.c |  8 +++-
 drivers/gpu/drm/bridge/tc358767.c |  9 -
 drivers/gpu/drm/bridge/tc358768.c |  6 --
 drivers/gpu/drm/bridge/thc63lvd1024.c |  5 +++--
 drivers/gpu/drm/bridge/ti-sn65dsi86.c |  8 +++-
 drivers/gpu/drm/bridge/ti-tfp410.c|  8 +++-
 drivers/gpu/drm/drm_bridge.c  |  6 --
 drivers/gpu/drm/drm_simple_kms_helper.c   |  2 +-
 drivers/gpu/drm/exynos/exynos_dp.c|  3 ++-
 drivers/gpu/drm/exynos/exynos_drm_dsi.c   |  4 ++--
 drivers/gpu/drm/exynos/exynos_hdmi.c  |  2 +-
 drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c |  2 +-
 drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c  |  

[PATCH v6 12/51] drm/bridge: Add bridge driver for display connectors

2020-02-16 Thread Laurent Pinchart
Display connectors are modelled in DT as a device node, but have so far
been handled manually in several bridge drivers. This resulted in
duplicate code in several bridge drivers, with slightly different (and
thus confusing) logics.

In order to fix this, implement a bridge driver for display connectors.
The driver centralises logic for the DVI, HDMI, VGAn composite and
S-video connectors and exposes corresponding bridge operations.

This driver in itself doesn't solve the issue completely, changes in
bridge and display controller drivers are needed to make use of the new
connector driver.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Maxime Ripard 
Reviewed-by: Boris Brezillon 
Acked-by: Sam Ravnborg 
---
Changes since v5:

- Set the drm_bridge.interlace_allowed flag

Changes since v3:

- Turn probe confirmation message into a dev_dbg()

Changes since v2:

- Fall back to polling if the GPIO IRQ chip doesn't support
  edge-triggered interrupts

Changes since v1:

- Use drm_get_connector_type_name() instead of open-coding
  display_connector_type_name()
- Remove empty .hpd_enable() and .hpd_disable() operations
- Set bridge.ddc
---
 drivers/gpu/drm/bridge/Kconfig |  11 +
 drivers/gpu/drm/bridge/Makefile|   1 +
 drivers/gpu/drm/bridge/display-connector.c | 295 +
 3 files changed, 307 insertions(+)
 create mode 100644 drivers/gpu/drm/bridge/display-connector.c

diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 10073ad88283..d63283661850 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -27,6 +27,17 @@ config DRM_CDNS_DSI
  Support Cadence DPI to DSI bridge. This is an internal
  bridge and is meant to be directly embedded in a SoC.
 
+config DRM_DISPLAY_CONNECTOR
+   tristate "Display connector support"
+   depends on OF
+   help
+ Driver for display connectors with support for DDC and hot-plug
+ detection. Most display controller handle display connectors
+ internally and don't need this driver, but the DRM subsystem is
+ moving towards separating connector handling from display controllers
+ on ARM-based platforms. Saying Y here when this driver is not needed
+ will not cause any issue.
+
 config DRM_LVDS_CODEC
tristate "Transparent LVDS encoders and decoders support"
depends on OF
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index b6b2e7029a78..17f1f155e803 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -1,5 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_DRM_CDNS_DSI) += cdns-dsi.o
+obj-$(CONFIG_DRM_DISPLAY_CONNECTOR) += display-connector.o
 obj-$(CONFIG_DRM_LVDS_CODEC) += lvds-codec.o
 obj-$(CONFIG_DRM_MEGACHIPS_STDP_GE_B850V3_FW) += 
megachips-stdp-ge-b850v3-fw.o
 obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
diff --git a/drivers/gpu/drm/bridge/display-connector.c 
b/drivers/gpu/drm/bridge/display-connector.c
new file mode 100644
index ..4d278573cdb9
--- /dev/null
+++ b/drivers/gpu/drm/bridge/display-connector.c
@@ -0,0 +1,295 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 Laurent Pinchart 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+struct display_connector {
+   struct drm_bridge   bridge;
+
+   struct gpio_desc*hpd_gpio;
+   int hpd_irq;
+};
+
+static inline struct display_connector *
+to_display_connector(struct drm_bridge *bridge)
+{
+   return container_of(bridge, struct display_connector, bridge);
+}
+
+static int display_connector_attach(struct drm_bridge *bridge,
+   enum drm_bridge_attach_flags flags)
+{
+   return flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR ? 0 : -EINVAL;
+}
+
+static enum drm_connector_status
+display_connector_detect(struct drm_bridge *bridge)
+{
+   struct display_connector *conn = to_display_connector(bridge);
+
+   if (conn->hpd_gpio) {
+   if (gpiod_get_value_cansleep(conn->hpd_gpio))
+   return connector_status_connected;
+   else
+   return connector_status_disconnected;
+   }
+
+   if (conn->bridge.ddc && drm_probe_ddc(conn->bridge.ddc))
+   return connector_status_connected;
+
+   switch (conn->bridge.type) {
+   case DRM_MODE_CONNECTOR_DVIA:
+   case DRM_MODE_CONNECTOR_DVID:
+   case DRM_MODE_CONNECTOR_DVII:
+   case DRM_MODE_CONNECTOR_HDMIA:
+   case DRM_MODE_CONNECTOR_HDMIB:
+   /*
+* For DVI and HDMI connectors a DDC probe failure indicates
+* that no cable is connected.
+*/
+   return connector_status_disconnected;
+
+   case DRM_MODE_CONNECTOR_Composite:
+   case DRM_MODE_CONNECTOR_SVIDEO:
+ 

[PATCH v6 14/51] drm/bridge: panel: Implement bridge connector operations

2020-02-16 Thread Laurent Pinchart
Implement the newly added bridge connector operations, allowing the
usage of drm_bridge_panel with drm_bridge_connector.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Boris Brezillon 
Reviewed-by: Sam Ravnborg 
---
Changes since v2:

- Use the connector type from the panel instead of hardcoding it to DPI
- Rebased on top top of Sam's panel .get_modes() rework
---
 drivers/gpu/drm/bridge/panel.c | 17 +
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c
index 81017b4afe25..bbc212cc53ac 100644
--- a/drivers/gpu/drm/bridge/panel.c
+++ b/drivers/gpu/drm/bridge/panel.c
@@ -60,10 +60,8 @@ static int panel_bridge_attach(struct drm_bridge *bridge,
struct drm_connector *connector = _bridge->connector;
int ret;
 
-   if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) {
-   DRM_ERROR("Fix bridge driver to make connector optional!");
-   return -EINVAL;
-   }
+   if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
+   return 0;
 
if (!bridge->encoder) {
DRM_ERROR("Missing encoder\n");
@@ -126,6 +124,14 @@ static void panel_bridge_post_disable(struct drm_bridge 
*bridge)
drm_panel_unprepare(panel_bridge->panel);
 }
 
+static int panel_bridge_get_modes(struct drm_bridge *bridge,
+ struct drm_connector *connector)
+{
+   struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
+
+   return drm_panel_get_modes(panel_bridge->panel, connector);
+}
+
 static const struct drm_bridge_funcs panel_bridge_bridge_funcs = {
.attach = panel_bridge_attach,
.detach = panel_bridge_detach,
@@ -133,6 +139,7 @@ static const struct drm_bridge_funcs 
panel_bridge_bridge_funcs = {
.enable = panel_bridge_enable,
.disable = panel_bridge_disable,
.post_disable = panel_bridge_post_disable,
+   .get_modes = panel_bridge_get_modes,
 };
 
 /**
@@ -202,6 +209,8 @@ struct drm_bridge *drm_panel_bridge_add_typed(struct 
drm_panel *panel,
 #ifdef CONFIG_OF
panel_bridge->bridge.of_node = panel->dev->of_node;
 #endif
+   panel_bridge->bridge.ops = DRM_BRIDGE_OP_MODES;
+   panel_bridge->bridge.type = connector_type;
 
drm_bridge_add(_bridge->bridge);
 
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v6 00/51] drm/omap: Replace custom display drivers with drm_bridge and drm_panel

2020-02-16 Thread Laurent Pinchart
Hello,

This patch series is the sixth attempt to (nearly, see [1]) complete the
rework of the omapdrm driver to move to drm_bridge and drm_panel.

Version 2, available at [2], explains in its long cover letter the
rationale for the changes. I won't duplicate it here as it is still
valid as-is.

Compared to v5, available at [3], this version has been rebased on top
of drm-misc-next, and minor bugs have been fixed, including interlaced
modes support with VENC.

The patches can be found at

git://linuxtv.org/pinchartl/media.git omapdrm/bridge/devel

[1] The only notable exception is the omapdrm-specific DSI panel driver
that implements a large number of custom operations. This is being
addressed separately.

[2] https://patchwork.kernel.org/cover/11102445/

[3] https://patchwork.kernel.org/cover/11349617/

Laurent Pinchart (51):
  video: hdmi: Change return type of hdmi_avi_infoframe_init() to void
  drm/connector: Add helper to get a connector type name
  drm/edid: Add flag to drm_display_info to identify HDMI sinks
  drm/bridge: Add connector-related bridge operations and data
  drm/bridge: Add interlace_allowed flag to drm_bridge
  drm/bridge: Extend bridge API to disable connector creation
  drm/bridge: dumb-vga-dac: Rename internal symbols to simple-bridge
  drm/bridge: dumb-vga-dac: Rename driver to simple-bridge
  drm/bridge: simple-bridge: Add support for non-VGA bridges
  drm/bridge: simple-bridge: Add support for enable GPIO
  drm/bridge: simple-bridge: Add support for the TI OPA362
  drm/bridge: Add bridge driver for display connectors
  drm/bridge: Add driver for the TI TPD12S015 HDMI level shifter
  drm/bridge: panel: Implement bridge connector operations
  drm/bridge: tfp410: Replace manual connector handling with bridge
  drm/bridge: tfp410: Allow operation without drm_connector
  drm: Add helper to create a connector for a chain of bridges
  drm/omap: dss: Cleanup DSS ports on initialisation failure
  drm/omap: Simplify HDMI mode and infoframe configuration
  drm/omap: Factor out display type to connector type conversion
  drm/omap: Use the drm_panel_bridge API
  drm/omap: dss: Fix output next device lookup in DT
  drm/omap: Add infrastructure to support drm_bridge local to DSS
outputs
  drm/omap: dss: Make omap_dss_device_ops optional
  drm/omap: hdmi: Allocate EDID in the .read_edid() operation
  drm/omap: hdmi4: Rework EDID read to isolate data read
  drm/omap: hdmi5: Rework EDID read to isolate data read
  drm/omap: hdmi4: Register a drm_bridge for EDID read
  drm/omap: hdmi5: Register a drm_bridge for EDID read
  drm/omap: hdmi4: Move mode set, enable and disable operations to
bridge
  drm/omap: hdmi5: Move mode set, enable and disable operations to
bridge
  drm/omap: hdmi4: Implement drm_bridge .hpd_notify() operation
  drm/omap: dss: Remove .set_hdmi_mode() and .set_infoframe() operations
  drm/omap: venc: Register a drm_bridge
  drm/omap: Create connector for bridges
  drm/omap: Switch the HDMI and VENC outputs to drm_bridge
  drm/omap: Remove HPD, detect and EDID omapdss operations
  drm/omap: hdmi: Remove omap_dss_device operations
  drm/omap: venc: Remove omap_dss_device operations
  drm/omap: hdmi4: Simplify EDID read
  drm/omap: hdmi5: Simplify EDID read
  drm/omap: dpi: Sort includes alphabetically
  drm/omap: dpi: Reorder functions in sections
  drm/omap: dpi: Simplify clock setting API
  drm/omap: dpi: Register a drm_bridge
  drm/omap: sdi: Sort includes alphabetically
  drm/omap: sdi: Register a drm_bridge
  drm/omap: Hardcode omap_connector type to DSI
  drm/omap: dss: Remove unused omap_dss_device operations
  drm/omap: dss: Inline the omapdss_display_get() function
  drm/omap: dss: Remove unused omapdss_of_find_connected_device()
function

 Documentation/gpu/todo.rst|  14 +
 arch/arm/configs/davinci_all_defconfig|   2 +-
 arch/arm/configs/integrator_defconfig |   2 +-
 arch/arm/configs/multi_v7_defconfig   |   2 +-
 arch/arm/configs/omap2plus_defconfig  |   7 +-
 arch/arm/configs/shmobile_defconfig   |   2 +-
 arch/arm/configs/sunxi_defconfig  |   2 +-
 arch/arm/configs/versatile_defconfig  |   2 +-
 drivers/gpu/drm/Makefile  |   3 +-
 drivers/gpu/drm/arc/arcpgu_hdmi.c |   2 +-
 .../gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c  |   2 +-
 drivers/gpu/drm/bridge/Kconfig|  29 +-
 drivers/gpu/drm/bridge/Makefile   |   4 +-
 drivers/gpu/drm/bridge/adv7511/adv7511_drv.c  |   8 +-
 .../drm/bridge/analogix/analogix-anx6345.c|   8 +-
 .../drm/bridge/analogix/analogix-anx78xx.c|   8 +-
 .../drm/bridge/analogix/analogix_dp_core.c|  10 +-
 drivers/gpu/drm/bridge/cdns-dsi.c |   6 +-
 drivers/gpu/drm/bridge/display-connector.c| 295 ++
 drivers/gpu/drm/bridge/dumb-vga-dac.c | 300 --
 drivers/gpu/drm/bridge/lvds-codec.c   |   5 +-
 

[PATCH v6 05/51] drm/bridge: Add interlace_allowed flag to drm_bridge

2020-02-16 Thread Laurent Pinchart
In preparation for a connector creation helper based on a chain of
bridges, add a flag to the drm_bridge structure to report support for
interlaced modes. This will be used to set the connector's
interlace_allowed flag.

Signed-off-by: Laurent Pinchart 
---
 include/drm/drm_bridge.h | 5 +
 1 file changed, 5 insertions(+)

diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index ba9b7c84f11e..d55bf5f61758 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -712,6 +712,11 @@ struct drm_bridge {
 * identifies the type of connected display.
 */
int type;
+   /**
+* @interlace_allowed: Indicate that the bridge can handle interlaced
+* modes.
+*/
+   bool interlace_allowed;
/**
 * @ddc: Associated I2C adapter for DDC access, if any.
 */
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v6 01/51] video: hdmi: Change return type of hdmi_avi_infoframe_init() to void

2020-02-16 Thread Laurent Pinchart
The hdmi_avi_infoframe_init() never needs to return an error, change its
return type to void.

Signed-off-by: Laurent Pinchart 
Reviewed-by: Andrzej Hajda 
Acked-by: Bartlomiej Zolnierkiewicz 
Reviewed-by: Boris Brezillon 
Acked-by: Sam Ravnborg 
---
Changes since v1:

- Removed documentation of the return value

Cc: Bartlomiej Zolnierkiewicz 
---
 drivers/gpu/drm/drm_edid.c |  5 +
 drivers/video/hdmi.c   | 11 ++-
 include/linux/hdmi.h   |  2 +-
 3 files changed, 4 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 097e54a4379e..8f2d5022d0bc 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -5449,14 +5449,11 @@ drm_hdmi_avi_infoframe_from_display_mode(struct 
hdmi_avi_infoframe *frame,
 {
enum hdmi_picture_aspect picture_aspect;
u8 vic, hdmi_vic;
-   int err;
 
if (!frame || !mode)
return -EINVAL;
 
-   err = hdmi_avi_infoframe_init(frame);
-   if (err < 0)
-   return err;
+   hdmi_avi_infoframe_init(frame);
 
if (mode->flags & DRM_MODE_FLAG_DBLCLK)
frame->pixel_repeat = 1;
diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c
index 9c82e2a0a411..856a8c4e84a2 100644
--- a/drivers/video/hdmi.c
+++ b/drivers/video/hdmi.c
@@ -53,18 +53,14 @@ static void hdmi_infoframe_set_checksum(void *buffer, 
size_t size)
 /**
  * hdmi_avi_infoframe_init() - initialize an HDMI AVI infoframe
  * @frame: HDMI AVI infoframe
- *
- * Returns 0 on success or a negative error code on failure.
  */
-int hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame)
+void hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame)
 {
memset(frame, 0, sizeof(*frame));
 
frame->type = HDMI_INFOFRAME_TYPE_AVI;
frame->version = 2;
frame->length = HDMI_AVI_INFOFRAME_SIZE;
-
-   return 0;
 }
 EXPORT_SYMBOL(hdmi_avi_infoframe_init);
 
@@ -1553,7 +1549,6 @@ static int hdmi_avi_infoframe_unpack(struct 
hdmi_avi_infoframe *frame,
 const void *buffer, size_t size)
 {
const u8 *ptr = buffer;
-   int ret;
 
if (size < HDMI_INFOFRAME_SIZE(AVI))
return -EINVAL;
@@ -1566,9 +1561,7 @@ static int hdmi_avi_infoframe_unpack(struct 
hdmi_avi_infoframe *frame,
if (hdmi_infoframe_checksum(buffer, HDMI_INFOFRAME_SIZE(AVI)) != 0)
return -EINVAL;
 
-   ret = hdmi_avi_infoframe_init(frame);
-   if (ret)
-   return ret;
+   hdmi_avi_infoframe_init(frame);
 
ptr += HDMI_INFOFRAME_HEADER_SIZE;
 
diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h
index 9918a6c910c5..9613d796cfb1 100644
--- a/include/linux/hdmi.h
+++ b/include/linux/hdmi.h
@@ -207,7 +207,7 @@ struct hdmi_drm_infoframe {
u16 max_fall;
 };
 
-int hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame);
+void hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame);
 ssize_t hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe *frame, void *buffer,
size_t size);
 ssize_t hdmi_avi_infoframe_pack_only(const struct hdmi_avi_infoframe *frame,
-- 
Regards,

Laurent Pinchart

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[pull] drm/msm: msm-fixes-v5.6-rc2

2020-02-16 Thread Rob Clark
Hi Dave,

Got a few more fixes this time around, so decided to send a dedicated
-fixes PR rather than try to route these all through -misc like we do
when there are only a couple misc fixes.  It mostly boils down to
fixing fallout from new hw enablement (sc7180):

+ fix UBWC on GPU and display side for sc7180
+ fix DSI suspend/resume issue encountered on sc7180
+ fix some breakage on so called "linux-android" devices
  (fallout from sc7180/a618 support, not seen earlier
  due to bootloader/firmware differences)
+ couple other misc fixes


The following changes since commit bb6d3fb354c5ee8d6bde2d576eb7220ea09862b9:

  Linux 5.6-rc1 (2020-02-09 16:08:48 -0800)

are available in the Git repository at:

  https://gitlab.freedesktop.org/drm/msm.git drm-msm-fixes-2020-02-16

for you to fetch changes up to 8fc7036ee652207ca992fbb9abb64090c355a9e0:

  drm/msm/dpu: fix BGR565 vs RGB565 confusion (2020-02-13 13:54:12 -0800)


Akhil P Oommen (1):
  drm/msm/a6xx: Correct the highestbank configuration

Brian Masney (1):
  drm/msm/mdp5: rate limit pp done timeout warnings

Harigovindan P (2):
  drm/msm/dsi: save pll state before dsi host is powered off
  drm/msm/dsi/pll: call vco set rate explicitly

John Stultz (1):
  drm: msm: Fix return type of dsi_mgr_connector_mode_valid for kCFI

Jordan Crouse (3):
  drm/msm/a6xx: Remove unneeded GBIF unhalt
  drm/msm/a6xx: Update the GMU bus tables for sc7180
  drm/msm: Fix a6xx GMU shutdown sequence

Kalyan Thota (1):
  msm:disp:dpu1: add UBWC support for display on SC7180

Rob Clark (1):
  drm/msm/dpu: fix BGR565 vs RGB565 confusion

 drivers/gpu/drm/msm/adreno/a6xx_gmu.c   | 37 +++--
 drivers/gpu/drm/msm/adreno/a6xx_gpu.c   | 65 ++
 drivers/gpu/drm/msm/adreno/a6xx_hfi.c   | 85 -
 drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c |  4 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c| 58 +++-
 drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c   |  4 +-
 drivers/gpu/drm/msm/dsi/dsi_manager.c   |  7 ++-
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.c   |  4 --
 drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c  |  6 ++
 9 files changed, 170 insertions(+), 100 deletions(-)
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[RFC PATCH v3 5/5] drm/panel: simple: add panel-dpi support

2020-02-16 Thread Sam Ravnborg
RFC only - not tested yet!

The panel-dpi compatible is a fallback that
allows the DT to specify the timing.

When matching panel-dpi expect the device tree to include the
timing information for the display-panel.

Background for this change:
There are a lot of panels and new models hits the market very often.
It is a lost cause trying to chase them all and users of new panels
will often find them in situations that the panel they ues are not
supported by the kernel.
On top of this a lot of panels are customized based on customer
specifications.

Including the panel timing in the device tree allows for a simple
way to describe the actual HW and use this description in a generic
way in the kernel.
This allows uses of proprietary panels, or panels which are not
included in the kernel, to specify the timing in the device tree
together with all the other HW descriptions.
And thus, using the device tree it is then easy to add support
for an otherwise unknown panel.

The current support expect panels that do not require any
delays for prepare/enable/disable/unprepare.

Signed-off-by: Sam Ravnborg 
Cc: Thierry Reding 
Cc: Laurent Pinchart 
Cc: Maxime Ripard 
Cc: Oleksandr Suvorov 
---
 drivers/gpu/drm/panel/panel-simple.c | 74 +++-
 1 file changed, 72 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-simple.c 
b/drivers/gpu/drm/panel/panel-simple.c
index 82363d05bad4..188526637398 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -351,6 +351,65 @@ static const struct drm_panel_funcs panel_simple_funcs = {
.get_timings = panel_simple_get_timings,
 };
 
+static struct panel_desc panel_dpi;
+
+static int panel_dpi_probe(struct device *dev,
+  struct panel_simple *panel)
+{
+   struct display_timing *timing;
+   const struct device_node *np;
+   struct panel_desc *desc;
+   unsigned int bus_flags;
+   struct videomode vm;
+   const char *mapping;
+   int ret;
+
+   np = dev->of_node;
+   desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+   if (!desc)
+   return -ENOMEM;
+
+   timing = devm_kzalloc(dev, sizeof(*timing), GFP_KERNEL);
+   if (!timing)
+   return -ENOMEM;
+
+   ret = of_get_display_timing(np, "panel-timing", timing);
+   if (ret < 0) {
+   dev_err(dev, "%pOF: no panel-timing node found for 
\"panel-dpi\" binding\n",
+   np);
+   return ret;
+   }
+
+   desc->timings = timing;
+   desc->num_timings = 1;
+
+   of_property_read_u32(np, "width-mm", >size.width);
+   of_property_read_u32(np, "height-mm", >size.height);
+
+   of_property_read_string(np, "data-mapping", );
+   if (!strcmp(mapping, "rgb24"))
+   desc->bus_format = MEDIA_BUS_FMT_RGB888_1X24;
+   else if (!strcmp(mapping, "rgb565"))
+   desc->bus_format = MEDIA_BUS_FMT_RGB565_1X16;
+   else if (!strcmp(mapping, "bgr666"))
+   desc->bus_format = MEDIA_BUS_FMT_RGB666_1X18;
+   else if (!strcmp(mapping, "lvds666"))
+   desc->bus_format = MEDIA_BUS_FMT_RGB666_1X24_CPADHI;
+
+   /* Extract bus_flags from display_timing */
+   bus_flags = 0;
+   vm.flags = timing->flags;
+   drm_bus_flags_from_videomode(, _flags);
+   desc->bus_flags = bus_flags;
+
+   /* We do not know the connector for the DT node, so guess it */
+   desc->connector_type = DRM_MODE_CONNECTOR_DPI;
+
+   panel->desc = desc;
+
+   return 0;
+}
+
 #define PANEL_SIMPLE_BOUNDS_CHECK(to_check, bounds, field) \
(to_check->field.typ >= bounds->field.min && \
 to_check->field.typ <= bounds->field.max)
@@ -437,8 +496,15 @@ static int panel_simple_probe(struct device *dev, const 
struct panel_desc *desc)
return -EPROBE_DEFER;
}
 
-   if (!of_get_display_timing(dev->of_node, "panel-timing", ))
-   panel_simple_parse_panel_timing_node(dev, panel, );
+   if (desc == _dpi) {
+   /* Handle the generic panel-dpi binding */
+   err = panel_dpi_probe(dev, panel);
+   if (err)
+   goto free_ddc;
+   } else {
+   if (!of_get_display_timing(dev->of_node, "panel-timing", ))
+   panel_simple_parse_panel_timing_node(dev, panel, );
+   }
 
drm_panel_init(>base, dev, _simple_funcs,
   desc->connector_type);
@@ -3688,6 +3754,10 @@ static const struct of_device_id platform_of_match[] = {
}, {
.compatible = "winstar,wf35ltiacd",
.data = _wf35ltiacd,
+   }, {
+   /* Must be the last entry */
+   .compatible = "panel-dpi",
+   .data = _dpi,
}, {
/* sentinel */
}
-- 
2.20.1

___
dri-devel mailing list

[PATCH v3 0/5] dt-bindings: convert timing + panel-dpi to DT schema

2020-02-16 Thread Sam Ravnborg
This set of patches convert display-timing.txt to DT schema.
To do that add a panel-timing.yaml file that include all the
panel-timing properties and use this in panel-common and in display-timings.

panel-dpi was also converted so we have no .txt users left of panel-timing
in panel/

Everything passed dt_binding_check - and the trivial errors I tried in
the examples was all catched during validation.

This work was triggered by a patch-set from Oleksandr Suvorov aiming
at updating panel-lvds to support panel-dpi.
This will make it simple to add additional properties to panel-dpi.

Thanks for the quick responses on v2 and likewise the quick
feedback on the request for the license change!

Highlight from v3 - se individual patches for details.
- Added panel-dpi support to panel-simple.
  We can now add a simple panel just by addding timing parameters
  in a DT node
  The patch [5/5] is RFC as test is pending
- To support panel-dpi in panel-simple - add a data-mapping
  property to panel-dpi

Highlights from v2 - see individual patches for details.
- Got acks for the license change
- Simplfied panel-timings bindings
- panel-dpi can now be used without a panel specific compatible
  So panel-dpi can be used as a generic binding for dumb panels

Feedback welcome!

Sam

Sam Ravnborg (5):
  dt-bindings: display: add panel-timing.yaml
  dt-bindings: display: convert display-timings to DT schema
  dt-bindings: display: convert panel-dpi to DT schema
  dt-bindings: display: add data-mapping to panel-dpi
  drm/panel: simple: add panel-dpi support

 .../bindings/display/panel/display-timing.txt  | 124 +--
 .../bindings/display/panel/display-timings.yaml|  77 +++
 .../bindings/display/panel/panel-common.yaml   |  15 +-
 .../bindings/display/panel/panel-dpi.txt   |  50 -
 .../bindings/display/panel/panel-dpi.yaml  |  82 
 .../bindings/display/panel/panel-timing.yaml   | 227 +
 drivers/gpu/drm/panel/panel-simple.c   |  74 ++-
 7 files changed, 470 insertions(+), 179 deletions(-)


___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v3 3/5] dt-bindings: display: convert panel-dpi to DT schema

2020-02-16 Thread Sam Ravnborg
With panel-timing converted, now convert the single
remaining .txt user in panel/ of panel-timing to DT schema.

v2:
  - Drop Thierry as maintainer, as this is not a general panel binding
and I have no acks.
  - Drop requirement for a panel- specific binding - "panel-dpi" is enough
  - Updated example

v3:
  - added yaml document terminator "..."
  - always require a specific binding - panel-dpi (based on feedback from Rob)
  - use "power-supply" for the supply property, and made it mandatory
"power-supply" is the standard property for panels

Signed-off-by: Sam Ravnborg 
Cc: Rob Herring 
Cc: Thierry Reding 
Cc: Laurent Pinchart 
Cc: Maxime Ripard 
---
 .../bindings/display/panel/panel-dpi.txt  | 50 -
 .../bindings/display/panel/panel-dpi.yaml | 72 +++
 2 files changed, 72 insertions(+), 50 deletions(-)
 delete mode 100644 
Documentation/devicetree/bindings/display/panel/panel-dpi.txt
 create mode 100644 
Documentation/devicetree/bindings/display/panel/panel-dpi.yaml

diff --git a/Documentation/devicetree/bindings/display/panel/panel-dpi.txt 
b/Documentation/devicetree/bindings/display/panel/panel-dpi.txt
deleted file mode 100644
index 6b203bc4d932..
--- a/Documentation/devicetree/bindings/display/panel/panel-dpi.txt
+++ /dev/null
@@ -1,50 +0,0 @@
-Generic MIPI DPI Panel
-==
-
-Required properties:
-- compatible: "panel-dpi"
-
-Optional properties:
-- label: a symbolic name for the panel
-- enable-gpios: panel enable gpio
-- reset-gpios: GPIO to control the RESET pin
-- vcc-supply: phandle of regulator that will be used to enable power to the 
display
-- backlight: phandle of the backlight device
-
-Required nodes:
-- "panel-timing" containing video timings
-  (Documentation/devicetree/bindings/display/panel/display-timing.txt)
-- Video port for DPI input
-
-Example

-
-lcd0: display@0 {
-compatible = "samsung,lte430wq-f0c", "panel-dpi";
-label = "lcd";
-
-backlight = <>;
-
-port {
-lcd_in: endpoint {
-remote-endpoint = <_out>;
-};
-};
-
-panel-timing {
-clock-frequency = <920>;
-hactive = <480>;
-vactive = <272>;
-hfront-porch = <8>;
-hback-porch = <4>;
-hsync-len = <41>;
-vback-porch = <2>;
-vfront-porch = <4>;
-vsync-len = <10>;
-
-hsync-active = <0>;
-vsync-active = <0>;
-de-active = <1>;
-pixelclk-active = <1>;
-};
-};
diff --git a/Documentation/devicetree/bindings/display/panel/panel-dpi.yaml 
b/Documentation/devicetree/bindings/display/panel/panel-dpi.yaml
new file mode 100644
index ..40079fc24a63
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/panel-dpi.yaml
@@ -0,0 +1,72 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/panel-dpi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Generic MIPI DPI Panel
+
+maintainers:
+  - Sam Ravnborg 
+
+allOf:
+  - $ref: panel-common.yaml#
+
+properties:
+  compatible:
+description:
+  Shall contain a panel specific compatible and "panel-dpi"
+  in that order.
+items:
+  - {}
+  - const: panel-dpi
+
+  backlight: true
+  enable-gpios: true
+  height-mm: true
+  label: true
+  panel-timing: true
+  port: true
+  power-supply: true
+  reset-gpios: true
+  width-mm: true
+
+required:
+  - panel-timing
+  - power-supply
+
+additionalProperties: false
+
+examples:
+  - |
+panel@0 {
+compatible = "osddisplays,osd057T0559-34ts", "panel-dpi";
+label = "osddisplay";
+power-supply = <_supply>;
+
+backlight = <>;
+
+port {
+lcd_in: endpoint {
+remote-endpoint = <_out>;
+};
+};
+panel-timing {
+clock-frequency = <920>;
+hactive = <800>;
+vactive = <480>;
+hfront-porch = <8>;
+hback-porch = <4>;
+hsync-len = <41>;
+vback-porch = <2>;
+vfront-porch = <4>;
+vsync-len = <10>;
+
+hsync-active = <0>;
+vsync-active = <0>;
+de-active = <1>;
+pixelclk-active = <1>;
+};
+};
+
+...
-- 
2.20.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v3 1/5] dt-bindings: display: add panel-timing.yaml

2020-02-16 Thread Sam Ravnborg
Add meta-schema variant of panel-timing and
reference it from panel-common.yaml.

Part of this came form other files with other
licenses - original commits:

cc3f414cf2e4 ("video: add of helper for display timings/videomode")
86f46565dff3 ("dt-bindings: display: display-timing: Add property to configure 
sync drive edge")
9cad9c95d7e8 ("Documentation: DocBook DRM framework documentation")

The original authors acked the license change to:
(GPL-2.0-only OR BSD-2-Clause)

v2:
  - Got OK from original authors for re-license
Huge thanks for the quick replies!
  - Typo fixes (Oleksandr)
  - Drop -array variant when not needed (Maxime)
  - Replace oneOf:... with enum (Maxime)
  - Drop type from clock-frequency (Rob)
  - Drop "|" when not needed (Rob)

v3:
  - Added comment to acks that are only for the license change
  - Add yaml document terminator "..."
  - Updated description (removed reference to native-mode)

Signed-off-by: Sam Ravnborg 
Acked-by: Laurent Pinchart  [license change]
Acked-by: Peter Ujfalusi  [license change]
Acked-by: Steffen Trumtrar  [license change]
Acked-by: Philipp Zabel  [license change]
Reviewed-by: Rob Herring 
Cc: Thierry Reding 
Cc: Oleksandr Suvorov 
Cc: Maxime Ripard 
Cc: devicet...@vger.kernel.org
---
 .../bindings/display/panel/panel-common.yaml  |   7 +-
 .../bindings/display/panel/panel-timing.yaml  | 227 ++
 2 files changed, 230 insertions(+), 4 deletions(-)
 create mode 100644 
Documentation/devicetree/bindings/display/panel/panel-timing.yaml

diff --git a/Documentation/devicetree/bindings/display/panel/panel-common.yaml 
b/Documentation/devicetree/bindings/display/panel/panel-common.yaml
index ef8d8cdfcede..8070c439adbd 100644
--- a/Documentation/devicetree/bindings/display/panel/panel-common.yaml
+++ b/Documentation/devicetree/bindings/display/panel/panel-common.yaml
@@ -54,13 +54,12 @@ properties:
 
   # Display Timings
   panel-timing:
-type: object
 description:
   Most display panels are restricted to a single resolution and
   require specific display timings. The panel-timing subnode expresses 
those
-  timings as specified in the timing subnode section of the display timing
-  bindings defined in
-  Documentation/devicetree/bindings/display/panel/display-timing.txt.
+  timings.
+allOf:
+  - $ref: panel-timing.yaml#
 
   # Connectivity
   port:
diff --git a/Documentation/devicetree/bindings/display/panel/panel-timing.yaml 
b/Documentation/devicetree/bindings/display/panel/panel-timing.yaml
new file mode 100644
index ..bd558ad7891f
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/panel-timing.yaml
@@ -0,0 +1,227 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/panel-timing.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: panel timing bindings
+
+maintainers:
+  - Thierry Reding 
+  - Sam Ravnborg 
+
+description: |
+  There are different ways of describing the timing data of a panel. The
+  devicetree representation corresponds to the one commonly found in datasheets
+  for panels.
+
+  The parameters are defined as seen in the following illustration.
+
+  +--+-+--+---+
+  |  |^|  |   |
+  |  ||vback_porch |  |   |
+  |  |v|  |   |
+  +--###--+---+
+  |  #^#  |   |
+  |  #|#  |   |
+  |  hback   #|#  hfront  | hsync |
+  |   porch  #|   hactive  #  porch   |  len  |
+  |<>#<---+--->#<>|<->|
+  |  #|#  |   |
+  |  #|vactive #  |   |
+  |  #|#  |   |
+  |  #v#  |   |
+  +--###--+---+
+  |  |^|  |   |
+  |  ||vfront_porch|  |   |
+  |  |v|  |   |
+  +--+-+--+---+
+  |  |^|  |   |
+  |  ||vsync_len   |  |   |
+  |  |v|  |   |
+  +--+-+--+---+
+
+
+  The following is the panel timings shown with time on the x-axis.
+  

[PATCH v3 4/5] dt-bindings: display: add data-mapping to panel-dpi

2020-02-16 Thread Sam Ravnborg
Add data-mapping property that can be used to specify
the media format used for the connection betwwen the
display controller (connector) and the panel.
Signed-off-by: Sam Ravnborg 
---
 .../devicetree/bindings/display/panel/panel-dpi.yaml | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/display/panel/panel-dpi.yaml 
b/Documentation/devicetree/bindings/display/panel/panel-dpi.yaml
index 40079fc24a63..6a03d2449701 100644
--- a/Documentation/devicetree/bindings/display/panel/panel-dpi.yaml
+++ b/Documentation/devicetree/bindings/display/panel/panel-dpi.yaml
@@ -21,6 +21,16 @@ properties:
   - {}
   - const: panel-dpi
 
+  data-mapping:
+enum:
+  - rgb24
+  - rgb565
+  - bgr666
+  - lvds666
+description: |
+  Describes the media format, how the display panel is connected
+  to the display interface.
+
   backlight: true
   enable-gpios: true
   height-mm: true
@@ -43,7 +53,7 @@ examples:
 compatible = "osddisplays,osd057T0559-34ts", "panel-dpi";
 label = "osddisplay";
 power-supply = <_supply>;
-
+data-mapping = "lvds666";
 backlight = <>;
 
 port {
-- 
2.20.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v3 2/5] dt-bindings: display: convert display-timings to DT schema

2020-02-16 Thread Sam Ravnborg
Add display-timings.yaml - that references panel-timings.yaml.
display-timings.yaml will be used for display bindings
when they are converted to meta-schema format.

For now the old display-timing.txt points to the new
display-timings.yaml - and all users are left as-is.

v2:
  - Updated native-mode description

v3:
  - Simpler "^timing" pattern (Rob)
  - timing node is of type object (Rob)
  - added display-timings to panel-common.yaml
  - added yaml document terminator "..."

Signed-off-by: Sam Ravnborg 
Reviewed-by: Rob Herring 
Cc: Laurent Pinchart 
Cc: Thierry Reding 
Cc: Oleksandr Suvorov 
Cc: devicet...@vger.kernel.org
---
 .../bindings/display/panel/display-timing.txt | 124 +-
 .../display/panel/display-timings.yaml|  77 +++
 .../bindings/display/panel/panel-common.yaml  |   8 ++
 3 files changed, 86 insertions(+), 123 deletions(-)
 create mode 100644 
Documentation/devicetree/bindings/display/panel/display-timings.yaml

diff --git a/Documentation/devicetree/bindings/display/panel/display-timing.txt 
b/Documentation/devicetree/bindings/display/panel/display-timing.txt
index 78222ced1874..7f55ad4a40c4 100644
--- a/Documentation/devicetree/bindings/display/panel/display-timing.txt
+++ b/Documentation/devicetree/bindings/display/panel/display-timing.txt
@@ -1,123 +1 @@
-display-timing bindings
-===
-
-display-timings node
-
-
-required properties:
- - none
-
-optional properties:
- - native-mode: The native mode for the display, in case multiple modes are
-   provided. When omitted, assume the first node is the native.
-
-timing subnode
---
-
-required properties:
- - hactive, vactive: display resolution
- - hfront-porch, hback-porch, hsync-len: horizontal display timing parameters
-   in pixels
-   vfront-porch, vback-porch, vsync-len: vertical display timing parameters in
-   lines
- - clock-frequency: display clock in Hz
-
-optional properties:
- - hsync-active: hsync pulse is active low/high/ignored
- - vsync-active: vsync pulse is active low/high/ignored
- - de-active: data-enable pulse is active low/high/ignored
- - pixelclk-active: with
-   - active high = drive pixel data on rising edge/
-   sample data on falling edge
-   - active low  = drive pixel data on falling edge/
-   sample data on rising edge
-   - ignored = ignored
- - syncclk-active: with
-   - active high = drive sync on rising edge/
-   sample sync on falling edge of pixel
-   clock
-   - active low  = drive sync on falling edge/
-   sample sync on rising edge of pixel
-   clock
-   - omitted = same configuration as pixelclk-active
- - interlaced (bool): boolean to enable interlaced mode
- - doublescan (bool): boolean to enable doublescan mode
- - doubleclk (bool): boolean to enable doubleclock mode
-
-All the optional properties that are not bool follow the following logic:
-<1>: high active
-<0>: low active
-omitted: not used on hardware
-
-There are different ways of describing the capabilities of a display. The
-devicetree representation corresponds to the one commonly found in datasheets
-for displays. If a display supports multiple signal timings, the native-mode
-can be specified.
-
-The parameters are defined as:
-
-  +--+-+--+---+
-  |  |^|  |   |
-  |  ||vback_porch |  |   |
-  |  |v|  |   |
-  +--###--+---+
-  |  #^#  |   |
-  |  #|#  |   |
-  |  hback   #|#  hfront  | hsync |
-  |   porch  #|   hactive  #  porch   |  len  |
-  |<>#<---+--->#<>|<->|
-  |  #|#  |   |
-  |  #|vactive #  |   |
-  |  #|#  |   |
-  |  #v#  |   |
-  +--###--+---+
-  |  |^|  |   |
-  |  ||vfront_porch|  |   |
-  |  |v|  |   |
-  +--+-+--+---+
-  

[RFC 2/9] mfd: Add driver for Multifunction USB Device

2020-02-16 Thread Noralf Trønnes
A Multifunction USB Device is a device that supports functions like gpio
and display or any other function that can be represented as a USB regmap.
Interrupts over USB is also supported if such an endpoint is present.

Signed-off-by: Noralf Trønnes 
---
 drivers/mfd/Kconfig |   8 +
 drivers/mfd/Makefile|   1 +
 drivers/mfd/mud.c   | 580 
 include/linux/mfd/mud.h |  16 ++
 4 files changed, 605 insertions(+)
 create mode 100644 drivers/mfd/mud.c
 create mode 100644 include/linux/mfd/mud.h

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 52818dbcfe1f..9950794d907e 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1968,6 +1968,14 @@ config MFD_STMFX
  additional drivers must be enabled in order to use the functionality
  of the device.
 
+config MFD_MUD
+   tristate "Multifunction USB Device core driver"
+   depends on USB
+   select MFD_CORE
+   select REGMAP_USB
+   help
+ Select this to get support for the Multifunction USB Device.
+
 menu "Multimedia Capabilities Port drivers"
depends on ARCH_SA1100
 
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 29e6767dd60c..0adfab9afaed 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -255,4 +255,5 @@ obj-$(CONFIG_MFD_ROHM_BD70528)  += rohm-bd70528.o
 obj-$(CONFIG_MFD_ROHM_BD718XX) += rohm-bd718x7.o
 obj-$(CONFIG_MFD_STMFX)+= stmfx.o
 obj-$(CONFIG_MFD_RPISENSE_CORE)+= rpisense-core.o
+obj-$(CONFIG_MFD_MUD)  += mud.o
 
diff --git a/drivers/mfd/mud.c b/drivers/mfd/mud.c
new file mode 100644
index ..f5f31478656d
--- /dev/null
+++ b/drivers/mfd/mud.c
@@ -0,0 +1,580 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2020 Noralf Trønnes
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* Temporary debugging aid */
+#undef dev_dbg
+#define dev_dbg dev_info
+
+#define mdebug(fmt, ...)   \
+do {   \
+   if (1)  \
+   pr_debug(fmt, ##__VA_ARGS__);   \
+} while (0)
+
+struct mud_irq_event {
+   struct list_head node;
+   DECLARE_BITMAP(status, REGMAP_USB_MAX_MAPS);
+};
+
+struct mud_irq {
+   struct irq_domain *domain;
+   unsigned int num_irqs;
+
+   struct workqueue_struct *workq;
+   struct work_struct work;
+   struct urb *urb;
+
+   spinlock_t lock; /* Protect the values below */
+   unsigned long *mask;
+   u16 tag;
+   struct list_head eventlist;
+
+   unsigned int stats_illegal;
+   unsigned int stats_already_seen;
+   unsigned int stats_lost;
+};
+
+struct mud_device {
+   struct usb_device *usb;
+   struct mud_irq *mirq;
+   struct mfd_cell *cells;
+   unsigned int num_cells;
+};
+
+static void mud_irq_work(struct work_struct *work)
+{
+   struct mud_irq *mirq = container_of(work, struct mud_irq, work);
+   struct mud_irq_event *event;
+   unsigned long n, flags;
+   unsigned int irq;
+
+   mdebug("%s: IN\n", __func__);
+
+   while (true) {
+   spin_lock_irqsave(>lock, flags);
+   event = list_first_entry_or_null(>eventlist, struct 
mud_irq_event, node);
+   if (event) {
+   list_del(>node);
+   mdebug("status: %*pb\n", mirq->num_irqs, 
event->status);
+   bitmap_and(event->status, event->status, mirq->mask, 
mirq->num_irqs);
+   }
+   spin_unlock_irqrestore(>lock, flags);
+   if (!event)
+   break;
+
+   for_each_set_bit(n, event->status, mirq->num_irqs) {
+   irq = irq_find_mapping(mirq->domain, n);
+   mdebug("n=%lu irq=%u\n", n, irq);
+   if (irq)
+   handle_nested_irq(irq);
+   }
+
+   kfree(event);
+   }
+
+   mdebug("%s: OUT\n", __func__);
+}
+
+#define BYTES_PER_LONG (BITS_PER_LONG / BITS_PER_BYTE)
+
+static void mud_irq_queue(struct urb *urb)
+{
+   u8 *buf = urb->transfer_buffer + sizeof(u16);
+   struct mud_irq *mirq = urb->context;
+   struct device *dev = >dev->dev;
+   struct mud_irq_event *event = NULL;
+   unsigned int i, tag, diff;
+   unsigned long flags;
+
+   if (urb->actual_length != urb->transfer_buffer_length) {
+   dev_err_once(dev, "Interrupt packet wrong length: %u\n",
+urb->actual_length);
+   mirq->stats_illegal++;
+   return;
+   }
+
+   spin_lock_irqsave(>lock, flags);
+
+   tag = le16_to_cpup(urb->transfer_buffer);
+   if (tag == mirq->tag) {
+   dev_dbg(dev, "Interrupt tag=%u already seen, 

[RFC 7/9] drm: Add Multifunction USB Device display driver

2020-02-16 Thread Noralf Trønnes
The Multifunction USB Device has optional support for displays.
LZ4 compression is used if the device supports it.

The driver is MIT licensed in the hope that parts of it can be used on
the BSD's.

Signed-off-by: Noralf Trønnes 
---
 drivers/gpu/drm/Kconfig   |2 +
 drivers/gpu/drm/Makefile  |1 +
 drivers/gpu/drm/mud/Kconfig   |   15 +
 drivers/gpu/drm/mud/Makefile  |3 +
 drivers/gpu/drm/mud/mud_drm.c | 1198 +
 drivers/gpu/drm/mud/mud_drm.h |  137 
 6 files changed, 1356 insertions(+)
 create mode 100644 drivers/gpu/drm/mud/Kconfig
 create mode 100644 drivers/gpu/drm/mud/Makefile
 create mode 100644 drivers/gpu/drm/mud/mud_drm.c
 create mode 100644 drivers/gpu/drm/mud/mud_drm.h

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index bfdadc3667e0..8ddc0d0e82cc 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -387,6 +387,8 @@ source "drivers/gpu/drm/aspeed/Kconfig"
 
 source "drivers/gpu/drm/mcde/Kconfig"
 
+source "drivers/gpu/drm/mud/Kconfig"
+
 # Keep legacy drivers last
 
 menuconfig DRM_LEGACY
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 9f1c7c486f88..5a5eab598d39 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -122,3 +122,4 @@ obj-$(CONFIG_DRM_LIMA)  += lima/
 obj-$(CONFIG_DRM_PANFROST) += panfrost/
 obj-$(CONFIG_DRM_ASPEED_GFX) += aspeed/
 obj-$(CONFIG_DRM_MCDE) += mcde/
+obj-y  += mud/
diff --git a/drivers/gpu/drm/mud/Kconfig b/drivers/gpu/drm/mud/Kconfig
new file mode 100644
index ..440e994ca0a2
--- /dev/null
+++ b/drivers/gpu/drm/mud/Kconfig
@@ -0,0 +1,15 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+config DRM_MUD
+   tristate "Multifunction USB Device Display"
+   depends on DRM && USB && MFD_MUD
+   select LZ4_COMPRESS
+   select DRM_KMS_HELPER
+
+   select DRM_GEM_CMA_HELPER
+   select DRM_GEM_SHMEM_HELPER
+
+   select BACKLIGHT_CLASS_DEVICE
+   help
+This is a KMS driver for Multifunction USB Device displays or display
+adapters.
diff --git a/drivers/gpu/drm/mud/Makefile b/drivers/gpu/drm/mud/Makefile
new file mode 100644
index ..d5941d33bcd9
--- /dev/null
+++ b/drivers/gpu/drm/mud/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+obj-$(CONFIG_DRM_MUD)  += mud_drm.o
diff --git a/drivers/gpu/drm/mud/mud_drm.c b/drivers/gpu/drm/mud/mud_drm.c
new file mode 100644
index ..51ba756940fd
--- /dev/null
+++ b/drivers/gpu/drm/mud/mud_drm.c
@@ -0,0 +1,1198 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2020 Noralf Trønnes
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+//#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "mud_drm.h"
+
+/*
+ * freerun: Userspace is told that the flush happended immediately, before the 
worker has begun.
+ *  Useful if the rendering loop handles several displays one after 
the other.
+ * steady:  Notify userspace at a fixed interval (FPS).
+ * inline:  Do flushing before returning to userspace from the update function.
+ *
+ * Rationale:
+ * In a worst case scenario a full buffer update can take 1 second.
+ *
+ * I believe Wayland/Weston has one rendering loop per display/device and if 
so doesn't need any special treatment.
+ * For Xorg I got the impression that it runs everything in one loop and one 
slow device will slow everything down.
+ * For games on embedded I believe maybe a fixed rate is best.
+ *
+ * I'd appreciate any insight into how userspace operates in this regard.
+ */
+static int pageflip;
+module_param(pageflip, int, 0644);
+MODULE_PARM_DESC(pageflip, "pageflip strategy: 0=freerun, 1=steady, 2=inline 
[default=0]");
+
+#define MUD_DRM_PAGEFLIP_FREERUN0
+#define MUD_DRM_PAGEFLIP_STEADY 1
+#define MUD_DRM_PAGEFLIP_INLINE 2
+
+struct mud_drm_damage {
+   struct list_head list;
+   struct drm_rect rect;
+   ktime_t time;
+};
+
+struct mud_drm_device {
+   struct drm_device drm;
+   struct drm_simple_display_pipe pipe;
+   struct usb_device *usb;
+   struct regmap *regmap;
+
+   void *buf;
+   size_t buf_len;
+
+   struct mutex lock;
+
+   bool run;
+   struct workqueue_struct *workq;
+   struct work_struct work;
+   wait_queue_head_t waitq;
+   struct drm_framebuffer *fb;
+   struct list_head damagelist;
+   unsigned int average_pageflip_ms;
+};
+
+static inline struct mud_drm_device *to_mud_drm_device(struct drm_device *drm)
+{
+   return container_of(drm, struct mud_drm_device, drm);
+}
+
+/**/
+/* TODO: Move to drm_encoder.c */
+
+static void drm_encoder_dummy_cleanup(struct drm_encoder 

[RFC 5/9] usb: gadget: function: mud: Add gpio support

2020-02-16 Thread Noralf Trønnes
Add optional gpio functionality to the Multifunction USB Device.

Signed-off-by: Noralf Trønnes 
---
 drivers/usb/gadget/Kconfig   |  14 +
 drivers/usb/gadget/function/Makefile |   2 +
 drivers/usb/gadget/function/f_mud_pins.c | 962 +++
 3 files changed, 978 insertions(+)
 create mode 100644 drivers/usb/gadget/function/f_mud_pins.c

diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 9551876ffe08..d6285146ec76 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -219,6 +219,9 @@ config USB_F_TCM
 config USB_F_MUD
tristate
 
+config USB_F_MUD_PINS
+   tristate
+
 # this first set of drivers all depend on bulk-capable hardware.
 
 config USB_CONFIGFS
@@ -493,6 +496,17 @@ menuconfig USB_CONFIGFS_F_MUD
help
  Core support for the Multifunction USB Device.
 
+if USB_F_MUD
+
+config USB_CONFIGFS_F_MUD_PINS
+   bool "Multifunction USB Device GPIO"
+   depends on PINCTRL
+   select USB_F_MUD_PINS
+   help
+ GPIO support for the Multifunction USB Device.
+
+endif # USB_F_MUD
+
 choice
tristate "USB Gadget precomposed configurations"
default USB_ETH
diff --git a/drivers/usb/gadget/function/Makefile 
b/drivers/usb/gadget/function/Makefile
index b6e31b511521..2e24227fcc12 100644
--- a/drivers/usb/gadget/function/Makefile
+++ b/drivers/usb/gadget/function/Makefile
@@ -52,3 +52,5 @@ usb_f_tcm-y   := f_tcm.o
 obj-$(CONFIG_USB_F_TCM)+= usb_f_tcm.o
 usb_f_mud-y:= f_mud.o mud_regmap.o
 obj-$(CONFIG_USB_F_MUD)+= usb_f_mud.o
+usb_f_mud_pins-y   := f_mud_pins.o
+obj-$(CONFIG_USB_F_MUD_PINS)   += usb_f_mud_pins.o
diff --git a/drivers/usb/gadget/function/f_mud_pins.c 
b/drivers/usb/gadget/function/f_mud_pins.c
new file mode 100644
index ..b3466804ad5e
--- /dev/null
+++ b/drivers/usb/gadget/function/f_mud_pins.c
@@ -0,0 +1,962 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 Noralf Trønnes
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "f_mud.h"
+#include "../../../pinctrl/pinctrl-mud.h"
+
+/*
+ * Even though the host side is a pinctrl driver, the device side is a gpio 
consumer.
+ * That's because not all boards have a pin controller.
+ */
+
+/* Temporary debugging aid */
+#define fmdebug(fmt, ...)  \
+do {   \
+   if (1)  \
+   printk(KERN_DEBUG fmt, ##__VA_ARGS__);  \
+} while (0)
+
+static DEFINE_IDA(f_mud_pins_ida);
+
+struct f_mud_pins_cell_item {
+   struct list_head node;
+   unsigned int index;
+   struct config_group group;
+
+   struct mutex lock; /* Protect the values below */
+   int refcnt;
+
+   const char *name;
+   const char *chip;
+   int offset;
+};
+
+static inline struct f_mud_pins_cell_item *ci_to_f_mud_pins_cell_item(struct 
config_item *item)
+{
+   return container_of(to_config_group(item), struct f_mud_pins_cell_item, 
group);
+}
+
+struct f_mud_pins_lookup_device {
+   struct device dev;
+   int id;
+   struct f_mud_cell *cell;
+   struct gpiod_lookup_table *lookup;
+   const char **names;
+   unsigned int count;
+};
+
+struct f_mud_pins_pin {
+   struct f_mud_pins_cell *parent;
+   unsigned int index;
+   struct gpio_desc *gpio;
+   unsigned long dflags;
+   unsigned int debounce;
+#define DEBOUNCE_NOT_SET UINT_MAX
+   bool config_requested;
+   int irq;
+   int irqflags;
+};
+
+struct f_mud_pins_cell {
+   struct f_mud_cell cell;
+
+   struct mutex lock; /* Protect refcnt and items */
+   int refcnt;
+   struct list_head items;
+
+   struct f_mud_pins_lookup_device *ldev;
+   struct f_mud_pins_pin *pins;
+   unsigned int count;
+   spinlock_t irq_status_lock;
+   unsigned long *irq_status;
+};
+
+static inline struct f_mud_pins_cell *ci_to_f_mud_pins_cell(struct config_item 
*item)
+{
+   return container_of(to_config_group(item), struct f_mud_pins_cell, 
cell.group);
+}
+
+static inline struct f_mud_pins_cell *cell_to_pcell(struct f_mud_cell *cell)
+{
+   return container_of(cell, struct f_mud_pins_cell, cell);
+}
+
+static irqreturn_t f_mud_pins_gpio_irq_thread(int irq, void *p)
+{
+   struct f_mud_pins_pin *pin = p;
+   struct f_mud_pins_cell *pcell = pin->parent;
+
+   spin_lock(>irq_status_lock);
+   set_bit(pin->index, pcell->irq_status);
+   spin_unlock(>irq_status_lock);
+
+   fmdebug("%s(index=%u): irq_status=%*pb\n", __func__, pin->index,
+   pcell->count, pcell->irq_status);
+
+   f_mud_irq(pcell->ldev->cell);
+
+   return IRQ_HANDLED;
+}
+
+static int f_mud_pins_gpio_irq_request(struct f_mud_pins_cell 

[RFC 3/9] usb: gadget: function: Add Multifunction USB Device support

2020-02-16 Thread Noralf Trønnes
This is the gadget side of the mfd host driver. It provides a USB
function that drivers can hook into providing functions like gpio and
display as regmaps to the host. These drivers are configured through
configfs.

Signed-off-by: Noralf Trønnes 
---
 drivers/usb/gadget/Kconfig   |  10 +
 drivers/usb/gadget/function/Makefile |   2 +
 drivers/usb/gadget/function/f_mud.c  | 913 ++
 drivers/usb/gadget/function/f_mud.h  | 210 +
 drivers/usb/gadget/function/mud_regmap.c | 936 +++
 5 files changed, 2071 insertions(+)
 create mode 100644 drivers/usb/gadget/function/f_mud.c
 create mode 100644 drivers/usb/gadget/function/f_mud.h
 create mode 100644 drivers/usb/gadget/function/mud_regmap.c

diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 02ff850278b1..9551876ffe08 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -216,6 +216,9 @@ config USB_F_PRINTER
 config USB_F_TCM
tristate
 
+config USB_F_MUD
+   tristate
+
 # this first set of drivers all depend on bulk-capable hardware.
 
 config USB_CONFIGFS
@@ -483,6 +486,13 @@ config USB_CONFIGFS_F_TCM
  Both protocols can work on USB2.0 and USB3.0.
  UAS utilizes the USB 3.0 feature called streams support.
 
+menuconfig USB_CONFIGFS_F_MUD
+   bool "Multifunction USB Device"
+   depends on USB_CONFIGFS
+   select USB_F_MUD
+   help
+ Core support for the Multifunction USB Device.
+
 choice
tristate "USB Gadget precomposed configurations"
default USB_ETH
diff --git a/drivers/usb/gadget/function/Makefile 
b/drivers/usb/gadget/function/Makefile
index 5d3a6cf02218..b6e31b511521 100644
--- a/drivers/usb/gadget/function/Makefile
+++ b/drivers/usb/gadget/function/Makefile
@@ -50,3 +50,5 @@ usb_f_printer-y   := f_printer.o
 obj-$(CONFIG_USB_F_PRINTER)+= usb_f_printer.o
 usb_f_tcm-y:= f_tcm.o
 obj-$(CONFIG_USB_F_TCM)+= usb_f_tcm.o
+usb_f_mud-y:= f_mud.o mud_regmap.o
+obj-$(CONFIG_USB_F_MUD)+= usb_f_mud.o
diff --git a/drivers/usb/gadget/function/f_mud.c 
b/drivers/usb/gadget/function/f_mud.c
new file mode 100644
index ..b15a571d2e5d
--- /dev/null
+++ b/drivers/usb/gadget/function/f_mud.c
@@ -0,0 +1,913 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 Noralf Trønnes
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "f_mud.h"
+
+/**
+ * DOC: overview
+ *
+ * f_mud is the device side counterpart to drivers/mfd/mud.
+ * It combines the regmap and mfd cell abstraction on the host side into one 
cell
+ * driver on the device side: @f_mud_cell_ops. The reason for not using the
+ * regmap library here is so drivers can do compression directly with their own
+ * buffers without going through a temporary buffer.
+ */
+
+/* Temporary debugging aid */
+static unsigned int debug = 8;
+
+#define fmdebug(level, fmt, ...)   \
+do {   \
+   if ((level) <= debug)   \
+   pr_debug(fmt, ##__VA_ARGS__);   \
+} while (0)
+
+struct f_mud {
+   struct usb_function func;
+   u8 interface_id;
+   struct mud_regmap *mreg;
+
+   struct f_mud_cell **cells;
+   unsigned int num_cells;
+
+   int interrupt_interval_ms;
+
+   spinlock_t irq_lock;
+   bool irq_enabled;
+   struct usb_ep *irq_ep;
+   struct usb_request *irq_req;
+   u16 int_tag;
+   unsigned long *irq_status;
+   bool irq_queued;
+};
+
+static inline struct f_mud *func_to_f_mud(struct usb_function *f)
+{
+   return container_of(f, struct f_mud, func);
+}
+
+struct f_mud_opts {
+   struct usb_function_instance func_inst;
+   struct mutex lock;
+   int refcnt;
+
+   int interrupt_interval_ms;
+
+   struct list_head cells;
+};
+
+static inline struct f_mud_opts *ci_to_f_mud_opts(struct config_item *item)
+{
+   return container_of(to_config_group(item), struct f_mud_opts,
+   func_inst.group);
+}
+
+static DEFINE_MUTEX(f_mud_cell_ops_list_mutex);
+static LIST_HEAD(f_mud_cell_ops_list);
+
+struct f_mud_cell_ops_list_item {
+   struct list_head list;
+   const struct f_mud_cell_ops *ops;
+   unsigned int refcnt;
+};
+
+static struct f_mud_cell_ops_list_item *f_mud_cell_item_lookup(const char 
*name)
+{
+   struct f_mud_cell_ops_list_item *item;
+
+   list_for_each_entry(item, _mud_cell_ops_list, list) {
+   if (!strcmp(name, item->ops->name))
+   return item;
+   }
+
+   return NULL;
+}
+
+/**
+ * f_mud_cell_register() - Register a cell driver
+ * @ops: Cell operations structure
+ *
+ * This function registers a cell driver for use in a gadget.
+ *
+ * Returns:
+ * Zero on success, negative 

[RFC 8/9] drm/client: Add drm_client_init_from_id() and drm_client_modeset_set()

2020-02-16 Thread Noralf Trønnes
drm_client_init_from_id() provides a way for clients to add a client based
on the minor. drm_client_modeset_set() provides a way to set the modeset
for clients that handles connectors and display mode on their own.

Signed-off-by: Noralf Trønnes 
---
 drivers/gpu/drm/drm_client.c | 37 
 drivers/gpu/drm/drm_client_modeset.c | 52 
 include/drm/drm_client.h |  4 +++
 3 files changed, 93 insertions(+)

diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c
index d9a2e3695525..dbd73fe8d987 100644
--- a/drivers/gpu/drm/drm_client.c
+++ b/drivers/gpu/drm/drm_client.c
@@ -112,6 +112,43 @@ int drm_client_init(struct drm_device *dev, struct 
drm_client_dev *client,
 }
 EXPORT_SYMBOL(drm_client_init);
 
+/**
+ * drm_client_init_from_id - Initialise a DRM client
+ * @minor_id: DRM minor id
+ * @client: DRM client
+ * @name: Client name
+ * @funcs: DRM client functions (optional)
+ *
+ * This function looks up the drm_device using the minor id and initializes 
the client.
+ * It also registeres the client to avoid a possible race with DRM device 
unregister.
+ *
+ * See drm_client_init() and drm_client_register().
+ *
+ * Returns:
+ * Zero on success or negative error code on failure.
+ */
+int drm_client_init_from_id(unsigned int minor_id, struct drm_client_dev 
*client,
+   const char *name, const struct drm_client_funcs 
*funcs)
+{
+   struct drm_minor *minor;
+   int ret;
+
+   minor = drm_minor_acquire(minor_id);
+   if (IS_ERR(minor))
+   return PTR_ERR(minor);
+
+   mutex_lock(>dev->clientlist_mutex);
+   ret = drm_client_init(minor->dev, client, name, funcs);
+   if (!ret)
+   list_add(>list, >dev->clientlist);
+   mutex_unlock(>dev->clientlist_mutex);
+
+   drm_minor_release(minor);
+
+   return ret;
+}
+EXPORT_SYMBOL(drm_client_init_from_id);
+
 /**
  * drm_client_register - Register client
  * @client: DRM client
diff --git a/drivers/gpu/drm/drm_client_modeset.c 
b/drivers/gpu/drm/drm_client_modeset.c
index 895b73f23079..9396267e646c 100644
--- a/drivers/gpu/drm/drm_client_modeset.c
+++ b/drivers/gpu/drm/drm_client_modeset.c
@@ -807,6 +807,58 @@ int drm_client_modeset_probe(struct drm_client_dev 
*client, unsigned int width,
 }
 EXPORT_SYMBOL(drm_client_modeset_probe);
 
+/**
+ * drm_client_modeset_set() - Set modeset
+ * @client: DRM client
+ * @connector: Connector
+ * @mode: Display mode
+ * @fb: Framebuffer
+ *
+ * This function releases any current modeset info and sets the new modeset in
+ * the client's modeset array.
+ *
+ * Returns:
+ * Zero on success or negative error code on failure.
+ */
+int drm_client_modeset_set(struct drm_client_dev *client, struct drm_connector 
*connector,
+  struct drm_display_mode *mode, struct 
drm_framebuffer *fb)
+{
+   struct drm_mode_set *modeset;
+   int ret = -ENOENT;
+
+   mutex_lock(>modeset_mutex);
+
+   drm_client_modeset_release(client);
+
+   if (!connector || !mode || !fb) {
+   ret = 0;
+   goto unlock;
+   }
+
+   drm_client_for_each_modeset(modeset, client) {
+   if (!connector_has_possible_crtc(connector, modeset->crtc))
+   continue;
+
+   modeset->mode = drm_mode_duplicate(client->dev, mode);
+   if (!modeset->mode) {
+   ret = -ENOMEM;
+   break;
+   }
+
+   drm_connector_get(connector);
+   modeset->connectors[modeset->num_connectors++] = connector;
+
+   modeset->fb = fb;
+   ret = 0;
+   break;
+   }
+unlock:
+   mutex_unlock(>modeset_mutex);
+
+   return ret;
+}
+EXPORT_SYMBOL(drm_client_modeset_set);
+
 /**
  * drm_client_rotation() - Check the initial rotation value
  * @modeset: DRM modeset
diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h
index 5cf2c5dd8b1e..97e4157d07c5 100644
--- a/include/drm/drm_client.h
+++ b/include/drm/drm_client.h
@@ -104,6 +104,8 @@ struct drm_client_dev {
 
 int drm_client_init(struct drm_device *dev, struct drm_client_dev *client,
const char *name, const struct drm_client_funcs *funcs);
+int drm_client_init_from_id(unsigned int minor_id, struct drm_client_dev 
*client,
+   const char *name, const struct drm_client_funcs 
*funcs);
 void drm_client_release(struct drm_client_dev *client);
 void drm_client_register(struct drm_client_dev *client);
 
@@ -155,6 +157,8 @@ void drm_client_buffer_vunmap(struct drm_client_buffer 
*buffer);
 int drm_client_modeset_create(struct drm_client_dev *client);
 void drm_client_modeset_free(struct drm_client_dev *client);
 int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int 
width, unsigned int height);
+int drm_client_modeset_set(struct drm_client_dev *client, struct drm_connector 

[RFC 9/9] usb: gadget: function: mud: Add display support

2020-02-16 Thread Noralf Trønnes
Add optional display functionality to the Multifunction USB Device.
The bulk of the code is placed in the drm subsystem since it's reaching
into the drm internals.

Signed-off-by: Noralf Trønnes 
---
 drivers/gpu/drm/mud/Kconfig |   3 +
 drivers/gpu/drm/mud/Makefile|   1 +
 drivers/gpu/drm/mud/mud_drm_gadget.c| 889 
 drivers/usb/gadget/Kconfig  |  12 +
 drivers/usb/gadget/function/Makefile|   2 +
 drivers/usb/gadget/function/f_mud_drm.c | 181 +
 6 files changed, 1088 insertions(+)
 create mode 100644 drivers/gpu/drm/mud/mud_drm_gadget.c
 create mode 100644 drivers/usb/gadget/function/f_mud_drm.c

diff --git a/drivers/gpu/drm/mud/Kconfig b/drivers/gpu/drm/mud/Kconfig
index 440e994ca0a2..b3c6d073cc9c 100644
--- a/drivers/gpu/drm/mud/Kconfig
+++ b/drivers/gpu/drm/mud/Kconfig
@@ -13,3 +13,6 @@ config DRM_MUD
help
 This is a KMS driver for Multifunction USB Device displays or display
 adapters.
+
+config DRM_MUD_GADGET
+   tristate
diff --git a/drivers/gpu/drm/mud/Makefile b/drivers/gpu/drm/mud/Makefile
index d5941d33bcd9..56d2c39ac0eb 100644
--- a/drivers/gpu/drm/mud/Makefile
+++ b/drivers/gpu/drm/mud/Makefile
@@ -1,3 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0-or-later
 
 obj-$(CONFIG_DRM_MUD)  += mud_drm.o
+obj-$(CONFIG_DRM_MUD_GADGET)   += mud_drm_gadget.o
diff --git a/drivers/gpu/drm/mud/mud_drm_gadget.c 
b/drivers/gpu/drm/mud/mud_drm_gadget.c
new file mode 100644
index ..9395d8b7cefe
--- /dev/null
+++ b/drivers/gpu/drm/mud/mud_drm_gadget.c
@@ -0,0 +1,889 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2020 Noralf Trønnes
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "mud_drm.h"
+
+/* Temporary debugging aid */
+static unsigned int debug = 8;
+
+#define pdebug(level, fmt, ...)\
+   if (level <= debug) \
+   printk(KERN_DEBUG fmt, ##__VA_ARGS__)
+
+struct mud_drm_gadget_connector {
+   struct drm_connector *connector;
+   u32 capabilities;
+   enum drm_connector_status status;
+   unsigned int width_mm;
+   unsigned int height_mm;
+   void *edid;
+   size_t edid_len;
+   struct mud_drm_display_mode *modes;
+   unsigned int num_modes;
+};
+
+struct mud_drm_gadget {
+   struct drm_client_dev client;
+
+   struct mud_drm_gadget_connector *connectors;
+   unsigned int connector_count;
+
+   const u32 *formats;
+   unsigned int format_count;
+
+   struct drm_connector *current_connector;
+   struct mud_drm_display_mode current_mode;
+   u32 current_format;
+
+   unsigned int rect_x;
+   unsigned int rect_y;
+   unsigned int rect_width;
+   unsigned int rect_height;
+
+   struct drm_client_buffer *buffer;
+   struct drm_client_buffer *buffer_check;
+   bool check_ok;
+
+   size_t max_transfer_size;
+   void *work_buf;
+};
+
+static int mud_drm_gadget_probe_connector(struct mud_drm_gadget_connector 
*mconn)
+{
+   struct drm_connector *connector = mconn->connector;
+   struct drm_device *dev = connector->dev;
+   struct drm_display_mode *mode;
+   unsigned int i = 0;
+   int ret = 0;
+   void *edid;
+
+   pdebug(2, "%s:\n", __func__);
+
+   mutex_lock(>mode_config.mutex);
+
+   connector->funcs->fill_modes(connector,
+dev->mode_config.max_width,
+dev->mode_config.max_height);
+
+   mconn->width_mm = connector->display_info.width_mm;
+   mconn->height_mm = connector->display_info.height_mm;
+   mconn->status = connector->status;
+
+   mconn->num_modes = 0;
+   list_for_each_entry(mode, >modes, head)
+   mconn->num_modes++;
+
+   pdebug(2, "num_modes=%u\n", mconn->num_modes);
+
+   if (!mconn->num_modes)
+   goto unlock;
+
+   // FIXME: Checkpatch complains: Reusing the krealloc arg is almost 
always a bug
+   mconn->modes = krealloc(mconn->modes, mconn->num_modes * 
sizeof(*mconn->modes), GFP_KERNEL);
+   if (!mconn->modes) {
+   ret = -ENOMEM;
+   mconn->num_modes = 0;
+   goto unlock;
+   }
+
+   list_for_each_entry(mode, >modes, head) {
+   pdebug(2, "Modeline " DRM_MODE_FMT "\n", 
DRM_MODE_ARG(mode));
+   mud_drm_from_display_mode(>modes[i++], mode);
+   }
+
+   if (!connector->edid_blob_ptr)
+   goto unlock;
+
+   edid = connector->edid_blob_ptr->data;
+   mconn->edid_len = connector->edid_blob_ptr->length;
+   pdebug(2, "edid_len=%zu\n", mconn->edid_len);
+   if (!mconn->edid_len || !edid) {
+   mconn->edid_len = 0;
+   goto unlock;
+   }
+
+   

[RFC 4/9] pinctrl: Add Multifunction USB Device pinctrl driver

2020-02-16 Thread Noralf Trønnes
The Multifunction USB Device has optional support for gpio and pin
configuration. Interrupts are supported if the device supports it.

Signed-off-by: Noralf Trønnes 
---
 drivers/pinctrl/Kconfig   |   9 +
 drivers/pinctrl/Makefile  |   1 +
 drivers/pinctrl/pinctrl-mud.c | 657 ++
 drivers/pinctrl/pinctrl-mud.h |  89 +
 4 files changed, 756 insertions(+)
 create mode 100644 drivers/pinctrl/pinctrl-mud.c
 create mode 100644 drivers/pinctrl/pinctrl-mud.h

diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index df0ef69dd474..ee3532c64411 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -384,6 +384,15 @@ config PINCTRL_OCELOT
select OF_GPIO
select REGMAP_MMIO
 
+config PINCTRL_MUD
+   tristate "Multifunction USB Device pinctrl driver"
+   depends on MFD_MUD
+   select GENERIC_PINCONF
+   select GPIOLIB
+   select GPIOLIB_IRQCHIP
+   help
+ Support for GPIOs on Multifunction USB Devices.
+
 source "drivers/pinctrl/actions/Kconfig"
 source "drivers/pinctrl/aspeed/Kconfig"
 source "drivers/pinctrl/bcm/Kconfig"
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 879f312bfb75..782cc7f286b7 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -47,6 +47,7 @@ obj-$(CONFIG_PINCTRL_INGENIC) += pinctrl-ingenic.o
 obj-$(CONFIG_PINCTRL_RK805)+= pinctrl-rk805.o
 obj-$(CONFIG_PINCTRL_OCELOT)   += pinctrl-ocelot.o
 obj-$(CONFIG_PINCTRL_EQUILIBRIUM)   += pinctrl-equilibrium.o
+obj-$(CONFIG_PINCTRL_MUD)  += pinctrl-mud.o
 
 obj-y  += actions/
 obj-$(CONFIG_ARCH_ASPEED)  += aspeed/
diff --git a/drivers/pinctrl/pinctrl-mud.c b/drivers/pinctrl/pinctrl-mud.c
new file mode 100644
index ..f890c8e68755
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-mud.c
@@ -0,0 +1,657 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2020 Noralf Trønnes
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "core.h"
+#include "pinconf.h"
+#include "pinmux.h"
+#include "pinctrl-utils.h"
+
+#include "pinctrl-mud.h"
+
+/* Temporary debugging aid */
+static unsigned int debug = 8;
+
+#define pdebug(level, fmt, ...)\
+do {   \
+   if ((level) <= debug)   \
+   printk(KERN_DEBUG fmt, ##__VA_ARGS__);  \
+} while (0)
+
+struct mud_pinctrl_pin {
+   unsigned int irq_types;
+   unsigned int irq_type;
+   bool irq_enabled;
+};
+
+struct mud_pinctrl {
+   struct device *dev;
+   struct regmap *regmap;
+   struct mud_pinctrl_pin *pins;
+   struct pinctrl_dev *pctl_dev;
+   struct pinctrl_desc pctl_desc;
+   struct gpio_chip gpio_chip;
+   struct irq_chip irq_chip;
+   struct mutex irqlock; /* IRQ bus lock */
+};
+
+static unsigned int mud_pinctrl_pin_reg(unsigned int pin, unsigned int offset)
+{
+   return MUD_PINCTRL_REG_PIN_BASE + (pin * MUD_PINCTRL_PIN_BLOCK_SIZE) + 
offset;
+}
+
+static int mud_pinctrl_pin_read_reg(struct mud_pinctrl *pctl, unsigned int pin,
+   unsigned int offset, unsigned int *val)
+{
+   return regmap_read(pctl->regmap, mud_pinctrl_pin_reg(pin, offset), val);
+}
+
+static int mud_pinctrl_pin_write_reg(struct mud_pinctrl *pctl, unsigned int 
pin,
+unsigned int offset, unsigned int val)
+{
+   return regmap_write(pctl->regmap, mud_pinctrl_pin_reg(pin, offset), 
val);
+}
+
+static int mud_pinctrl_read_bitmap(struct mud_pinctrl *pctl, unsigned int reg,
+  unsigned long *bitmap, unsigned int nbits)
+{
+   unsigned int nregs = DIV_ROUND_UP(nbits, 32);
+   u32 *vals;
+   int ret;
+
+   vals = kmalloc_array(nregs, sizeof(*vals), GFP_KERNEL);
+   if (!vals)
+   return -ENOMEM;
+
+   ret = regmap_bulk_read(pctl->regmap, reg, vals, nregs);
+   if (ret)
+   goto free;
+
+   bitmap_from_arr32(bitmap, vals, nbits);
+free:
+   kfree(vals);
+
+   return ret;
+}
+
+static int mud_pinctrl_gpio_request(struct gpio_chip *gc, unsigned int offset)
+{
+   struct mud_pinctrl *pctl = gpiochip_get_data(gc);
+   int ret;
+
+   pdebug(1, "%s: offset=%u\n", __func__, offset);
+
+   ret = mud_pinctrl_pin_write_reg(pctl, offset, MUD_PIN_GPIO_REQUEST, 1);
+   if (ret == -EBUSY) {
+   dev_err(pctl->dev,
+   "pin %u is claimed by another function on the USB 
device\n",
+   offset);
+   ret = -EINVAL; /* follow pinmux.c:pin_request() */
+   }
+
+   return ret;
+}
+
+static void mud_pinctrl_gpio_free(struct gpio_chip *gc, unsigned int offset)
+{
+   struct mud_pinctrl *pctl = gpiochip_get_data(gc);
+
+   pdebug(1, 

[RFC 0/9] Regmap over USB for Multifunction USB Device (gpio, display, ...)

2020-02-16 Thread Noralf Trønnes
Hi,

A while back I had the idea to turn a Raspberry Pi Zero into a $5
USB to HDMI/SDTV/DSI/DPI display adapter.

Thinking about how to represent the display to the driver I realised
that hardware use registers as API. And Linux does have a generic
register abstraction: regmap. Furthermore this means that if I can do a
regmap over USB implementation, it will be easy to do other functions
like gpio, adc and others. After a few iterations trying to understand
the USB subsystem and satisfying driver requirements, I now have
something that looks promising.

I'm sending out an early version hoping to get feedback especially on
the core parts that handles regmap and interrupts.

Overview:

  USB Host  : USB Device
:
--  :  --
--  | mfd: mud   |  :  | f_mud  |  --
| Driver |  --  :  ||  | Driver |
--  | regmap-usb |  :  | (mud_regmap)   |  --
--  :  --


I've attached 2 drivers:
- gpio/pinctrl: is more or less finished
- display: needs a lot more work


USB3 device
I've only tested this with usb2 devices (Pi, BBB) so I should get myself
a usb3 gadget capable board. My searching didn't turn up much, so this
seems to be quite rare. ROCK960 has USB 3.0 type C OTG but the price is
$139 which is a bit expensive for this hobby project. Does anyone know
of a cheap board?

Noralf.


Noralf Trønnes (9):
  regmap: Add USB support
  mfd: Add driver for Multifunction USB Device
  usb: gadget: function: Add Multifunction USB Device support
  pinctrl: Add Multifunction USB Device pinctrl driver
  usb: gadget: function: mud: Add gpio support
  regmap: Speed up _regmap_raw_write_impl() for large buffers
  drm: Add Multifunction USB Device display driver
  drm/client: Add drm_client_init_from_id() and drm_client_modeset_set()
  usb: gadget: function: mud: Add display support

 drivers/base/regmap/Kconfig  |8 +-
 drivers/base/regmap/Makefile |1 +
 drivers/base/regmap/regmap-usb.c | 1026 ++
 drivers/base/regmap/regmap.c |   10 +-
 drivers/gpu/drm/Kconfig  |2 +
 drivers/gpu/drm/Makefile |1 +
 drivers/gpu/drm/drm_client.c |   37 +
 drivers/gpu/drm/drm_client_modeset.c |   52 +
 drivers/gpu/drm/mud/Kconfig  |   18 +
 drivers/gpu/drm/mud/Makefile |4 +
 drivers/gpu/drm/mud/mud_drm.c| 1198 ++
 drivers/gpu/drm/mud/mud_drm.h|  137 +++
 drivers/gpu/drm/mud/mud_drm_gadget.c |  889 
 drivers/mfd/Kconfig  |8 +
 drivers/mfd/Makefile |1 +
 drivers/mfd/mud.c|  580 +++
 drivers/pinctrl/Kconfig  |9 +
 drivers/pinctrl/Makefile |1 +
 drivers/pinctrl/pinctrl-mud.c|  657 
 drivers/pinctrl/pinctrl-mud.h|   89 ++
 drivers/usb/gadget/Kconfig   |   36 +
 drivers/usb/gadget/function/Makefile |6 +
 drivers/usb/gadget/function/f_mud.c  |  913 +
 drivers/usb/gadget/function/f_mud.h  |  210 
 drivers/usb/gadget/function/f_mud_drm.c  |  181 
 drivers/usb/gadget/function/f_mud_pins.c |  962 +
 drivers/usb/gadget/function/mud_regmap.c |  936 +
 include/drm/drm_client.h |4 +
 include/linux/mfd/mud.h  |   16 +
 include/linux/regmap.h   |   23 +
 include/linux/regmap_usb.h   |   97 ++
 31 files changed, 8107 insertions(+), 5 deletions(-)
 create mode 100644 drivers/base/regmap/regmap-usb.c
 create mode 100644 drivers/gpu/drm/mud/Kconfig
 create mode 100644 drivers/gpu/drm/mud/Makefile
 create mode 100644 drivers/gpu/drm/mud/mud_drm.c
 create mode 100644 drivers/gpu/drm/mud/mud_drm.h
 create mode 100644 drivers/gpu/drm/mud/mud_drm_gadget.c
 create mode 100644 drivers/mfd/mud.c
 create mode 100644 drivers/pinctrl/pinctrl-mud.c
 create mode 100644 drivers/pinctrl/pinctrl-mud.h
 create mode 100644 drivers/usb/gadget/function/f_mud.c
 create mode 100644 drivers/usb/gadget/function/f_mud.h
 create mode 100644 drivers/usb/gadget/function/f_mud_drm.c
 create mode 100644 drivers/usb/gadget/function/f_mud_pins.c
 create mode 100644 drivers/usb/gadget/function/mud_regmap.c
 create mode 100644 include/linux/mfd/mud.h
 create mode 100644 include/linux/regmap_usb.h

-- 
2.23.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[RFC 1/9] regmap: Add USB support

2020-02-16 Thread Noralf Trønnes
Add support for regmap over USB for use with the Multifunction USB Device.
Two endpoints IN/OUT are used. Up to 255 regmaps are supported on one USB
interface. The register index width is always 32-bit, but the register
value can be 8, 16 or 32 bits wide. LZ4 compression is supported on bulk
transfers.

Signed-off-by: Noralf Trønnes 
---
 drivers/base/regmap/Kconfig  |8 +-
 drivers/base/regmap/Makefile |1 +
 drivers/base/regmap/regmap-usb.c | 1026 ++
 include/linux/regmap.h   |   23 +
 include/linux/regmap_usb.h   |   97 +++
 5 files changed, 1154 insertions(+), 1 deletion(-)
 create mode 100644 drivers/base/regmap/regmap-usb.c
 create mode 100644 include/linux/regmap_usb.h

diff --git a/drivers/base/regmap/Kconfig b/drivers/base/regmap/Kconfig
index 0fd6f97ee523..6c937c196825 100644
--- a/drivers/base/regmap/Kconfig
+++ b/drivers/base/regmap/Kconfig
@@ -4,7 +4,7 @@
 # subsystems should select the appropriate symbols.
 
 config REGMAP
-   default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_W1 || 
REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ || REGMAP_SCCB || REGMAP_I3C)
+   default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_W1 || 
REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ || REGMAP_SCCB || REGMAP_I3C || 
REGMAP_USB)
select IRQ_DOMAIN if REGMAP_IRQ
bool
 
@@ -53,3 +53,9 @@ config REGMAP_SCCB
 config REGMAP_I3C
tristate
depends on I3C
+
+config REGMAP_USB
+   tristate
+   depends on USB
+   select LZ4_COMPRESS
+   select LZ4_DECOMPRESS
diff --git a/drivers/base/regmap/Makefile b/drivers/base/regmap/Makefile
index ff6c7d8ec1cd..7e6932f100ea 100644
--- a/drivers/base/regmap/Makefile
+++ b/drivers/base/regmap/Makefile
@@ -17,3 +17,4 @@ obj-$(CONFIG_REGMAP_W1) += regmap-w1.o
 obj-$(CONFIG_REGMAP_SOUNDWIRE) += regmap-sdw.o
 obj-$(CONFIG_REGMAP_SCCB) += regmap-sccb.o
 obj-$(CONFIG_REGMAP_I3C) += regmap-i3c.o
+obj-$(CONFIG_REGMAP_USB) += regmap-usb.o
diff --git a/drivers/base/regmap/regmap-usb.c b/drivers/base/regmap/regmap-usb.c
new file mode 100644
index ..bb4f0df44d1d
--- /dev/null
+++ b/drivers/base/regmap/regmap-usb.c
@@ -0,0 +1,1026 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Register map access API - USB support
+ *
+ * Copyright 2020 Noralf Trønnes
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "internal.h"
+
+/**
+ * DOC: overview
+ *
+ * This regmap over USB supports multiple regmaps over a single USB interface.
+ * Two endpoints are needed and the first IN and OUT endpoints are used.
+ * A REGMAP_USB_DT_INTERFACE descriptor request is issued to get the number of
+ * regmaps supported on the interface. A REGMAP_USB_DT_MAP descriptor request 
is
+ * issued to get details about a specific regmap. This is done when
+ * devm_regmap_init_usb() is called to get access to a regmap.
+ *
+ * A regmap transfer begins with the host sending OUT a _usb_header 
which
+ * contains info about the index of the regmap, the register address etc. Next
+ * it does an IN or OUT transfer of the register value(s) depending on if it's 
a
+ * read or write. This transfer can be compressed using lz4 if the device
+ * supports it. Finally a _usb_status IN request is issued to receive 
the
+ * status of the transfer.
+ *
+ * If a transfer fails with the error code -EPIPE, a reset control request
+ * (REGMAP_USB_REQ_PROTOCOL_RESET) is issued. The device should reset it's 
state
+ * machine and return its previous error code if any. The device can halt its
+ * IN/OUT endpoints to force the host to perform a reset if it fails to
+ * understand a transfer.
+ */
+
+/* Provides exclusive interface access */
+struct regmap_usb_interface {
+   struct usb_interface *interface;
+   struct mutex lock; /* Ensures exclusive interface access */
+   unsigned int refcount;
+   struct list_head link;
+
+   u32 tag;
+};
+
+struct regmap_usb_context;
+
+struct regmap_usb_transfer {
+   struct regmap_usb_context *ctx;
+   struct usb_anchor anchor;
+   struct urb *header_urb;
+   struct urb *buf_out_urb;
+   struct urb *buf_in_urb;
+   void *buf;
+   size_t bufsize;
+   struct urb *status_urb;
+   spinlock_t lock; /* Protect dynamic values */
+   u32 tag;
+   int status;
+
+   u8 compression;
+   void *buf_in_dest;
+   unsigned int length;
+   unsigned int actual_length;
+
+   ktime_t start; /* FIXME: Temporary debug/perf aid */
+};
+
+struct regmap_usb_context {
+   struct usb_device *usb;
+   struct regmap_usb_interface *ruif;
+   u8 ifnum;
+   unsigned int in_pipe;
+   unsigned int out_pipe;
+   u16 index;
+   unsigned int val_bytes;
+   void *lz4_comp_mem;
+   u8 compression;
+   unsigned int max_transfer_size;
+   struct regmap_usb_transfer *transfers[2];
+#ifdef 

[RFC 6/9] regmap: Speed up _regmap_raw_write_impl() for large buffers

2020-02-16 Thread Noralf Trønnes
When writing a 3MB buffer the unwritable check in _regmap_raw_write_impl()
adds a ~20ms overhead on a Raspberry Pi 4.
Amend this by avoiding the check if it's not necessary.

Signed-off-by: Noralf Trønnes 
---
 drivers/base/regmap/regmap.c | 10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 19f57ccfbe1d..cd876309a74b 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -1489,10 +1489,12 @@ static int _regmap_raw_write_impl(struct regmap *map, 
unsigned int reg,
WARN_ON(!map->bus);
 
/* Check for unwritable registers before we start */
-   for (i = 0; i < val_len / map->format.val_bytes; i++)
-   if (!regmap_writeable(map,
-reg + regmap_get_offset(map, i)))
-   return -EINVAL;
+   if (map->max_register || map->writeable_reg || map->wr_table) {
+   for (i = 0; i < val_len / map->format.val_bytes; i++)
+   if (!regmap_writeable(map,
+ reg + regmap_get_offset(map, i)))
+   return -EINVAL;
+   }
 
if (!map->cache_bypass && map->format.parse_val) {
unsigned int ival;
-- 
2.23.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH v5 17/52] drm: Add helper to create a connector for a chain of bridges

2020-02-16 Thread Laurent Pinchart
Hi Tomi,

On Tue, Jan 28, 2020 at 01:19:53PM +0200, Tomi Valkeinen wrote:
> On 24/01/2020 05:54, Laurent Pinchart wrote:
> 
> > +struct drm_connector *drm_bridge_connector_init(struct drm_device *drm,
> > +   struct drm_encoder *encoder)
> > +{
> > +   struct drm_bridge_connector *bridge_connector;
> > +   struct drm_connector *connector;
> > +   struct i2c_adapter *ddc = NULL;
> > +   struct drm_bridge *bridge;
> > +   int connector_type;
> > +
> > +   bridge_connector = kzalloc(sizeof(*bridge_connector), GFP_KERNEL);
> > +   if (!bridge_connector)
> > +   return ERR_PTR(-ENOMEM);
> > +
> > +   bridge_connector->encoder = encoder;
> > +
> > +   /*
> > +* TODO: Handle doublescan_allowed, stereo_allowed and
> > +* ycbcr_420_allowed.
> > +*/
> > +   connector = _connector->base;
> > +   connector->interlace_allowed = true;
> > +
> > +   /*
> > +* Initialise connector status handling. First locate the furthest
> > +* bridges in the pipeline that support HPD and output detection. Then
> > +* initialise the connector polling mode, using HPD if available and
> > +* falling back to polling if supported. If neither HPD nor output
> > +* detection are available, we don't support hotplug detection at all.
> > +*/
> > +   connector_type = DRM_MODE_CONNECTOR_Unknown;
> > +   drm_for_each_bridge_in_chain(encoder, bridge) {
> > +   if (bridge->interlace_allowed)
> > +   connector->interlace_allowed = false;
> 
> This doesn't work on Beagle-xM's venc output.
> 
> The above test should be !bridge->interlace_allowed.

I wonder how this passed my tests :-S I'll fix it in v6.

> But that doesn't solve it fully. We have VENC and display-connector as 
> bridges in the beagle's VENC 
> output path. Only VENC is marked as interlace_allowed.
> 
> Setting "conn->bridge.interlace_allowed = true;" in display_connector_probe 
> got the VENC output 
> working. But what's the correct fix here? set interlace_allowed based on 
> connector type?

All the supported connector types (Composite, DVII, HDMIA, SVIDEO and
VGA) support interlaced modes, so I think we can just set the flag
unconditionally.

-- 
Regards,

Laurent Pinchart
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH v5 1/3] dt-bindings: drm/bridge: Document Cadence MHDP bridge bindings.

2020-02-16 Thread Laurent Pinchart
Hi Yuti,

Thank you for the patch.

On Wed, Feb 12, 2020 at 05:26:42AM +0100, Yuti Amonkar wrote:
> Document the bindings used for the Cadence MHDP DPI/DP bridge in
> yaml format.
> 
> Signed-off-by: Yuti Amonkar 
> Reviewed-by: Rob Herring 
> ---
>  .../bindings/display/bridge/cdns,mhdp.yaml| 125 ++
>  1 file changed, 125 insertions(+)
>  create mode 100644 
> Documentation/devicetree/bindings/display/bridge/cdns,mhdp.yaml
> 
> diff --git a/Documentation/devicetree/bindings/display/bridge/cdns,mhdp.yaml 
> b/Documentation/devicetree/bindings/display/bridge/cdns,mhdp.yaml
> new file mode 100644
> index ..e7f84ed1d2da
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/bridge/cdns,mhdp.yaml
> @@ -0,0 +1,125 @@
> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: "http://devicetree.org/schemas/display/bridge/cdns,mhdp.yaml#;
> +$schema: "http://devicetree.org/meta-schemas/core.yaml#;
> +
> +title: Cadence MHDP bridge
> +
> +maintainers:
> +  - Swapnil Jakhade 
> +  - Yuti Amonkar 
> +
> +properties:
> +  compatible:
> +enum:
> +  - cdns,mhdp8546
> +  - ti,j721e-mhdp8546
> +
> +  reg:
> +minItems: 1
> +maxItems: 2
> +items:
> +  - description:
> +  Register block of mhdptx apb registers upto PHY mapped 
> area(AUX_CONFIG_P).
> +  The AUX and PMA registers are mapped to associated phy driver.
> +  - description:
> +  Register block for DSS_EDP0_INTG_CFG_VP registers in case of TI J7 
> SoCs.
> +
> +  reg-names:
> +minItems: 1
> +maxItems: 2
> +items:
> +  - const: mhdptx
> +  - const: j721e-intg
> +
> +  clocks:
> +maxItems: 1
> +description:
> +  DP bridge clock, it's used by the IP to know how to translate a number 
> of
> +  clock cycles into a time (which is used to comply with DP standard 
> timings
> +  and delays).
> +
> +  phys:
> +description: Phandle to the DisplyPort phy.
> +
> +  ports:
> +type: object
> +description:
> +  Ports as described in Documentation/devicetree/bindings/graph.txt
> +
> +properties:
> +  '#address-cells':
> +const: 1
> +
> +  '#size-cells':
> +const: 0
> +
> +  port@0:
> +type: object
> +description:
> +  input port representing the DP bridge input

s/input port/Input port/ and s/bridge input/bridge input./

> +
> +  port@1:
> +type: object
> +description:
> +  output port representing the DP bridge output.

s/output port/Output port/

> +
> +required:
> +  - port@0
> +  - port@1
> +  - '#address-cells'
> +  - '#size-cells'
> +
> +allOf:
> +  - if:
> +  properties:
> +compatible:
> +  contains:
> +const: ti,j721e-mhdp8546
> +then:
> +  properties:
> +reg:
> +  minItems: 2
> +reg-names:
> +  minItems: 2
> +
> +required:
> +  - compatible
> +  - clocks
> +  - reg
> +  - reg-names
> +  - phys
> +  - ports
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +mhdp: dp-bridge@f0fb00 {
> +compatible = "cdns,mhdp8546";
> +reg = <0xf0 0xfb00 0x0 0x100>;
> +reg-names = "mhdptx";
> +clocks = <_clock>;
> +phys = <_phy>;
> +
> +ports {
> +  #address-cells = <1>;
> +  #size-cells = <0>;
> +
> +  port@0 {
> + reg = <0>;
> + dp_bridge_input: endpoint {
> +remote-endpoint = <_dpi_output>;
> + };
> +  };
> +
> +  port@1 {
> + reg = <1>;
> + dp_bridge_output: endpoint {
> +remote-endpoint = <_dp_connector_input>;
> + };
> +  };
> +};
> +};
> +...

Really good bindings ! With the above comments addressed, as well as he
one in reply to Tomi's review,

Reviewed-by: Laurent Pinchart 

-- 
Regards,

Laurent Pinchart
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH v5 1/3] dt-bindings: drm/bridge: Document Cadence MHDP bridge bindings.

2020-02-16 Thread Laurent Pinchart
Hi Yuti,

On Sun, Feb 16, 2020 at 05:28:40PM +0200, Laurent Pinchart wrote:
> On Thu, Feb 13, 2020 at 11:16:51AM +0200, Tomi Valkeinen wrote:
> > On 12/02/2020 06:26, Yuti Amonkar wrote:
> > > Document the bindings used for the Cadence MHDP DPI/DP bridge in
> > > yaml format.
> > > 
> > > Signed-off-by: Yuti Amonkar 
> > > Reviewed-by: Rob Herring 
> > > ---
> > >   .../bindings/display/bridge/cdns,mhdp.yaml| 125 ++
> > >   1 file changed, 125 insertions(+)
> > >   create mode 100644 
> > > Documentation/devicetree/bindings/display/bridge/cdns,mhdp.yaml
> > > 
> > > diff --git 
> > > a/Documentation/devicetree/bindings/display/bridge/cdns,mhdp.yaml 
> > > b/Documentation/devicetree/bindings/display/bridge/cdns,mhdp.yaml
> > > new file mode 100644
> > > index ..e7f84ed1d2da
> > > --- /dev/null
> > > +++ b/Documentation/devicetree/bindings/display/bridge/cdns,mhdp.yaml
> > > @@ -0,0 +1,125 @@
> > > +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> > > +%YAML 1.2
> > > +---
> > > +$id: "http://devicetree.org/schemas/display/bridge/cdns,mhdp.yaml#;
> > > +$schema: "http://devicetree.org/meta-schemas/core.yaml#;
> > > +
> > > +title: Cadence MHDP bridge
> > > +
> > > +maintainers:
> > > +  - Swapnil Jakhade 
> > > +  - Yuti Amonkar 
> > > +
> > > +properties:
> > > +  compatible:
> > > +enum:
> > > +  - cdns,mhdp8546
> > > +  - ti,j721e-mhdp8546
> > > +
> > > +  reg:
> > > +minItems: 1
> > > +maxItems: 2
> > > +items:
> > > +  - description:
> > > +  Register block of mhdptx apb registers upto PHY mapped 
> > > area(AUX_CONFIG_P).
> > 
> > "up to". Add space before (.
> > 
> > > +  The AUX and PMA registers are mapped to associated phy driver.
> 
> I wouldn't mention driver here, as that's a software concept unrelated
> to DT bindings. You could write "The AUX and PMA registers are not part
> of this range, they are instead included in the associated PHY.".
> 
> > > +  - description:
> > > +  Register block for DSS_EDP0_INTG_CFG_VP registers in case of 
> > > TI J7 SoCs.
> > > +
> > > +  reg-names:
> > > +minItems: 1
> > > +maxItems: 2
> > > +items:
> > > +  - const: mhdptx
> > > +  - const: j721e-intg
> > > +
> > > +  clocks:
> > > +maxItems: 1
> > > +description:
> > > +  DP bridge clock, it's used by the IP to know how to translate a 
> > > number of
> 
> s/it's //
> 
> > > +  clock cycles into a time (which is used to comply with DP standard 
> > > timings
> > > +  and delays).
> > > +
> > > +  phys:
> > > +description: Phandle to the DisplyPort phy.
> > 
> > "Display"
> 
> And s/Phandle/phandle/, and s/phy/PHY/.
> 
> Shouldn't this bridge also have port nodes ?

Oops, sorry, I missed that Tomi's reply has removed part of the original
patch. Please disregard this last comment, I'll reply to the original.

-- 
Regards,

Laurent Pinchart
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH v5 1/3] dt-bindings: drm/bridge: Document Cadence MHDP bridge bindings.

2020-02-16 Thread Laurent Pinchart
Hi Yuti,

Thank you for the patch.

On Thu, Feb 13, 2020 at 11:16:51AM +0200, Tomi Valkeinen wrote:
> On 12/02/2020 06:26, Yuti Amonkar wrote:
> > Document the bindings used for the Cadence MHDP DPI/DP bridge in
> > yaml format.
> > 
> > Signed-off-by: Yuti Amonkar 
> > Reviewed-by: Rob Herring 
> > ---
> >   .../bindings/display/bridge/cdns,mhdp.yaml| 125 ++
> >   1 file changed, 125 insertions(+)
> >   create mode 100644 
> > Documentation/devicetree/bindings/display/bridge/cdns,mhdp.yaml
> > 
> > diff --git 
> > a/Documentation/devicetree/bindings/display/bridge/cdns,mhdp.yaml 
> > b/Documentation/devicetree/bindings/display/bridge/cdns,mhdp.yaml
> > new file mode 100644
> > index ..e7f84ed1d2da
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/display/bridge/cdns,mhdp.yaml
> > @@ -0,0 +1,125 @@
> > +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: "http://devicetree.org/schemas/display/bridge/cdns,mhdp.yaml#;
> > +$schema: "http://devicetree.org/meta-schemas/core.yaml#;
> > +
> > +title: Cadence MHDP bridge
> > +
> > +maintainers:
> > +  - Swapnil Jakhade 
> > +  - Yuti Amonkar 
> > +
> > +properties:
> > +  compatible:
> > +enum:
> > +  - cdns,mhdp8546
> > +  - ti,j721e-mhdp8546
> > +
> > +  reg:
> > +minItems: 1
> > +maxItems: 2
> > +items:
> > +  - description:
> > +  Register block of mhdptx apb registers upto PHY mapped 
> > area(AUX_CONFIG_P).
> 
> "up to". Add space before (.
> 
> > +  The AUX and PMA registers are mapped to associated phy driver.

I wouldn't mention driver here, as that's a software concept unrelated
to DT bindings. You could write "The AUX and PMA registers are not part
of this range, they are instead included in the associated PHY.".

> > +  - description:
> > +  Register block for DSS_EDP0_INTG_CFG_VP registers in case of TI 
> > J7 SoCs.
> > +
> > +  reg-names:
> > +minItems: 1
> > +maxItems: 2
> > +items:
> > +  - const: mhdptx
> > +  - const: j721e-intg
> > +
> > +  clocks:
> > +maxItems: 1
> > +description:
> > +  DP bridge clock, it's used by the IP to know how to translate a 
> > number of

s/it's //

> > +  clock cycles into a time (which is used to comply with DP standard 
> > timings
> > +  and delays).
> > +
> > +  phys:
> > +description: Phandle to the DisplyPort phy.
> 
> "Display"

And s/Phandle/phandle/, and s/phy/PHY/.

Shouldn't this bridge also have port nodes ?

-- 
Regards,

Laurent Pinchart
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[Bug 200695] Blank screen on RX 580 with amdgpu.dc=1 enabled (no displays detected)

2020-02-16 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=200695

--- Comment #37 from Adam (magicm...@magicmyth.com) ---
As several comments mention different behavior between the different connector
types I found a spare DVI cable and tried connecting to the same monitor via
that input and it worked! So once logged in I plugged in the HDMI cable and
switched input and it worked just fine (monitor was glitchy at first but once I
disabled DVI output in monitor configuration it worked perfectly). To confirm
this was indeed working with the DC code path I tested audio over HDMI and it
worked just fine (and does not work with DC disabled, as expected). So I
rebooted with both the DVI and HDMI in and the output over HDMI worked all
through boot. I then disconnected the DVI and rebooted and the HDMI continues
to work so far. Unfortunately I don't have a displayport monitor around to test
if that behaves as weirdly. Just to be clear, I had tried to make this monitor
work for a couple weeks over HDMI and the only thing that worked was
amdgpu.dc=0 until I plugged in the DVI connector so this was not a one off
fail.

I forgot to mention before that when the HDMI output was not working with DC my
Xorg logs also showed no monitor detected.

I can attach the two different Xorg logs if that helps?

-- 
You are receiving this mail because:
You are watching the assignee of the bug.
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH v1 1/1] drm: drop unused drm_display_mode.private

2020-02-16 Thread Daniel Vetter
On Sat, Feb 15, 2020 at 9:08 PM Sam Ravnborg  wrote:
>
> Hi Daniel.
>
> > > I also checked private_flags - it is used in a few modules.
> > > And it looked legit.
> > >
> > Iirc i915 used this, before we went full overdrive with entire atomic
> > state structure subclassing :-)
>
> $ git grep -l private_flags
> gma500/psb_intel_drv.h
> i915/display/intel_display.c
> i915/display/intel_display_types.h
> i915/display/intel_tv.c
> i915/display/vlv_dsi.c
> i915/i915_irq.c
> msm/disp/dpu1/dpu_encoder.c
> msm/disp/dpu1/dpu_trace.h <= false hit
>
> i915 still has a few uses of private_flags.
> Likewise msm and gma500
>
> Looks doable to address this, but not on my TODO list.

Oh I meant the private pointer, not the flags stuff. And yeah maybe we
could add this as a todo, at least for i915 and msm. For gma500 first
step would be converting that driver over to atomic, which I don't
think will happen.
-Daniel

>
> Sam
>
> >
> > Reviewed-by: Daniel Vetter 
>
> Thanks - applied.
>
> Sam



-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel