Re: [PATCH v3 1/6] drm/modes: Rewrite the command line parser

2019-04-18 Thread Noralf Trønnes


Den 18.04.2019 14.41, skrev Maxime Ripard:
> From: Maxime Ripard 
> 
> Rewrite the command line parser in order to get away from the state machine
> parsing the video mode lines.
> 
> Hopefully, this will allow to extend it more easily to support named modes
> and / or properties set directly on the command line.
> 
> Signed-off-by: Maxime Ripard 
> ---
>  drivers/gpu/drm/drm_modes.c | 305 +++--
>  1 file changed, 190 insertions(+), 115 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
> index 56f92a0bba62..3f89198f0891 100644
> --- a/drivers/gpu/drm/drm_modes.c
> +++ b/drivers/gpu/drm/drm_modes.c
> @@ -30,6 +30,7 @@
>   * authorization from the copyright holder(s) and author(s).
>   */
>  
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -1405,6 +1406,131 @@ void drm_connector_list_update(struct drm_connector 
> *connector)
>  }
>  EXPORT_SYMBOL(drm_connector_list_update);
>  
> +static int drm_mode_parse_cmdline_bpp(const char *str, char **end_ptr,
> +   struct drm_cmdline_mode *mode)
> +{
> + if (str[0] != '-')
> + return -EINVAL;
> +
> + mode->bpp = simple_strtol(str + 1, end_ptr, 10);

What happens if this is not a number? I didn't find a test for that in
your unit tests. The same goes for _refresh().

> + mode->bpp_specified = true;
> +
> + return 0;
> +}
> +
> +static int drm_mode_parse_cmdline_refresh(const char *str, char **end_ptr,
> +   struct drm_cmdline_mode *mode)
> +{
> + if (str[0] != '@')
> + return -EINVAL;
> +
> + mode->refresh = simple_strtol(str + 1, end_ptr, 10);
> + mode->refresh_specified = true;
> +
> + return 0;
> +}
> +
> +static int drm_mode_parse_cmdline_extra(const char *str, int length,
> + struct drm_connector *connector,
> + struct drm_cmdline_mode *mode)
> +{
> + int i;
> +
> + for (i = 0; i < length; i++) {
> + switch (str[i]) {
> + case 'i':
> + mode->interlace = true;
> + break;
> + case 'm':
> + mode->margins = true;
> + break;
> + case 'D':
> + if (mode->force != DRM_FORCE_UNSPECIFIED)
> + return -EINVAL;
> +
> + if ((connector->connector_type != 
> DRM_MODE_CONNECTOR_DVII) &&
> + (connector->connector_type != 
> DRM_MODE_CONNECTOR_HDMIB))
> + mode->force = DRM_FORCE_ON;
> + else
> + mode->force = DRM_FORCE_ON_DIGITAL;
> + break;
> + case 'd':
> + if (mode->force != DRM_FORCE_UNSPECIFIED)
> + return -EINVAL;
> +
> + mode->force = DRM_FORCE_OFF;
> + break;
> + case 'e':
> + if (mode->force != DRM_FORCE_UNSPECIFIED)
> + return -EINVAL;
> +
> + mode->force = DRM_FORCE_ON;
> + break;
> + default:
> + return -EINVAL;
> + }
> + }
> +
> + return 0;
> +}
> +
> +static int drm_mode_parse_cmdline_res_mode(const char *str, unsigned int 
> length,
> +bool extras,
> +struct drm_connector *connector,
> +struct drm_cmdline_mode *mode)
> +{
> + bool rb = false, cvt = false;
> + int xres = 0, yres = 0;
> + int remaining, i;
> + char *end_ptr;
> +
> + xres = simple_strtol(str, _ptr, 10);
> +
> + if (end_ptr[0] != 'x')

'x600' looks to be a valid resolution here, so I think:
if (str == end_ptr || end_ptr[0] != 'x')

> + return -EINVAL;
> + end_ptr++;
> +
> + yres = simple_strtol(end_ptr, _ptr, 10);
> +
> + remaining = length - (end_ptr - str);
> + if (remaining < 0)
> + return -EINVAL;

Maybe some unit tests: '1024xy' and '1024x', to verify that this does
indeed require a number for yres.

Noralf.

> +
> + for (i = 0; i < remaining; i++) {
> + switch (end_ptr[i]) {
> + case 'M':
> + cvt = true;
> + break;
> + case 'R':
> + rb = true;
> + break;
> + default:
> + /*
> +  * Try to pass that to our extras parsing
> +  * function to handle the case where the
> +  * extras are directly after the resolution
> +  */
> + if (extras) {
> + int ret = drm_mode_parse_cmdline_extra(end_ptr 
> + i,
> 

Re: [PATCH v2 00/12] drm/fb-helper: Move modesetting code to drm_client

2019-04-17 Thread Noralf Trønnes


Den 16.04.2019 10.41, skrev Daniel Vetter:
> On Sun, Apr 07, 2019 at 06:52:31PM +0200, Noralf Trønnes wrote:
>> This moves the modesetting code from drm_fb_helper to drm_client so it
>> can be shared by all internal clients.
>>
>> The main change this time is to attach the modeset array to
>> drm_client_dev and honour the drm_fb_helper MIT license. I've dropped
>> the display abstraction.
>>
>> Noralf.
>>
>> Cc: Emmanuel Vadot 
>>
>> Noralf Trønnes (12):
>>   drm/atomic: Move __drm_atomic_helper_disable_plane/set_config()
>>   drm/fb-helper: Avoid race with DRM userspace
>>   drm/i915/fbdev: Move intel_fb_initial_config() to fbdev helper
>>   drm/fb-helper: No need to cache rotation and sw_rotations
>>   drm/fb-helper: Remove drm_fb_helper_crtc->{x,y,desired_mode}
>>   drm/fb-helper: Remove drm_fb_helper_crtc
>>   drm/fb-helper: Prepare to move out commit code
>>   drm/fb-helper: Move out commit code
>>   drm/fb-helper: Remove drm_fb_helper_connector
>>   drm/fb-helper: Prepare to move out modeset config code
>>   drm/fb-helper: Move out modeset config code
>>   drm/client: Hack: Add bootsplash example
> 
> I like.
> 

Glad you like it, this turned out to be way more work than I first
imagined when I started toying with this generic fbdev emulation idea :-)

> Reviewed some of the prep patches, plus some more suggestions for
> drm_client_modeset api polishing ideas.
> 
> Maxime is working on some other fbdev helper features and your two patch
> series will conflict badly I think. Probably best if you coordinate and
> cross-review for final details and best coordination for merging into
> drm-misc-next.
> 

Yep, I'll coordinate with Maxime.

> I think for the bootsplash good option would be to add it as a todo item,
> with a link to patch of your latest proof of concept.
> 

Sure, I'll make a todo patch when stuff is applied and I know which
patchset is the last.

Noralf.

> Cheers, Daniel
> 
>>
>>  Documentation/gpu/todo.rst   |   10 +
>>  drivers/gpu/drm/Kconfig  |5 +
>>  drivers/gpu/drm/Makefile |3 +-
>>  drivers/gpu/drm/drm_atomic.c |  168 
>>  drivers/gpu/drm/drm_atomic_helper.c  |  164 
>>  drivers/gpu/drm/drm_auth.c   |   20 +
>>  drivers/gpu/drm/drm_bootsplash.c |  359 
>>  drivers/gpu/drm/drm_client.c |   17 +-
>>  drivers/gpu/drm/drm_client_modeset.c | 1086 +++
>>  drivers/gpu/drm/drm_crtc_internal.h  |5 +
>>  drivers/gpu/drm/drm_drv.c|4 +
>>  drivers/gpu/drm/drm_fb_helper.c  | 1195 +++---
>>  drivers/gpu/drm/drm_internal.h   |2 +
>>  drivers/gpu/drm/i915/intel_fbdev.c   |  218 -
>>  include/drm/drm_atomic_helper.h  |4 -
>>  include/drm/drm_client.h |   48 ++
>>  include/drm/drm_fb_helper.h  |  125 +--
>>  17 files changed, 1859 insertions(+), 1574 deletions(-)
>>  create mode 100644 drivers/gpu/drm/drm_bootsplash.c
>>  create mode 100644 drivers/gpu/drm/drm_client_modeset.c
>>
>> -- 
>> 2.20.1
>>
> 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Re: [PATCH v2 08/12] drm/fb-helper: Move out commit code

2019-04-17 Thread Noralf Trønnes


Den 16.04.2019 10.38, skrev Daniel Vetter:
> On Sun, Apr 07, 2019 at 06:52:39PM +0200, Noralf Trønnes wrote:
>> Move the modeset commit code to drm_client_modeset.
>> No changes except exporting API.
>>
>> v2: Move to drm_client_modeset.c instead of drm_client.c
>>
>> Signed-off-by: Noralf Trønnes 
>> ---
>>  drivers/gpu/drm/drm_client_modeset.c | 287 +++



>> -/**
>> - * drm_client_panel_rotation() - Check panel orientation
>> - * @modeset: DRM modeset
>> - * @rotation: Returned rotation value
>> - *
>> - * This function checks if the primary plane in @modeset can hw rotate to 
>> match
>> - * the panel orientation on its connector.
>> - *
>> - * Note: Currently only 0 and 180 degrees are supported.
>> - *
>> - * Return:
>> - * True if the plane can do the rotation, false otherwise.
>> - */
>> -bool drm_client_panel_rotation(struct drm_mode_set *modeset, unsigned int 
>> *rotation)
> 
> Why not static? Doesn't seem to be used by anything outside of
> drm_client_modeset.c.
> 

It is used in drm_fb_helper.c:drm_setup_crtcs_fb() to set up any
rotation and do fbcon sw rotation if necessary. Clients that support
rotation need to call it.

>> -{
>> -struct drm_connector *connector = modeset->connectors[0];
>> -struct drm_plane *plane = modeset->crtc->primary;
>> -u64 valid_mask = 0;
>> -unsigned int i;
>> -
>> -if (!modeset->num_connectors)
>> -return false;
>> -
>> -switch (connector->display_info.panel_orientation) {
>> -case DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP:
>> -*rotation = DRM_MODE_ROTATE_180;
>> -break;
>> -case DRM_MODE_PANEL_ORIENTATION_LEFT_UP:
>> -*rotation = DRM_MODE_ROTATE_90;
>> -break;
>> -case DRM_MODE_PANEL_ORIENTATION_RIGHT_UP:
>> -*rotation = DRM_MODE_ROTATE_270;
>> -break;
>> -default:
>> -*rotation = DRM_MODE_ROTATE_0;
>> -}
>> -
>> -/*
>> - * TODO: support 90 / 270 degree hardware rotation,
>> - * depending on the hardware this may require the framebuffer
>> - * to be in a specific tiling format.
>> - */
>> -if (*rotation != DRM_MODE_ROTATE_180 || !plane->rotation_property)
>> -return false;
>> -
>> -for (i = 0; i < plane->rotation_property->num_values; i++)
>> -valid_mask |= (1ULL << plane->rotation_property->values[i]);
>> -
>> -if (!(*rotation & valid_mask))
>> -return false;
>> -
>> -return true;
>> -}
>> -



>> diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h
>> index 858c8be70870..64b725b318f2 100644
>> --- a/include/drm/drm_client.h
>> +++ b/include/drm/drm_client.h
>> @@ -154,6 +154,10 @@ int drm_client_modeset_create(struct drm_client_dev 
>> *client);
>>  void drm_client_modeset_free(struct drm_client_dev *client);
>>  void drm_client_modeset_release(struct drm_client_dev *client);
>>  struct drm_mode_set *drm_client_find_modeset(struct drm_client_dev *client, 
>> struct drm_crtc *crtc);
>> +bool drm_client_panel_rotation(struct drm_mode_set *modeset, unsigned int 
>> *rotation);
>> +int drm_client_modeset_commit_force(struct drm_client_dev *client);
> 
> I think latest here the _force postfix stopped making sense. It's just a
> commit. Also I'm wondering whether we shouldn't pull the
> master_acquire_internal into these helpers here, there's not really a
> use-case I can think of where we should not check for other masters.
> 

drm_master_internal_acquire() is used in various places in drm_fb_helper
for functions that doesn't make sense to move to drm_client, like:
- drm_fb_helper_setcmap
- drm_fb_helper_ioctl
- drm_fb_helper_pan_display

Noralf.

> Only two kernel modeset requests want to ignore master status:
> - debug enter/leave, which is utterly broken by design (and outright
>   disable for any atomic driver)
> - panic handling, for which we now have a really nice plan, plus first
>   sketches of an implementation.
> 
> Cheers, Daniel
> 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Re: [PATCH v2 4/5] drm/modes: Parse overscan properties

2019-04-17 Thread Noralf Trønnes


Den 17.04.2019 17.30, skrev Noralf Trønnes:
> 
> 
> Den 17.04.2019 16.07, skrev Maxime Ripard:
>> Hi Noralf,
>>
>> On Tue, Apr 16, 2019 at 04:52:20PM +0200, Noralf Trønnes wrote:
>>> Den 11.04.2019 15.22, skrev Maxime Ripard:
>>>> Properly configuring the overscan properties might be needed for the
>>>> initial setup of the framebuffer for display that still have overscan.
>>>> Let's allow for more properties on the kernel command line to setup each
>>>> margin.
>>>>
>>>> Signed-off-by: Maxime Ripard 
>>>> ---
>>>>  drivers/gpu/drm/drm_fb_helper.c | 47 ++-
>>>>  drivers/gpu/drm/drm_modes.c | 44 -
>>>>  include/drm/drm_connector.h |  1 +-
>>>>  3 files changed, 92 insertions(+)
>>>>
>>>> diff --git a/drivers/gpu/drm/drm_fb_helper.c 
>>>> b/drivers/gpu/drm/drm_fb_helper.c
>>>> index 8781897559b2..4e403fe1f451 100644
>>>> --- a/drivers/gpu/drm/drm_fb_helper.c
>>>> +++ b/drivers/gpu/drm/drm_fb_helper.c
>>>> @@ -2567,6 +2567,51 @@ static void drm_setup_crtc_rotation(struct 
>>>> drm_fb_helper *fb_helper,
>>>>fb_helper->sw_rotations |= DRM_MODE_ROTATE_0;
>>>>  }
>>>>
>>>> +static void drm_setup_connector_margins(struct drm_connector *connector)
>>>> +{
>>>> +  struct drm_cmdline_mode *cmdline = >cmdline_mode;
>>>> +  struct drm_modeset_acquire_ctx ctx;
>>>> +  struct drm_atomic_state *state;
>>>> +  struct drm_device *dev = connector->dev;
>>>> +  int ret;
>>>> +
>>>> +  if (!drm_drv_uses_atomic_modeset(dev))
>>>> +  return;
>>>> +
>>>> +  drm_modeset_acquire_init(, 0);
>>>> +
>>>> +  state = drm_atomic_state_alloc(dev);
>>>> +  state->acquire_ctx = 
>>>> +
>>>> +retry:
>>>> +  drm_atomic_set_property(state, >base,
>>>> +  dev->mode_config.tv_left_margin_property,
>>>> +  cmdline->overscan_left);
>>>> +
>>>> +  drm_atomic_set_property(state, >base,
>>>> +  dev->mode_config.tv_right_margin_property,
>>>> +  cmdline->overscan_right);
>>>> +
>>>> +  drm_atomic_set_property(state, >base,
>>>> +  dev->mode_config.tv_top_margin_property,
>>>> +  cmdline->overscan_top);
>>>> +
>>>> +  drm_atomic_set_property(state, >base,
>>>> +  dev->mode_config.tv_bottom_margin_property,
>>>> +  cmdline->overscan_bottom);
>>>> +
>>>> +  ret = drm_atomic_commit(state);
>>>> +  if (ret == -EDEADLK) {
>>>> +  drm_atomic_state_clear(state);
>>>> +  drm_modeset_backoff();
>>>> +  goto retry;
>>>> +  }
>>>> +
>>>> +  drm_atomic_state_put(state);
>>>> +  drm_modeset_drop_locks();
>>>> +  drm_modeset_acquire_fini();
>>>> +}
>>>> +
>>>
>>> Should we set these property values in drm_connector_init()?
>>> I assume that DRM userspace would want to use these values as well.
>>
>> I'm not sure, I've looked into it, and most drivers will create those
>> properties and attached *after* running drm_connector_init.
>>
>> If you're using drm_mode_create_tv_margin_properties, then the first
>> thing it does is to check whether that property has been created
>> already, so we're covered.
>>
>> For drm_connector_attach_tv_margins_properties though, this will force
>> overwrite the value.
>>
>> One thing I'm not really fond of either is that you would do this even
>> if the driver cannot support the margins at all.
>>
>> Maybe we can put this into drm_connector_attach_tv_margins_properties?
>>
> 
> That sounds like a good idea.
> It would leave out these which doesn't use that _attach function though:
> - i2c/ch7006_drv.c
> - i915/intel_tv.c
> 
> Not sure how to handle those. i915 uses the connector state to set the
> initial margins. Can we set the margins on the connector state in
> drm_connector_init() and use those as default values in
> drm_connector_attach_tv_margin_properties()?

Nevermind, that won't work as there's no state yet at that point if I'm
not mistaken.

> 
> Noralf.
> 
>> Maxime
>>
>> --
>> Maxime Ripard, Bootlin
>> Embedded Linux and Kernel engineering
>> https://bootlin.com
>>
> ___
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
> 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Re: [PATCH v2 4/5] drm/modes: Parse overscan properties

2019-04-17 Thread Noralf Trønnes


Den 17.04.2019 16.07, skrev Maxime Ripard:
> Hi Noralf,
> 
> On Tue, Apr 16, 2019 at 04:52:20PM +0200, Noralf Trønnes wrote:
>> Den 11.04.2019 15.22, skrev Maxime Ripard:
>>> Properly configuring the overscan properties might be needed for the
>>> initial setup of the framebuffer for display that still have overscan.
>>> Let's allow for more properties on the kernel command line to setup each
>>> margin.
>>>
>>> Signed-off-by: Maxime Ripard 
>>> ---
>>>  drivers/gpu/drm/drm_fb_helper.c | 47 ++-
>>>  drivers/gpu/drm/drm_modes.c | 44 -
>>>  include/drm/drm_connector.h |  1 +-
>>>  3 files changed, 92 insertions(+)
>>>
>>> diff --git a/drivers/gpu/drm/drm_fb_helper.c 
>>> b/drivers/gpu/drm/drm_fb_helper.c
>>> index 8781897559b2..4e403fe1f451 100644
>>> --- a/drivers/gpu/drm/drm_fb_helper.c
>>> +++ b/drivers/gpu/drm/drm_fb_helper.c
>>> @@ -2567,6 +2567,51 @@ static void drm_setup_crtc_rotation(struct 
>>> drm_fb_helper *fb_helper,
>>> fb_helper->sw_rotations |= DRM_MODE_ROTATE_0;
>>>  }
>>>
>>> +static void drm_setup_connector_margins(struct drm_connector *connector)
>>> +{
>>> +   struct drm_cmdline_mode *cmdline = >cmdline_mode;
>>> +   struct drm_modeset_acquire_ctx ctx;
>>> +   struct drm_atomic_state *state;
>>> +   struct drm_device *dev = connector->dev;
>>> +   int ret;
>>> +
>>> +   if (!drm_drv_uses_atomic_modeset(dev))
>>> +   return;
>>> +
>>> +   drm_modeset_acquire_init(, 0);
>>> +
>>> +   state = drm_atomic_state_alloc(dev);
>>> +   state->acquire_ctx = 
>>> +
>>> +retry:
>>> +   drm_atomic_set_property(state, >base,
>>> +   dev->mode_config.tv_left_margin_property,
>>> +   cmdline->overscan_left);
>>> +
>>> +   drm_atomic_set_property(state, >base,
>>> +   dev->mode_config.tv_right_margin_property,
>>> +   cmdline->overscan_right);
>>> +
>>> +   drm_atomic_set_property(state, >base,
>>> +   dev->mode_config.tv_top_margin_property,
>>> +   cmdline->overscan_top);
>>> +
>>> +   drm_atomic_set_property(state, >base,
>>> +   dev->mode_config.tv_bottom_margin_property,
>>> +   cmdline->overscan_bottom);
>>> +
>>> +   ret = drm_atomic_commit(state);
>>> +   if (ret == -EDEADLK) {
>>> +   drm_atomic_state_clear(state);
>>> +   drm_modeset_backoff();
>>> +   goto retry;
>>> +   }
>>> +
>>> +   drm_atomic_state_put(state);
>>> +   drm_modeset_drop_locks();
>>> +   drm_modeset_acquire_fini();
>>> +}
>>> +
>>
>> Should we set these property values in drm_connector_init()?
>> I assume that DRM userspace would want to use these values as well.
> 
> I'm not sure, I've looked into it, and most drivers will create those
> properties and attached *after* running drm_connector_init.
> 
> If you're using drm_mode_create_tv_margin_properties, then the first
> thing it does is to check whether that property has been created
> already, so we're covered.
> 
> For drm_connector_attach_tv_margins_properties though, this will force
> overwrite the value.
> 
> One thing I'm not really fond of either is that you would do this even
> if the driver cannot support the margins at all.
> 
> Maybe we can put this into drm_connector_attach_tv_margins_properties?
> 

That sounds like a good idea.
It would leave out these which doesn't use that _attach function though:
- i2c/ch7006_drv.c
- i915/intel_tv.c

Not sure how to handle those. i915 uses the connector state to set the
initial margins. Can we set the margins on the connector state in
drm_connector_init() and use those as default values in
drm_connector_attach_tv_margin_properties()?

Noralf.

> Maxime
> 
> --
> Maxime Ripard, Bootlin
> Embedded Linux and Kernel engineering
> https://bootlin.com
> 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Re: [PATCH v2 3/5] drm/modes: Allow to specify rotation and reflection on the commandline

2019-04-17 Thread Noralf Trønnes


Den 17.04.2019 16.30, skrev Maxime Ripard:
> Hi Noralf,
> 
> On Tue, Apr 16, 2019 at 04:50:00PM +0200, Noralf Trønnes wrote:
>> Den 11.04.2019 15.22, skrev Maxime Ripard:
>>> Rotations and reflections setup are needed in some scenarios to initialise
>>> properly the initial framebuffer. Some drivers already had a bunch of
>>> quirks to deal with this, such as either a private kernel command line
>>> parameter (omapdss) or on the device tree (various panels).
>>>
>>> In order to accomodate this, let's create a video mode parameter to deal
>>> with the rotation and reflexion.
>>>
>>> Signed-off-by: Maxime Ripard 
>>> ---
>>>  drivers/gpu/drm/drm_fb_helper.c |   4 +-
>>>  drivers/gpu/drm/drm_modes.c | 110 +++--
>>>  include/drm/drm_connector.h |   1 +-
>>>  3 files changed, 95 insertions(+), 20 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/drm_fb_helper.c 
>>> b/drivers/gpu/drm/drm_fb_helper.c
>>> index b3a5d79436ae..8781897559b2 100644
>>> --- a/drivers/gpu/drm/drm_fb_helper.c
>>> +++ b/drivers/gpu/drm/drm_fb_helper.c
>>> @@ -2521,6 +2521,7 @@ static void drm_setup_crtc_rotation(struct 
>>> drm_fb_helper *fb_helper,
>>> struct drm_connector *connector)
>>>  {
>>> struct drm_plane *plane = fb_crtc->mode_set.crtc->primary;
>>> +   struct drm_cmdline_mode *mode = >cmdline_mode;
>>> uint64_t valid_mask = 0;
>>> int i, rotation;
>>>
>>> @@ -2540,6 +2541,9 @@ static void drm_setup_crtc_rotation(struct 
>>> drm_fb_helper *fb_helper,
>>> rotation = DRM_MODE_ROTATE_0;
>>> }
>>>
>>> +   if (mode->rotation != DRM_MODE_ROTATE_0)
>>> +   fb_crtc->rotation = mode->rotation;
>>> +
>>
>> We already have a property to describe initial display/panel rotation.
>> If we can set connector->display_info.panel_orientation from the video=
>> parameter, then there's no need to modify drm_fb_helper, it will just work.
>>
>> In that case, maybe 'orientation' is a better argument name with values
>> mapped to the enum.
> 
> I wouldn't put it at the same level though. As far as I understand it,
> the orientation is a hardware constraint: the hardware has been
> designed that way, and should honor that orientation to make it look
> with the top, well, on top.
> 
> However, the rotation is more of a user choice, and you could
> definitely envision having a combination of a rotation and an
> orientation constraint.
> 

Does this rotation only apply to the fbdev emulation and should not
propogate to DRM userspace?

I actually don't understand how the DRM plane rotation works for 90/270
rotation. Should the framebuffer width/height be swapped when attaching
to a rotated plane?

Btw drm_setup_crtc_rotation() doesn't support 90/270 plane rotation even
if the hw supports it. It will instead sw rotate fbcon, but fbdev
userspace remains unrotated.

Noralf.

> Maxime
> 
> --
> Maxime Ripard, Bootlin
> Embedded Linux and Kernel engineering
> https://bootlin.com
> 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Re: [PATCH v2 02/12] drm/fb-helper: Avoid race with DRM userspace

2019-04-17 Thread Noralf Trønnes


Den 17.04.2019 15.26, skrev Daniel Vetter:
> On Wed, Apr 17, 2019 at 03:24:00PM +0200, Daniel Vetter wrote:
>> On Tue, Apr 16, 2019 at 08:46:24PM +0200, Noralf Trønnes wrote:
>>>
>>>
>>> Den 16.04.2019 09.59, skrev Daniel Vetter:
>>>> On Sun, Apr 07, 2019 at 06:52:33PM +0200, Noralf Trønnes wrote:
>>>>> drm_fb_helper_is_bound() is used to check if DRM userspace is in control.
>>>>> This is done by looking at the fb on the primary plane. By the time
>>>>> fb-helper gets around to committing, it's possible that the facts have
>>>>> changed.
>>>>>
>>>>> Avoid this race by holding the drm_device->master_mutex lock while
>>>>> committing. When DRM userspace does its first open, it will now wait
>>>>> until fb-helper is done. The helper will stay away if there's a master.
>>>>>
>>>>> Locking rule: Always take the fb-helper lock first.
>>>>>
>>>>> v2:
>>>>> - Remove drm_fb_helper_is_bound() (Daniel Vetter)
>>>>> - No need to check fb_helper->dev->master in
>>>>>   drm_fb_helper_single_fb_probe(), restore_fbdev_mode() has the check.
>>>>>
>>>>> Suggested-by: Daniel Vetter 
>>>>> Signed-off-by: Noralf Trønnes 
>>>>> ---



> Ok, I read the later patches and you already have a commit() and a
> commit_force(). Count me convinced on all points.
> 
> Reviewed-by: Daniel Vetter 
> 
> as-is on this patch.
> 

Thanks. I want to apply this after the for-5.2 cutoff so we can get some
testing on this before it hits the world. I know from the timeline chart
that the cutoff is some time after -rc5, but I don't know _excatly_ when
that is. I looked at dim, but all I could glean from it was that it had
something to do with the state of a -fixes branch.

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

Re: [PATCH v2 02/12] drm/fb-helper: Avoid race with DRM userspace

2019-04-16 Thread Noralf Trønnes


Den 16.04.2019 09.59, skrev Daniel Vetter:
> On Sun, Apr 07, 2019 at 06:52:33PM +0200, Noralf Trønnes wrote:
>> drm_fb_helper_is_bound() is used to check if DRM userspace is in control.
>> This is done by looking at the fb on the primary plane. By the time
>> fb-helper gets around to committing, it's possible that the facts have
>> changed.
>>
>> Avoid this race by holding the drm_device->master_mutex lock while
>> committing. When DRM userspace does its first open, it will now wait
>> until fb-helper is done. The helper will stay away if there's a master.
>>
>> Locking rule: Always take the fb-helper lock first.
>>
>> v2:
>> - Remove drm_fb_helper_is_bound() (Daniel Vetter)
>> - No need to check fb_helper->dev->master in
>>   drm_fb_helper_single_fb_probe(), restore_fbdev_mode() has the check.
>>
>> Suggested-by: Daniel Vetter 
>> Signed-off-by: Noralf Trønnes 
>> ---
>>  drivers/gpu/drm/drm_auth.c  | 20 
>>  drivers/gpu/drm/drm_fb_helper.c | 90 -
>>  drivers/gpu/drm/drm_internal.h  |  2 +
>>  3 files changed, 67 insertions(+), 45 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c
>> index 1669c42c40ed..db199807b7dc 100644
>> --- a/drivers/gpu/drm/drm_auth.c
>> +++ b/drivers/gpu/drm/drm_auth.c
>> @@ -368,3 +368,23 @@ void drm_master_put(struct drm_master **master)
>>  *master = NULL;
>>  }
>>  EXPORT_SYMBOL(drm_master_put);
>> +
>> +/* Used by drm_client and drm_fb_helper */
>> +bool drm_master_internal_acquire(struct drm_device *dev)
>> +{
>> +mutex_lock(>master_mutex);
>> +if (dev->master) {
>> +mutex_unlock(>master_mutex);
>> +return false;
>> +}
>> +
>> +return true;
>> +}
>> +EXPORT_SYMBOL(drm_master_internal_acquire);
>> +
>> +/* Used by drm_client and drm_fb_helper */
>> +void drm_master_internal_release(struct drm_device *dev)
>> +{
>> +mutex_unlock(>master_mutex);
>> +}
>> +EXPORT_SYMBOL(drm_master_internal_release);
>> diff --git a/drivers/gpu/drm/drm_fb_helper.c 
>> b/drivers/gpu/drm/drm_fb_helper.c
>> index 84791dd4a90d..a6be09ae899b 100644
>> --- a/drivers/gpu/drm/drm_fb_helper.c
>> +++ b/drivers/gpu/drm/drm_fb_helper.c
>> @@ -44,6 +44,7 @@
>>  
>>  #include "drm_crtc_internal.h"
>>  #include "drm_crtc_helper_internal.h"
>> +#include "drm_internal.h"
>>  
>>  static bool drm_fbdev_emulation = true;
>>  module_param_named(fbdev_emulation, drm_fbdev_emulation, bool, 0600);
>> @@ -509,7 +510,7 @@ static int restore_fbdev_mode_legacy(struct 
>> drm_fb_helper *fb_helper)
>>  return ret;
>>  }
>>  
>> -static int restore_fbdev_mode(struct drm_fb_helper *fb_helper)
>> +static int restore_fbdev_mode_force(struct drm_fb_helper *fb_helper)
> 
> Bikeshed: usually the function variant that's run with locks already taken
> is called _locked or has a __ prefix. _force feels a bit misplaced.

This isn't a _locked function in the usual sense, it is: apply modeset
even if there is a DRM master. So we are _forcing a modeset on a
possibly unexpecting DRM userspace. To me a _locked function would imply
that the caller _must_ take a lock in order to use it.

But no big deal, I can rename it _locked if that reads better. After a
few years of reading kernel code I've come to appreciate the consistency
in how things are done and named. Every time things are different it
slows down my internal logic/pattern parser.

>>  {
>>  struct drm_device *dev = fb_helper->dev;
>>  
>> @@ -519,6 +520,21 @@ static int restore_fbdev_mode(struct drm_fb_helper 
>> *fb_helper)
>>  return restore_fbdev_mode_legacy(fb_helper);
>>  }
>>  
>> +static int restore_fbdev_mode(struct drm_fb_helper *fb_helper)
>> +{
>> +struct drm_device *dev = fb_helper->dev;
>> +int ret;
>> +
>> +if (!drm_master_internal_acquire(dev))
>> +return -EBUSY;
>> +
>> +ret = restore_fbdev_mode_force(fb_helper);
>> +
>> +drm_master_internal_release(dev);
>> +
>> +return ret;
>> +}
>> +
>>  /**
>>   * drm_fb_helper_restore_fbdev_mode_unlocked - restore fbdev configuration
>>   * @fb_helper: driver-allocated fbdev helper, can be NULL
>> @@ -556,34 +572,6 @@ int drm_fb_helper_restore_fbdev_mode_unlocked(struct 
>> drm_fb_helper *fb_helper)
>>  }
>>  EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode_

Re: [PATCH v2 09/12] drm/fb-helper: Remove drm_fb_helper_connector

2019-04-16 Thread Noralf Trønnes


Den 16.04.2019 11.42, skrev Maxime Ripard:
> Hi,
> 
> On Sun, Apr 07, 2019 at 06:52:40PM +0200, Noralf Trønnes wrote:
>> All drivers add all their connectors so there's no need to keep around an
>> array of available connectors.
>>
>> Rename functions which signature is changed since they will be moved to
>> drm_client in a later patch.
>>
>> Signed-off-by: Noralf Trønnes 
> 
> The patch itself looks fine in itself, but I was planning on using
> connector_info to store the connector properties set on the kernel
> command line as part of video=
> 
> Where should we put them now?
> 

I don't follow you here. Where do you see the conflict?

Noralf.

> Maxime
> 
> --
> Maxime Ripard, Bootlin
> Embedded Linux and Kernel engineering
> https://bootlin.com
> 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Re: [PATCH v2 4/5] drm/modes: Parse overscan properties

2019-04-16 Thread Noralf Trønnes


Den 11.04.2019 15.22, skrev Maxime Ripard:
> Properly configuring the overscan properties might be needed for the
> initial setup of the framebuffer for display that still have overscan.
> Let's allow for more properties on the kernel command line to setup each
> margin.
> 
> Signed-off-by: Maxime Ripard 
> ---
>  drivers/gpu/drm/drm_fb_helper.c | 47 ++-
>  drivers/gpu/drm/drm_modes.c | 44 -
>  include/drm/drm_connector.h |  1 +-
>  3 files changed, 92 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
> index 8781897559b2..4e403fe1f451 100644
> --- a/drivers/gpu/drm/drm_fb_helper.c
> +++ b/drivers/gpu/drm/drm_fb_helper.c
> @@ -2567,6 +2567,51 @@ static void drm_setup_crtc_rotation(struct 
> drm_fb_helper *fb_helper,
>   fb_helper->sw_rotations |= DRM_MODE_ROTATE_0;
>  }
>  
> +static void drm_setup_connector_margins(struct drm_connector *connector)
> +{
> + struct drm_cmdline_mode *cmdline = >cmdline_mode;
> + struct drm_modeset_acquire_ctx ctx;
> + struct drm_atomic_state *state;
> + struct drm_device *dev = connector->dev;
> + int ret;
> +
> + if (!drm_drv_uses_atomic_modeset(dev))
> + return;
> +
> + drm_modeset_acquire_init(, 0);
> +
> + state = drm_atomic_state_alloc(dev);
> + state->acquire_ctx = 
> +
> +retry:
> + drm_atomic_set_property(state, >base,
> + dev->mode_config.tv_left_margin_property,
> + cmdline->overscan_left);
> +
> + drm_atomic_set_property(state, >base,
> + dev->mode_config.tv_right_margin_property,
> + cmdline->overscan_right);
> +
> + drm_atomic_set_property(state, >base,
> + dev->mode_config.tv_top_margin_property,
> + cmdline->overscan_top);
> +
> + drm_atomic_set_property(state, >base,
> + dev->mode_config.tv_bottom_margin_property,
> + cmdline->overscan_bottom);
> +
> + ret = drm_atomic_commit(state);
> + if (ret == -EDEADLK) {
> + drm_atomic_state_clear(state);
> + drm_modeset_backoff();
> + goto retry;
> + }
> +
> + drm_atomic_state_put(state);
> + drm_modeset_drop_locks();
> + drm_modeset_acquire_fini();
> +}
> +

Should we set these property values in drm_connector_init()?
I assume that DRM userspace would want to use these values as well.

Noralf.

>  static void drm_setup_crtcs(struct drm_fb_helper *fb_helper,
>   u32 width, u32 height)
>  {
> @@ -2680,6 +2725,8 @@ static void drm_setup_crtcs_fb(struct drm_fb_helper 
> *fb_helper)
>   struct drm_connector *connector =
>   fb_helper->connector_info[i]->connector;
>  
> + drm_setup_connector_margins(connector);
> +
>   /* use first connected connector for the physical dimensions */
>   if (connector->status == connector_status_connected) {
>   info->var.width = connector->display_info.width_mm;
> diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
> index ac8d70b92b62..493ba3ccde70 100644
> --- a/drivers/gpu/drm/drm_modes.c
> +++ b/drivers/gpu/drm/drm_modes.c
> @@ -1586,6 +1586,50 @@ static int drm_mode_parse_cmdline_options(char *str, 
> size_t len,
>   } else if (!strncmp(option, "reflect_y", delim - option)) {
>   rotation |= DRM_MODE_REFLECT_Y;
>   sep = delim;
> + } else if (!strncmp(option, "overscan_right", delim - option)) {
> + const char *value = delim + 1;
> + unsigned int margin;
> +
> + margin = simple_strtol(value, , 10);
> +
> + /* Make sure we have parsed something */
> + if (sep == value)
> + return -EINVAL;
> +
> + mode->overscan_right = margin;
> + } else if (!strncmp(option, "overscan_left", delim - option)) {
> + const char *value = delim + 1;
> + unsigned int margin;
> +
> + margin = simple_strtol(value, , 10);
> +
> + /* Make sure we have parsed something */
> + if (sep == value)
> + return -EINVAL;
> +
> + mode->overscan_left = margin;
> + } else if (!strncmp(option, "overscan_top", delim - option)) {
> + const char *value = delim + 1;
> + unsigned int margin;
> +
> + margin = simple_strtol(value, , 10);
> +
> + /* Make sure we have parsed something */
> + if (sep == value)
> + return 

Re: [PATCH v2 3/5] drm/modes: Allow to specify rotation and reflection on the commandline

2019-04-16 Thread Noralf Trønnes


Den 11.04.2019 15.22, skrev Maxime Ripard:
> Rotations and reflections setup are needed in some scenarios to initialise
> properly the initial framebuffer. Some drivers already had a bunch of
> quirks to deal with this, such as either a private kernel command line
> parameter (omapdss) or on the device tree (various panels).
> 
> In order to accomodate this, let's create a video mode parameter to deal
> with the rotation and reflexion.
> 
> Signed-off-by: Maxime Ripard 
> ---
>  drivers/gpu/drm/drm_fb_helper.c |   4 +-
>  drivers/gpu/drm/drm_modes.c | 110 +++--
>  include/drm/drm_connector.h |   1 +-
>  3 files changed, 95 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
> index b3a5d79436ae..8781897559b2 100644
> --- a/drivers/gpu/drm/drm_fb_helper.c
> +++ b/drivers/gpu/drm/drm_fb_helper.c
> @@ -2521,6 +2521,7 @@ static void drm_setup_crtc_rotation(struct 
> drm_fb_helper *fb_helper,
>   struct drm_connector *connector)
>  {
>   struct drm_plane *plane = fb_crtc->mode_set.crtc->primary;
> + struct drm_cmdline_mode *mode = >cmdline_mode;
>   uint64_t valid_mask = 0;
>   int i, rotation;
>  
> @@ -2540,6 +2541,9 @@ static void drm_setup_crtc_rotation(struct 
> drm_fb_helper *fb_helper,
>   rotation = DRM_MODE_ROTATE_0;
>   }
>  
> + if (mode->rotation != DRM_MODE_ROTATE_0)
> + fb_crtc->rotation = mode->rotation;
> +

We already have a property to describe initial display/panel rotation.
If we can set connector->display_info.panel_orientation from the video=
parameter, then there's no need to modify drm_fb_helper, it will just work.

In that case, maybe 'orientation' is a better argument name with values
mapped to the enum.

And further, should we add the property
(drm_connector_init_panel_orientation_property()) so DRM userspace can
know about it to?

Some pointers:
- 8d70f395e6cb ("drm: Add support for a panel-orientation connector
property")
- 8f0cb418393b ("drm/fb-helper: Apply panel orientation connector prop
to the primary plane")
- drivers/gpu/drm/drm_panel_orientation_quirks.c

Noralf.

>   /*
>* TODO: support 90 / 270 degree hardware rotation,
>* depending on the hardware this may require the framebuffer
> diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
> index 9613c1a28487..ac8d70b92b62 100644
> --- a/drivers/gpu/drm/drm_modes.c
> +++ b/drivers/gpu/drm/drm_modes.c
> @@ -1531,6 +1531,71 @@ static int drm_mode_parse_cmdline_res_mode(const char 
> *str, unsigned int length,
>   return 0;
>  }
>  
> +static int drm_mode_parse_cmdline_options(char *str, size_t len,
> +   struct drm_connector *connector,
> +   struct drm_cmdline_mode *mode)
> +{
> + unsigned int rotation = 0;
> + char *sep = str;
> +
> + while ((sep = strchr(sep, ','))) {
> + char *delim, *option;
> +
> + option = sep + 1;
> + delim = strchr(option, '=');
> + if (!delim) {
> + delim = strchr(option, ',');
> +
> + if (!delim)
> + delim = str + len;
> + }
> +
> + if (!strncmp(option, "rotate", delim - option)) {
> + const char *value = delim + 1;
> + unsigned int deg;
> +
> + deg = simple_strtol(value, , 10);
> +
> + /* Make sure we have parsed something */
> + if (sep == value)
> + return -EINVAL;
> +
> + switch (deg) {
> + case 0:
> + rotation |= DRM_MODE_ROTATE_0;
> + break;
> +
> + case 90:
> + rotation |= DRM_MODE_ROTATE_90;
> + break;
> +
> + case 180:
> + rotation |= DRM_MODE_ROTATE_180;
> + break;
> +
> + case 270:
> + rotation |= DRM_MODE_ROTATE_270;
> + break;
> +
> + default:
> + return -EINVAL;
> + }
> + } else if (!strncmp(option, "reflect_x", delim - option)) {
> + rotation |= DRM_MODE_REFLECT_X;
> + sep = delim;
> + } else if (!strncmp(option, "reflect_y", delim - option)) {
> + rotation |= DRM_MODE_REFLECT_Y;
> + sep = delim;
> + } else {
> + return -EINVAL;
> + }
> + }
> +
> + mode->rotation = rotation;
> +
> + return 0;
> +}
> +
>  /**
>   * drm_mode_parse_command_line_for_connector - parse command line 

[PATCH v5 4/4] drm/tinydrm: Remove chunk splitting in tinydrm_spi_transfer

2019-04-13 Thread Noralf Trønnes
From: Meghana Madhyastha 

Remove chunk splitting in tinydrm_spi_transfer in tinydrm-helpers as
spi-bcm2835 now can handle large buffers using DMA, automatic byte
swapping in tinydrm_spi_transfer as it doesn't have users.

Remove the spi_max module argument that now has lost its cause.

The 16kB buffer size for Type C Option 1 (9-bit) interface is somewhat
arbitrary, but a bigger buffer will have a miniscule impact on transfer
speed, so it's probably fine.

Signed-off-by: Meghana Madhyastha 
Signed-off-by: Noralf Trønnes 
---
 .../gpu/drm/tinydrm/core/tinydrm-helpers.c| 83 ++-
 drivers/gpu/drm/tinydrm/mipi-dbi.c| 10 +--
 2 files changed, 7 insertions(+), 86 deletions(-)

diff --git a/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c 
b/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c
index 6d540d93758f..a32dc859a9c1 100644
--- a/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c
+++ b/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c
@@ -22,41 +22,8 @@
 #include 
 #include 
 
-static unsigned int spi_max;
-module_param(spi_max, uint, 0400);
-MODULE_PARM_DESC(spi_max, "Set a lower SPI max transfer size");
-
 #if IS_ENABLED(CONFIG_SPI)
 
-/**
- * tinydrm_spi_max_transfer_size - Determine max SPI transfer size
- * @spi: SPI device
- * @max_len: Maximum buffer size needed (optional)
- *
- * This function returns the maximum size to use for SPI transfers. It checks
- * the SPI master, the optional @max_len and the module parameter spi_max and
- * returns the smallest.
- *
- * Returns:
- * Maximum size for SPI transfers
- */
-size_t tinydrm_spi_max_transfer_size(struct spi_device *spi, size_t max_len)
-{
-   size_t ret;
-
-   ret = min(spi_max_transfer_size(spi), spi->master->max_dma_len);
-   if (max_len)
-   ret = min(ret, max_len);
-   if (spi_max)
-   ret = min_t(size_t, ret, spi_max);
-   ret &= ~0x3;
-   if (ret < 4)
-   ret = 4;
-
-   return ret;
-}
-EXPORT_SYMBOL(tinydrm_spi_max_transfer_size);
-
 /**
  * tinydrm_spi_bpw_supported - Check if bits per word is supported
  * @spi: SPI device
@@ -147,62 +114,22 @@ int tinydrm_spi_transfer(struct spi_device *spi, u32 
speed_hz,
struct spi_transfer tr = {
.bits_per_word = bpw,
.speed_hz = speed_hz,
+   .tx_buf = buf,
+   .len = len
};
struct spi_message m;
-   u16 *swap_buf = NULL;
-   size_t max_chunk;
-   size_t chunk;
-   int ret = 0;
-
-   if (WARN_ON_ONCE(bpw != 8 && bpw != 16))
-   return -EINVAL;
-
-   max_chunk = tinydrm_spi_max_transfer_size(spi, 0);
 
if (drm_debug & DRM_UT_DRIVER)
-   pr_debug("[drm:%s] bpw=%u, max_chunk=%zu, transfers:\n",
-__func__, bpw, max_chunk);
-
-   if (bpw == 16 && !tinydrm_spi_bpw_supported(spi, 16)) {
-   tr.bits_per_word = 8;
-   if (tinydrm_machine_little_endian()) {
-   swap_buf = kmalloc(min(len, max_chunk), GFP_KERNEL);
-   if (!swap_buf)
-   return -ENOMEM;
-   }
-   }
+   pr_debug("[drm:%s] bpw=%u, transfers:\n", __func__, bpw);
 
spi_message_init();
if (header)
spi_message_add_tail(header, );
spi_message_add_tail(, );
 
-   while (len) {
-   chunk = min(len, max_chunk);
+   tinydrm_dbg_spi_message(spi, );
 
-   tr.tx_buf = buf;
-   tr.len = chunk;
-
-   if (swap_buf) {
-   const u16 *buf16 = buf;
-   unsigned int i;
-
-   for (i = 0; i < chunk / 2; i++)
-   swap_buf[i] = swab16(buf16[i]);
-
-   tr.tx_buf = swap_buf;
-   }
-
-   buf += chunk;
-   len -= chunk;
-
-   tinydrm_dbg_spi_message(spi, );
-   ret = spi_sync(spi, );
-   if (ret)
-   return ret;
-   }
-
-   return 0;
+   return spi_sync(spi, );
 }
 EXPORT_SYMBOL(tinydrm_spi_transfer);
 
diff --git a/drivers/gpu/drm/tinydrm/mipi-dbi.c 
b/drivers/gpu/drm/tinydrm/mipi-dbi.c
index 85761b4abb83..0bcf6c764893 100644
--- a/drivers/gpu/drm/tinydrm/mipi-dbi.c
+++ b/drivers/gpu/drm/tinydrm/mipi-dbi.c
@@ -975,15 +975,9 @@ static int mipi_dbi_typec3_command(struct mipi_dbi *mipi, 
u8 *cmd,
 int mipi_dbi_spi_init(struct spi_device *spi, struct mipi_dbi *mipi,
  struct gpio_desc *dc)
 {
-   size_t tx_size = tinydrm_spi_max_transfer_size(spi, 0);
struct device *dev = >dev;
int ret;
 
-   if (tx_size < 16) {
-   DRM_ERROR("SPI transmit buffer too small: %zu\n", tx_size);
-   return -EINVAL;
-   }
-
/*
 * Even though it's not th

[PATCH v5 2/4] spi: Release spi_res after finalizing message

2019-04-13 Thread Noralf Trønnes
spi_split_transfers_maxsize() can be used to split a transfer. This
function uses spi_res to lifetime manage the added transfer structures.
So in order to finalize the current message while it contains the split
transfers, spi_res_release() must be called after finalizing.

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

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 05875e63be43..35939ffdeebe 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -1162,10 +1162,10 @@ static int spi_transfer_one_message(struct 
spi_controller *ctlr,
if (msg->status && ctlr->handle_err)
ctlr->handle_err(ctlr, msg);
 
-   spi_res_release(ctlr, msg);
-
spi_finalize_current_message(ctlr);
 
+   spi_res_release(ctlr, msg);
+
return ret;
 }
 
-- 
2.20.1

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

[PATCH v5 3/4] spi/spi-bcm2835: Split transfers that exceed DLEN

2019-04-13 Thread Noralf Trønnes
From: Meghana Madhyastha 

Split spi transfers into chunks of <=65532 to enable the driver to
perform DMA transfer on big buffers. The DLEN register specifies the
number of bytes to transfer in DMA mode. It is 16-bit wide and thus the
maximum DMA transfer is 65535 bytes. Set the maximum to 65532 (4 byte
aligned) since the FIFO in DMA mode is accessed in 4 byte chunks.

->max_dma_len is the value the spi core uses when splitting the buffer
into scatter gather entries.
The BCM2835 DMA block has 2 types of channels/engines:
- Normal: Max length: 1G
- Lite: Max length: 65535

Even when using a Lite channel we will not exceed the max length, so
let's drop setting ->max_dma_len.

Signed-off-by: Meghana Madhyastha 
Signed-off-by: Noralf Trønnes 
---
 drivers/spi/spi-bcm2835.c | 39 +++
 1 file changed, 11 insertions(+), 28 deletions(-)

diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c
index 35aebdfd3b4e..8aa22713c483 100644
--- a/drivers/spi/spi-bcm2835.c
+++ b/drivers/spi/spi-bcm2835.c
@@ -335,20 +335,6 @@ static int bcm2835_spi_transfer_one_irq(struct spi_master 
*master,
return 1;
 }
 
-/*
- * DMA support
- *
- * this implementation has currently a few issues in so far as it does
- * not work arrount limitations of the HW.
- *
- * the main one being that DMA transfers are limited to 16 bit
- * (so 0 to 65535 bytes) by the SPI HW due to BCM2835_SPI_DLEN
- *
- * there may be a few more border-cases we may need to address as well
- * but unfortunately this would mean splitting up the scatter-gather
- * list making it slightly unpractical...
- */
-
 /**
  * bcm2835_spi_transfer_prologue() - transfer first few bytes without DMA
  * @master: SPI master
@@ -630,19 +616,6 @@ static bool bcm2835_spi_can_dma(struct spi_master *master,
if (tfr->len < BCM2835_SPI_DMA_MIN_LENGTH)
return false;
 
-   /* BCM2835_SPI_DLEN has defined a max transfer size as
-* 16 bit, so max is 65535
-* we can revisit this by using an alternative transfer
-* method - ideally this would get done without any more
-* interaction...
-*/
-   if (tfr->len > 65535) {
-   dev_warn_once(>dev,
- "transfer size of %d too big for dma-transfer\n",
- tfr->len);
-   return false;
-   }
-
/* return OK */
return true;
 }
@@ -707,7 +680,6 @@ static void bcm2835_dma_init(struct spi_master *master, 
struct device *dev)
 
/* all went well, so set can_dma */
master->can_dma = bcm2835_spi_can_dma;
-   master->max_dma_len = 65535; /* limitation by BCM2835_SPI_DLEN */
/* need to do TX AND RX DMA, so we need dummy buffers */
master->flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX;
 
@@ -844,6 +816,17 @@ static int bcm2835_spi_prepare_message(struct spi_master 
*master,
struct spi_device *spi = msg->spi;
struct bcm2835_spi *bs = spi_master_get_devdata(master);
u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS);
+   int ret;
+
+   /*
+* DMA transfers are limited to 16 bit (0 to 65535 bytes) by the SPI HW
+* due to DLEN. Split up transfers (32-bit FIFO aligned) if the limit is
+* exceeded.
+*/
+   ret = spi_split_transfers_maxsize(master, msg, 65532,
+ GFP_KERNEL | GFP_DMA);
+   if (ret)
+   return ret;
 
cs &= ~(BCM2835_SPI_CS_CPOL | BCM2835_SPI_CS_CPHA);
 
-- 
2.20.1

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

[PATCH v5 0/4] Chunk splitting of spi transfers

2019-04-13 Thread Noralf Trønnes
spi-bcm2835 has a ~64kB upper limit on DMA transfers. Drivers in
drivers/gpu/drm/tinydrm work around this limitation by splitting the
buffer into multiple transfers. This patchset lifts this driver
limitation by splitting affected transfers using
spi_split_transfers_maxsize().

Based on the feedback on the previous version, I now understand that
->max_dma_len is used to make scatter gather entries that the DMA engine
can handle. For a BCM2835 Lite DMA channel this is 65535 bytes, the same
limitation that the SPI block has on the combined DMA transfer length
through its DLEN register. The SPI block in DMA mode accesses the FIFO 4
bytes at a time, so the aligned maximum length is thus 65532 bytes.

Since this is a BCM2835 SPI block limitation and not a common DMA
limitation that drivers face, I've moved the splitting to the driver.

I also found out why buffer unmapping happened on the original transfer
instead of the split one. spi_res_release() restored the original
transfer before the message was finalized. AFAICT reordering this
shouldn't cause any problems.

Noralf.

Meghana Madhyastha (2):
  spi/spi-bcm2835: Split transfers that exceed DLEN
  drm/tinydrm: Remove chunk splitting in tinydrm_spi_transfer

Noralf Trønnes (2):
  spi: Remove warning in spi_split_transfers_maxsize()
  spi: Release spi_res after finalizing message

 .../gpu/drm/tinydrm/core/tinydrm-helpers.c| 83 ++-
 drivers/gpu/drm/tinydrm/mipi-dbi.c| 10 +--
 drivers/spi/spi-bcm2835.c | 39 +++--
 drivers/spi/spi.c |  9 +-
 4 files changed, 20 insertions(+), 121 deletions(-)

-- 
2.20.1

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

[PATCH v5 1/4] spi: Remove warning in spi_split_transfers_maxsize()

2019-04-13 Thread Noralf Trønnes
Don't warn about splitting transfers, the info is available in the
statistics if needed.

Signed-off-by: Noralf Trønnes 
---
 drivers/spi/spi.c | 5 -
 1 file changed, 5 deletions(-)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 9a7def7c3237..05875e63be43 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -2692,11 +2692,6 @@ static int __spi_split_transfer_maxsize(struct 
spi_controller *ctlr,
size_t offset;
size_t count, i;
 
-   /* warn once about this fact that we are splitting a transfer */
-   dev_warn_once(>spi->dev,
- "spi_transfer of length %i exceed max length of %zu - 
needed to split transfers\n",
- xfer->len, maxsize);
-
/* calculate how many we have to replace */
count = DIV_ROUND_UP(xfer->len, maxsize);
 
-- 
2.20.1

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

[PATCH 1/2] spi: Add spi_is_bpw_supported()

2019-04-12 Thread Noralf Trønnes
This let SPI clients check if the controller supports a particular word
width. drivers/gpu/drm/tinydrm/mipi-dbi.c will use this to determine if
the controller supports 16-bit for RGB565 pixels. If it doesn't it will
swap the bytes before transfer on little endian machines.

Signed-off-by: Noralf Trønnes 
---
 include/linux/spi/spi.h | 20 
 1 file changed, 20 insertions(+)

diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 662b336aa2e4..b30e3d13a5ac 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -983,6 +983,26 @@ spi_max_transfer_size(struct spi_device *spi)
return min(tr_max, msg_max);
 }
 
+/**
+ * spi_is_bpw_supported - Check if bits per word is supported
+ * @spi: SPI device
+ * @bpw: Bits per word
+ *
+ * This function checks to see if the SPI controller supports @bpw.
+ *
+ * Returns:
+ * True if @bpw is supported, false otherwise.
+ */
+static inline bool spi_is_bpw_supported(struct spi_device *spi, u32 bpw)
+{
+   u32 bpw_mask = spi->master->bits_per_word_mask;
+
+   if (bpw == 8 || (bpw <= 32 && bpw_mask & SPI_BPW_MASK(bpw)))
+   return true;
+
+   return false;
+}
+
 /*---*/
 
 /* SPI transfer replacement methods which make use of spi_res */
-- 
2.20.1

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

[PATCH 2/2] drm/tinydrm: Use spi_is_bpw_supported()

2019-04-12 Thread Noralf Trønnes
This means that tinydrm_spi_bpw_supported() can be removed.

Signed-off-by: Noralf Trønnes 
---
 .../gpu/drm/tinydrm/core/tinydrm-helpers.c| 32 +--
 drivers/gpu/drm/tinydrm/mipi-dbi.c|  5 ++-
 include/drm/tinydrm/tinydrm-helpers.h |  1 -
 3 files changed, 3 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c 
b/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c
index 6d540d93758f..a2b24b5680ba 100644
--- a/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c
+++ b/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c
@@ -57,36 +57,6 @@ size_t tinydrm_spi_max_transfer_size(struct spi_device *spi, 
size_t max_len)
 }
 EXPORT_SYMBOL(tinydrm_spi_max_transfer_size);
 
-/**
- * tinydrm_spi_bpw_supported - Check if bits per word is supported
- * @spi: SPI device
- * @bpw: Bits per word
- *
- * This function checks to see if the SPI master driver supports @bpw.
- *
- * Returns:
- * True if @bpw is supported, false otherwise.
- */
-bool tinydrm_spi_bpw_supported(struct spi_device *spi, u8 bpw)
-{
-   u32 bpw_mask = spi->master->bits_per_word_mask;
-
-   if (bpw == 8)
-   return true;
-
-   if (!bpw_mask) {
-   dev_warn_once(>dev,
- "bits_per_word_mask not set, assume 8-bit 
only\n");
-   return false;
-   }
-
-   if (bpw_mask & SPI_BPW_MASK(bpw))
-   return true;
-
-   return false;
-}
-EXPORT_SYMBOL(tinydrm_spi_bpw_supported);
-
 static void
 tinydrm_dbg_spi_print(struct spi_device *spi, struct spi_transfer *tr,
  const void *buf, int idx, bool tx)
@@ -163,7 +133,7 @@ int tinydrm_spi_transfer(struct spi_device *spi, u32 
speed_hz,
pr_debug("[drm:%s] bpw=%u, max_chunk=%zu, transfers:\n",
 __func__, bpw, max_chunk);
 
-   if (bpw == 16 && !tinydrm_spi_bpw_supported(spi, 16)) {
+   if (bpw == 16 && !spi_is_bpw_supported(spi, 16)) {
tr.bits_per_word = 8;
if (tinydrm_machine_little_endian()) {
swap_buf = kmalloc(min(len, max_chunk), GFP_KERNEL);
diff --git a/drivers/gpu/drm/tinydrm/mipi-dbi.c 
b/drivers/gpu/drm/tinydrm/mipi-dbi.c
index 85761b4abb83..534b16926bee 100644
--- a/drivers/gpu/drm/tinydrm/mipi-dbi.c
+++ b/drivers/gpu/drm/tinydrm/mipi-dbi.c
@@ -787,7 +787,7 @@ static int mipi_dbi_spi1_transfer(struct mipi_dbi *mipi, 
int dc,
u16 *dst16;
int ret;
 
-   if (!tinydrm_spi_bpw_supported(spi, 9))
+   if (!spi_is_bpw_supported(spi, 9))
return mipi_dbi_spi1e_transfer(mipi, dc, buf, len, bpw);
 
tr.speed_hz = mipi_dbi_spi_cmd_max_speed(spi, len);
@@ -1008,8 +1008,7 @@ int mipi_dbi_spi_init(struct spi_device *spi, struct 
mipi_dbi *mipi,
if (dc) {
mipi->command = mipi_dbi_typec3_command;
mipi->dc = dc;
-   if (tinydrm_machine_little_endian() &&
-   !tinydrm_spi_bpw_supported(spi, 16))
+   if (tinydrm_machine_little_endian() && 
!spi_is_bpw_supported(spi, 16))
mipi->swap_bytes = true;
} else {
mipi->command = mipi_dbi_typec1_command;
diff --git a/include/drm/tinydrm/tinydrm-helpers.h 
b/include/drm/tinydrm/tinydrm-helpers.h
index 7d259acb8826..a35a78e7b109 100644
--- a/include/drm/tinydrm/tinydrm-helpers.h
+++ b/include/drm/tinydrm/tinydrm-helpers.h
@@ -47,7 +47,6 @@ int tinydrm_display_pipe_init(struct drm_device *drm,
  unsigned int rotation);
 
 size_t tinydrm_spi_max_transfer_size(struct spi_device *spi, size_t max_len);
-bool tinydrm_spi_bpw_supported(struct spi_device *spi, u8 bpw);
 int tinydrm_spi_transfer(struct spi_device *spi, u32 speed_hz,
 struct spi_transfer *header, u8 bpw, const void *buf,
 size_t len);
-- 
2.20.1

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

Re: [PATCH v4 2/4] spi: Split spi message into max_dma_len size chunks

2019-04-11 Thread Noralf Trønnes


Den 11.04.2019 20.18, skrev Lukas Wunner:
> On Thu, Apr 11, 2019 at 06:42:33PM +0200, Noralf Trønnes wrote:
>> @@ -1299,6 +1299,11 @@ static void __spi_pump_messages(struct spi_controller 
>> *ctlr, bool in_kthread)
>>  
>>  trace_spi_message_start(ctlr->cur_msg);
>>  
>> +ret = spi_split_transfers_maxsize(ctlr, ctlr->cur_msg, 
>> ctlr->max_dma_len,
>> +  GFP_KERNEL | GFP_DMA);
> 
> Um, shouldn't this be ifdef'ed to CONFIG_HAS_DMA?
> 

Maybe, I don't know. Mark didn't mentioned it when he commented on a
previous version of this. Some hate ifdef's and want to avoid them, some
don't.

> 
>> Some drivers like spi_bcm2835 have a max size on DMA transfers. Work
>> around this by splitting up the transfer if necessary.
> 
> This feels like a very expensive solution to the problem:  Large transfers
> are split into multiple smaller transfers (requiring lots of overhead to
> allocate and populate the structures) and the split transfers seem to be
> cached for later reuse.
> 

Only drivers that set ->max_dma_len will be split, and only when the
length is bigger. I can't see any caching with a quick glance, where do
you see it?

> I'm wondering, for a frame buffer, doesn't the buffer (and hence the SPI
> message) change on every transmission?  In other words, does a frame
> buffer benefit from the caching?  If not, then the caching seems to incur
> unnecessary overhead.
> 
> Even the normal case when no transfers exceed the limit is affected by
> additional overhead, namely an iteration over the transfer list to
> check each transfers' length. :-(
> 
> Note that spi_map_buf() already splits every transfer's sglist into
> segments that are smaller than ctlr->max_dma_len.  Now all that needs
> to be done is to amend spi-bcm2835.c to iterate over the sglist
> and transmit it in portions which do not exceed 65535.  Addressing the
> problem at this lower level would drastically reduce the overhead
> compared to the approach in the present patch and hence appears to be
> more recommendable.
> 

In a previous version of this I suggested to Meghana to put this in the
driver, but Mark wanted it in the core.

Noralf.

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

Re: [PATCH v4 2/4] spi: Split spi message into max_dma_len size chunks

2019-04-11 Thread Noralf Trønnes


Den 11.04.2019 18.42, skrev Noralf Trønnes:
> From: Meghana Madhyastha 
> 
> Some drivers like spi_bcm2835 have a max size on DMA transfers. Work
> around this by splitting up the transfer if necessary.
> 
> ->max_transfer_size is MAX_INT if the driver doesn't set it, so this change
> will only affect drivers that set the value.
> 
> Signed-off-by: Meghana Madhyastha 
> Signed-off-by: Noralf Trønnes 
> ---
>  drivers/spi/spi.c | 5 +
>  1 file changed, 5 insertions(+)
> 
> diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
> index 05875e63be43..22bc658032b3 100644
> --- a/drivers/spi/spi.c
> +++ b/drivers/spi/spi.c
> @@ -1299,6 +1299,11 @@ static void __spi_pump_messages(struct spi_controller 
> *ctlr, bool in_kthread)
>  
>   trace_spi_message_start(ctlr->cur_msg);
>  
> + ret = spi_split_transfers_maxsize(ctlr, ctlr->cur_msg, 
> ctlr->max_dma_len,
> +   GFP_KERNEL | GFP_DMA);
> + if (ret)
> + goto out;
> +
>   if (ctlr->prepare_message) {
>   ret = ctlr->prepare_message(ctlr, ctlr->cur_msg);
>   if (ret) {
> 

This doesn't work.

I started to wonder why it was necessary to lift the upper bound in
spi-bcm2835, so I put the test back and it triggered. Adding some
printk's show that the split transfer are mapped correctly, but when
unmap happens there's only the one big transfer:

[   70.935524] __spi_map_msg: msg=ae711dd4
[   70.935572] xfer=95c5acd8, xfer->len=65532
[   70.955800] xfer=aee3f198, xfer->len=65532
[   70.956034] xfer=7fc3464e, xfer->len=22536
[   70.982802] __spi_unmap_msg: msg=ae711dd4
[   70.982889] xfer=d5b5dbbf, xfer->len=153600

I need to study this more tomorrow to find out why this is, unless
someone knows off hand what the problem is.

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

[PATCH v4 4/4] drm/tinydrm: Remove chunk splitting in tinydrm_spi_transfer

2019-04-11 Thread Noralf Trønnes
From: Meghana Madhyastha 

Remove chunk splitting in tinydrm_spi_transfer in tinydrm-helpers as the
spi core will split a buffer into max_dma_len chunks for the spi
controller driver to handle, automatic byte swapping in
tinydrm_spi_transfer as it doesn't have users.

Remove the spi_max module argument that now has lost its cause.

The 16kB buffer size for Type C Option 1 (9-bit) interface is somewhat
arbitrary, but a bigger buffer will have a miniscule impact on transfer
speed, so it's probably fine.

Signed-off-by: Meghana Madhyastha 
Signed-off-by: Noralf Trønnes 
---
 .../gpu/drm/tinydrm/core/tinydrm-helpers.c| 83 ++-
 drivers/gpu/drm/tinydrm/mipi-dbi.c| 10 +--
 2 files changed, 7 insertions(+), 86 deletions(-)

diff --git a/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c 
b/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c
index 6d540d93758f..a32dc859a9c1 100644
--- a/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c
+++ b/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c
@@ -22,41 +22,8 @@
 #include 
 #include 
 
-static unsigned int spi_max;
-module_param(spi_max, uint, 0400);
-MODULE_PARM_DESC(spi_max, "Set a lower SPI max transfer size");
-
 #if IS_ENABLED(CONFIG_SPI)
 
-/**
- * tinydrm_spi_max_transfer_size - Determine max SPI transfer size
- * @spi: SPI device
- * @max_len: Maximum buffer size needed (optional)
- *
- * This function returns the maximum size to use for SPI transfers. It checks
- * the SPI master, the optional @max_len and the module parameter spi_max and
- * returns the smallest.
- *
- * Returns:
- * Maximum size for SPI transfers
- */
-size_t tinydrm_spi_max_transfer_size(struct spi_device *spi, size_t max_len)
-{
-   size_t ret;
-
-   ret = min(spi_max_transfer_size(spi), spi->master->max_dma_len);
-   if (max_len)
-   ret = min(ret, max_len);
-   if (spi_max)
-   ret = min_t(size_t, ret, spi_max);
-   ret &= ~0x3;
-   if (ret < 4)
-   ret = 4;
-
-   return ret;
-}
-EXPORT_SYMBOL(tinydrm_spi_max_transfer_size);
-
 /**
  * tinydrm_spi_bpw_supported - Check if bits per word is supported
  * @spi: SPI device
@@ -147,62 +114,22 @@ int tinydrm_spi_transfer(struct spi_device *spi, u32 
speed_hz,
struct spi_transfer tr = {
.bits_per_word = bpw,
.speed_hz = speed_hz,
+   .tx_buf = buf,
+   .len = len
};
struct spi_message m;
-   u16 *swap_buf = NULL;
-   size_t max_chunk;
-   size_t chunk;
-   int ret = 0;
-
-   if (WARN_ON_ONCE(bpw != 8 && bpw != 16))
-   return -EINVAL;
-
-   max_chunk = tinydrm_spi_max_transfer_size(spi, 0);
 
if (drm_debug & DRM_UT_DRIVER)
-   pr_debug("[drm:%s] bpw=%u, max_chunk=%zu, transfers:\n",
-__func__, bpw, max_chunk);
-
-   if (bpw == 16 && !tinydrm_spi_bpw_supported(spi, 16)) {
-   tr.bits_per_word = 8;
-   if (tinydrm_machine_little_endian()) {
-   swap_buf = kmalloc(min(len, max_chunk), GFP_KERNEL);
-   if (!swap_buf)
-   return -ENOMEM;
-   }
-   }
+   pr_debug("[drm:%s] bpw=%u, transfers:\n", __func__, bpw);
 
spi_message_init();
if (header)
spi_message_add_tail(header, );
spi_message_add_tail(, );
 
-   while (len) {
-   chunk = min(len, max_chunk);
+   tinydrm_dbg_spi_message(spi, );
 
-   tr.tx_buf = buf;
-   tr.len = chunk;
-
-   if (swap_buf) {
-   const u16 *buf16 = buf;
-   unsigned int i;
-
-   for (i = 0; i < chunk / 2; i++)
-   swap_buf[i] = swab16(buf16[i]);
-
-   tr.tx_buf = swap_buf;
-   }
-
-   buf += chunk;
-   len -= chunk;
-
-   tinydrm_dbg_spi_message(spi, );
-   ret = spi_sync(spi, );
-   if (ret)
-   return ret;
-   }
-
-   return 0;
+   return spi_sync(spi, );
 }
 EXPORT_SYMBOL(tinydrm_spi_transfer);
 
diff --git a/drivers/gpu/drm/tinydrm/mipi-dbi.c 
b/drivers/gpu/drm/tinydrm/mipi-dbi.c
index 85761b4abb83..0bcf6c764893 100644
--- a/drivers/gpu/drm/tinydrm/mipi-dbi.c
+++ b/drivers/gpu/drm/tinydrm/mipi-dbi.c
@@ -975,15 +975,9 @@ static int mipi_dbi_typec3_command(struct mipi_dbi *mipi, 
u8 *cmd,
 int mipi_dbi_spi_init(struct spi_device *spi, struct mipi_dbi *mipi,
  struct gpio_desc *dc)
 {
-   size_t tx_size = tinydrm_spi_max_transfer_size(spi, 0);
struct device *dev = >dev;
int ret;
 
-   if (tx_size < 16) {
-   DRM_ERROR("SPI transmit buffer too small: %zu\n", tx_size);
-   return -EINVAL;
-   }
-
  

[PATCH v4 3/4] spi/spi-bcm2835: Remove DMA transfer size cap

2019-04-11 Thread Noralf Trønnes
From: Meghana Madhyastha 

The spi core splits up transfers larger than ->max_dma_len now so we can
remove the upper bound on DMA transfers. Limit max_dma_len to 65532,
because the scatter gather segment is required to be a multiple of 4.

Signed-off-by: Meghana Madhyastha 
Signed-off-by: Noralf Trønnes 
---
 drivers/spi/spi-bcm2835.c | 15 +--
 1 file changed, 1 insertion(+), 14 deletions(-)

diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c
index 35aebdfd3b4e..caf33da01ac1 100644
--- a/drivers/spi/spi-bcm2835.c
+++ b/drivers/spi/spi-bcm2835.c
@@ -630,19 +630,6 @@ static bool bcm2835_spi_can_dma(struct spi_master *master,
if (tfr->len < BCM2835_SPI_DMA_MIN_LENGTH)
return false;
 
-   /* BCM2835_SPI_DLEN has defined a max transfer size as
-* 16 bit, so max is 65535
-* we can revisit this by using an alternative transfer
-* method - ideally this would get done without any more
-* interaction...
-*/
-   if (tfr->len > 65535) {
-   dev_warn_once(>dev,
- "transfer size of %d too big for dma-transfer\n",
- tfr->len);
-   return false;
-   }
-
/* return OK */
return true;
 }
@@ -707,7 +694,7 @@ static void bcm2835_dma_init(struct spi_master *master, 
struct device *dev)
 
/* all went well, so set can_dma */
master->can_dma = bcm2835_spi_can_dma;
-   master->max_dma_len = 65535; /* limitation by BCM2835_SPI_DLEN */
+   master->max_dma_len = 65532; /* limitation by BCM2835_SPI_DLEN */
/* need to do TX AND RX DMA, so we need dummy buffers */
master->flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX;
 
-- 
2.20.1

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

[PATCH v4 1/4] spi: Remove warning in spi_split_transfers_maxsize()

2019-04-11 Thread Noralf Trønnes
Don't warn about splitting transfers, the info is available in the
statistics if needed.

Signed-off-by: Noralf Trønnes 
---
 drivers/spi/spi.c | 5 -
 1 file changed, 5 deletions(-)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 9a7def7c3237..05875e63be43 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -2692,11 +2692,6 @@ static int __spi_split_transfer_maxsize(struct 
spi_controller *ctlr,
size_t offset;
size_t count, i;
 
-   /* warn once about this fact that we are splitting a transfer */
-   dev_warn_once(>spi->dev,
- "spi_transfer of length %i exceed max length of %zu - 
needed to split transfers\n",
- xfer->len, maxsize);
-
/* calculate how many we have to replace */
count = DIV_ROUND_UP(xfer->len, maxsize);
 
-- 
2.20.1

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

[PATCH v4 2/4] spi: Split spi message into max_dma_len size chunks

2019-04-11 Thread Noralf Trønnes
From: Meghana Madhyastha 

Some drivers like spi_bcm2835 have a max size on DMA transfers. Work
around this by splitting up the transfer if necessary.

->max_transfer_size is MAX_INT if the driver doesn't set it, so this change
will only affect drivers that set the value.

Signed-off-by: Meghana Madhyastha 
Signed-off-by: Noralf Trønnes 
---
 drivers/spi/spi.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 05875e63be43..22bc658032b3 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -1299,6 +1299,11 @@ static void __spi_pump_messages(struct spi_controller 
*ctlr, bool in_kthread)
 
trace_spi_message_start(ctlr->cur_msg);
 
+   ret = spi_split_transfers_maxsize(ctlr, ctlr->cur_msg, 
ctlr->max_dma_len,
+ GFP_KERNEL | GFP_DMA);
+   if (ret)
+   goto out;
+
if (ctlr->prepare_message) {
ret = ctlr->prepare_message(ctlr, ctlr->cur_msg);
if (ret) {
-- 
2.20.1

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

[PATCH v4 0/4] Chunk splitting of spi transfers

2019-04-11 Thread Noralf Trønnes
spi-bcm2835 has a ~64kB upper limit on DMA transfers. Drivers in
drivers/gpu/drm/tinydrm work around this limitation by splitting the
buffer into multiple transfers. This patchset lifts this limitation by
splitting affected transfers in the SPI core using
spi_split_transfers_maxsize().

This work[1] was begun by Meghana Madhyastha.

Main changes in this version:
- Remove warning in spi_split_transfers_maxsize()
- Split SPI patch into core patch and driver patch

Noralf.

[1] https://patchwork.freedesktop.org/series/38913/

Meghana Madhyastha (3):
  spi: Split spi message into max_dma_len size chunks
  spi/spi-bcm2835: Remove DMA transfer size cap
  drm/tinydrm: Remove chunk splitting in tinydrm_spi_transfer

Noralf Trønnes (1):
  spi: Remove warning in spi_split_transfers_maxsize()

 .../gpu/drm/tinydrm/core/tinydrm-helpers.c| 83 ++-
 drivers/gpu/drm/tinydrm/mipi-dbi.c| 10 +--
 drivers/spi/spi-bcm2835.c | 15 +---
 drivers/spi/spi.c | 10 +--
 4 files changed, 13 insertions(+), 105 deletions(-)

-- 
2.20.1

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

Re: [PATCH] drm/tinydrm: Fix fbdev pixel format

2019-04-11 Thread Noralf Trønnes


Den 10.04.2019 15.03, skrev Neil Armstrong:
> On 10/04/2019 14:43, Noralf Trønnes wrote:
>> Due to copy/paste error, the fbdev format was changed to 32bpp = XRGB
>> which is an emulated format for the RGB565 drivers. Revert to to using the
>> fallback which is dev->mode_config.preferred_depth for the drivers that
>> set it or 32bpp for those that don't (repaper, st7586).
>>
>> Fixes: 3eba3922819f ("drm/tinydrm: Drop using tinydrm_device")
>> Signed-off-by: Noralf Trønnes 
>> ---
>>  drivers/gpu/drm/tinydrm/hx8357d.c  | 2 +-
>>  drivers/gpu/drm/tinydrm/ili9225.c  | 2 +-
>>  drivers/gpu/drm/tinydrm/ili9341.c  | 2 +-
>>  drivers/gpu/drm/tinydrm/mi0283qt.c | 2 +-
>>  drivers/gpu/drm/tinydrm/repaper.c  | 2 +-
>>  drivers/gpu/drm/tinydrm/st7586.c   | 2 +-
>>  drivers/gpu/drm/tinydrm/st7735r.c  | 2 +-
>>  7 files changed, 7 insertions(+), 7 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/tinydrm/hx8357d.c 
>> b/drivers/gpu/drm/tinydrm/hx8357d.c
>> index fab961dded87..5773d0fb6ca1 100644
>> --- a/drivers/gpu/drm/tinydrm/hx8357d.c
>> +++ b/drivers/gpu/drm/tinydrm/hx8357d.c
>> @@ -267,7 +267,7 @@ static int hx8357d_probe(struct spi_device *spi)
>>  
>>  spi_set_drvdata(spi, drm);
>>  
>> -drm_fbdev_generic_setup(drm, 32);
>> +drm_fbdev_generic_setup(drm, 0);
>>  
>>  return 0;
>>  }
>> diff --git a/drivers/gpu/drm/tinydrm/ili9225.c 
>> b/drivers/gpu/drm/tinydrm/ili9225.c
>> index e9116ef4b5bc..4b1a587c0134 100644
>> --- a/drivers/gpu/drm/tinydrm/ili9225.c
>> +++ b/drivers/gpu/drm/tinydrm/ili9225.c
>> @@ -433,7 +433,7 @@ static int ili9225_probe(struct spi_device *spi)
>>  
>>  spi_set_drvdata(spi, drm);
>>  
>> -drm_fbdev_generic_setup(drm, 32);
>> +drm_fbdev_generic_setup(drm, 0);
>>  
>>  return 0;
>>  }
>> diff --git a/drivers/gpu/drm/tinydrm/ili9341.c 
>> b/drivers/gpu/drm/tinydrm/ili9341.c
>> index d15f85e837ae..4ade9e4b924f 100644
>> --- a/drivers/gpu/drm/tinydrm/ili9341.c
>> +++ b/drivers/gpu/drm/tinydrm/ili9341.c
>> @@ -229,7 +229,7 @@ static int ili9341_probe(struct spi_device *spi)
>>  
>>  spi_set_drvdata(spi, drm);
>>  
>> -drm_fbdev_generic_setup(drm, 32);
>> +drm_fbdev_generic_setup(drm, 0);
>>  
>>  return 0;
>>  }
>> diff --git a/drivers/gpu/drm/tinydrm/mi0283qt.c 
>> b/drivers/gpu/drm/tinydrm/mi0283qt.c
>> index c6dc31084a4e..8e169846fbd8 100644
>> --- a/drivers/gpu/drm/tinydrm/mi0283qt.c
>> +++ b/drivers/gpu/drm/tinydrm/mi0283qt.c
>> @@ -242,7 +242,7 @@ static int mi0283qt_probe(struct spi_device *spi)
>>  
>>  spi_set_drvdata(spi, drm);
>>  
>> -drm_fbdev_generic_setup(drm, 32);
>> +drm_fbdev_generic_setup(drm, 0);
>>  
>>  return 0;
>>  }
>> diff --git a/drivers/gpu/drm/tinydrm/repaper.c 
>> b/drivers/gpu/drm/tinydrm/repaper.c
>> index a29b8278324b..370629e2de94 100644
>> --- a/drivers/gpu/drm/tinydrm/repaper.c
>> +++ b/drivers/gpu/drm/tinydrm/repaper.c
>> @@ -1131,7 +1131,7 @@ static int repaper_probe(struct spi_device *spi)
>>  
>>  DRM_DEBUG_DRIVER("SPI speed: %uMHz\n", spi->max_speed_hz / 100);
>>  
>> -drm_fbdev_generic_setup(drm, 32);
>> +drm_fbdev_generic_setup(drm, 0);
>>  
>>  return 0;
>>  }
>> diff --git a/drivers/gpu/drm/tinydrm/st7586.c 
>> b/drivers/gpu/drm/tinydrm/st7586.c
>> index 560d7ac0cadc..36bb16a15f7e 100644
>> --- a/drivers/gpu/drm/tinydrm/st7586.c
>> +++ b/drivers/gpu/drm/tinydrm/st7586.c
>> @@ -408,7 +408,7 @@ static int st7586_probe(struct spi_device *spi)
>>  DRM_DEBUG_KMS("preferred_depth=%u, rotation = %u\n",
>>drm->mode_config.preferred_depth, rotation);
>>  
>> -drm_fbdev_generic_setup(drm, 32);
>> +drm_fbdev_generic_setup(drm, 0);
>>  
>>  return 0;
>>  }
>> diff --git a/drivers/gpu/drm/tinydrm/st7735r.c 
>> b/drivers/gpu/drm/tinydrm/st7735r.c
>> index 022e9849b95b..ce9109e613e0 100644
>> --- a/drivers/gpu/drm/tinydrm/st7735r.c
>> +++ b/drivers/gpu/drm/tinydrm/st7735r.c
>> @@ -207,7 +207,7 @@ static int st7735r_probe(struct spi_device *spi)
>>  
>>  spi_set_drvdata(spi, drm);
>>  
>> -drm_fbdev_generic_setup(drm, 32);
>> +drm_fbdev_generic_setup(drm, 0);
>>  
>>  return 0;
>>  }
>>
> 
> Reviewed-by: Neil Armstrong 
> 

Thanks, applied.

Noralf.

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

Re: [PATCH v2 03/12] drm/i915/fbdev: Move intel_fb_initial_config() to fbdev helper

2019-04-11 Thread Noralf Trønnes


Den 07.04.2019 18.52, skrev Noralf Trønnes:
> It is generic code and having it in the helper will let other drivers
> benefit from it.
> 
> One change was necessary assuming this to be true:
> INTEL_INFO(dev_priv)->num_pipes == dev->mode_config.num_crtc
> 
> Suggested-by: Daniel Vetter 
> Cc: Jani Nikula 
> Cc: Joonas Lahtinen 
> Cc: Rodrigo Vivi 
> Cc: intel-...@lists.freedesktop.org
> Signed-off-by: Noralf Trønnes 
> Reviewed-by: Jani Nikula 
> ---
>  drivers/gpu/drm/drm_fb_helper.c| 194 -
>  drivers/gpu/drm/i915/intel_fbdev.c | 218 -
>  include/drm/drm_fb_helper.h|  23 ---
>  3 files changed, 190 insertions(+), 245 deletions(-)
> 

Applied to drm-misc-next.

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

Re: [PATCH] drm: fix drm_fb_xrgb8888_to_rgb888_dstclip()

2019-04-11 Thread Noralf Trønnes


Den 11.04.2019 06.49, skrev Gerd Hoffmann:
> Oops, the __iomem annotation was added to the header file only.
> Add it to the implementation (and documentation) too.
> 
> Fixes: 5c5373b51bec ("drm: switch drm_fb_xrgb_to_rgb888_dstclip to accept 
> __iomem dst")
> Signed-off-by: Gerd Hoffmann 
> ---

Reviewed-by: Noralf Trønnes 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Re: [PATCH] drm/bochs: use simple display pipe

2019-04-10 Thread Noralf Trønnes


Den 10.04.2019 09.48, skrev Gerd Hoffmann:
> Signed-off-by: Gerd Hoffmann 
> ---

Acked-by: Noralf Trønnes 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH] drm/tinydrm: Fix fbdev pixel format

2019-04-10 Thread Noralf Trønnes
Due to copy/paste error, the fbdev format was changed to 32bpp = XRGB
which is an emulated format for the RGB565 drivers. Revert to to using the
fallback which is dev->mode_config.preferred_depth for the drivers that
set it or 32bpp for those that don't (repaper, st7586).

Fixes: 3eba3922819f ("drm/tinydrm: Drop using tinydrm_device")
Signed-off-by: Noralf Trønnes 
---
 drivers/gpu/drm/tinydrm/hx8357d.c  | 2 +-
 drivers/gpu/drm/tinydrm/ili9225.c  | 2 +-
 drivers/gpu/drm/tinydrm/ili9341.c  | 2 +-
 drivers/gpu/drm/tinydrm/mi0283qt.c | 2 +-
 drivers/gpu/drm/tinydrm/repaper.c  | 2 +-
 drivers/gpu/drm/tinydrm/st7586.c   | 2 +-
 drivers/gpu/drm/tinydrm/st7735r.c  | 2 +-
 7 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/tinydrm/hx8357d.c 
b/drivers/gpu/drm/tinydrm/hx8357d.c
index fab961dded87..5773d0fb6ca1 100644
--- a/drivers/gpu/drm/tinydrm/hx8357d.c
+++ b/drivers/gpu/drm/tinydrm/hx8357d.c
@@ -267,7 +267,7 @@ static int hx8357d_probe(struct spi_device *spi)
 
spi_set_drvdata(spi, drm);
 
-   drm_fbdev_generic_setup(drm, 32);
+   drm_fbdev_generic_setup(drm, 0);
 
return 0;
 }
diff --git a/drivers/gpu/drm/tinydrm/ili9225.c 
b/drivers/gpu/drm/tinydrm/ili9225.c
index e9116ef4b5bc..4b1a587c0134 100644
--- a/drivers/gpu/drm/tinydrm/ili9225.c
+++ b/drivers/gpu/drm/tinydrm/ili9225.c
@@ -433,7 +433,7 @@ static int ili9225_probe(struct spi_device *spi)
 
spi_set_drvdata(spi, drm);
 
-   drm_fbdev_generic_setup(drm, 32);
+   drm_fbdev_generic_setup(drm, 0);
 
return 0;
 }
diff --git a/drivers/gpu/drm/tinydrm/ili9341.c 
b/drivers/gpu/drm/tinydrm/ili9341.c
index d15f85e837ae..4ade9e4b924f 100644
--- a/drivers/gpu/drm/tinydrm/ili9341.c
+++ b/drivers/gpu/drm/tinydrm/ili9341.c
@@ -229,7 +229,7 @@ static int ili9341_probe(struct spi_device *spi)
 
spi_set_drvdata(spi, drm);
 
-   drm_fbdev_generic_setup(drm, 32);
+   drm_fbdev_generic_setup(drm, 0);
 
return 0;
 }
diff --git a/drivers/gpu/drm/tinydrm/mi0283qt.c 
b/drivers/gpu/drm/tinydrm/mi0283qt.c
index c6dc31084a4e..8e169846fbd8 100644
--- a/drivers/gpu/drm/tinydrm/mi0283qt.c
+++ b/drivers/gpu/drm/tinydrm/mi0283qt.c
@@ -242,7 +242,7 @@ static int mi0283qt_probe(struct spi_device *spi)
 
spi_set_drvdata(spi, drm);
 
-   drm_fbdev_generic_setup(drm, 32);
+   drm_fbdev_generic_setup(drm, 0);
 
return 0;
 }
diff --git a/drivers/gpu/drm/tinydrm/repaper.c 
b/drivers/gpu/drm/tinydrm/repaper.c
index a29b8278324b..370629e2de94 100644
--- a/drivers/gpu/drm/tinydrm/repaper.c
+++ b/drivers/gpu/drm/tinydrm/repaper.c
@@ -1131,7 +1131,7 @@ static int repaper_probe(struct spi_device *spi)
 
DRM_DEBUG_DRIVER("SPI speed: %uMHz\n", spi->max_speed_hz / 100);
 
-   drm_fbdev_generic_setup(drm, 32);
+   drm_fbdev_generic_setup(drm, 0);
 
return 0;
 }
diff --git a/drivers/gpu/drm/tinydrm/st7586.c b/drivers/gpu/drm/tinydrm/st7586.c
index 560d7ac0cadc..36bb16a15f7e 100644
--- a/drivers/gpu/drm/tinydrm/st7586.c
+++ b/drivers/gpu/drm/tinydrm/st7586.c
@@ -408,7 +408,7 @@ static int st7586_probe(struct spi_device *spi)
DRM_DEBUG_KMS("preferred_depth=%u, rotation = %u\n",
  drm->mode_config.preferred_depth, rotation);
 
-   drm_fbdev_generic_setup(drm, 32);
+   drm_fbdev_generic_setup(drm, 0);
 
return 0;
 }
diff --git a/drivers/gpu/drm/tinydrm/st7735r.c 
b/drivers/gpu/drm/tinydrm/st7735r.c
index 022e9849b95b..ce9109e613e0 100644
--- a/drivers/gpu/drm/tinydrm/st7735r.c
+++ b/drivers/gpu/drm/tinydrm/st7735r.c
@@ -207,7 +207,7 @@ static int st7735r_probe(struct spi_device *spi)
 
spi_set_drvdata(spi, drm);
 
-   drm_fbdev_generic_setup(drm, 32);
+   drm_fbdev_generic_setup(drm, 0);
 
return 0;
 }
-- 
2.20.1

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

Re: [PATCH v2 2/3] drm: switch drm_fb_xrgb8888_to_rgb565_dstclip to accept __iomem dst

2019-04-10 Thread Noralf Trønnes


Den 10.04.2019 08.38, skrev Gerd Hoffmann:
> Not all archs have the __io_virt() macro, so cirrus can't simply convert
> pointers that way.  The drm format helpers have to use memcpy_toio()
> instead.
> 
> This patch makes drm_fb_xrgb_to_rgb565_dstclip() accept a __iomem
> dst pointer and use memcpy_toio() instead of memcpy().  The helper
> function (drm_fb_xrgb_to_rgb565_line) has been changed to process
> a single scanline.
> 
> Signed-off-by: Gerd Hoffmann 
> ---
>  include/drm/drm_format_helper.h |   2 +-
>  drivers/gpu/drm/cirrus/cirrus.c |   2 +-
>  drivers/gpu/drm/drm_format_helper.c | 113 ++--
>  3 files changed, 60 insertions(+), 57 deletions(-)
> 
> diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h
> index bc2e1004e166..d1b8a9ea01b4 100644
> --- a/include/drm/drm_format_helper.h
> +++ b/include/drm/drm_format_helper.h
> @@ -23,7 +23,7 @@ void drm_fb_swab16(u16 *dst, void *vaddr, struct 
> drm_framebuffer *fb,
>  void drm_fb_xrgb_to_rgb565(void *dst, void *vaddr,
>  struct drm_framebuffer *fb,
>  struct drm_rect *clip, bool swap);
> -void drm_fb_xrgb_to_rgb565_dstclip(void *dst, unsigned int dst_pitch,
> +void drm_fb_xrgb_to_rgb565_dstclip(void __iomem *dst, unsigned int 
> dst_pitch,
>  void *vaddr, struct drm_framebuffer *fb,
>  struct drm_rect *clip, bool swap);
>  void drm_fb_xrgb_to_rgb888_dstclip(void *dst, unsigned int dst_pitch,
> diff --git a/drivers/gpu/drm/cirrus/cirrus.c b/drivers/gpu/drm/cirrus/cirrus.c
> index 0fc3aa31b5a4..ed2f2d8cfb6f 100644
> --- a/drivers/gpu/drm/cirrus/cirrus.c
> +++ b/drivers/gpu/drm/cirrus/cirrus.c
> @@ -311,7 +311,7 @@ static int cirrus_fb_blit_rect(struct drm_framebuffer *fb,
> vmap, fb, rect);
>  
>   else if (fb->format->cpp[0] == 4 && cirrus->cpp == 2)
> - drm_fb_xrgb_to_rgb565_dstclip(__io_virt(cirrus->vram),
> + drm_fb_xrgb_to_rgb565_dstclip(cirrus->vram,
> cirrus->pitch,
> vmap, fb, rect, false);
>  
> diff --git a/drivers/gpu/drm/drm_format_helper.c 
> b/drivers/gpu/drm/drm_format_helper.c
> index dace05638bc3..c9521af4e90b 100644
> --- a/drivers/gpu/drm/drm_format_helper.c
> +++ b/drivers/gpu/drm/drm_format_helper.c
> @@ -113,42 +113,22 @@ void drm_fb_swab16(u16 *dst, void *vaddr, struct 
> drm_framebuffer *fb,
>  }
>  EXPORT_SYMBOL(drm_fb_swab16);
>  
> -static void drm_fb_xrgb_to_rgb565_lines(void *dst, unsigned int 
> dst_pitch,
> - void *src, unsigned int src_pitch,
> - unsigned int src_linelength,
> - unsigned int lines,
> - bool swap)
> +static void drm_fb_xrgb_to_rgb565_line(u16 *dbuf, u32 *sbuf,
> +unsigned int pixels,
> +        bool swab)

Both here and further down you change the argument name: swap -> swab.
If you want that, you need to fix the function declaration and the docs
as well.

With that sorted out:
Reviewed-by: Noralf Trønnes 


>  {
> - unsigned int linepixels = src_linelength / sizeof(u32);
> - unsigned int x, y;
> - u32 *sbuf;
> - u16 *dbuf, val16;
> + unsigned int x;
> + u16 val16;
>  
> - /*
> -  * The cma memory is write-combined so reads are uncached.
> -  * Speed up by fetching one line at a time.
> -  */
> - sbuf = kmalloc(src_linelength, GFP_KERNEL);
> - if (!sbuf)
> - return;
> -
> - for (y = 0; y < lines; y++) {
> - memcpy(sbuf, src, src_linelength);
> - dbuf = dst;
> - for (x = 0; x < linepixels; x++) {
> - val16 = ((sbuf[x] & 0x00F8) >> 8) |
> - ((sbuf[x] & 0xFC00) >> 5) |
> - ((sbuf[x] & 0x00F8) >> 3);
> - if (swap)
> - *dbuf++ = swab16(val16);
> - else
> - *dbuf++ = val16;
> - }
> - src += src_pitch;
> - dst += dst_pitch;
> + for (x = 0; x < pixels; x++) {
> + val16 = ((sbuf[x] & 0x00F8) >> 8) |
> + ((sbuf[x] & 0xFC00) >> 5) |
> + ((sbuf[x]

Re: [PATCH v2 3/3] drm: switch drm_fb_xrgb8888_to_rgb888_dstclip to accept __iomem dst

2019-04-10 Thread Noralf Trønnes


Den 10.04.2019 08.38, skrev Gerd Hoffmann:
> Not all archs have the __io_virt() macro, so cirrus can't simply convert
> pointers that way.  The drm format helpers have to use memcpy_toio()
> instead.
> 
> This patch makes drm_fb_xrgb_to_rgb888_dstclip() accept a __iomem
> dst pointer and use memcpy_toio() instead of memcpy().  The helper
> function (drm_fb_xrgb_to_rgb888_line) has been changed to process a
> single scanline.
> 
> Signed-off-by: Gerd Hoffmann 
> ---

Reviewed-by: Noralf Trønnes 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Re: [PATCH v2 1/3] drm: switch drm_fb_memcpy_dstclip to accept __iomem dst

2019-04-10 Thread Noralf Trønnes


Den 10.04.2019 08.38, skrev Gerd Hoffmann:
> Not all archs have the __io_virt() macro, so cirrus can't simply convert
> pointers that way.  The drm format helpers have to use memcpy_toio()
> instead.
> 
> This patch makes drm_fb_memcpy_dstclip() accept a __iomem dst pointer
> and use memcpy_toio() instead of memcpy().  With that separating out the
> memcpy loop into the drm_fb_memcpy_lines() helper isn't useful any more,
> so move the code back into the calling functins.
> 
> Signed-off-by: Gerd Hoffmann 
> ---

Reviewed-by: Noralf Trønnes 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Re: [PATCH 2/4] drm: use convert_lines() in xrgb8888_to_rgb565 helpers.

2019-04-09 Thread Noralf Trønnes


Den 09.04.2019 13.59, skrev Gerd Hoffmann:
> Also add two conversion functions for the swab / not swab cases.
> That way we have to check the swab flag only once.
> 
> Signed-off-by: Gerd Hoffmann 
> ---
>  drivers/gpu/drm/drm_format_helper.c | 117 +++-
>  1 file changed, 62 insertions(+), 55 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_format_helper.c 
> b/drivers/gpu/drm/drm_format_helper.c
> index f32e0173600c..b8d17cd0a9f8 100644
> --- a/drivers/gpu/drm/drm_format_helper.c
> +++ b/drivers/gpu/drm/drm_format_helper.c
> @@ -38,6 +38,46 @@ static struct drm_format_convert convert_swab16 = {
>   .func = convert_swab16_fn,
>  };
>  
> +static void convert_xrgb_to_rgb565_fn(void *dst, void *src, u32 pixels)
> +{
> + u32 *sbuf = src;
> + u16 *dbuf = dst;
> + u32 x;
> +
> + for (x = 0; x < pixels; x++) {
> + dbuf[x] = ((sbuf[x] & 0x00F8) >> 8) |
> + ((sbuf[x] & 0xFC00) >> 5) |
> + ((sbuf[x] & 0x00F8) >> 3);
> + }
> +}
> +
> +static struct drm_format_convert convert_xrgb_to_rgb565 = {
> + .dst_cpp = 2,
> + .src_cpp = 4,
> + .func = convert_xrgb_to_rgb565_fn,
> +};
> +
> +static void convert_xrgb_to_rgb565_swab_fn(void *dst, void *src, u32 
> pixels)
> +{
> + u32 *sbuf = src;
> + u16 *dbuf = dst;
> + u16 val16;
> + u32 x;
> +
> + for (x = 0; x < pixels; x++) {
> + val16 = ((sbuf[x] & 0x00F8) >> 8) |
> + ((sbuf[x] & 0xFC00) >> 5) |
> + ((sbuf[x] & 0x00F8) >> 3);
> + dbuf[x] = swab16(val16);
> + }
> +}
> +
> +static struct drm_format_convert convert_xrgb_to_rgb565_swap = {
> + .dst_cpp = 2,
> + .src_cpp = 4,
> + .func = convert_xrgb_to_rgb565_swab_fn,
> +};
> +

I find that drm_format_convert makes the code more difficult to read.
The only shared code is the xrgb to rgb565 conversion.

Can we do something like this instead:

static void drm_fb_xrgb_to_rgb565_line(u16 *dst, u32 *src, unsigned
int width, bool swap)
{
unsigned int x;

for (x = 0; x < width; x++) {
u16 val = ((*src & 0x00F8) >> 8) |
  ((*src & 0xFC00) >> 5) |
  ((*src & 0x00F8) >> 3);
src++;
if (swap)
*dst++ = swab16(val);
else
*dst++ = val;
}
}

void drm_fb_xrgb_to_rgb565(void *dst, void *vaddr,
   struct drm_framebuffer *fb,
   struct drm_rect *clip, bool swap)
{
void *src = vaddr + clip_offset(clip, fb->pitches[0], 4);
unsigned width = clip->x2 - clip->x1;
unsigned height = clip->y2 - clip->y1;
size_t src_clip_pitch = width * 4;
size_t dst_clip_pitch = width * 2;
unsigned int y;
void *sbuf;

/*
 * The cma memory is write-combined so reads are uncached.
 * Speed up by fetching one line at a time.
 */
sbuf = kmalloc(src_clip_pitch, GFP_KERNEL);
if (!sbuf)
return;

for (y = 0; y < height; y++) {
memcpy(sbuf, src, src_clip_pitch);

drm_fb_xrgb_to_rgb565_line(dst, sbuf, width, swap);

src += fb->pitches[0];
dst += dst_clip_pitch;
}

kfree(sbuf);
}
EXPORT_SYMBOL(drm_fb_xrgb_to_rgb565);

void drm_fb_xrgb_to_rgb565_dstclip(void __iomem *dst,
   unsigned int dst_pitch,
   void *vaddr, struct drm_framebuffer *fb,
   struct drm_rect *clip, bool swap)
{
void *src = vaddr + clip_offset(clip, fb->pitches[0], 4);
unsigned width = clip->x2 - clip->x1;
unsigned height = clip->y2 - clip->y1;
size_t dst_clip_pitch = width * 2;
unsigned int y;
void *dbuf;

dst += clip_offset(clip, dst_pitch, 2);

dbuf = kmalloc(dst_clip_pitch, GFP_KERNEL);
if (!dbuf)
return;

for (y = 0; y < height; y++) {
drm_fb_xrgb_to_rgb565_line(dbuf, src, width, swap);

memcpy_toio(dst, dbuf, dst_clip_pitch);

src += fb->pitches[0];
dst += dst_pitch;
}

kfree(dbuf);
}
EXPORT_SYMBOL(drm_fb_xrgb_to_rgb565_dstclip);


Other things I noticed:

drm_fb_memcpy() is just a wrapper around drm_fb_memcpy_lines() and
drm_fb_memcpy_dstclip() around drm_fb_memcpy_lines_toio(). They can be
merged.

checkpatch gave this:

WARNING: Use #include  instead of 
#50: FILE: drivers/gpu/drm/drm_format_helper.c:14:
+#include 

Noralf.

>  static void convert_lines(void *dst, unsigned int dst_pitch,
> void *src, unsigned int src_pitch,
> unsigned int 

[PATCH v2 12/12] drm/client: Hack: Add bootsplash example

2019-04-07 Thread Noralf Trønnes
An example to showcase the client API.

TODO:
A bootsplash client needs a way to tell drm_fb_helper to stay away,
otherwise it will chime in on setup and hotplug.
Most DRM drivers register fbdev before calling drm_dev_register() (the
generic emulation is an exception). This have to be reversed for
bootsplash to fend off fbdev.

Signed-off-by: Noralf Trønnes 
---
 drivers/gpu/drm/Kconfig  |   5 +
 drivers/gpu/drm/Makefile |   1 +
 drivers/gpu/drm/drm_bootsplash.c | 359 +++
 drivers/gpu/drm/drm_client.c |   7 +
 drivers/gpu/drm/drm_drv.c|   4 +
 include/drm/drm_client.h |   3 +
 6 files changed, 379 insertions(+)
 create mode 100644 drivers/gpu/drm/drm_bootsplash.c

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 98e9ac8498c0..d61de804068a 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -65,6 +65,11 @@ config DRM_DEBUG_SELFTEST
 
  If in doubt, say "N".
 
+config DRM_CLIENT_BOOTSPLASH
+   bool "DRM Bootsplash"
+   help
+ DRM Bootsplash
+
 config DRM_KMS_HELPER
tristate
depends on DRM
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 08c77c10ccbb..ae42c9a91c57 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -32,6 +32,7 @@ drm-$(CONFIG_OF) += drm_of.o
 drm-$(CONFIG_AGP) += drm_agpsupport.o
 drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o
 drm-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
+drm-$(CONFIG_DRM_CLIENT_BOOTSPLASH) += drm_bootsplash.o
 
 drm_kms_helper-y := 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 \
diff --git a/drivers/gpu/drm/drm_bootsplash.c b/drivers/gpu/drm/drm_bootsplash.c
new file mode 100644
index ..37f3ac3fce95
--- /dev/null
+++ b/drivers/gpu/drm/drm_bootsplash.c
@@ -0,0 +1,359 @@
+/* DRM internal client example */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+// drm_lastclose()
+#include "drm_internal.h"
+
+static bool drm_bootsplash_enabled = true;
+module_param_named(bootsplash_enabled, drm_bootsplash_enabled, bool, 0600);
+MODULE_PARM_DESC(bootsplash_enabled, "Enable bootsplash client 
[default=true]");
+
+struct drm_bootsplash {
+   struct drm_client_dev client;
+   struct mutex lock;
+   struct work_struct worker;
+   bool started;
+   bool stop;
+
+   unsigned int modeset_mask;
+   struct drm_client_buffer *buffers[2];
+};
+
+static bool drm_bootsplash_key_pressed;
+
+static int drm_bootsplash_keyboard_notifier_call(struct notifier_block *blk,
+unsigned long code, void 
*_param)
+{
+   /* Any key is good */
+   drm_bootsplash_key_pressed = true;
+
+   return NOTIFY_OK;
+}
+
+static struct notifier_block drm_bootsplash_keyboard_notifier_block = {
+   .notifier_call = drm_bootsplash_keyboard_notifier_call,
+};
+
+static void drm_bootsplash_buffer_delete(struct drm_bootsplash *splash)
+{
+   unsigned int i;
+
+   for (i = 0; i < 2; i++) {
+   if (!IS_ERR_OR_NULL(splash->buffers[i]))
+   drm_client_framebuffer_delete(splash->buffers[i]);
+   splash->buffers[i] = NULL;
+   }
+}
+
+static int drm_bootsplash_buffer_create(struct drm_bootsplash *splash, u32 
width, u32 height)
+{
+   unsigned int i;
+
+   for (i = 0; i < 2; i++) {
+   splash->buffers[i] = 
drm_client_framebuffer_create(>client, width, height, 
DRM_FORMAT_XRGB);
+   if (IS_ERR(splash->buffers[i])) {
+   drm_bootsplash_buffer_delete(splash);
+   return PTR_ERR(splash->buffers[i]);
+   }
+   }
+
+   return 0;
+}
+
+static int drm_bootsplash_display_probe(struct drm_bootsplash *splash)
+{
+   struct drm_client_dev *client = >client;
+   unsigned int width = 0, height = 0;
+   unsigned int num_non_tiled = 0, i;
+   struct drm_mode_set *modeset;
+   bool tiled = false;
+   int ret;
+
+   splash->modeset_mask = 0;
+
+   ret = drm_client_modeset_probe(client, 0, 0);
+   if (ret)
+   return ret;
+
+   mutex_lock(>modeset_mutex);
+
+   drm_client_for_each_modeset(modeset, client) {
+   if (!modeset->mode)
+   continue;
+
+   if (modeset->connectors[0]->has_tile)
+   tiled = true;
+   else
+   num_non_tiled++;
+   }
+
+   if (!tiled && !num_non_tiled) {
+   drm_bootsplash_buffer_delete(splash);
+   ret = -ENOENT;
+   goto out;
+   }
+
+   /* Assume only one tiled monitor is possible */

[PATCH v2 11/12] drm/fb-helper: Move out modeset config code

2019-04-07 Thread Noralf Trønnes
No functional changes, just moving code as-is and fixing includes.

Signed-off-by: Noralf Trønnes 
---
 drivers/gpu/drm/drm_client_modeset.c | 703 ++-
 drivers/gpu/drm/drm_fb_helper.c  | 692 --
 include/drm/drm_client.h |   4 +-
 3 files changed, 701 insertions(+), 698 deletions(-)

diff --git a/drivers/gpu/drm/drm_client_modeset.c 
b/drivers/gpu/drm/drm_client_modeset.c
index 94b52f97c06b..2a428ac00930 100644
--- a/drivers/gpu/drm/drm_client_modeset.c
+++ b/drivers/gpu/drm/drm_client_modeset.c
@@ -13,13 +13,22 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
+#include 
+#include 
 
 #include "drm_crtc_internal.h"
 #include "drm_internal.h"
 
+#define DRM_CLIENT_MAX_CLONED_CONNECTORS   8
+
+struct drm_client_offset {
+   int x, y;
+};
+
 /* Used by drm_client and drm_fb_helper */
 int drm_client_modeset_create(struct drm_client_dev *client)
 {
@@ -93,7 +102,8 @@ void drm_client_modeset_release(struct drm_client_dev 
*client)
 }
 EXPORT_SYMBOL(drm_client_modeset_release);
 
-struct drm_mode_set *drm_client_find_modeset(struct drm_client_dev *client, 
struct drm_crtc *crtc)
+static struct drm_mode_set *
+drm_client_find_modeset(struct drm_client_dev *client, struct drm_crtc *crtc)
 {
struct drm_mode_set *modeset;
 
@@ -103,8 +113,695 @@ struct drm_mode_set *drm_client_find_modeset(struct 
drm_client_dev *client, stru
 
return NULL;
 }
-/* TODO: Remove export when modeset code has been moved over */
-EXPORT_SYMBOL(drm_client_find_modeset);
+
+static struct drm_display_mode *
+drm_connector_has_preferred_mode(struct drm_connector *connector, int width, 
int height)
+{
+   struct drm_display_mode *mode;
+
+   list_for_each_entry(mode, >modes, head) {
+   if (mode->hdisplay > width ||
+   mode->vdisplay > height)
+   continue;
+   if (mode->type & DRM_MODE_TYPE_PREFERRED)
+   return mode;
+   }
+   return NULL;
+}
+
+static struct drm_display_mode *
+drm_connector_pick_cmdline_mode(struct drm_connector *connector)
+{
+   struct drm_cmdline_mode *cmdline_mode;
+   struct drm_display_mode *mode;
+   bool prefer_non_interlace;
+
+   cmdline_mode = >cmdline_mode;
+   if (cmdline_mode->specified == false)
+   return NULL;
+
+   /* attempt to find a matching mode in the list of modes
+*  we have gotten so far, if not add a CVT mode that conforms
+*/
+   if (cmdline_mode->rb || cmdline_mode->margins)
+   goto create_mode;
+
+   prefer_non_interlace = !cmdline_mode->interlace;
+again:
+   list_for_each_entry(mode, >modes, head) {
+   /* check width/height */
+   if (mode->hdisplay != cmdline_mode->xres ||
+   mode->vdisplay != cmdline_mode->yres)
+   continue;
+
+   if (cmdline_mode->refresh_specified) {
+   if (mode->vrefresh != cmdline_mode->refresh)
+   continue;
+   }
+
+   if (cmdline_mode->interlace) {
+   if (!(mode->flags & DRM_MODE_FLAG_INTERLACE))
+   continue;
+   } else if (prefer_non_interlace) {
+   if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+   continue;
+   }
+   return mode;
+   }
+
+   if (prefer_non_interlace) {
+   prefer_non_interlace = false;
+   goto again;
+   }
+
+create_mode:
+   mode = drm_mode_create_from_cmdline_mode(connector->dev, cmdline_mode);
+   list_add(>head, >modes);
+
+   return mode;
+}
+
+static bool drm_connector_enabled(struct drm_connector *connector, bool strict)
+{
+   bool enable;
+
+   if (connector->display_info.non_desktop)
+   return false;
+
+   if (strict)
+   enable = connector->status == connector_status_connected;
+   else
+   enable = connector->status != connector_status_disconnected;
+
+   return enable;
+}
+
+static void drm_client_connectors_enabled(struct drm_connector **connectors,
+ unsigned int connector_count,
+ bool *enabled)
+{
+   bool any_enabled = false;
+   struct drm_connector *connector;
+   int i = 0;
+
+   for (i = 0; i < connector_count; i++) {
+   connector = connectors[i];
+   enabled[i] = drm_connector_enabled(connector, true);
+   DRM_DEBUG_KMS("connector %d enabled? %s\n", connector->base.id,
+ connector->display_info.non_desktop ? "non 
desktop" : enabled[i] ? "yes" : &q

[PATCH v2 10/12] drm/fb-helper: Prepare to move out modeset config code

2019-04-07 Thread Noralf Trønnes
This prepares the modeset code so it can be moved out as-is in the next
patch.

Signed-off-by: Noralf Trønnes 
---
 drivers/gpu/drm/drm_fb_helper.c | 63 +++--
 include/drm/drm_fb_helper.h |  4 ---
 2 files changed, 45 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index e13026724b2c..9287ff4ae2d8 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -43,6 +43,10 @@
 
 #include "drm_internal.h"
 
+struct drm_client_offset {
+   int x, y;
+};
+
 static bool drm_fbdev_emulation = true;
 module_param_named(fbdev_emulation, drm_fbdev_emulation, bool, 0600);
 MODULE_PARM_DESC(fbdev_emulation,
@@ -1794,7 +1798,7 @@ static bool drm_client_target_cloned(struct drm_device 
*dev,
 struct drm_connector **connectors,
 unsigned int connector_count,
 struct drm_display_mode **modes,
-struct drm_fb_offset *offsets,
+struct drm_client_offset *offsets,
 bool *enabled, int width, int height)
 {
int count, i, j;
@@ -1873,7 +1877,7 @@ static bool drm_client_target_cloned(struct drm_device 
*dev,
 static int drm_client_get_tile_offsets(struct drm_connector **connectors,
   unsigned int connector_count,
   struct drm_display_mode **modes,
-  struct drm_fb_offset *offsets,
+  struct drm_client_offset *offsets,
   int idx,
   int h_idx, int v_idx)
 {
@@ -1906,7 +1910,7 @@ static int drm_client_get_tile_offsets(struct 
drm_connector **connectors,
 static bool drm_client_target_preferred(struct drm_connector **connectors,
unsigned int connector_count,
struct drm_display_mode **modes,
-   struct drm_fb_offset *offsets,
+   struct drm_client_offset *offsets,
bool *enabled, int width, int height)
 {
const u64 mask = BIT_ULL(connector_count) - 1;
@@ -2070,7 +2074,7 @@ static bool drm_client_firmware_config(struct 
drm_client_dev *client,
   unsigned int connector_count,
   struct drm_crtc **crtcs,
   struct drm_display_mode **modes,
-  struct drm_fb_offset *offsets,
+  struct drm_client_offset *offsets,
   bool *enabled, int width, int height)
 {
unsigned int count = min_t(unsigned int, connector_count, 
BITS_PER_LONG);
@@ -2239,30 +2243,48 @@ static bool drm_client_firmware_config(struct 
drm_client_dev *client,
return ret;
 }
 
-static void drm_setup_crtcs(struct drm_fb_helper *fb_helper,
-   u32 width, u32 height)
+/**
+ * drm_client_modeset_probe() - Probe for displays
+ * @client: DRM client
+ * @width: Maximum display mode width (optional)
+ * @height: Maximum display mode height (optional)
+ *
+ * This function sets up display pipelines for enabled connectors and stores 
the
+ * config in the client's modeset array.
+ *
+ * Returns:
+ * Zero on success or negative error code on failure.
+ */
+
+int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int 
width, unsigned int height)
 {
struct drm_connector *connector, **connectors = NULL;
-   struct drm_client_dev *client = _helper->client;
struct drm_connector_list_iter conn_iter;
-   struct drm_device *dev = fb_helper->dev;
+   struct drm_device *dev = client->dev;
unsigned int total_modes_count = 0;
+   struct drm_client_offset *offsets;
unsigned int connector_count = 0;
struct drm_display_mode **modes;
-   struct drm_fb_offset *offsets;
struct drm_crtc **crtcs;
+   int i, ret = 0;
bool *enabled;
-   int i;
 
DRM_DEBUG_KMS("\n");
 
+   if (!width)
+   width = dev->mode_config.max_width;
+   if (!height)
+   height = dev->mode_config.max_height;
+
drm_connector_list_iter_begin(dev, _iter);
drm_client_for_each_connector_iter(connector, _iter) {
struct drm_connector **tmp;
 
tmp = krealloc(connectors, (connector_count + 1) * 
sizeof(*connectors), GFP_KERNEL);
-   if (!tmp)
+   if (!tmp) {
+   ret = -ENOMEM;
goto free_connectors;
+   }
 
connectors = tmp

[PATCH v2 08/12] drm/fb-helper: Move out commit code

2019-04-07 Thread Noralf Trønnes
Move the modeset commit code to drm_client_modeset.
No changes except exporting API.

v2: Move to drm_client_modeset.c instead of drm_client.c

Signed-off-by: Noralf Trønnes 
---
 drivers/gpu/drm/drm_client_modeset.c | 287 +++
 drivers/gpu/drm/drm_fb_helper.c  | 282 --
 include/drm/drm_client.h |   4 +
 3 files changed, 291 insertions(+), 282 deletions(-)

diff --git a/drivers/gpu/drm/drm_client_modeset.c 
b/drivers/gpu/drm/drm_client_modeset.c
index bb34222c9db8..94b52f97c06b 100644
--- a/drivers/gpu/drm/drm_client_modeset.c
+++ b/drivers/gpu/drm/drm_client_modeset.c
@@ -11,9 +11,14 @@
 #include 
 #include 
 
+#include 
 #include 
 #include 
 #include 
+#include 
+
+#include "drm_crtc_internal.h"
+#include "drm_internal.h"
 
 /* Used by drm_client and drm_fb_helper */
 int drm_client_modeset_create(struct drm_client_dev *client)
@@ -100,3 +105,285 @@ struct drm_mode_set *drm_client_find_modeset(struct 
drm_client_dev *client, stru
 }
 /* TODO: Remove export when modeset code has been moved over */
 EXPORT_SYMBOL(drm_client_find_modeset);
+
+/**
+ * drm_client_panel_rotation() - Check panel orientation
+ * @modeset: DRM modeset
+ * @rotation: Returned rotation value
+ *
+ * This function checks if the primary plane in @modeset can hw rotate to match
+ * the panel orientation on its connector.
+ *
+ * Note: Currently only 0 and 180 degrees are supported.
+ *
+ * Return:
+ * True if the plane can do the rotation, false otherwise.
+ */
+bool drm_client_panel_rotation(struct drm_mode_set *modeset, unsigned int 
*rotation)
+{
+   struct drm_connector *connector = modeset->connectors[0];
+   struct drm_plane *plane = modeset->crtc->primary;
+   u64 valid_mask = 0;
+   unsigned int i;
+
+   if (!modeset->num_connectors)
+   return false;
+
+   switch (connector->display_info.panel_orientation) {
+   case DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP:
+   *rotation = DRM_MODE_ROTATE_180;
+   break;
+   case DRM_MODE_PANEL_ORIENTATION_LEFT_UP:
+   *rotation = DRM_MODE_ROTATE_90;
+   break;
+   case DRM_MODE_PANEL_ORIENTATION_RIGHT_UP:
+   *rotation = DRM_MODE_ROTATE_270;
+   break;
+   default:
+   *rotation = DRM_MODE_ROTATE_0;
+   }
+
+   /*
+* TODO: support 90 / 270 degree hardware rotation,
+* depending on the hardware this may require the framebuffer
+* to be in a specific tiling format.
+*/
+   if (*rotation != DRM_MODE_ROTATE_180 || !plane->rotation_property)
+   return false;
+
+   for (i = 0; i < plane->rotation_property->num_values; i++)
+   valid_mask |= (1ULL << plane->rotation_property->values[i]);
+
+   if (!(*rotation & valid_mask))
+   return false;
+
+   return true;
+}
+
+static int drm_client_modeset_commit_atomic(struct drm_client_dev *client, 
bool active)
+{
+   struct drm_device *dev = client->dev;
+   struct drm_plane_state *plane_state;
+   struct drm_plane *plane;
+   struct drm_atomic_state *state;
+   struct drm_modeset_acquire_ctx ctx;
+   struct drm_mode_set *mode_set;
+   int ret;
+
+   drm_modeset_acquire_init(, 0);
+
+   state = drm_atomic_state_alloc(dev);
+   if (!state) {
+   ret = -ENOMEM;
+   goto out_ctx;
+   }
+
+   state->acquire_ctx = 
+retry:
+   drm_for_each_plane(plane, dev) {
+   plane_state = drm_atomic_get_plane_state(state, plane);
+   if (IS_ERR(plane_state)) {
+   ret = PTR_ERR(plane_state);
+   goto out_state;
+   }
+
+   plane_state->rotation = DRM_MODE_ROTATE_0;
+
+   /* disable non-primary: */
+   if (plane->type == DRM_PLANE_TYPE_PRIMARY)
+   continue;
+
+   ret = __drm_atomic_helper_disable_plane(plane, plane_state);
+   if (ret != 0)
+   goto out_state;
+   }
+
+   drm_client_for_each_modeset(mode_set, client) {
+   struct drm_plane *primary = mode_set->crtc->primary;
+   unsigned int rotation;
+
+   if (drm_client_panel_rotation(mode_set, )) {
+   /* Cannot fail as we've already gotten the plane state 
above */
+   plane_state = drm_atomic_get_new_plane_state(state, 
primary);
+   plane_state->rotation = rotation;
+   }
+
+   ret = __drm_atomic_helper_set_config(mode_set, state);
+   if (ret != 0)
+   goto out_state;
+
+   /*
+* __drm_atomic_helper_set_config() sets active when a
+* mode is set, unconditionally clear it if we force DPMS off
+ 

[PATCH v2 06/12] drm/fb-helper: Remove drm_fb_helper_crtc

2019-04-07 Thread Noralf Trønnes
It now only contains the modeset so use that directly instead and attach
a modeset array to drm_client_dev. drm_fb_helper will use this array.
Code will later be moved to drm_client, so add code there in a new file
drm_client_modeset.c with MIT license to match drm_fb_helper.c.

The modeset connector array size is hardcoded for the cloned case to avoid
having to pass in a value from the driver. A value of 8 is chosen to err
on the safe side. This means that the max connector argument for
drm_fb_helper_init() and drm_fb_helper_fbdev_setup() isn't used anymore,
a todo entry for this is added.

In pan_display_atomic() restore_fbdev_mode_force() is used instead of
restore_fbdev_mode_atomic() because that one will later become internal
to drm_client_modeset.

Locking order:
1. drm_fb_helper->lock
2. drm_master_internal_acquire
3. drm_client_dev->modeset_mutex

v2:
- Add modesets array to drm_client (Daniel Vetter)
- Use a new file for the modeset code (Daniel Vetter)
- File has to be MIT licensed (Emmanuel Vadot)
- Add copyrights from drm_fb_helper.c

Signed-off-by: Noralf Trønnes 
---
 Documentation/gpu/todo.rst   |   7 +
 drivers/gpu/drm/Makefile |   2 +-
 drivers/gpu/drm/drm_client.c |  10 +-
 drivers/gpu/drm/drm_client_modeset.c | 102 +
 drivers/gpu/drm/drm_fb_helper.c  | 301 +++
 include/drm/drm_client.h |  28 +++
 include/drm/drm_fb_helper.h  |   8 -
 7 files changed, 272 insertions(+), 186 deletions(-)
 create mode 100644 drivers/gpu/drm/drm_client_modeset.c

diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst
index 1528ad2d598b..8fa08b5feab7 100644
--- a/Documentation/gpu/todo.rst
+++ b/Documentation/gpu/todo.rst
@@ -300,6 +300,13 @@ it to use drm_mode_hsync() instead.
 
 Contact: Sean Paul
 
+drm_fb_helper cleanup tasks
+---
+
+- The max connector argument for drm_fb_helper_init() and
+  drm_fb_helper_fbdev_setup() isn't used anymore and can be removed.
+
+
 Core refactorings
 =
 
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 6c7e8d162b4e..08c77c10ccbb 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -19,7 +19,7 @@ drm-y   :=drm_auth.o drm_bufs.o drm_cache.o \
drm_plane.o drm_color_mgmt.o drm_print.o \
drm_dumb_buffers.o drm_mode_config.o drm_vblank.o \
drm_syncobj.o drm_lease.o drm_writeback.o drm_client.o \
-   drm_atomic_uapi.o
+   drm_client_modeset.o drm_atomic_uapi.o
 
 drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o
 drm-$(CONFIG_DRM_VM) += drm_vm.o
diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c
index 9b2bd28dde0a..3ad5b57c1419 100644
--- a/drivers/gpu/drm/drm_client.c
+++ b/drivers/gpu/drm/drm_client.c
@@ -91,14 +91,20 @@ int drm_client_init(struct drm_device *dev, struct 
drm_client_dev *client,
client->name = name;
client->funcs = funcs;
 
-   ret = drm_client_open(client);
+   ret = drm_client_modeset_create(client);
if (ret)
goto err_put_module;
 
+   ret = drm_client_open(client);
+   if (ret)
+   goto err_free;
+
drm_dev_get(dev);
 
return 0;
 
+err_free:
+   drm_client_modeset_free(client);
 err_put_module:
if (funcs)
module_put(funcs->owner);
@@ -147,6 +153,8 @@ void drm_client_release(struct drm_client_dev *client)
 
DRM_DEV_DEBUG_KMS(dev->dev, "%s\n", client->name);
 
+   drm_client_modeset_release(client);
+   drm_client_modeset_free(client);
drm_client_close(client);
drm_dev_put(dev);
if (client->funcs)
diff --git a/drivers/gpu/drm/drm_client_modeset.c 
b/drivers/gpu/drm/drm_client_modeset.c
new file mode 100644
index ..bb34222c9db8
--- /dev/null
+++ b/drivers/gpu/drm/drm_client_modeset.c
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2018 Noralf Trønnes
+ * Copyright (c) 2006-2009 Red Hat Inc.
+ * Copyright (c) 2006-2008 Intel Corporation
+ *   Jesse Barnes 
+ * Copyright (c) 2007 Dave Airlie 
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+/* Used by drm_client and drm_fb_helper */
+int drm_client_modeset_create(struct drm_client_dev *client)
+{
+   struct drm_device *dev = client->dev;
+   unsigned int num_crtc = dev->mode_config.num_crtc;
+   unsigned int max_connector_count = 1;
+   struct drm_mode_set *modeset;
+   struct drm_crtc *crtc;
+   unsigned int i = 0;
+
+   /* Add terminating zero entry to enable index less iteration */
+   client->modesets = kcalloc(num_crtc + 1, sizeof(*client->modesets), 
GFP_KERNEL);
+   if (!client->modesets)
+   return -ENOMEM;
+
+   mutex_init(>modeset_mutex);
+
+   drm_for_each_crtc(crtc, dev)
+   client->

[PATCH v2 04/12] drm/fb-helper: No need to cache rotation and sw_rotations

2019-04-07 Thread Noralf Trønnes
Getting rotation info is cheap so we can do it on demand.

This is done in preparation for the removal of struct drm_fb_helper_crtc.

Cc: Hans de Goede 
Signed-off-by: Noralf Trønnes 
Acked-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_fb_helper.c | 131 
 include/drm/drm_fb_helper.h |   8 --
 2 files changed, 65 insertions(+), 74 deletions(-)

diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index eda8b63f350d..2f71160cc904 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -388,6 +388,49 @@ int drm_fb_helper_debug_leave(struct fb_info *info)
 }
 EXPORT_SYMBOL(drm_fb_helper_debug_leave);
 
+/* Check if the plane can hw rotate to match panel orientation */
+static bool drm_fb_helper_panel_rotation(struct drm_mode_set *modeset,
+unsigned int *rotation)
+{
+   struct drm_connector *connector = modeset->connectors[0];
+   struct drm_plane *plane = modeset->crtc->primary;
+   u64 valid_mask = 0;
+   unsigned int i;
+
+   if (!modeset->num_connectors)
+   return false;
+
+   switch (connector->display_info.panel_orientation) {
+   case DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP:
+   *rotation = DRM_MODE_ROTATE_180;
+   break;
+   case DRM_MODE_PANEL_ORIENTATION_LEFT_UP:
+   *rotation = DRM_MODE_ROTATE_90;
+   break;
+   case DRM_MODE_PANEL_ORIENTATION_RIGHT_UP:
+   *rotation = DRM_MODE_ROTATE_270;
+   break;
+   default:
+   *rotation = DRM_MODE_ROTATE_0;
+   }
+
+   /*
+* TODO: support 90 / 270 degree hardware rotation,
+* depending on the hardware this may require the framebuffer
+* to be in a specific tiling format.
+*/
+   if (*rotation != DRM_MODE_ROTATE_180 || !plane->rotation_property)
+   return false;
+
+   for (i = 0; i < plane->rotation_property->num_values; i++)
+   valid_mask |= (1ULL << plane->rotation_property->values[i]);
+
+   if (!(*rotation & valid_mask))
+   return false;
+
+   return true;
+}
+
 static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool 
active)
 {
struct drm_device *dev = fb_helper->dev;
@@ -428,10 +471,13 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper 
*fb_helper, bool activ
for (i = 0; i < fb_helper->crtc_count; i++) {
struct drm_mode_set *mode_set = 
_helper->crtc_info[i].mode_set;
struct drm_plane *primary = mode_set->crtc->primary;
+   unsigned int rotation;
 
-   /* Cannot fail as we've already gotten the plane state above */
-   plane_state = drm_atomic_get_new_plane_state(state, primary);
-   plane_state->rotation = fb_helper->crtc_info[i].rotation;
+   if (drm_fb_helper_panel_rotation(mode_set, )) {
+   /* Cannot fail as we've already gotten the plane state 
above */
+   plane_state = drm_atomic_get_new_plane_state(state, 
primary);
+   plane_state->rotation = rotation;
+   }
 
ret = __drm_atomic_helper_set_config(mode_set, state);
if (ret != 0)
@@ -871,7 +917,6 @@ int drm_fb_helper_init(struct drm_device *dev,
if (!fb_helper->crtc_info[i].mode_set.connectors)
goto out_free;
fb_helper->crtc_info[i].mode_set.num_connectors = 0;
-   fb_helper->crtc_info[i].rotation = DRM_MODE_ROTATE_0;
}
 
i = 0;
@@ -2500,62 +2545,6 @@ static int drm_pick_crtcs(struct drm_fb_helper 
*fb_helper,
return best_score;
 }
 
-/*
- * This function checks if rotation is necessary because of panel orientation
- * and if it is, if it is supported.
- * If rotation is necessary and supported, it gets set in fb_crtc.rotation.
- * If rotation is necessary but not supported, a DRM_MODE_ROTATE_* flag gets
- * or-ed into fb_helper->sw_rotations. In drm_setup_crtcs_fb() we check if only
- * one bit is set and then we set fb_info.fbcon_rotate_hint to make fbcon do
- * the unsupported rotation.
- */
-static void drm_setup_crtc_rotation(struct drm_fb_helper *fb_helper,
-   struct drm_fb_helper_crtc *fb_crtc,
-   struct drm_connector *connector)
-{
-   struct drm_plane *plane = fb_crtc->mode_set.crtc->primary;
-   uint64_t valid_mask = 0;
-   int i, rotation;
-
-   fb_crtc->rotation = DRM_MODE_ROTATE_0;
-
-   switch (connector->display_info.panel_orientation) {
-   case DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP:
-   rotation = DRM_MODE_ROTATE_180;
-   break;
-   case DRM_MODE_PANEL_ORIENTATI

[PATCH v2 07/12] drm/fb-helper: Prepare to move out commit code

2019-04-07 Thread Noralf Trønnes
This makes the necessary changes so the commit code can be moved out to
drm_client as-is in the next patch. It's split up to ease review.

Signed-off-by: Noralf Trønnes 
---
 drivers/gpu/drm/drm_fb_helper.c | 122 +---
 1 file changed, 81 insertions(+), 41 deletions(-)

diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index b65edfc99feb..0229e187e6de 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -388,9 +388,20 @@ int drm_fb_helper_debug_leave(struct fb_info *info)
 }
 EXPORT_SYMBOL(drm_fb_helper_debug_leave);
 
-/* Check if the plane can hw rotate to match panel orientation */
-static bool drm_fb_helper_panel_rotation(struct drm_mode_set *modeset,
-unsigned int *rotation)
+/**
+ * drm_client_panel_rotation() - Check panel orientation
+ * @modeset: DRM modeset
+ * @rotation: Returned rotation value
+ *
+ * This function checks if the primary plane in @modeset can hw rotate to match
+ * the panel orientation on its connector.
+ *
+ * Note: Currently only 0 and 180 degrees are supported.
+ *
+ * Return:
+ * True if the plane can do the rotation, false otherwise.
+ */
+bool drm_client_panel_rotation(struct drm_mode_set *modeset, unsigned int 
*rotation)
 {
struct drm_connector *connector = modeset->connectors[0];
struct drm_plane *plane = modeset->crtc->primary;
@@ -431,10 +442,9 @@ static bool drm_fb_helper_panel_rotation(struct 
drm_mode_set *modeset,
return true;
 }
 
-static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool 
active)
+static int drm_client_modeset_commit_atomic(struct drm_client_dev *client, 
bool active)
 {
-   struct drm_client_dev *client = _helper->client;
-   struct drm_device *dev = fb_helper->dev;
+   struct drm_device *dev = client->dev;
struct drm_plane_state *plane_state;
struct drm_plane *plane;
struct drm_atomic_state *state;
@@ -474,7 +484,7 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper 
*fb_helper, bool activ
struct drm_plane *primary = mode_set->crtc->primary;
unsigned int rotation;
 
-   if (drm_fb_helper_panel_rotation(mode_set, )) {
+   if (drm_client_panel_rotation(mode_set, )) {
/* Cannot fail as we've already gotten the plane state 
above */
plane_state = drm_atomic_get_new_plane_state(state, 
primary);
plane_state->rotation = rotation;
@@ -516,15 +526,14 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper 
*fb_helper, bool activ
goto retry;
 }
 
-static int restore_fbdev_mode_legacy(struct drm_fb_helper *fb_helper)
+static int drm_client_modeset_commit_legacy(struct drm_client_dev *client)
 {
-   struct drm_client_dev *client = _helper->client;
-   struct drm_device *dev = fb_helper->dev;
+   struct drm_device *dev = client->dev;
struct drm_mode_set *mode_set;
struct drm_plane *plane;
int ret = 0;
 
-   drm_modeset_lock_all(fb_helper->dev);
+   drm_modeset_lock_all(dev);
drm_for_each_plane(plane, dev) {
if (plane->type != DRM_PLANE_TYPE_PRIMARY)
drm_plane_force_disable(plane);
@@ -553,35 +562,53 @@ static int restore_fbdev_mode_legacy(struct drm_fb_helper 
*fb_helper)
goto out;
}
 out:
-   drm_modeset_unlock_all(fb_helper->dev);
+   drm_modeset_unlock_all(dev);
 
return ret;
 }
 
-static int restore_fbdev_mode_force(struct drm_fb_helper *fb_helper)
+/**
+ * drm_client_modeset_commit_force() - Force commit CRTC configuration
+ * @client: DRM client
+ *
+ * Commit modeset configuration to crtcs without checking if there is a DRM 
master.
+ *
+ * Returns:
+ * Zero on success or negative error code on failure.
+ */
+int drm_client_modeset_commit_force(struct drm_client_dev *client)
 {
-   struct drm_device *dev = fb_helper->dev;
+   struct drm_device *dev = client->dev;
int ret;
 
-   mutex_lock(_helper->client.modeset_mutex);
+   mutex_lock(>modeset_mutex);
if (drm_drv_uses_atomic_modeset(dev))
-   ret = restore_fbdev_mode_atomic(fb_helper, true);
+   ret = drm_client_modeset_commit_atomic(client, true);
else
-   ret = restore_fbdev_mode_legacy(fb_helper);
-   mutex_unlock(_helper->client.modeset_mutex);
+   ret = drm_client_modeset_commit_legacy(client);
+   mutex_unlock(>modeset_mutex);
 
return ret;
 }
 
-static int restore_fbdev_mode(struct drm_fb_helper *fb_helper)
+/**
+ * drm_client_modeset_commit() - Commit CRTC configuration
+ * @client: DRM client
+ *
+ * Commit modeset configuration to crtcs.
+ *
+ * Returns:
+ * Zero on success or negative error code on failure.
+ */
+int drm_client_

[PATCH v2 09/12] drm/fb-helper: Remove drm_fb_helper_connector

2019-04-07 Thread Noralf Trønnes
All drivers add all their connectors so there's no need to keep around an
array of available connectors.

Rename functions which signature is changed since they will be moved to
drm_client in a later patch.

Signed-off-by: Noralf Trønnes 
---

checkpatch complains, but I'm unable to satisfy it:

ERROR: Macros with complex values should be enclosed in parentheses
#941: FILE: include/drm/drm_client.h:181:
+#define drm_client_for_each_connector_iter(connector, iter) \
+   drm_for_each_connector_iter(connector, iter) \
+   if (connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK)

 Documentation/gpu/todo.rst  |   3 +
 drivers/gpu/drm/drm_fb_helper.c | 498 ++--
 include/drm/drm_client.h|  15 +
 include/drm/drm_fb_helper.h |  80 ++---
 4 files changed, 192 insertions(+), 404 deletions(-)

diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst
index 8fa08b5feab7..f6cdd1c26788 100644
--- a/Documentation/gpu/todo.rst
+++ b/Documentation/gpu/todo.rst
@@ -306,6 +306,9 @@ drm_fb_helper cleanup tasks
 - The max connector argument for drm_fb_helper_init() and
   drm_fb_helper_fbdev_setup() isn't used anymore and can be removed.
 
+- The helper doesn't keep an array of connectors anymore so these can be
+  removed: drm_fb_helper_single_add_all_connectors(),
+  drm_fb_helper_add_one_connector() and drm_fb_helper_remove_one_connector().
 
 Core refactorings
 =
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 73fbcd748ddd..e13026724b2c 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -90,12 +90,6 @@ static DEFINE_MUTEX(kernel_fb_helper_lock);
  * Setup fbdev emulation by calling drm_fb_helper_fbdev_setup() and tear it
  * down by calling drm_fb_helper_fbdev_teardown().
  *
- * Drivers that need to handle connector hotplugging (e.g. dp mst) can't use
- * the setup helper and will need to do the whole four-step setup process with
- * drm_fb_helper_prepare(), drm_fb_helper_init(),
- * drm_fb_helper_single_add_all_connectors(), enable hotplugging and
- * drm_fb_helper_initial_config() to avoid a possible race window.
- *
  * At runtime drivers should restore the fbdev console by using
  * drm_fb_helper_lastclose() as their _driver.lastclose callback.
  * They should also notify the fb helper code from updates to the output
@@ -118,8 +112,7 @@ static DEFINE_MUTEX(kernel_fb_helper_lock);
  * encoders and connectors. To finish up the fbdev helper initialization, the
  * drm_fb_helper_init() function is called. To probe for all attached displays
  * and set up an initial configuration using the detected hardware, drivers
- * should call drm_fb_helper_single_add_all_connectors() followed by
- * drm_fb_helper_initial_config().
+ * should call drm_fb_helper_initial_config().
  *
  * If _framebuffer_funcs.dirty is set, the
  * drm_fb_helper_{cfb,sys}_{write,fillrect,copyarea,imageblit} functions will
@@ -132,165 +125,6 @@ static DEFINE_MUTEX(kernel_fb_helper_lock);
  * deferred I/O (coupled with drm_fb_helper_fbdev_teardown()).
  */
 
-#define drm_fb_helper_for_each_connector(fbh, i__) \
-   for (({ lockdep_assert_held(&(fbh)->lock); }), \
-i__ = 0; i__ < (fbh)->connector_count; i__++)
-
-static int __drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper,
-struct drm_connector *connector)
-{
-   struct drm_fb_helper_connector *fb_conn;
-   struct drm_fb_helper_connector **temp;
-   unsigned int count;
-
-   if (!drm_fbdev_emulation)
-   return 0;
-
-   lockdep_assert_held(_helper->lock);
-
-   count = fb_helper->connector_count + 1;
-
-   if (count > fb_helper->connector_info_alloc_count) {
-   size_t size = count * sizeof(fb_conn);
-
-   temp = krealloc(fb_helper->connector_info, size, GFP_KERNEL);
-   if (!temp)
-   return -ENOMEM;
-
-   fb_helper->connector_info_alloc_count = count;
-   fb_helper->connector_info = temp;
-   }
-
-   fb_conn = kzalloc(sizeof(*fb_conn), GFP_KERNEL);
-   if (!fb_conn)
-   return -ENOMEM;
-
-   drm_connector_get(connector);
-   fb_conn->connector = connector;
-   fb_helper->connector_info[fb_helper->connector_count++] = fb_conn;
-
-   return 0;
-}
-
-int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper,
-   struct drm_connector *connector)
-{
-   int err;
-
-   if (!fb_helper)
-   return 0;
-
-   mutex_lock(_helper->lock);
-   err = __drm_fb_helper_add_one_connector(fb_helper, connector);
-   mutex_unlock(_helper->lock);
-
-   return err;
-}
-EXPORT_SYMBOL(drm_fb_helper_add_one_connector);
-
-/**
- * drm_fb_helper_single_add_all_connectors() - add all connectors to fbdev
- * 

[PATCH v2 05/12] drm/fb-helper: Remove drm_fb_helper_crtc->{x, y, desired_mode}

2019-04-07 Thread Noralf Trønnes
The values are already present in the modeset.

This is done in preparation for the removal of struct drm_fb_helper_crtc.

Signed-off-by: Noralf Trønnes 
Reviewed-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_fb_helper.c | 12 
 include/drm/drm_fb_helper.h |  2 --
 2 files changed, 4 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 2f71160cc904..69dddc4a9231 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -2021,16 +2021,16 @@ static int drm_fb_helper_single_fb_probe(struct 
drm_fb_helper *fb_helper,
 */
bool lastv = true, lasth = true;
 
-   desired_mode = fb_helper->crtc_info[i].desired_mode;
mode_set = _helper->crtc_info[i].mode_set;
+   desired_mode = mode_set->mode;
 
if (!desired_mode)
continue;
 
crtc_count++;
 
-   x = fb_helper->crtc_info[i].x;
-   y = fb_helper->crtc_info[i].y;
+   x = mode_set->x;
+   y = mode_set->y;
 
sizes.surface_width  = max_t(u32, desired_mode->hdisplay + x, 
sizes.surface_width);
sizes.surface_height = max_t(u32, desired_mode->vdisplay + y, 
sizes.surface_height);
@@ -2803,11 +2803,7 @@ static void drm_setup_crtcs(struct drm_fb_helper 
*fb_helper,
DRM_DEBUG_KMS("desired mode %s set on crtc %d 
(%d,%d)\n",
  mode->name, 
fb_crtc->mode_set.crtc->base.id, offset->x, offset->y);
 
-   fb_crtc->desired_mode = mode;
-   fb_crtc->x = offset->x;
-   fb_crtc->y = offset->y;
-   modeset->mode = drm_mode_duplicate(dev,
-  
fb_crtc->desired_mode);
+   modeset->mode = drm_mode_duplicate(dev, mode);
drm_connector_get(connector);
modeset->connectors[modeset->num_connectors++] = 
connector;
modeset->x = offset->x;
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
index d954f48c9636..0d6d23a15b42 100644
--- a/include/drm/drm_fb_helper.h
+++ b/include/drm/drm_fb_helper.h
@@ -48,8 +48,6 @@ struct drm_fb_offset {
 
 struct drm_fb_helper_crtc {
struct drm_mode_set mode_set;
-   struct drm_display_mode *desired_mode;
-   int x, y;
 };
 
 /**
-- 
2.20.1

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

[PATCH v2 00/12] drm/fb-helper: Move modesetting code to drm_client

2019-04-07 Thread Noralf Trønnes
This moves the modesetting code from drm_fb_helper to drm_client so it
can be shared by all internal clients.

The main change this time is to attach the modeset array to
drm_client_dev and honour the drm_fb_helper MIT license. I've dropped
the display abstraction.

Noralf.

Cc: Emmanuel Vadot 

Noralf Trønnes (12):
  drm/atomic: Move __drm_atomic_helper_disable_plane/set_config()
  drm/fb-helper: Avoid race with DRM userspace
  drm/i915/fbdev: Move intel_fb_initial_config() to fbdev helper
  drm/fb-helper: No need to cache rotation and sw_rotations
  drm/fb-helper: Remove drm_fb_helper_crtc->{x,y,desired_mode}
  drm/fb-helper: Remove drm_fb_helper_crtc
  drm/fb-helper: Prepare to move out commit code
  drm/fb-helper: Move out commit code
  drm/fb-helper: Remove drm_fb_helper_connector
  drm/fb-helper: Prepare to move out modeset config code
  drm/fb-helper: Move out modeset config code
  drm/client: Hack: Add bootsplash example

 Documentation/gpu/todo.rst   |   10 +
 drivers/gpu/drm/Kconfig  |5 +
 drivers/gpu/drm/Makefile |3 +-
 drivers/gpu/drm/drm_atomic.c |  168 
 drivers/gpu/drm/drm_atomic_helper.c  |  164 
 drivers/gpu/drm/drm_auth.c   |   20 +
 drivers/gpu/drm/drm_bootsplash.c |  359 
 drivers/gpu/drm/drm_client.c |   17 +-
 drivers/gpu/drm/drm_client_modeset.c | 1086 +++
 drivers/gpu/drm/drm_crtc_internal.h  |5 +
 drivers/gpu/drm/drm_drv.c|4 +
 drivers/gpu/drm/drm_fb_helper.c  | 1195 +++---
 drivers/gpu/drm/drm_internal.h   |2 +
 drivers/gpu/drm/i915/intel_fbdev.c   |  218 -
 include/drm/drm_atomic_helper.h  |4 -
 include/drm/drm_client.h |   48 ++
 include/drm/drm_fb_helper.h  |  125 +--
 17 files changed, 1859 insertions(+), 1574 deletions(-)
 create mode 100644 drivers/gpu/drm/drm_bootsplash.c
 create mode 100644 drivers/gpu/drm/drm_client_modeset.c

-- 
2.20.1

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

[PATCH v2 03/12] drm/i915/fbdev: Move intel_fb_initial_config() to fbdev helper

2019-04-07 Thread Noralf Trønnes
It is generic code and having it in the helper will let other drivers
benefit from it.

One change was necessary assuming this to be true:
INTEL_INFO(dev_priv)->num_pipes == dev->mode_config.num_crtc

Suggested-by: Daniel Vetter 
Cc: Jani Nikula 
Cc: Joonas Lahtinen 
Cc: Rodrigo Vivi 
Cc: intel-...@lists.freedesktop.org
Signed-off-by: Noralf Trønnes 
Reviewed-by: Jani Nikula 
---
 drivers/gpu/drm/drm_fb_helper.c| 194 -
 drivers/gpu/drm/i915/intel_fbdev.c | 218 -
 include/drm/drm_fb_helper.h|  23 ---
 3 files changed, 190 insertions(+), 245 deletions(-)

diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index a6be09ae899b..eda8b63f350d 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -2556,6 +2556,194 @@ static void drm_setup_crtc_rotation(struct 
drm_fb_helper *fb_helper,
fb_helper->sw_rotations |= DRM_MODE_ROTATE_0;
 }
 
+static struct drm_fb_helper_crtc *
+drm_fb_helper_crtc(struct drm_fb_helper *fb_helper, struct drm_crtc *crtc)
+{
+   int i;
+
+   for (i = 0; i < fb_helper->crtc_count; i++)
+   if (fb_helper->crtc_info[i].mode_set.crtc == crtc)
+   return _helper->crtc_info[i];
+
+   return NULL;
+}
+
+/* Try to read the BIOS display configuration and use it for the initial 
config */
+static bool drm_fb_helper_firmware_config(struct drm_fb_helper *fb_helper,
+ struct drm_fb_helper_crtc **crtcs,
+ struct drm_display_mode **modes,
+ struct drm_fb_offset *offsets,
+ bool *enabled, int width, int height)
+{
+   struct drm_device *dev = fb_helper->dev;
+   unsigned int count = min(fb_helper->connector_count, BITS_PER_LONG);
+   unsigned long conn_configured, conn_seq;
+   int i, j;
+   bool *save_enabled;
+   bool fallback = true, ret = true;
+   int num_connectors_enabled = 0;
+   int num_connectors_detected = 0;
+   struct drm_modeset_acquire_ctx ctx;
+
+   save_enabled = kcalloc(count, sizeof(bool), GFP_KERNEL);
+   if (!save_enabled)
+   return false;
+
+   drm_modeset_acquire_init(, 0);
+
+   while (drm_modeset_lock_all_ctx(dev, ) != 0)
+   drm_modeset_backoff();
+
+   memcpy(save_enabled, enabled, count);
+   conn_seq = GENMASK(count - 1, 0);
+   conn_configured = 0;
+retry:
+   for (i = 0; i < count; i++) {
+   struct drm_fb_helper_connector *fb_conn;
+   struct drm_connector *connector;
+   struct drm_encoder *encoder;
+   struct drm_fb_helper_crtc *new_crtc;
+
+   fb_conn = fb_helper->connector_info[i];
+   connector = fb_conn->connector;
+
+   if (conn_configured & BIT(i))
+   continue;
+
+   /* First pass, only consider tiled connectors */
+   if (conn_seq == GENMASK(count - 1, 0) && !connector->has_tile)
+   continue;
+
+   if (connector->status == connector_status_connected)
+   num_connectors_detected++;
+
+   if (!enabled[i]) {
+   DRM_DEBUG_KMS("connector %s not enabled, skipping\n",
+ connector->name);
+   conn_configured |= BIT(i);
+   continue;
+   }
+
+   if (connector->force == DRM_FORCE_OFF) {
+   DRM_DEBUG_KMS("connector %s is disabled by user, 
skipping\n",
+ connector->name);
+   enabled[i] = false;
+   continue;
+   }
+
+   encoder = connector->state->best_encoder;
+   if (!encoder || WARN_ON(!connector->state->crtc)) {
+   if (connector->force > DRM_FORCE_OFF)
+   goto bail;
+
+   DRM_DEBUG_KMS("connector %s has no encoder or crtc, 
skipping\n",
+ connector->name);
+   enabled[i] = false;
+   conn_configured |= BIT(i);
+   continue;
+   }
+
+   num_connectors_enabled++;
+
+   new_crtc = drm_fb_helper_crtc(fb_helper, 
connector->state->crtc);
+
+   /*
+* Make sure we're not trying to drive multiple connectors
+* with a single CRTC, since our cloning support may not
+* match the BIOS.
+*/
+   for (j = 0; j < count; j++) {
+   if (crtcs[j] == new_crtc) {
+ 

[PATCH v2 02/12] drm/fb-helper: Avoid race with DRM userspace

2019-04-07 Thread Noralf Trønnes
drm_fb_helper_is_bound() is used to check if DRM userspace is in control.
This is done by looking at the fb on the primary plane. By the time
fb-helper gets around to committing, it's possible that the facts have
changed.

Avoid this race by holding the drm_device->master_mutex lock while
committing. When DRM userspace does its first open, it will now wait
until fb-helper is done. The helper will stay away if there's a master.

Locking rule: Always take the fb-helper lock first.

v2:
- Remove drm_fb_helper_is_bound() (Daniel Vetter)
- No need to check fb_helper->dev->master in
  drm_fb_helper_single_fb_probe(), restore_fbdev_mode() has the check.

Suggested-by: Daniel Vetter 
Signed-off-by: Noralf Trønnes 
---
 drivers/gpu/drm/drm_auth.c  | 20 
 drivers/gpu/drm/drm_fb_helper.c | 90 -
 drivers/gpu/drm/drm_internal.h  |  2 +
 3 files changed, 67 insertions(+), 45 deletions(-)

diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c
index 1669c42c40ed..db199807b7dc 100644
--- a/drivers/gpu/drm/drm_auth.c
+++ b/drivers/gpu/drm/drm_auth.c
@@ -368,3 +368,23 @@ void drm_master_put(struct drm_master **master)
*master = NULL;
 }
 EXPORT_SYMBOL(drm_master_put);
+
+/* Used by drm_client and drm_fb_helper */
+bool drm_master_internal_acquire(struct drm_device *dev)
+{
+   mutex_lock(>master_mutex);
+   if (dev->master) {
+   mutex_unlock(>master_mutex);
+   return false;
+   }
+
+   return true;
+}
+EXPORT_SYMBOL(drm_master_internal_acquire);
+
+/* Used by drm_client and drm_fb_helper */
+void drm_master_internal_release(struct drm_device *dev)
+{
+   mutex_unlock(>master_mutex);
+}
+EXPORT_SYMBOL(drm_master_internal_release);
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 84791dd4a90d..a6be09ae899b 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -44,6 +44,7 @@
 
 #include "drm_crtc_internal.h"
 #include "drm_crtc_helper_internal.h"
+#include "drm_internal.h"
 
 static bool drm_fbdev_emulation = true;
 module_param_named(fbdev_emulation, drm_fbdev_emulation, bool, 0600);
@@ -509,7 +510,7 @@ static int restore_fbdev_mode_legacy(struct drm_fb_helper 
*fb_helper)
return ret;
 }
 
-static int restore_fbdev_mode(struct drm_fb_helper *fb_helper)
+static int restore_fbdev_mode_force(struct drm_fb_helper *fb_helper)
 {
struct drm_device *dev = fb_helper->dev;
 
@@ -519,6 +520,21 @@ static int restore_fbdev_mode(struct drm_fb_helper 
*fb_helper)
return restore_fbdev_mode_legacy(fb_helper);
 }
 
+static int restore_fbdev_mode(struct drm_fb_helper *fb_helper)
+{
+   struct drm_device *dev = fb_helper->dev;
+   int ret;
+
+   if (!drm_master_internal_acquire(dev))
+   return -EBUSY;
+
+   ret = restore_fbdev_mode_force(fb_helper);
+
+   drm_master_internal_release(dev);
+
+   return ret;
+}
+
 /**
  * drm_fb_helper_restore_fbdev_mode_unlocked - restore fbdev configuration
  * @fb_helper: driver-allocated fbdev helper, can be NULL
@@ -556,34 +572,6 @@ int drm_fb_helper_restore_fbdev_mode_unlocked(struct 
drm_fb_helper *fb_helper)
 }
 EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode_unlocked);
 
-static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper)
-{
-   struct drm_device *dev = fb_helper->dev;
-   struct drm_crtc *crtc;
-   int bound = 0, crtcs_bound = 0;
-
-   /*
-* Sometimes user space wants everything disabled, so don't steal the
-* display if there's a master.
-*/
-   if (READ_ONCE(dev->master))
-   return false;
-
-   drm_for_each_crtc(crtc, dev) {
-   drm_modeset_lock(>mutex, NULL);
-   if (crtc->primary->fb)
-   crtcs_bound++;
-   if (crtc->primary->fb == fb_helper->fb)
-   bound++;
-   drm_modeset_unlock(>mutex);
-   }
-
-   if (bound < crtcs_bound)
-   return false;
-
-   return true;
-}
-
 #ifdef CONFIG_MAGIC_SYSRQ
 /*
  * restore fbcon display for all kms driver's using this helper, used for sysrq
@@ -604,7 +592,7 @@ static bool drm_fb_helper_force_kernel_mode(void)
continue;
 
mutex_lock(>lock);
-   ret = restore_fbdev_mode(helper);
+   ret = restore_fbdev_mode_force(helper);
if (ret)
error = true;
mutex_unlock(>lock);
@@ -663,20 +651,22 @@ static void dpms_legacy(struct drm_fb_helper *fb_helper, 
int dpms_mode)
 static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode)
 {
struct drm_fb_helper *fb_helper = info->par;
+   struct drm_device *dev = fb_helper->dev;
 
/*
 * For each CRTC in this fb, turn the connectors o

[PATCH v2 01/12] drm/atomic: Move __drm_atomic_helper_disable_plane/set_config()

2019-04-07 Thread Noralf Trønnes
Prepare for moving drm_fb_helper modesetting code to drm_client.
drm_client will be linked to drm.ko, so move
__drm_atomic_helper_disable_plane() and __drm_atomic_helper_set_config()
out of drm_kms_helper.ko.

While at it, fix two checkpatch complaints:
- WARNING: Block comments use a trailing */ on a separate line
- CHECK: Alignment should match open parenthesis

Signed-off-by: Noralf Trønnes 
Reviewed-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_atomic.c| 168 
 drivers/gpu/drm/drm_atomic_helper.c | 164 ---
 drivers/gpu/drm/drm_crtc_internal.h |   5 +
 include/drm/drm_atomic_helper.h |   4 -
 4 files changed, 173 insertions(+), 168 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 5eb40130fafb..c3a9ffbf2310 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -1130,6 +1130,174 @@ int drm_atomic_nonblocking_commit(struct 
drm_atomic_state *state)
 }
 EXPORT_SYMBOL(drm_atomic_nonblocking_commit);
 
+/* just used from drm-client and atomic-helper: */
+int __drm_atomic_helper_disable_plane(struct drm_plane *plane,
+ struct drm_plane_state *plane_state)
+{
+   int ret;
+
+   ret = drm_atomic_set_crtc_for_plane(plane_state, NULL);
+   if (ret != 0)
+   return ret;
+
+   drm_atomic_set_fb_for_plane(plane_state, NULL);
+   plane_state->crtc_x = 0;
+   plane_state->crtc_y = 0;
+   plane_state->crtc_w = 0;
+   plane_state->crtc_h = 0;
+   plane_state->src_x = 0;
+   plane_state->src_y = 0;
+   plane_state->src_w = 0;
+   plane_state->src_h = 0;
+
+   return 0;
+}
+EXPORT_SYMBOL(__drm_atomic_helper_disable_plane);
+
+static int update_output_state(struct drm_atomic_state *state,
+  struct drm_mode_set *set)
+{
+   struct drm_device *dev = set->crtc->dev;
+   struct drm_crtc *crtc;
+   struct drm_crtc_state *new_crtc_state;
+   struct drm_connector *connector;
+   struct drm_connector_state *new_conn_state;
+   int ret, i;
+
+   ret = drm_modeset_lock(>mode_config.connection_mutex,
+  state->acquire_ctx);
+   if (ret)
+   return ret;
+
+   /* First disable all connectors on the target crtc. */
+   ret = drm_atomic_add_affected_connectors(state, set->crtc);
+   if (ret)
+   return ret;
+
+   for_each_new_connector_in_state(state, connector, new_conn_state, i) {
+   if (new_conn_state->crtc == set->crtc) {
+   ret = drm_atomic_set_crtc_for_connector(new_conn_state,
+   NULL);
+   if (ret)
+   return ret;
+
+   /* Make sure legacy setCrtc always re-trains */
+   new_conn_state->link_status = DRM_LINK_STATUS_GOOD;
+   }
+   }
+
+   /* Then set all connectors from set->connectors on the target crtc */
+   for (i = 0; i < set->num_connectors; i++) {
+   new_conn_state = drm_atomic_get_connector_state(state,
+   
set->connectors[i]);
+   if (IS_ERR(new_conn_state))
+   return PTR_ERR(new_conn_state);
+
+   ret = drm_atomic_set_crtc_for_connector(new_conn_state,
+   set->crtc);
+   if (ret)
+   return ret;
+   }
+
+   for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
+   /*
+* Don't update ->enable for the CRTC in the set_config request,
+* since a mismatch would indicate a bug in the upper layers.
+* The actual modeset code later on will catch any
+* inconsistencies here.
+*/
+   if (crtc == set->crtc)
+   continue;
+
+   if (!new_crtc_state->connector_mask) {
+   ret = drm_atomic_set_mode_prop_for_crtc(new_crtc_state,
+   NULL);
+   if (ret < 0)
+   return ret;
+
+   new_crtc_state->active = false;
+   }
+   }
+
+   return 0;
+}
+
+/* just used from drm-client and atomic-helper: */
+int __drm_atomic_helper_set_config(struct drm_mode_set *set,
+  struct drm_atomic_state *state)
+{
+   struct drm_crtc_state *crtc_state;
+   struct drm_plane_state *primary_state;
+   struct drm_crtc *crtc = set->crtc;
+   int hdisplay, vdisplay;
+   int ret;
+
+   crtc_state = drm_atomic_get_crtc_state(state, crtc);
+   if (IS_ERR

Re: [PATCH v3 5/5] drm/cirrus: rewrite and modernize driver.

2019-04-05 Thread Noralf Trønnes


Den 05.04.2019 11.52, skrev Gerd Hoffmann:
> Time to kill some bad sample code people are copying from ;)
> 
> This is a complete rewrite of the cirrus driver.  The cirrus_mode_set()
> function is pretty much the only function which is carried over largely
> unmodified.  Everything else is upside down.
> 
> It is a single monster patch.  But given that it does some pretty
> fundamental changes to the drivers workflow and also reduces the code
> size by roughly 70% I think it'll still be alot easier to review than a
> longish baby-step patch series.
> 
> Changes summary:
>  - Given the small amout of video memory (4 MB) the cirrus device has
>the rewritten driver doesn't try to manage buffers there.  Instead
>it will blit (memcpy) the active framebuffer to video memory.
>  - All gem objects are stored in main memory and are manged using the
>new shmem helpers.  ttm is out.
>  - It supports RG16, RG24 and XR24 formats.  XR24 gets converted to RG24
>or RG16 at blit time if needed, to avoid the pitch becoming larger
>than what the cirrus hardware can handle.
>  - The simple display pipeline is used.
>  - The generic fbdev emulation is used.
>  - It's a atomic driver now.
>  - It runs wayland.
> 
> Signed-off-by: Gerd Hoffmann 
> ---

Acked-by: Noralf Trønnes 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Re: [PATCH v3 4/5] drm: add drm_fb_xrgb8888_to_rgb888_dstclip()

2019-04-05 Thread Noralf Trønnes


Den 05.04.2019 11.52, skrev Gerd Hoffmann:
> Simliar to drm_fb_xrgb_to_rgb565_dstclip() but converts to rgb888

Simliar -> Similar

> instead of rgb565.
> 
> Signed-off-by: Gerd Hoffmann 
> ---

Reviewed-by: Noralf Trønnes 

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

Re: [PATCH v3 3/5] drm: add drm_fb_xrgb8888_to_rgb565_dstclip()

2019-04-05 Thread Noralf Trønnes


Den 05.04.2019 11.52, skrev Gerd Hoffmann:
> It is a drm_fb_xrgb_to_rgb565() variant which checks the clip
> rectangle for the destination too.
> 
> Common code between drm_fb_xrgb_to_rgb565() and
> drm_fb_xrgb_to_rgb565_dstclip() was factored out into the
> drm_fb_xrgb_to_rgb565_lines() helper function.
> 
> Signed-off-by: Gerd Hoffmann 
> ---

Reviewed-by: Noralf Trønnes 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Re: [PATCH v3 2/5] drm: add drm_fb_memcpy_dstclip() helper

2019-04-05 Thread Noralf Trønnes


Den 05.04.2019 11.52, skrev Gerd Hoffmann:
> It is a drm_fb_memcpy() variant which checks the clip rectangle for the
> destination too.
> 
> Common code between drm_fb_memcpy() and drm_fb_memcpy_dstclip() was
> factored out into the drm_fb_memcpy_lines() helper function.
> 
> Signed-off-by: Gerd Hoffmann 
> ---

Reviewed-by: Noralf Trønnes 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Re: [PATCH v3 1/5] drm: move tinydrm format conversion helpers to new drm_format_helper.c

2019-04-05 Thread Noralf Trønnes


Den 05.04.2019 11.52, skrev Gerd Hoffmann:
> Also rename them from tinydrm_* to drm_fb_*
> Pure code motion, no functional change.
> 
> Signed-off-by: Gerd Hoffmann 
> ---

Thanks for doing this!

Reviewed-by: Noralf Trønnes 

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

Re: [PATCH] drm: aspeed: Select CMA only if available

2019-04-05 Thread Noralf Trønnes


Den 05.04.2019 07.28, skrev Joel Stanley:
> When building this driver for architectures where CMA is not available.
> 
> Fixes: 4f2a8f5898ec ("drm: Add ASPEED GFX driver")
> Reported-by: Stephen Rothwell 
> Reported-by: kernel test robot 
> Signed-off-by: Joel Stanley 
> ---
> This fixes the build break.
> 
> Another question is if we need to select this at all, as we have a
> reserved memory region to allocate from. I am not familiar with this
> area, so advice is welcome.
> 
>  drivers/gpu/drm/aspeed/Kconfig | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/aspeed/Kconfig b/drivers/gpu/drm/aspeed/Kconfig
> index 42b74d18a41b..1775fb85ec74 100644
> --- a/drivers/gpu/drm/aspeed/Kconfig
> +++ b/drivers/gpu/drm/aspeed/Kconfig
> @@ -4,8 +4,8 @@ config DRM_ASPEED_GFX
>   select DRM_KMS_HELPER
>   select DRM_KMS_CMA_HELPER
>   select DRM_PANEL
> - select DMA_CMA
> - select CMA
> + select DMA_CMA if HAVE_DMA_CONTIGUOUS
> + select CMA if HAVE_DMA_CONTIGUOUS

I'm no expert on this, but the rule is that you should not select
options that are user visible which both of these are. The user should
select them. So I believe that you should remove them.

Docs: Documentation/kbuild/kconfig-language.txt

Noralf.

>   select MFD_SYSCON
>   help
> Chose this option if you have an ASPEED AST2500 SOC Display
> 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Re: [PATCH v2 3/6] drm: move tinydrm_xrgb8888_to_rgb565() to drm_fb_helper.c

2019-04-04 Thread Noralf Trønnes


Den 04.04.2019 17.24, skrev Gerd Hoffmann:
> Also rename to drm_fb_xrgb_to_rgb565().
> Pure code motion, no functional change.
> 
> Signed-off-by: Gerd Hoffmann 
> ---


> diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
> index fabeb408dce6..087e49741094 100644
> --- a/drivers/gpu/drm/drm_fb_helper.c
> +++ b/drivers/gpu/drm/drm_fb_helper.c
> @@ -3380,3 +3380,48 @@ void drm_fb_memcpy(void *dst, void *vaddr, struct 
> drm_framebuffer *fb,
>   }
>  }
>  EXPORT_SYMBOL(drm_fb_memcpy);
> +
> +/**
> + * drm_fb_xrgb_to_rgb565 - Convert XRGB to RGB565 clip buffer
> + * @dst: RGB565 destination buffer
> + * @vaddr: XRGB source buffer
> + * @fb: DRM framebuffer
> + * @clip: Clip rectangle area to copy
> + * @swap: Swap bytes
> + *
> + * Drivers can use this function for RGB565 devices that don't natively
> + * support XRGB.
> + */
> +void drm_fb_xrgb_to_rgb565(u16 *dst, void *vaddr,
> +struct drm_framebuffer *fb,
> +struct drm_rect *clip, bool swap)
> +{
> + size_t len = (clip->x2 - clip->x1) * sizeof(u32);
> + unsigned int x, y;
> + u32 *src, *buf;
> + u16 val16;
> +
> + buf = kmalloc(len, GFP_KERNEL);

It's not obvious what purpose this buffer serves and there's no help
from the surrounding functions either (tinydrm_swab16() has a comment).

I think we need a comment, something along these lines:

/*
 * Write-combined buffers have uncached reads.
 * Speed up by fetching one line at a time.
 */

Noralf.

> + if (!buf)
> + return;
> +
> + for (y = clip->y1; y < clip->y2; y++) {
> + src = vaddr + (y * fb->pitches[0]);
> + src += clip->x1;
> + memcpy(buf, src, len);
> + src = buf;
> + for (x = clip->x1; x < clip->x2; x++) {
> + val16 = ((*src & 0x00F8) >> 8) |
> + ((*src & 0xFC00) >> 5) |
> + ((*src & 0x00F8) >> 3);
> + src++;
> + if (swap)
> + *dst++ = swab16(val16);
> + else
> + *dst++ = val16;
> + }
> + }
> +
> + kfree(buf);
> +}
> +EXPORT_SYMBOL(drm_fb_xrgb_to_rgb565);
> diff --git a/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c 
> b/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c
> index f5c6f35e6161..f4b84b15da75 100644
> --- a/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c
> +++ b/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c
> @@ -61,51 +61,6 @@ void tinydrm_swab16(u16 *dst, void *vaddr, struct 
> drm_framebuffer *fb,
>  }
>  EXPORT_SYMBOL(tinydrm_swab16);
>  
> -/**
> - * tinydrm_xrgb_to_rgb565 - Convert XRGB to RGB565 clip buffer
> - * @dst: RGB565 destination buffer
> - * @vaddr: XRGB source buffer
> - * @fb: DRM framebuffer
> - * @clip: Clip rectangle area to copy
> - * @swap: Swap bytes
> - *
> - * Drivers can use this function for RGB565 devices that don't natively
> - * support XRGB.
> - */
> -void tinydrm_xrgb_to_rgb565(u16 *dst, void *vaddr,
> - struct drm_framebuffer *fb,
> - struct drm_rect *clip, bool swap)
> -{
> - size_t len = (clip->x2 - clip->x1) * sizeof(u32);
> - unsigned int x, y;
> - u32 *src, *buf;
> - u16 val16;
> -
> - buf = kmalloc(len, GFP_KERNEL);
> - if (!buf)
> - return;
> -
> - for (y = clip->y1; y < clip->y2; y++) {
> - src = vaddr + (y * fb->pitches[0]);
> - src += clip->x1;
> - memcpy(buf, src, len);
> - src = buf;
> - for (x = clip->x1; x < clip->x2; x++) {
> - val16 = ((*src & 0x00F8) >> 8) |
> - ((*src & 0xFC00) >> 5) |
> - ((*src & 0x00F8) >> 3);
> - src++;
> - if (swap)
> - *dst++ = swab16(val16);
> - else
> - *dst++ = val16;
> - }
> - }
> -
> - kfree(buf);
> -}
> -EXPORT_SYMBOL(tinydrm_xrgb_to_rgb565);
> -
>  /**
>   * tinydrm_xrgb_to_gray8 - Convert XRGB to grayscale
>   * @dst: 8-bit grayscale destination buffer
> diff --git a/drivers/gpu/drm/tinydrm/mipi-dbi.c 
> b/drivers/gpu/drm/tinydrm/mipi-dbi.c
> index e26fd61360a3..cf8df5fb7494 100644
> --- a/drivers/gpu/drm/tinydrm/mipi-dbi.c
> +++ b/drivers/gpu/drm/tinydrm/mipi-dbi.c
> @@ -224,7 +224,7 @@ int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer 
> *fb,
>   drm_fb_memcpy(dst, src, fb, clip, false);
>   break;
>   case DRM_FORMAT_XRGB:
> - tinydrm_xrgb_to_rgb565(dst, src, fb, clip, swap);
> + drm_fb_xrgb_to_rgb565(dst, src, fb, clip, swap);
>   break;
>   

Re: [PATCH v2 1/6] drm: move tinydrm_memcpy() to drm_fb_helper.c

2019-04-04 Thread Noralf Trønnes


Den 04.04.2019 17.24, skrev Gerd Hoffmann:
> Also rename to drm_fb_memcpy().
> Pure code motion, no functional change.
> 
> Signed-off-by: Gerd Hoffmann 
> ---
>  include/drm/drm_fb_helper.h   |  3 +++
>  include/drm/tinydrm/tinydrm-helpers.h |  2 --
>  drivers/gpu/drm/drm_fb_helper.c   | 25 +++

drm_fb_helper.c is for fbdev code so not a good place for this code, and
it's MIT licensed as well.
Daniel have in two rounds suggested a new drm_framebuffer_helper.c or
drm_format_helper.c as possible destinations for these functions.

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

Re: [PATCH] drm/cirrus: rewrite and modernize driver.

2019-04-04 Thread Noralf Trønnes


Den 04.04.2019 12.27, skrev Gerd Hoffmann:
>   Hi,
> 
>>> tinydrm_xrgb_to_*
>>>
>>> imo these could be put into some drm_format_helpers.c to be shared.
>>
>> I agree, my long term goal is to get rid of tinydrm.ko. Just haven't got
>> there yet.
>>
>> Gerd, if you end up using some of those functions, feel free to move
>> just those you need and I can do the rest later. But if you have time to
>> spare I wouldn't mind getting all of them moved ;-)
> 
> For now I just promoted cirrus to be a tinydrm driver ;)
> 
> Noticed that those helpers (including tinydrm_memcpy for the
> non-converting case) apply clipping on the source but not on
> the destination.  So, for fullscreen updates that works ok,
> but for updating sub-rectangles it doesn't ...

Ah yes, these MIPI type controllers support setting the destination
window in controller RAM for the incoming buffer so there has been no
need for clipping on the destination buffer.

> 
> So I guess I have to add a dest_clip bool parameter when moving them.
> /me looks for a good place.  drm_fb_helpers.c I think.
> 
> cheers,
>   Gerd
> 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Re: [PATCH] drm/cirrus: rewrite and modernize driver.

2019-04-04 Thread Noralf Trønnes


Den 04.04.2019 10.52, skrev Daniel Vetter:
> On Thu, Apr 4, 2019 at 10:30 AM Gerd Hoffmann  wrote:
>>
>>   Hi,
>>
 Speaking of wayland:  Seems at least gnome-shell insists on using XR24.
>>>
>>> Yeah XR24 is pretty much mandatory. Noralf added a few helpers to
>>> convert XR24 to other formats, for display not supporting anything
>>> else. Because userspace.
>>
>> Have a pointer to these helpers?  grepping around in drm didn't turn up
>> anything so far ...
> 
> tinydrm_xrgb_to_*
> 
> imo these could be put into some drm_format_helpers.c to be shared.

I agree, my long term goal is to get rid of tinydrm.ko. Just haven't got
there yet.

Gerd, if you end up using some of those functions, feel free to move
just those you need and I can do the rest later. But if you have time to
spare I wouldn't mind getting all of them moved ;-)

Noralf.

> From a quick look the xrgb_to_rgb888 is missing, but for a quick
> hack you can just use rgb565 to get going.
> -Daniel
> 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH] drm/client: Rename drm_client_add() to drm_client_register()

2019-04-03 Thread Noralf Trønnes
This is done to stay consistent with our naming scheme of
_register() = others can start calling us from any thread.

Suggested-by: Daniel Vetter 
Signed-off-by: Noralf Trønnes 
---
 drivers/gpu/drm/drm_client.c| 11 ++-
 drivers/gpu/drm/drm_fb_helper.c |  2 +-
 include/drm/drm_client.h|  2 +-
 3 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c
index 9b2bd28dde0a..f20d1dda3961 100644
--- a/drivers/gpu/drm/drm_client.c
+++ b/drivers/gpu/drm/drm_client.c
@@ -69,7 +69,8 @@ EXPORT_SYMBOL(drm_client_close);
  * @name: Client name
  * @funcs: DRM client functions (optional)
  *
- * This initialises the client and opens a _file. Use drm_client_add() to 
complete the process.
+ * This initialises the client and opens a _file.
+ * Use drm_client_register() to complete the process.
  * The caller needs to hold a reference on @dev before calling this function.
  * The client is freed when the _device is unregistered. See 
drm_client_release().
  *
@@ -108,16 +109,16 @@ int drm_client_init(struct drm_device *dev, struct 
drm_client_dev *client,
 EXPORT_SYMBOL(drm_client_init);
 
 /**
- * drm_client_add - Add client to the device list
+ * drm_client_register - Register client
  * @client: DRM client
  *
  * Add the client to the _device client list to activate its callbacks.
  * @client must be initialized by a call to drm_client_init(). After
- * drm_client_add() it is no longer permissible to call drm_client_release()
+ * drm_client_register() it is no longer permissible to call 
drm_client_release()
  * directly (outside the unregister callback), instead cleanup will happen
  * automatically on driver unload.
  */
-void drm_client_add(struct drm_client_dev *client)
+void drm_client_register(struct drm_client_dev *client)
 {
struct drm_device *dev = client->dev;
 
@@ -125,7 +126,7 @@ void drm_client_add(struct drm_client_dev *client)
list_add(>list, >clientlist);
mutex_unlock(>clientlist_mutex);
 }
-EXPORT_SYMBOL(drm_client_add);
+EXPORT_SYMBOL(drm_client_register);
 
 /**
  * drm_client_release - Release DRM client resources
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 84791dd4a90d..367641c7754f 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -3322,7 +3322,7 @@ int drm_fbdev_generic_setup(struct drm_device *dev, 
unsigned int preferred_bpp)
if (ret)
DRM_DEV_DEBUG(dev->dev, "client hotplug ret=%d\n", ret);
 
-   drm_client_add(_helper->client);
+   drm_client_register(_helper->client);
 
return 0;
 }
diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h
index 8b552b1a6ce9..268b2cf0052a 100644
--- a/include/drm/drm_client.h
+++ b/include/drm/drm_client.h
@@ -90,7 +90,7 @@ 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);
 void drm_client_release(struct drm_client_dev *client);
-void drm_client_add(struct drm_client_dev *client);
+void drm_client_register(struct drm_client_dev *client);
 
 void drm_client_dev_unregister(struct drm_device *dev);
 void drm_client_dev_hotplug(struct drm_device *dev);
-- 
2.20.1

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

Re: [PATCH] drm/cirrus: rewrite and modernize driver.

2019-04-03 Thread Noralf Trønnes


Den 03.04.2019 10.53, skrev Gerd Hoffmann:
>>> +struct cirrus_device {
>>> +   struct drm_device  *dev;
>>
>> Why not embed drm_device? It's the latest rage :-)
> 
> Sure, can do that.
> 
>>> +void cirrus_pipe_update(struct drm_simple_display_pipe *pipe,
>>> +   struct drm_plane_state *old_state)
>>> +{
>>> +   struct drm_plane_state *state = pipe->plane.state;
>>> +   struct drm_crtc *crtc = >crtc;
>>> +   struct drm_rect rect;
>>> +
>>> +   if (drm_atomic_helper_damage_merged(old_state, state, ))
>>> +   cirrus_fb_blit_rect(pipe->plane.state->fb, );
>>> +
>>> +   if (crtc->state->event) {
>>> +   spin_lock_irq(>dev->event_lock);
>>> +   drm_crtc_send_vblank_event(crtc, crtc->state->event);
>>> +   spin_unlock_irq(>dev->event_lock);
>>> +   crtc->state->event = NULL;
>>> +   }
>>> +}
> 
>>> +static int cirrus_fb_dirty(struct drm_framebuffer *fb,
>>> +  struct drm_file *file_priv,
>>> +  unsigned int flags, unsigned int color,
>>> +  struct drm_clip_rect *clips,
>>> +  unsigned int num_clips)
>>> +{
>>> +   struct cirrus_device *cirrus = fb->dev->dev_private;
>>> +
>>> +   if (cirrus->pipe.plane.state->fb != fb)
>>> +   return 0;
>>> +
>>> +   if (num_clips)
>>> +   cirrus_fb_blit_clips(fb, clips, num_clips);
>>> +   else
>>> +   cirrus_fb_blit_fullscreen(fb);
>>> +   return 0;
>>> +}
>>
>> Why not use the dirty helpers and implement dirty rect support in your
>> main plane update function?
> 
> Dirty rect support is already there, see above.
> 
> So I can just remove cirrus_fb_dirty() and hook up
> drm_atomic_helper_dirtyfb() instead.  Easy ;)
> 

You can even use drm_gem_fb_create_with_dirty() instead of
drm_gem_fb_create_with_funcs().

Noralf.

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

Re: [PATCH] drm/fb-helper: generic: Call drm_client_add() after setup is done

2019-04-03 Thread Noralf Trønnes


Den 02.04.2019 09.55, skrev Daniel Vetter:
> On Mon, Apr 01, 2019 at 04:13:58PM +0200, Noralf Trønnes wrote:
>> Hotplug can happen while drm_fbdev_generic_setup() is running so move
>> drm_client_add() call after setup is done to avoid
>> drm_fbdev_client_hotplug() running in two threads at the same time.
>>
>> Fixes: 9060d7f49376 ("drm/fb-helper: Finish the generic fbdev emulation")
>> Reported-by: Daniel Vetter 
>> Signed-off-by: Noralf Trønnes 
> 
> Not sure we even want a cc: stable on this, things could go boom. I guess
> we could backport once there's a bug report, up to you.
> 
> Reviewed-by: Daniel Vetter 

Thanks, applied with cc stable.

Noralf.

> 
>> ---
>>  drivers/gpu/drm/drm_fb_helper.c | 4 ++--
>>  1 file changed, 2 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/drm_fb_helper.c 
>> b/drivers/gpu/drm/drm_fb_helper.c
>> index 03749a24e4dd..601b17310411 100644
>> --- a/drivers/gpu/drm/drm_fb_helper.c
>> +++ b/drivers/gpu/drm/drm_fb_helper.c
>> @@ -3317,8 +3317,6 @@ int drm_fbdev_generic_setup(struct drm_device *dev, 
>> unsigned int preferred_bpp)
>>  return ret;
>>  }
>>  
>> -drm_client_add(_helper->client);
>> -
>>  if (!preferred_bpp)
>>  preferred_bpp = dev->mode_config.preferred_depth;
>>  if (!preferred_bpp)
>> @@ -3329,6 +3327,8 @@ int drm_fbdev_generic_setup(struct drm_device *dev, 
>> unsigned int preferred_bpp)
>>  if (ret)
>>  DRM_DEV_DEBUG(dev->dev, "client hotplug ret=%d\n", ret);
>>  
>> +drm_client_add(_helper->client);
>> +
>>  return 0;
>>  }
>>  EXPORT_SYMBOL(drm_fbdev_generic_setup);
>> -- 
>> 2.20.1
>>
> 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Re: [Intel-gfx] [PATCH 01/16] drm/fb-helper: Remove unused gamma_size variable

2019-04-03 Thread Noralf Trønnes


Den 26.03.2019 19.23, skrev Daniel Vetter:
> On Tue, Mar 26, 2019 at 06:55:31PM +0100, Noralf Trønnes wrote:
>> The gamma_size variable has not been used since
>> commit 4abe35204af8 ("drm/kms/fb: use slow work mechanism for normal hotplug 
>> also.")
>>
>> While in the area move a comment back to its code block.
>> They got separated by
>> commit d50ba256b5f1 ("drm/kms: start adding command line interface using 
>> fb.").
>>
>> Signed-off-by: Noralf Trønnes 
> 
> Reviewed-by: Daniel Vetter 

Thanks, patches 1 & 2 applied to drm-misc-next.

Noralf.

> 
>> ---
>>  drivers/gpu/drm/drm_fb_helper.c | 6 +-
>>  1 file changed, 1 insertion(+), 5 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/drm_fb_helper.c 
>> b/drivers/gpu/drm/drm_fb_helper.c
>> index 04d23cb430bf..eea15465da7a 100644
>> --- a/drivers/gpu/drm/drm_fb_helper.c
>> +++ b/drivers/gpu/drm/drm_fb_helper.c
>> @@ -1873,7 +1873,6 @@ static int drm_fb_helper_single_fb_probe(struct 
>> drm_fb_helper *fb_helper,
>>  int crtc_count = 0;
>>  int i;
>>  struct drm_fb_helper_surface_size sizes;
>> -int gamma_size = 0;
>>  int best_depth = 0;
>>  
>>  memset(, 0, sizeof(struct drm_fb_helper_surface_size));
>> @@ -1889,7 +1888,6 @@ static int drm_fb_helper_single_fb_probe(struct 
>> drm_fb_helper *fb_helper,
>>  if (preferred_bpp != sizes.surface_bpp)
>>  sizes.surface_depth = sizes.surface_bpp = preferred_bpp;
>>  
>> -/* first up get a count of crtcs now in use and new min/maxes 
>> width/heights */
>>  drm_fb_helper_for_each_connector(fb_helper, i) {
>>  struct drm_fb_helper_connector *fb_helper_conn = 
>> fb_helper->connector_info[i];
>>  struct drm_cmdline_mode *cmdline_mode;
>> @@ -1969,6 +1967,7 @@ static int drm_fb_helper_single_fb_probe(struct 
>> drm_fb_helper *fb_helper,
>>  sizes.surface_depth = best_depth;
>>  }
>>  
>> +/* first up get a count of crtcs now in use and new min/maxes 
>> width/heights */
>>  crtc_count = 0;
>>  for (i = 0; i < fb_helper->crtc_count; i++) {
>>  struct drm_display_mode *desired_mode;
>> @@ -1991,9 +1990,6 @@ static int drm_fb_helper_single_fb_probe(struct 
>> drm_fb_helper *fb_helper,
>>  x = fb_helper->crtc_info[i].x;
>>  y = fb_helper->crtc_info[i].y;
>>  
>> -if (gamma_size == 0)
>> -gamma_size = 
>> fb_helper->crtc_info[i].mode_set.crtc->gamma_size;
>> -
>>  sizes.surface_width  = max_t(u32, desired_mode->hdisplay + x, 
>> sizes.surface_width);
>>  sizes.surface_height = max_t(u32, desired_mode->vdisplay + y, 
>> sizes.surface_height);
>>  
>> -- 
>> 2.20.1
>>
>> ___
>> Intel-gfx mailing list
>> intel-...@lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Re: [PATCH 16/16] drm/vc4: Call drm_dev_register() after all setup is done

2019-04-03 Thread Noralf Trønnes


Den 27.03.2019 17.36, skrev Eric Anholt:
> Noralf Trønnes  writes:
> 
>> drm_dev_register() initializes internal clients like bootsplash as the
>> last thing it does, so all setup needs to be done at this point.
>>
>> Fix by calling vc4_kms_load() before registering.
>> Also check the error code returned from that function.
>>
>> Cc: Eric Anholt 
>> Signed-off-by: Noralf Trønnes 
> 
> Reviewed-by: Eric Anholt 
> 

Applied to drm-misc-next.

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

Re: [PATCH 2/2] drm: Add ASPEED GFX driver

2019-04-01 Thread Noralf Trønnes
quot;Cannot setup simple display pipe\n");
> + return ret;
> + }
> +
> + ret = devm_request_irq(drm->dev, platform_get_irq(pdev, 0),
> +aspeed_gfx_irq_handler, 0, "aspeed gfx", drm);
> + if (ret < 0) {
> + dev_err(drm->dev, "Failed to install IRQ handler\n");
> + return ret;
> + }
> +
> + drm_mode_config_reset(drm);
> +
> + drm_fbdev_generic_setup(drm, 32);
> +
> + return 0;
> +}
> +
> +static void aspeed_gfx_unload(struct drm_device *drm)
> +{
> + drm_kms_helper_poll_fini(drm);
> + drm_mode_config_cleanup(drm);
> +
> + drm->dev_private = NULL;
> +}
> +
> +DEFINE_DRM_GEM_CMA_FOPS(fops);
> +
> +static struct drm_driver aspeed_gfx_driver = {
> + .driver_features= DRIVER_GEM | DRIVER_MODESET |
> + DRIVER_PRIME | DRIVER_ATOMIC |
> + DRIVER_HAVE_IRQ,

There's a vtable on the GEM object now, so this section:

> + .gem_free_object_unlocked = drm_gem_cma_free_object,
> + .gem_vm_ops = _gem_cma_vm_ops,
> + .dumb_create= drm_gem_cma_dumb_create,
> + .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
> + .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
> + .gem_prime_export   = drm_gem_prime_export,
> + .gem_prime_import   = drm_gem_prime_import,
> + .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
> + .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
> + .gem_prime_vmap = drm_gem_cma_prime_vmap,
> + .gem_prime_vunmap   = drm_gem_cma_prime_vunmap,
> + .gem_prime_mmap = drm_gem_cma_prime_mmap,

Can be substituted with this:

.gem_create_object  = drm_cma_gem_create_object_default_funcs,
.dumb_create= drm_gem_cma_dumb_create,
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
.gem_prime_mmap = drm_gem_prime_mmap,

> + .fops = ,
> + .name = "aspeed-gfx-drm",
> + .desc = "ASPEED GFX DRM",
> + .date = "20180319",
> + .major = 1,
> + .minor = 0,
> +};
> +
> +static const struct of_device_id aspeed_gfx_match[] = {
> + { .compatible = "aspeed,ast2400-gfx" },
> + { .compatible = "aspeed,ast2500-gfx" },
> + { }
> +};
> +
> +static int aspeed_gfx_probe(struct platform_device *pdev)
> +{
> + struct drm_device *drm;
> + int ret;
> +
> + drm = drm_dev_alloc(_gfx_driver, >dev);
> + if (IS_ERR(drm))
> + return PTR_ERR(drm);
> +
> + ret = aspeed_gfx_load(drm);
> + if (ret)
> + goto err_free;
> +
> + ret = drm_dev_register(drm, 0);
> + if (ret)
> + goto err_unload;
> +
> + return 0;
> +
> +err_unload:
> + aspeed_gfx_unload(drm);
> +err_free:
> + drm_dev_put(drm);
> +
> + return ret;
> +}
> +
> +static int aspeed_gfx_remove(struct platform_device *pdev)
> +{
> + struct drm_device *drm = platform_get_drvdata(pdev);
> +
> + drm_dev_unregister(drm);
> + aspeed_gfx_unload(drm);
> + drm_dev_put(drm);
> +
> + return 0;
> +}
> +
> +static struct platform_driver aspeed_gfx_platform_driver = {
> + .probe  = aspeed_gfx_probe,
> + .remove = aspeed_gfx_remove,
> + .driver = {
> + .name = "aspeed_gfx",
> + .of_match_table = aspeed_gfx_match,
> + },
> +};
> +
> +module_platform_driver(aspeed_gfx_platform_driver);
> +
> +MODULE_AUTHOR("Joel Stanley ");
> +MODULE_DESCRIPTION("ASPEED BMC DRM/KMS driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/gpu/drm/aspeed/aspeed_gfx_out.c 
> b/drivers/gpu/drm/aspeed/aspeed_gfx_out.c
> new file mode 100644
> index ..7d2057e00056
> --- /dev/null
> +++ b/drivers/gpu/drm/aspeed/aspeed_gfx_out.c
> @@ -0,0 +1,49 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +// Copyright 2018 IBM Corporation
> +
> +#include 

Same here, don't include drmP.h

> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include "aspeed_gfx.h"
> +
> +static int aspeed_gfx_get_modes(struct drm_connector *connector)
> +{
> + return drm_add_modes_noedid(connector, 800, 600);
> +}
> +
> +static const struct
> +drm_connector_helper_funcs aspeed_gfx_connector_helper_funcs = {
> + .get_modes = aspeed_gfx_get_modes,
> +};
> +
> +static void aspeed_gfx_connector_destroy(struct drm_connector *connector)
> +{
> + drm_connector_unregister(connector);
> + drm_connector_cleanup(connector);
> +}
> +
> +static const struct drm_connector_funcs aspeed_gfx_connector_funcs = {
> + .fill_modes = drm_helper_probe_single_connector_modes,
> + .destroy= aspeed_gfx_connector_destroy,

As Daniel said, you can use drm_connector_cleanup directly here.

Otherwise looks good:

Reviewed-by: Noralf Trønnes 

> + .reset  = drm_atomic_helper_connector_reset,
> + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> + .atomic_destroy_state   = drm_atomic_helper_connector_destroy_state,
> +};
> +
> +int aspeed_gfx_create_output(struct drm_device *drm)
> +{
> + struct aspeed_gfx *priv = drm->dev_private;
> + int ret;
> +
> + priv->connector.dpms = DRM_MODE_DPMS_OFF;
> + priv->connector.polled = 0;
> + drm_connector_helper_add(>connector,
> +  _gfx_connector_helper_funcs);
> + ret = drm_connector_init(drm, >connector,
> +  _gfx_connector_funcs,
> +  DRM_MODE_CONNECTOR_Unknown);
> + return ret;
> +}
> 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH] drm/fb-helper: generic: Call drm_client_add() after setup is done

2019-04-01 Thread Noralf Trønnes
Hotplug can happen while drm_fbdev_generic_setup() is running so move
drm_client_add() call after setup is done to avoid
drm_fbdev_client_hotplug() running in two threads at the same time.

Fixes: 9060d7f49376 ("drm/fb-helper: Finish the generic fbdev emulation")
Reported-by: Daniel Vetter 
Signed-off-by: Noralf Trønnes 
---
 drivers/gpu/drm/drm_fb_helper.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 03749a24e4dd..601b17310411 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -3317,8 +3317,6 @@ int drm_fbdev_generic_setup(struct drm_device *dev, 
unsigned int preferred_bpp)
return ret;
}
 
-   drm_client_add(_helper->client);
-
if (!preferred_bpp)
preferred_bpp = dev->mode_config.preferred_depth;
if (!preferred_bpp)
@@ -3329,6 +3327,8 @@ int drm_fbdev_generic_setup(struct drm_device *dev, 
unsigned int preferred_bpp)
if (ret)
DRM_DEV_DEBUG(dev->dev, "client hotplug ret=%d\n", ret);
 
+   drm_client_add(_helper->client);
+
return 0;
 }
 EXPORT_SYMBOL(drm_fbdev_generic_setup);
-- 
2.20.1

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

Re: [PATCH 13/16] drm/fb-helper: Avoid race with DRM userspace

2019-04-01 Thread Noralf Trønnes


Den 01.04.2019 09.12, skrev Daniel Vetter:
> On Sat, Mar 30, 2019 at 10:07:58PM +0100, Noralf Trønnes wrote:
>>
>>
>> Den 28.03.2019 09.17, skrev Daniel Vetter:
>>> On Tue, Mar 26, 2019 at 06:55:43PM +0100, Noralf Trønnes wrote:
>>>> drm_fb_helper_is_bound() is used to check if DRM userspace is in control.
>>>> This is done by looking at the fb on the primary plane. By the time
>>>> fb-helper gets around to committing, it's possible that the facts have
>>>> changed.
>>>>
>>>> Avoid this race by holding the drm_device->master_mutex lock while
>>>> committing. When DRM userspace does its first open, it will now wait
>>>> until fb-helper is done. The helper will stay away if there's a master.
>>>>
>>>> Locking rule: Always take the fb-helper lock first.
>>>>
>>>> Suggested-by: Daniel Vetter 
>>>> Signed-off-by: Noralf Trønnes 
>>>
>>> I think it'd be good to reorder this earlier in the series. And I'm
>>> wondering why you didn't replace all occurences of the _is_bound()
>>> function. With the consistent master state check we're doing with this I
>>> don't think any of the fbdev checking is still needed. Plus looking at
>>> crtc->primary->fb without any locks is racy, so would be good to ditch
>>> that hack.
>>
>> _is_bound() is used in drm_fb_helper_hotplug_event() to decide on
>> delayed hotplug. The master lock won't help here. I have studied
>> drm_fb_helper for 2 years now, and I still think it is convoluted and
>> difficult to grasp in places. So I kept this one call site. I'm vary of
>> making unrelated changes in this series.
> 
> Hm, why would it not work for the hotplug case? _is_bound already checks
> dev->master (but with races, unlike this here). And the other checks are
> various levels of cargo-culting. dev->master is (well, has become through
> retrofitting) the "who owns the display" tracking, I think fully
> standardizing on that makes sense. The only case where there's a
> difference is if:
> - some compositor dropped master
> - but didn't disable it's framebuffers
> We actually want that for smooth vt switching, so that the new compositor
> could take over in a transition. Having a special case with fbdev where
> the compositor has to disable all its fb or fbcon won't take over feels a
> bit irky.

You're right ofc.
I read '->deferred_setup = true' when in fact it is '->delayed_hotplug =
true', so I assumed there was something that _is_bound() was protecting
wrt. to setup state.
I'll fix it in the next version.

Noralf.

> -Daniel
> 
>> The reason I included this patch is because it's used with the
>> bootsplash example support code. I can move the patch earlier in the series.
>>
>> Noralf.
>>
>>> -Daniel
>>>
>>>> ---
>>>>  drivers/gpu/drm/drm_auth.c  | 20 ++
>>>>  drivers/gpu/drm/drm_fb_helper.c | 49 -
>>>>  drivers/gpu/drm/drm_internal.h  |  2 ++
>>>>  3 files changed, 58 insertions(+), 13 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c
>>>> index 1669c42c40ed..db199807b7dc 100644
>>>> --- a/drivers/gpu/drm/drm_auth.c
>>>> +++ b/drivers/gpu/drm/drm_auth.c
>>>> @@ -368,3 +368,23 @@ void drm_master_put(struct drm_master **master)
>>>>*master = NULL;
>>>>  }
>>>>  EXPORT_SYMBOL(drm_master_put);
>>>> +
>>>> +/* Used by drm_client and drm_fb_helper */
>>>> +bool drm_master_internal_acquire(struct drm_device *dev)
>>>> +{
>>>> +  mutex_lock(>master_mutex);
>>>> +  if (dev->master) {
>>>> +  mutex_unlock(>master_mutex);
>>>> +  return false;
>>>> +  }
>>>> +
>>>> +  return true;
>>>> +}
>>>> +EXPORT_SYMBOL(drm_master_internal_acquire);
>>>> +
>>>> +/* Used by drm_client and drm_fb_helper */
>>>> +void drm_master_internal_release(struct drm_device *dev)
>>>> +{
>>>> +  mutex_unlock(>master_mutex);
>>>> +}
>>>> +EXPORT_SYMBOL(drm_master_internal_release);
>>>> diff --git a/drivers/gpu/drm/drm_fb_helper.c 
>>>> b/drivers/gpu/drm/drm_fb_helper.c
>>>> index 4a073cd4e423..9f253fcf3f79 100644
>>>> --- a/drivers/gpu/drm/drm_fb_helper.c
>>>> +++ b/drivers/gpu/drm/drm_fb_helper.c
>>>> @@ -41,6 +41,8 @@

Re: [Intel-gfx] [PATCH 00/16] drm/fb-helper: Move modesetting code to drm_client

2019-03-31 Thread Noralf Trønnes


Den 28.03.2019 10.31, skrev Daniel Vetter:
> On Tue, Mar 26, 2019 at 06:55:30PM +0100, Noralf Trønnes wrote:
>> This moves the modesetting code from drm_fb_helper to drm_client so it
>> can be shared by all internal clients.
>>
>> I have also added a client display abstraction and a bootsplash example
>> client to show where this might be heading. Hopefully Max Staudt will be
>> able to pick up his bootsplash work now.
> 
> First a fairly unrelated thing that I noticed while reading stuff:
> 
> In drm_fbdev_generic_setup() we register the drm_client to the world (with
> drm_client_add) before it's fully set up. And the checks in the setup code
> aren't safe against a concurrent hotplug call from another thread. Which
> can happen, because usually by that point, and definitely by the time the
> driver called drm_dev_register() the hotplug handler is running.
> 

Ah, this hasn't crossed my mind. I'll move drm_client_add() after setup.

> Maybe good idea to rename drm_client_add to drm_client_register (to stay
> consistent with our naming scheme of _register() = others can start
> calling us from any thread).
> 

Makes sense, I'll change the name.

> We need to do the basic setup code _before_ we call drm_client_register.
> The kerneldoc for the various fbdev setup functions have explanations for
> when exactly it's ok to handle hotplug events.
> 
> The other bit is kinda the high-level review on the drm_client modeset
> api:
> - Allowing multiple different modeset clients per drm_client feels like
>   overkill. I think we can just require a 1:1 mapping between drm_client
>   and modeset config. If a client wants to have multiple different modeset
>   configs per drm_device they can create more drm_clients.
> 

The reason I ended up doing this is that there can be more than one
display connected. So for me the natural choice was to have each display
represented individually with its own modeset(s).

I did consider having the modeset array attached to drm_client and use a
modesets mask to tell the displays apart. It would have been easier if
we didn't have those tiled monitors driven by multiple outputs, because
that would have given us one modeset per display.

drm_fb_helper uses the same framebuffer for all displays, sizing it to
match the smallest.

Ofc the easy way out is to only support one display per drm_device. I
don't see how multiple drm_clients per drm_device should work. Should
the client keep an array of drm_client for as many displays as it supports?

The bootsplash client example I made, puts a splash on all displays it
can find. But maybe it should do it on only one display? If so we need
some heuristics to determine which is the primary display.

Not sure how kmscon is supposed to work, but I believe it is meant to be
a developer console. So I guess it will also just use the primary display.

> - That also fixes your "do we need embedding" question, since drm_client
>   supports that already.
> 
> - That means we could clean up the api considerably by embedding all the
>   modeset stuff into drm_client, and e.g. allocating the modeset arrays at
>   drm_client_init() time.
> 
> - Except that wouldn't work with the current fbdev emulation code, because
>   that one isn't always using drm_client.
> 
> Hence my question/suggestion: Could we rework the fbdev emulation to
> always allocate a drm_client, but only use drm_client for buffer
> allocation for generic_setup(). That could also provide us with a smoother
> upgrade path for other drivers to generic_setup, e.g. we could ditch all
> the hotplug handling already.
> 
> I'm thinking of embedding a drm_client into drm_fb_helper, and calling
> drm_client_init() on it at the right time. But only call drm_client_add()
> for generic_setup(). At least as a first step.
> 

Yeah, this certainly makes sense if we have the modesets attached to
drm_client_dev.

> Related question: What's the plan for drivers which don't support
> generic_setup()? If we eventually have stuff like kmscon running on top of
> drm_client, we'd have to somehow port them all ...
> 

It should just work as long the driver supports ->dumb_create and
->gem_prime_vmap.

rockchip and mediatek (I think) don't provide a virtual address on its
buffers because of limited virtual address space.
We could add a ->dumb_create_internal hook so these drivers could
provide an address to internal clients. This way they could use the
generic fbdev emualtion as well. Unless Rob finds a way to vmap a dma
buffer after allocation. He has looked at converting rockchip to generic
fbdev.

> And finally the bikeshed: I thik drm_client_modeset would be a good prefix
> for all this (maybe even in a separate file):

I have used prefix drm_client_modesets_ for all functions that operates
on the 

Re: [PATCH 13/16] drm/fb-helper: Avoid race with DRM userspace

2019-03-30 Thread Noralf Trønnes


Den 28.03.2019 09.17, skrev Daniel Vetter:
> On Tue, Mar 26, 2019 at 06:55:43PM +0100, Noralf Trønnes wrote:
>> drm_fb_helper_is_bound() is used to check if DRM userspace is in control.
>> This is done by looking at the fb on the primary plane. By the time
>> fb-helper gets around to committing, it's possible that the facts have
>> changed.
>>
>> Avoid this race by holding the drm_device->master_mutex lock while
>> committing. When DRM userspace does its first open, it will now wait
>> until fb-helper is done. The helper will stay away if there's a master.
>>
>> Locking rule: Always take the fb-helper lock first.
>>
>> Suggested-by: Daniel Vetter 
>> Signed-off-by: Noralf Trønnes 
> 
> I think it'd be good to reorder this earlier in the series. And I'm
> wondering why you didn't replace all occurences of the _is_bound()
> function. With the consistent master state check we're doing with this I
> don't think any of the fbdev checking is still needed. Plus looking at
> crtc->primary->fb without any locks is racy, so would be good to ditch
> that hack.

_is_bound() is used in drm_fb_helper_hotplug_event() to decide on
delayed hotplug. The master lock won't help here. I have studied
drm_fb_helper for 2 years now, and I still think it is convoluted and
difficult to grasp in places. So I kept this one call site. I'm vary of
making unrelated changes in this series.

The reason I included this patch is because it's used with the
bootsplash example support code. I can move the patch earlier in the series.

Noralf.

> -Daniel
> 
>> ---
>>  drivers/gpu/drm/drm_auth.c  | 20 ++
>>  drivers/gpu/drm/drm_fb_helper.c | 49 -
>>  drivers/gpu/drm/drm_internal.h  |  2 ++
>>  3 files changed, 58 insertions(+), 13 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c
>> index 1669c42c40ed..db199807b7dc 100644
>> --- a/drivers/gpu/drm/drm_auth.c
>> +++ b/drivers/gpu/drm/drm_auth.c
>> @@ -368,3 +368,23 @@ void drm_master_put(struct drm_master **master)
>>  *master = NULL;
>>  }
>>  EXPORT_SYMBOL(drm_master_put);
>> +
>> +/* Used by drm_client and drm_fb_helper */
>> +bool drm_master_internal_acquire(struct drm_device *dev)
>> +{
>> +mutex_lock(>master_mutex);
>> +if (dev->master) {
>> +mutex_unlock(>master_mutex);
>> +return false;
>> +}
>> +
>> +return true;
>> +}
>> +EXPORT_SYMBOL(drm_master_internal_acquire);
>> +
>> +/* Used by drm_client and drm_fb_helper */
>> +void drm_master_internal_release(struct drm_device *dev)
>> +{
>> +mutex_unlock(>master_mutex);
>> +}
>> +EXPORT_SYMBOL(drm_master_internal_release);
>> diff --git a/drivers/gpu/drm/drm_fb_helper.c 
>> b/drivers/gpu/drm/drm_fb_helper.c
>> index 4a073cd4e423..9f253fcf3f79 100644
>> --- a/drivers/gpu/drm/drm_fb_helper.c
>> +++ b/drivers/gpu/drm/drm_fb_helper.c
>> @@ -41,6 +41,8 @@
>>  #include 
>>  #include 
>>  
>> +#include "drm_internal.h"
>> +
>>  static bool drm_fbdev_emulation = true;
>>  module_param_named(fbdev_emulation, drm_fbdev_emulation, bool, 0600);
>>  MODULE_PARM_DESC(fbdev_emulation,
>> @@ -235,7 +237,12 @@ int drm_fb_helper_restore_fbdev_mode_unlocked(struct 
>> drm_fb_helper *fb_helper)
>>  return 0;
>>  
>>  mutex_lock(_helper->lock);
>> -ret = drm_client_modesets_commit(fb_helper->dev, fb_helper->modesets);
>> +if (drm_master_internal_acquire(fb_helper->dev)) {
>> +ret = drm_client_modesets_commit(fb_helper->dev, 
>> fb_helper->modesets);
>> +drm_master_internal_release(fb_helper->dev);
>> +} else {
>> +ret = -EBUSY;
>> +}
>>  
>>  do_delayed = fb_helper->delayed_hotplug;
>>  if (do_delayed)
>> @@ -332,13 +339,16 @@ static struct sysrq_key_op 
>> sysrq_drm_fb_helper_restore_op = { };
>>  static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode)
>>  {
>>  struct drm_fb_helper *fb_helper = info->par;
>> +struct drm_device *dev = fb_helper->dev;
>>  
>>  /*
>>   * For each CRTC in this fb, turn the connectors on/off.
>>   */
>>  mutex_lock(_helper->lock);
>> -if (drm_fb_helper_is_bound(fb_helper))
>> -drm_client_modesets_dpms(fb_helper->dev, fb_helper->modesets, 
>> dpms_mode);
>> +if (drm_master_internal_acquire(dev)) {
>

Re: [PATCH 06/16] drm/i915/fbdev: Move intel_fb_initial_config() to fbdev helper

2019-03-30 Thread Noralf Trønnes


Den 27.03.2019 14.33, skrev Jani Nikula:
> On Tue, 26 Mar 2019, Noralf Trønnes  wrote:
>> It is generic code and having it in the helper will let other drivers
>> benefit from it.
>>
>> One change was necessary assuming this to be true:
>> INTEL_INFO(dev_priv)->num_pipes == dev->mode_config.num_crtc
> 
> This holds after intel_modeset_init(), in time for the use here.
> 
>> Suggested-by: Daniel Vetter 
>> Cc: Jani Nikula 
>> Cc: Joonas Lahtinen 
>> Cc: Rodrigo Vivi 
>> Cc: intel-...@lists.freedesktop.org
>> Signed-off-by: Noralf Trønnes 
> 
> Reviewed-by: Jani Nikula 
> 
> and
> 
> Acked-by: Jani Nikula 
> 
> for merging via drm-misc or whichever tree makes most sense.
> 

Thanks, I'll take it through drm-misc.

One of the patches had a conflict with drm-tip, so I didn't get a CI
run. I'll apply this if CI agrees when I submit the next version.

Noralf.

> 
>> ---
>>  drivers/gpu/drm/drm_fb_helper.c| 194 -
>>  drivers/gpu/drm/i915/intel_fbdev.c | 218 -
>>  include/drm/drm_fb_helper.h|  23 ---
>>  3 files changed, 190 insertions(+), 245 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/drm_fb_helper.c 
>> b/drivers/gpu/drm/drm_fb_helper.c
>> index 36310901e935..634f4dcf0c41 100644
>> --- a/drivers/gpu/drm/drm_fb_helper.c
>> +++ b/drivers/gpu/drm/drm_fb_helper.c
>> @@ -2545,6 +2545,194 @@ static int drm_pick_crtcs(struct drm_fb_helper 
>> *fb_helper,
>>  return best_score;
>>  }
>>  
>> +static struct drm_fb_helper_crtc *
>> +drm_fb_helper_crtc(struct drm_fb_helper *fb_helper, struct drm_crtc *crtc)
>> +{
>> +int i;
>> +
>> +for (i = 0; i < fb_helper->crtc_count; i++)
>> +if (fb_helper->crtc_info[i].mode_set.crtc == crtc)
>> +return _helper->crtc_info[i];
>> +
>> +return NULL;
>> +}
>> +
>> +/* Try to read the BIOS display configuration and use it for the initial 
>> config */
>> +static bool drm_fb_helper_firmware_config(struct drm_fb_helper *fb_helper,
>> +  struct drm_fb_helper_crtc **crtcs,
>> +  struct drm_display_mode **modes,
>> +  struct drm_fb_offset *offsets,
>> +  bool *enabled, int width, int height)
>> +{
>> +struct drm_device *dev = fb_helper->dev;
>> +unsigned int count = min(fb_helper->connector_count, BITS_PER_LONG);
>> +unsigned long conn_configured, conn_seq;
>> +int i, j;
>> +bool *save_enabled;
>> +bool fallback = true, ret = true;
>> +int num_connectors_enabled = 0;
>> +int num_connectors_detected = 0;
>> +struct drm_modeset_acquire_ctx ctx;
>> +
>> +save_enabled = kcalloc(count, sizeof(bool), GFP_KERNEL);
>> +if (!save_enabled)
>> +return false;
>> +
>> +drm_modeset_acquire_init(, 0);
>> +
>> +while (drm_modeset_lock_all_ctx(dev, ) != 0)
>> +drm_modeset_backoff();
>> +
>> +memcpy(save_enabled, enabled, count);
>> +conn_seq = GENMASK(count - 1, 0);
>> +conn_configured = 0;
>> +retry:
>> +for (i = 0; i < count; i++) {
>> +struct drm_fb_helper_connector *fb_conn;
>> +struct drm_connector *connector;
>> +struct drm_encoder *encoder;
>> +struct drm_fb_helper_crtc *new_crtc;
>> +
>> +fb_conn = fb_helper->connector_info[i];
>> +connector = fb_conn->connector;
>> +
>> +if (conn_configured & BIT(i))
>> +continue;
>> +
>> +/* First pass, only consider tiled connectors */
>> +if (conn_seq == GENMASK(count - 1, 0) && !connector->has_tile)
>> +continue;
>> +
>> +if (connector->status == connector_status_connected)
>> +num_connectors_detected++;
>> +
>> +if (!enabled[i]) {
>> +DRM_DEBUG_KMS("connector %s not enabled, skipping\n",
>> +  connector->name);
>> +conn_configured |= BIT(i);
>> +continue;
>> +}
>> +
>> +if (connector->force == DRM_FORCE_OFF) {
>> +DRM_DEBUG_KMS("connector %s is di

Re: [PATCH 09/16] drm/fb-helper: Move out commit code

2019-03-27 Thread Noralf Trønnes


Den 27.03.2019 15.13, skrev Emmanuel Vadot:
> 
>  Hi Noralf,
> 
> On Tue, 26 Mar 2019 18:55:39 +0100
> Noralf Trønnes  wrote:
> 
>> Move the modeset commit code to drm_client.
>> No changes except exporting API.
>>
>> Signed-off-by: Noralf Trønnes 
>> ---
>>  drivers/gpu/drm/drm_client.c| 236 
>>  drivers/gpu/drm/drm_fb_helper.c | 232 ---
>>  include/drm/drm_client.h|   3 +
>>  3 files changed, 239 insertions(+), 232 deletions(-)
>>
> 
>  It looks like you are moving MIT licenced code to a GPL-only
> licenced file.
> 

I had planned to copy over the copyrights, but forgot. Didn't know it
was MIT though. I think I'll just copy over the whole copyrights section
from drm_fb_helper to drm_client and drop GPL. I wrote the whole of
drm_client so that should be fine.

Thanks,
Noralf

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

Re: [PATCH v3 5/5] drm/virtio: rework resource creation workflow.

2019-03-27 Thread Noralf Trønnes


Den 18.03.2019 12.33, skrev Gerd Hoffmann:
> This patch moves the virtio_gpu_cmd_create_resource() call (which
> notifies the host about the new resource created) into the
> virtio_gpu_object_create() function.  That way we can call
> virtio_gpu_cmd_create_resource() before ttm_bo_init(), so the host
> already knows about the object when ttm initializes the object and calls
> our driver callbacks.
> 
> Specifically the object is already created when the
> virtio_gpu_ttm_tt_bind() callback invokes virtio_gpu_object_attach(),
> so the extra virtio_gpu_object_attach() calls done after
> virtio_gpu_object_create() are not needed any more.
> 
> The fence support for the create ioctl becomes a bit more tricky though.
> The code moved into virtio_gpu_object_create() too.  We first submit the
> (fenced) virtio_gpu_cmd_create_resource() command, then initialize the
> ttm object, and finally attach just created object to the fence for the
> command in case it didn't finish yet.
> 
> Signed-off-by: Gerd Hoffmann 
> ---

Acked-by: Noralf Trønnes 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Re: [PATCH v3 2/5] drm/virtio: use struct to pass params to virtio_gpu_object_create()

2019-03-27 Thread Noralf Trønnes


Den 18.03.2019 12.33, skrev Gerd Hoffmann:
> Create virtio_gpu_object_params, use that to pass object parameters to
> virtio_gpu_object_create.  This is just the first step, followup patches
> will add more parameters to the struct.  The plan is to use the struct
> for all object parameters.
> 
> Drop unused "kernel" parameter for virtio_gpu_alloc_object(), it is
> unused and always false.
> 
> Also drop "pinned" parameter.  virtio-gpu doesn't shuffle around
> objects, so effecively they all are pinned anyway.  Hardcode
> TTM_PL_FLAG_NO_EVICT so ttm knows.  Doesn't change much for the moment
> as virtio-gpu supports TTM_PL_FLAG_TT only so there is no opportunity to
> move around objects.  That'll probably change in the future though.
> 
> Signed-off-by: Gerd Hoffmann 
> ---

Acked-by: Noralf Trønnes 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Re: [Intel-gfx] [PATCH 03/16] drm/atomic: Move __drm_atomic_helper_disable_plane/set_config()

2019-03-27 Thread Noralf Trønnes


Den 27.03.2019 14.55, skrev Daniel Vetter:
> On Wed, Mar 27, 2019 at 2:42 PM Noralf Trønnes  wrote:
>>
>>
>>
>> Den 26.03.2019 21.48, skrev Daniel Vetter:
>>> On Tue, Mar 26, 2019 at 06:55:33PM +0100, Noralf Trønnes wrote:
>>>> Prepare for moving drm_fb_helper modesetting code to drm_client.
>>>> drm_client will be linked to drm.ko, so move
>>>> __drm_atomic_helper_disable_plane() and __drm_atomic_helper_set_config()
>>>> out of drm_kms_helper.ko.
>>>>
>>>> While at it, fix two checkpatch complaints:
>>>> - WARNING: Block comments use a trailing */ on a separate line
>>>> - CHECK: Alignment should match open parenthesis
>>>>
>>>> Signed-off-by: Noralf Trønnes 
>>>
>>> Triggers a bit my midlayer ocd, but I can't come up with a better idea
>>> either.
>>>
>>> Reviewed-by: Daniel Vetter 
>>>
>>
>> The Intel CI informed me that this patch didn't apply..
>>
>> Turns out there's a patch in drm-next by Sean:
>>
>> drm: Merge __drm_atomic_helper_disable_all() into
>> drm_atomic_helper_disable_all()
>>
>> https://cgit.freedesktop.org/drm/drm/commit?id=37406a60fac7de336dec331a8707a94462ac5a5e
>>
>> Should I move the whole function with the kerneldoc to drm_atomic.c, or
>> should I keep the doc and function in drm_atomic_helper.c and just
>> recreate __drm_atomic_helper_disable_all() and call that ?
> 
> So my longterm goal with all these compat helpers is to move them into
> the core anyway, and make them at least the default, if not only the
> only accepted choice for atomic drivers. We've already done that for
> the dpms hook. We can't make it the enforced default yet for planes
> because of cursors, but I think we could just move both of these into
> the core (disable_plane and update_plane), make it the default option,
> and remove all driver users that just set it as the default hook.
> 
> Would need to be renamed to something like drm_atomic_default_* ofc.
> 
> Not sure why you're talking about disable_all here though, since that
> doesn't seem to be touched in this patch at all?

Sorry my bad, I was just confused. Looking at it again, I see that I can
just rebase on top of that patch.

Noralf.

> -Daniel
> 
>>
>> Noralf.
>>
>>>> ---
>>>>  drivers/gpu/drm/drm_atomic.c| 168 
>>>>  drivers/gpu/drm/drm_atomic_helper.c | 164 ---
>>>>  drivers/gpu/drm/drm_crtc_internal.h |   5 +
>>>>  include/drm/drm_atomic_helper.h |   4 -
>>>>  4 files changed, 173 insertions(+), 168 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
>>>> index 5eb40130fafb..c3a9ffbf2310 100644
>>>> --- a/drivers/gpu/drm/drm_atomic.c
>>>> +++ b/drivers/gpu/drm/drm_atomic.c
>>>> @@ -1130,6 +1130,174 @@ int drm_atomic_nonblocking_commit(struct 
>>>> drm_atomic_state *state)
>>>>  }
>>>>  EXPORT_SYMBOL(drm_atomic_nonblocking_commit);
>>>>
>>>> +/* just used from drm-client and atomic-helper: */
>>>> +int __drm_atomic_helper_disable_plane(struct drm_plane *plane,
>>>> +  struct drm_plane_state *plane_state)
>>>> +{
>>>> +int ret;
>>>> +
>>>> +ret = drm_atomic_set_crtc_for_plane(plane_state, NULL);
>>>> +if (ret != 0)
>>>> +return ret;
>>>> +
>>>> +drm_atomic_set_fb_for_plane(plane_state, NULL);
>>>> +plane_state->crtc_x = 0;
>>>> +plane_state->crtc_y = 0;
>>>> +plane_state->crtc_w = 0;
>>>> +plane_state->crtc_h = 0;
>>>> +plane_state->src_x = 0;
>>>> +plane_state->src_y = 0;
>>>> +plane_state->src_w = 0;
>>>> +plane_state->src_h = 0;
>>>> +
>>>> +return 0;
>>>> +}
>>>> +EXPORT_SYMBOL(__drm_atomic_helper_disable_plane);
>>>> +
>>>> +static int update_output_state(struct drm_atomic_state *state,
>>>> +   struct drm_mode_set *set)
>>>> +{
>>>> +struct drm_device *dev = set->crtc->dev;
>>>> +struct drm_crtc *crtc;
>>>> +struct drm_crtc_state *new_crtc_state;
>>>> +struct drm_connector *connector;
>>>> +struct drm_connector

Re: [PATCH] drm/virtio: add virtio-gpu-features debugfs file.

2019-03-27 Thread Noralf Trønnes


Den 20.03.2019 09.36, skrev Gerd Hoffmann:
> This file prints which features the virtio-gpu device has.
> 
> Also add "virtio-gpu-" prefix to the existing fence file,
> to make clear this is a driver-specific debugfs file.
> 
> Signed-off-by: Gerd Hoffmann 
> ---

Acked-by: Noralf Trønnes 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Re: [PATCH 00/16] drm/fb-helper: Move modesetting code to drm_client

2019-03-27 Thread Noralf Trønnes


Den 26.03.2019 18.55, skrev Noralf Trønnes:
> This moves the modesetting code from drm_fb_helper to drm_client so it
> can be shared by all internal clients.
> 
> I have also added a client display abstraction and a bootsplash example
> client to show where this might be heading. Hopefully Max Staudt will be
> able to pick up his bootsplash work now.

I get 'User has moved to ' failure on Max's email address. If
someone knows his new address, please cc him this cover letter.

Noralf.

> 
> Noralf.
> 
> Noralf Trønnes (16):
>   drm/fb-helper: Remove unused gamma_size variable
>   drm/fb-helper: dpms_legacy(): Only set on connectors in use
>   drm/atomic: Move __drm_atomic_helper_disable_plane/set_config()
>   drm/fb-helper: No need to cache rotation and sw_rotations
>   drm/fb-helper: Remove drm_fb_helper_crtc->{x,y,desired_mode}
>   drm/i915/fbdev: Move intel_fb_initial_config() to fbdev helper
>   drm/fb-helper: Remove drm_fb_helper_crtc
>   drm/fb-helper: Prepare to move out commit code
>   drm/fb-helper: Move out commit code
>   drm/fb-helper: Remove drm_fb_helper_connector
>   drm/fb-helper: Prepare to move out modeset config code
>   drm/fb-helper: Move out modeset config code
>   drm/fb-helper: Avoid race with DRM userspace
>   drm/client: Add display abstraction
>   drm/client: Hack: Add bootsplash example
>   drm/vc4: Call drm_dev_register() after all setup is done
> 
>  Documentation/gpu/todo.rst  |   10 +
>  drivers/gpu/drm/Kconfig |5 +
>  drivers/gpu/drm/Makefile|1 +
>  drivers/gpu/drm/drm_atomic.c|  168 
>  drivers/gpu/drm/drm_atomic_helper.c |  164 ---
>  drivers/gpu/drm/drm_auth.c  |   20 +
>  drivers/gpu/drm/drm_bootsplash.c|  216 
>  drivers/gpu/drm/drm_client.c| 1449 +++
>  drivers/gpu/drm/drm_crtc_internal.h |5 +
>  drivers/gpu/drm/drm_drv.c   |4 +
>  drivers/gpu/drm/drm_fb_helper.c | 1151 ++---
>  drivers/gpu/drm/drm_internal.h  |2 +
>  drivers/gpu/drm/i915/intel_fbdev.c  |  218 
>  drivers/gpu/drm/vc4/vc4_drv.c   |6 +-
>  include/drm/drm_atomic_helper.h |4 -
>  include/drm/drm_client.h|  117 +++
>  include/drm/drm_fb_helper.h |  127 +--
>  17 files changed, 2128 insertions(+), 1539 deletions(-)
>  create mode 100644 drivers/gpu/drm/drm_bootsplash.c
> 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Re: [Intel-gfx] [PATCH 03/16] drm/atomic: Move __drm_atomic_helper_disable_plane/set_config()

2019-03-27 Thread Noralf Trønnes


Den 26.03.2019 21.48, skrev Daniel Vetter:
> On Tue, Mar 26, 2019 at 06:55:33PM +0100, Noralf Trønnes wrote:
>> Prepare for moving drm_fb_helper modesetting code to drm_client.
>> drm_client will be linked to drm.ko, so move
>> __drm_atomic_helper_disable_plane() and __drm_atomic_helper_set_config()
>> out of drm_kms_helper.ko.
>>
>> While at it, fix two checkpatch complaints:
>> - WARNING: Block comments use a trailing */ on a separate line
>> - CHECK: Alignment should match open parenthesis
>>
>> Signed-off-by: Noralf Trønnes 
> 
> Triggers a bit my midlayer ocd, but I can't come up with a better idea
> either.
> 
> Reviewed-by: Daniel Vetter 
> 

The Intel CI informed me that this patch didn't apply.

Turns out there's a patch in drm-next by Sean:

drm: Merge __drm_atomic_helper_disable_all() into
drm_atomic_helper_disable_all()

https://cgit.freedesktop.org/drm/drm/commit?id=37406a60fac7de336dec331a8707a94462ac5a5e

Should I move the whole function with the kerneldoc to drm_atomic.c, or
should I keep the doc and function in drm_atomic_helper.c and just
recreate __drm_atomic_helper_disable_all() and call that ?

Noralf.

>> ---
>>  drivers/gpu/drm/drm_atomic.c| 168 
>>  drivers/gpu/drm/drm_atomic_helper.c | 164 ---
>>  drivers/gpu/drm/drm_crtc_internal.h |   5 +
>>  include/drm/drm_atomic_helper.h |   4 -
>>  4 files changed, 173 insertions(+), 168 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
>> index 5eb40130fafb..c3a9ffbf2310 100644
>> --- a/drivers/gpu/drm/drm_atomic.c
>> +++ b/drivers/gpu/drm/drm_atomic.c
>> @@ -1130,6 +1130,174 @@ int drm_atomic_nonblocking_commit(struct 
>> drm_atomic_state *state)
>>  }
>>  EXPORT_SYMBOL(drm_atomic_nonblocking_commit);
>>  
>> +/* just used from drm-client and atomic-helper: */
>> +int __drm_atomic_helper_disable_plane(struct drm_plane *plane,
>> +  struct drm_plane_state *plane_state)
>> +{
>> +int ret;
>> +
>> +ret = drm_atomic_set_crtc_for_plane(plane_state, NULL);
>> +if (ret != 0)
>> +return ret;
>> +
>> +drm_atomic_set_fb_for_plane(plane_state, NULL);
>> +plane_state->crtc_x = 0;
>> +plane_state->crtc_y = 0;
>> +plane_state->crtc_w = 0;
>> +plane_state->crtc_h = 0;
>> +plane_state->src_x = 0;
>> +plane_state->src_y = 0;
>> +plane_state->src_w = 0;
>> +plane_state->src_h = 0;
>> +
>> +return 0;
>> +}
>> +EXPORT_SYMBOL(__drm_atomic_helper_disable_plane);
>> +
>> +static int update_output_state(struct drm_atomic_state *state,
>> +   struct drm_mode_set *set)
>> +{
>> +struct drm_device *dev = set->crtc->dev;
>> +struct drm_crtc *crtc;
>> +struct drm_crtc_state *new_crtc_state;
>> +struct drm_connector *connector;
>> +struct drm_connector_state *new_conn_state;
>> +int ret, i;
>> +
>> +ret = drm_modeset_lock(>mode_config.connection_mutex,
>> +   state->acquire_ctx);
>> +if (ret)
>> +return ret;
>> +
>> +/* First disable all connectors on the target crtc. */
>> +ret = drm_atomic_add_affected_connectors(state, set->crtc);
>> +if (ret)
>> +return ret;
>> +
>> +for_each_new_connector_in_state(state, connector, new_conn_state, i) {
>> +if (new_conn_state->crtc == set->crtc) {
>> +ret = drm_atomic_set_crtc_for_connector(new_conn_state,
>> +NULL);
>> +if (ret)
>> +return ret;
>> +
>> +/* Make sure legacy setCrtc always re-trains */
>> +new_conn_state->link_status = DRM_LINK_STATUS_GOOD;
>> +}
>> +}
>> +
>> +/* Then set all connectors from set->connectors on the target crtc */
>> +for (i = 0; i < set->num_connectors; i++) {
>> +new_conn_state = drm_atomic_get_connector_state(state,
>> +
>> set->connectors[i]);
>> +if (IS_ERR(new_conn_state))
>> +return PTR_ERR(new_conn_state);
>> +
>> +ret = drm_atomic_set_crtc_for_connector(new_conn_state,
>> +  

Re: [PATCH] drm/fb-helper: Fixup fill_info cleanup

2019-03-27 Thread Noralf Trønnes


Den 27.03.2019 13.58, skrev Daniel Vetter:
> I forgot the !CONFIG_FBDEV case. Also some kerneldoc needed more
> adjusting.
> 
> Cc: Noralf Trønnes 
> Cc: Alex Deucher 
> Signed-off-by: Daniel Vetter 
> ---

Really nice that we have all these bots helping us out.

Reviewed-by: Noralf Trønnes 

>  drivers/gpu/drm/drm_fb_helper.c |  5 ++---
>  include/drm/drm_fb_helper.h | 18 ++
>  2 files changed, 8 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
> index 5c5ab6a2aa1f..c2e8dae6d828 100644
> --- a/drivers/gpu/drm/drm_fb_helper.c
> +++ b/drivers/gpu/drm/drm_fb_helper.c
> @@ -2783,9 +2783,8 @@ __drm_fb_helper_initial_config_and_unlock(struct 
> drm_fb_helper *fb_helper,
>   *
>   * This function will call down into the _fb_helper_funcs.fb_probe 
> callback
>   * to let the driver allocate and initialize the fbdev info structure and the
> - * drm framebuffer used to back the fbdev. drm_fb_helper_fill_var() and
> - * drm_fb_helper_fill_fix() are provided as helpers to setup simple default
> - * values for the fbdev info structure.
> + * drm framebuffer used to back the fbdev. drm_fb_helper_fill_info() is 
> provided
> + * as a helper to setup simple default values for the fbdev info structure.
>   *
>   * HANG DEBUGGING:
>   *
> diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
> index 9ba9db5dc34d..17857e458ac3 100644
> --- a/include/drm/drm_fb_helper.h
> +++ b/include/drm/drm_fb_helper.h
> @@ -68,10 +68,8 @@ struct drm_fb_helper_crtc {
>   * according to the largest width/height (so it is large enough for all CRTCs
>   * to scanout).  But the fbdev width/height is sized to the minimum width/
>   * height of all the displays.  This ensures that fbcon fits on the smallest
> - * of the attached displays.
> - *
> - * So what is passed to drm_fb_helper_fill_var() should be 
> fb_width/fb_height,
> - * rather than the surface size.
> + * of the attached displays. fb_width/fb_height is used by
> + * drm_fb_helper_fill_info() to fill out the _info.var structure.
>   */
>  struct drm_fb_helper_surface_size {
>   u32 fb_width;
> @@ -417,14 +415,10 @@ static inline void drm_fb_helper_unregister_fbi(struct 
> drm_fb_helper *fb_helper)
>  {
>  }
>  
> -static inline void drm_fb_helper_fill_var(struct fb_info *info,
> -   struct drm_fb_helper *fb_helper,
> -   uint32_t fb_width, uint32_t fb_height)
> -{
> -}
> -
> -static inline void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t 
> pitch,
> -   uint32_t depth)
> +static inline void
> +drm_fb_helper_fill_info(struct fb_info *info,
> + struct drm_fb_helper *fb_helper,
> + struct drm_fb_helper_surface_size *sizes)
>  {
>  }
>  
> 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH 14/16] drm/client: Add display abstraction

2019-03-26 Thread Noralf Trønnes
Add display abstraction and helpers to probe for displays and commit
modesets.

TODO:
If the bootsplash client doesn't need to subclass drm_client_display,
the callbacks can be removed.

Signed-off-by: Noralf Trønnes 
---
 drivers/gpu/drm/drm_client.c | 415 +++
 include/drm/drm_client.h |  80 +++
 2 files changed, 495 insertions(+)

diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c
index 3bc96b0b30ec..ef01a31a9dbe 100644
--- a/drivers/gpu/drm/drm_client.c
+++ b/drivers/gpu/drm/drm_client.c
@@ -4,6 +4,7 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -106,6 +107,9 @@ int drm_client_init(struct drm_device *dev, struct 
drm_client_dev *client,
 
drm_dev_get(dev);
 
+   mutex_init(>displaylist_mutex);
+   INIT_LIST_HEAD(>displaylist);
+
return 0;
 
 err_put_module:
@@ -156,6 +160,9 @@ void drm_client_release(struct drm_client_dev *client)
 
DRM_DEV_DEBUG_KMS(dev->dev, "%s\n", client->name);
 
+   drm_client_release_displays(client);
+   mutex_destroy(>displaylist_mutex);
+
drm_client_close(client);
drm_dev_put(dev);
if (client->funcs)
@@ -1419,6 +1426,414 @@ void drm_client_modesets_dpms(struct drm_device *dev, 
struct drm_mode_set *modes
 }
 EXPORT_SYMBOL(drm_client_modesets_dpms);
 
+static struct drm_client_display *
+drm_client_display_alloc(struct drm_client_dev *client, unsigned int 
num_modesets)
+{
+   struct drm_client_display *display;
+   struct drm_mode_set *modesets;
+
+   modesets = kcalloc(num_modesets + 1, sizeof(*modesets), GFP_KERNEL);
+   if (!modesets)
+   return ERR_PTR(-ENOMEM);
+
+   if (client->funcs && client->funcs->display_alloc)
+   display = client->funcs->display_alloc(client);
+   else
+   display = kzalloc(sizeof(*display), GFP_KERNEL);
+   if (!display)
+   display = ERR_PTR(-ENOMEM);
+
+   if (IS_ERR(display)) {
+   kfree(modesets);
+   return display;
+   }
+
+   display->client = client;
+   display->modesets = modesets;
+
+   return display;
+}
+
+static void drm_client_display_release(struct drm_client_display *display)
+{
+   unsigned int i;
+
+   if (!display)
+   return;
+
+   for (i = 0; i < display->num_buffers; i++)
+   drm_client_framebuffer_delete(display->buffers[i]);
+   kfree(display->buffers);
+
+   drm_mode_destroy(display->client->dev, display->mode);
+
+   drm_client_modesets_release(display->modesets);
+
+   if (display->client->funcs && display->client->funcs->display_free)
+   display->client->funcs->display_free(display);
+   else
+   kfree(display);
+}
+
+static void drm_client_display_debugprint(struct drm_client_display *display)
+{
+   struct drm_display_mode *mode = display->mode;
+   struct drm_mode_set *modeset;
+   unsigned int i;
+
+   DRM_DEBUG_KMS("  %dx%d %dHz\n", mode->hdisplay, mode->vdisplay, 
mode->vrefresh);
+
+   drm_client_for_each_modeset(modeset, display->modesets) {
+   DRM_DEBUG_KMS("crtc=%d, connectors:", 
modeset->crtc->base.id);
+   for (i = 0; i < modeset->num_connectors; i++)
+   DRM_DEBUG_KMS("  %s\n", 
modeset->connectors[i]->name);
+   }
+}
+
+static bool drm_client_modeset_equal(struct drm_mode_set *modeset1, struct 
drm_mode_set *modeset2)
+{
+   unsigned int i;
+
+   if (modeset1->crtc != modeset2->crtc ||
+   !drm_mode_equal(modeset1->mode, modeset2->mode) ||
+   modeset1->x != modeset2->x || modeset1->y != modeset2->y ||
+   modeset1->num_connectors != modeset2->num_connectors)
+   return false;
+
+   for (i = 0; i < modeset1->num_connectors; i++) {
+   if (modeset1->connectors[i] != modeset2->connectors[i])
+   return false;
+   }
+
+   return true;
+}
+
+static bool drm_client_display_equal(struct drm_client_display *display1,
+struct drm_client_display *display2)
+{
+   struct drm_mode_set *modeset1, *modeset2;
+
+   if (!display1 || !display2)
+   return false;
+
+   if (display1 == display2)
+   return true;
+
+   if (!drm_mode_equal(display1->mode, display2->mode))
+   return false;
+
+   for (modeset1 = display1->modesets, modeset2 = display2->modesets;
+modeset1->crtc && modeset2->crtc; modeset1++, modeset2++)
+   if (!drm_client_modeset_equal(modeset1, modeset2))
+   return false;
+
+   return !modeset1->crtc && !mo

[PATCH 15/16] drm/client: Hack: Add bootsplash example

2019-03-26 Thread Noralf Trønnes
An example to showcase the client API.

TODO:
A bootsplash client needs a way to tell drm_fb_helper to stay away,
otherwise it will chime in on setup and hotplug.
Most DRM drivers register fbdev before calling drm_dev_register() (the
generic emulation is an exception). This have to be reversed for
bootsplash to fend off fbdev.

Signed-off-by: Noralf Trønnes 
---
 drivers/gpu/drm/Kconfig  |   5 +
 drivers/gpu/drm/Makefile |   1 +
 drivers/gpu/drm/drm_bootsplash.c | 216 +++
 drivers/gpu/drm/drm_client.c |   7 +
 drivers/gpu/drm/drm_drv.c|   4 +
 include/drm/drm_client.h |   3 +
 6 files changed, 236 insertions(+)
 create mode 100644 drivers/gpu/drm/drm_bootsplash.c

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 5e1bc630b885..a7019c54e2a2 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -65,6 +65,11 @@ config DRM_DEBUG_SELFTEST
 
  If in doubt, say "N".
 
+config DRM_CLIENT_BOOTSPLASH
+   bool "DRM Bootsplash"
+   help
+ DRM Bootsplash
+
 config DRM_KMS_HELPER
tristate
depends on DRM
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index e630eccb951c..ac0573023842 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -32,6 +32,7 @@ drm-$(CONFIG_OF) += drm_of.o
 drm-$(CONFIG_AGP) += drm_agpsupport.o
 drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o
 drm-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
+drm-$(CONFIG_DRM_CLIENT_BOOTSPLASH) += drm_bootsplash.o
 
 drm_kms_helper-y := 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 \
diff --git a/drivers/gpu/drm/drm_bootsplash.c b/drivers/gpu/drm/drm_bootsplash.c
new file mode 100644
index ..fdc3349a2496
--- /dev/null
+++ b/drivers/gpu/drm/drm_bootsplash.c
@@ -0,0 +1,216 @@
+/* DRM internal client example */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+// drm_lastclose()
+#include "drm_internal.h"
+
+static bool drm_bootsplash_enabled = true;
+module_param_named(bootsplash_enabled, drm_bootsplash_enabled, bool, 0600);
+MODULE_PARM_DESC(bootsplash_enabled, "Enable bootsplash client 
[default=true]");
+
+struct drm_bootsplash {
+   struct drm_client_dev client;
+   struct mutex lock;
+   struct work_struct worker;
+   bool started;
+   bool stop;
+};
+
+static bool drm_bootsplash_key_pressed;
+
+static int drm_bootsplash_keyboard_notifier_call(struct notifier_block *blk,
+unsigned long code, void 
*_param)
+{
+   /* Any key is good */
+   drm_bootsplash_key_pressed = true;
+
+   return NOTIFY_OK;
+}
+
+static struct notifier_block drm_bootsplash_keyboard_notifier_block = {
+   .notifier_call = drm_bootsplash_keyboard_notifier_call,
+};
+
+static u32 drm_bootsplash_color_table[3] = {
+   0x00ff, 0xff00, 0x00ff,
+};
+
+/* Draw a box with changing colors */
+static void drm_bootsplash_draw(struct drm_client_buffer *buffer, unsigned int 
sequence)
+{
+   unsigned int width = buffer->fb->width;
+   unsigned int height = buffer->fb->height;
+   unsigned int x, y;
+   u32 *pix;
+
+   pix = buffer->vaddr;
+   pix += ((height / 2) - 50) * width;
+   pix += (width / 2) - 50;
+
+   for (y = 0; y < 100; y++) {
+   for (x = 0; x < 100; x++)
+   *pix++ = drm_bootsplash_color_table[sequence];
+   pix += width - 100;
+   }
+}
+
+static void drm_bootsplash_worker(struct work_struct *work)
+{
+   struct drm_bootsplash *splash = container_of(work, struct 
drm_bootsplash, worker);
+   struct drm_client_dev *client = >client;
+   struct drm_device *dev = client->dev;
+   struct drm_client_display *display;
+   unsigned int buffer_num = 0, sequence = 0, i;
+   bool stop;
+   int ret = 0;
+
+   while (!drm_bootsplash_key_pressed) {
+   mutex_lock(>lock);
+   stop = splash->stop;
+   mutex_unlock(>lock);
+   if (stop)
+   break;
+
+   buffer_num = !buffer_num;
+
+   mutex_lock(>displaylist_mutex);
+
+   ret = -ENOENT;
+
+   i = 0;
+   drm_client_for_each_display(display, client) {
+   DRM_DEBUG_KMS("draw: i=%u, buffer_num=%u, 
sequence=%u\n", i++, buffer_num, sequence);
+
+   drm_bootsplash_draw(display->buffers[buffer_num], 
sequence);
+
+   ret = drm_client_display_commit_buffer(display, 
buffer_num);
+   if (ret == -EBUSY)
+   break;
+
+   }
+

[PATCH 16/16] drm/vc4: Call drm_dev_register() after all setup is done

2019-03-26 Thread Noralf Trønnes
drm_dev_register() initializes internal clients like bootsplash as the
last thing it does, so all setup needs to be done at this point.

Fix by calling vc4_kms_load() before registering.
Also check the error code returned from that function.

Cc: Eric Anholt 
Signed-off-by: Noralf Trønnes 
---
 drivers/gpu/drm/vc4/vc4_drv.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c
index 4daf44fd4548..ba87b2dfa767 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.c
+++ b/drivers/gpu/drm/vc4/vc4_drv.c
@@ -280,11 +280,13 @@ static int vc4_drm_bind(struct device *dev)
 
drm_fb_helper_remove_conflicting_framebuffers(NULL, "vc4drmfb", false);
 
-   ret = drm_dev_register(drm, 0);
+   ret = vc4_kms_load(drm);
if (ret < 0)
goto unbind_all;
 
-   vc4_kms_load(drm);
+   ret = drm_dev_register(drm, 0);
+   if (ret < 0)
+   goto unbind_all;
 
drm_fbdev_generic_setup(drm, 16);
 
-- 
2.20.1

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

[PATCH 13/16] drm/fb-helper: Avoid race with DRM userspace

2019-03-26 Thread Noralf Trønnes
drm_fb_helper_is_bound() is used to check if DRM userspace is in control.
This is done by looking at the fb on the primary plane. By the time
fb-helper gets around to committing, it's possible that the facts have
changed.

Avoid this race by holding the drm_device->master_mutex lock while
committing. When DRM userspace does its first open, it will now wait
until fb-helper is done. The helper will stay away if there's a master.

Locking rule: Always take the fb-helper lock first.

Suggested-by: Daniel Vetter 
Signed-off-by: Noralf Trønnes 
---
 drivers/gpu/drm/drm_auth.c  | 20 ++
 drivers/gpu/drm/drm_fb_helper.c | 49 -
 drivers/gpu/drm/drm_internal.h  |  2 ++
 3 files changed, 58 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c
index 1669c42c40ed..db199807b7dc 100644
--- a/drivers/gpu/drm/drm_auth.c
+++ b/drivers/gpu/drm/drm_auth.c
@@ -368,3 +368,23 @@ void drm_master_put(struct drm_master **master)
*master = NULL;
 }
 EXPORT_SYMBOL(drm_master_put);
+
+/* Used by drm_client and drm_fb_helper */
+bool drm_master_internal_acquire(struct drm_device *dev)
+{
+   mutex_lock(>master_mutex);
+   if (dev->master) {
+   mutex_unlock(>master_mutex);
+   return false;
+   }
+
+   return true;
+}
+EXPORT_SYMBOL(drm_master_internal_acquire);
+
+/* Used by drm_client and drm_fb_helper */
+void drm_master_internal_release(struct drm_device *dev)
+{
+   mutex_unlock(>master_mutex);
+}
+EXPORT_SYMBOL(drm_master_internal_release);
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 4a073cd4e423..9f253fcf3f79 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -41,6 +41,8 @@
 #include 
 #include 
 
+#include "drm_internal.h"
+
 static bool drm_fbdev_emulation = true;
 module_param_named(fbdev_emulation, drm_fbdev_emulation, bool, 0600);
 MODULE_PARM_DESC(fbdev_emulation,
@@ -235,7 +237,12 @@ int drm_fb_helper_restore_fbdev_mode_unlocked(struct 
drm_fb_helper *fb_helper)
return 0;
 
mutex_lock(_helper->lock);
-   ret = drm_client_modesets_commit(fb_helper->dev, fb_helper->modesets);
+   if (drm_master_internal_acquire(fb_helper->dev)) {
+   ret = drm_client_modesets_commit(fb_helper->dev, 
fb_helper->modesets);
+   drm_master_internal_release(fb_helper->dev);
+   } else {
+   ret = -EBUSY;
+   }
 
do_delayed = fb_helper->delayed_hotplug;
if (do_delayed)
@@ -332,13 +339,16 @@ static struct sysrq_key_op sysrq_drm_fb_helper_restore_op 
= { };
 static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode)
 {
struct drm_fb_helper *fb_helper = info->par;
+   struct drm_device *dev = fb_helper->dev;
 
/*
 * For each CRTC in this fb, turn the connectors on/off.
 */
mutex_lock(_helper->lock);
-   if (drm_fb_helper_is_bound(fb_helper))
-   drm_client_modesets_dpms(fb_helper->dev, fb_helper->modesets, 
dpms_mode);
+   if (drm_master_internal_acquire(dev)) {
+   drm_client_modesets_dpms(dev, fb_helper->modesets, dpms_mode);
+   drm_master_internal_release(dev);
+   }
mutex_unlock(_helper->lock);
 }
 
@@ -1097,6 +1107,7 @@ static int setcmap_atomic(struct fb_cmap *cmap, struct 
fb_info *info)
 int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info)
 {
struct drm_fb_helper *fb_helper = info->par;
+   struct drm_device *dev = fb_helper->dev;
int ret;
 
if (oops_in_progress)
@@ -1104,9 +1115,9 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct 
fb_info *info)
 
mutex_lock(_helper->lock);
 
-   if (!drm_fb_helper_is_bound(fb_helper)) {
+   if (!drm_master_internal_acquire(dev)) {
ret = -EBUSY;
-   goto out;
+   goto unlock;
}
 
if (info->fix.visual == FB_VISUAL_TRUECOLOR)
@@ -1116,7 +1127,8 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct 
fb_info *info)
else
ret = setcmap_legacy(cmap, info);
 
-out:
+   drm_master_internal_release(dev);
+unlock:
mutex_unlock(_helper->lock);
 
return ret;
@@ -1136,11 +1148,13 @@ int drm_fb_helper_ioctl(struct fb_info *info, unsigned 
int cmd,
unsigned long arg)
 {
struct drm_fb_helper *fb_helper = info->par;
+   struct drm_device *dev = fb_helper->dev;
struct drm_crtc *crtc;
int ret = 0;
 
mutex_lock(_helper->lock);
-   if (!drm_fb_helper_is_bound(fb_helper)) {
+
+   if (!drm_master_internal_acquire(dev)) {
ret = -EBUSY;
goto unlock;
}
@@ -1177,13 +1191,15 @@ int drm_fb_helper_ioctl(struct fb_info *info, unsigned 
int cmd,
 

[PATCH 12/16] drm/fb-helper: Move out modeset config code

2019-03-26 Thread Noralf Trønnes
No functional changes, just moving code as-is and fixing includes.
There is one addition and that is exporting drm_client_modesets_probe().

Signed-off-by: Noralf Trønnes 
---
 drivers/gpu/drm/drm_client.c| 698 
 drivers/gpu/drm/drm_fb_helper.c | 697 ---
 include/drm/drm_client.h|   4 +-
 3 files changed, 700 insertions(+), 699 deletions(-)

diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c
index 5b199c051960..3bc96b0b30ec 100644
--- a/drivers/gpu/drm/drm_client.c
+++ b/drivers/gpu/drm/drm_client.c
@@ -11,9 +11,11 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -24,6 +26,12 @@
 #include "drm_crtc_internal.h"
 #include "drm_internal.h"
 
+#define DRM_CLIENT_MAX_CLONED_CONNECTORS   8
+
+struct drm_client_offset {
+   int x, y;
+};
+
 /**
  * DOC: overview
  *
@@ -486,6 +494,696 @@ struct drm_mode_set *drm_client_find_modeset(struct 
drm_mode_set *modesets, stru
 }
 EXPORT_SYMBOL(drm_client_find_modeset);
 
+static struct drm_display_mode *
+drm_connector_has_preferred_mode(struct drm_connector *connector, int width, 
int height)
+{
+   struct drm_display_mode *mode;
+
+   list_for_each_entry(mode, >modes, head) {
+   if (mode->hdisplay > width ||
+   mode->vdisplay > height)
+   continue;
+   if (mode->type & DRM_MODE_TYPE_PREFERRED)
+   return mode;
+   }
+   return NULL;
+}
+
+static struct drm_display_mode *
+drm_connector_pick_cmdline_mode(struct drm_connector *connector)
+{
+   struct drm_cmdline_mode *cmdline_mode;
+   struct drm_display_mode *mode;
+   bool prefer_non_interlace;
+
+   cmdline_mode = >cmdline_mode;
+   if (cmdline_mode->specified == false)
+   return NULL;
+
+   /* attempt to find a matching mode in the list of modes
+*  we have gotten so far, if not add a CVT mode that conforms
+*/
+   if (cmdline_mode->rb || cmdline_mode->margins)
+   goto create_mode;
+
+   prefer_non_interlace = !cmdline_mode->interlace;
+again:
+   list_for_each_entry(mode, >modes, head) {
+   /* check width/height */
+   if (mode->hdisplay != cmdline_mode->xres ||
+   mode->vdisplay != cmdline_mode->yres)
+   continue;
+
+   if (cmdline_mode->refresh_specified) {
+   if (mode->vrefresh != cmdline_mode->refresh)
+   continue;
+   }
+
+   if (cmdline_mode->interlace) {
+   if (!(mode->flags & DRM_MODE_FLAG_INTERLACE))
+   continue;
+   } else if (prefer_non_interlace) {
+   if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+   continue;
+   }
+   return mode;
+   }
+
+   if (prefer_non_interlace) {
+   prefer_non_interlace = false;
+   goto again;
+   }
+
+create_mode:
+   mode = drm_mode_create_from_cmdline_mode(connector->dev, cmdline_mode);
+   list_add(>head, >modes);
+   return mode;
+}
+
+static bool drm_connector_enabled(struct drm_connector *connector, bool strict)
+{
+   bool enable;
+
+   if (connector->display_info.non_desktop)
+   return false;
+
+   if (strict)
+   enable = connector->status == connector_status_connected;
+   else
+   enable = connector->status != connector_status_disconnected;
+
+   return enable;
+}
+
+static void drm_client_connectors_enabled(struct drm_connector **connectors,
+ unsigned int connector_count,
+ bool *enabled)
+{
+   bool any_enabled = false;
+   struct drm_connector *connector;
+   int i = 0;
+
+   for (i = 0; i < connector_count; i++) {
+   connector = connectors[i];
+   enabled[i] = drm_connector_enabled(connector, true);
+   DRM_DEBUG_KMS("connector %d enabled? %s\n", connector->base.id,
+ connector->display_info.non_desktop ? "non 
desktop" : enabled[i] ? "yes" : "no");
+
+   any_enabled |= enabled[i];
+   }
+
+   if (any_enabled)
+   return;
+
+   for (i = 0; i < connector_count; i++)
+   enabled[i] = drm_connector_enabled(connectors[i], false);
+}
+
+static bool drm_client_target_cloned(struct drm_device *dev,
+struct drm_connector **connectors,
+unsigned int connector_count,
+str

[PATCH 11/16] drm/fb-helper: Prepare to move out modeset config code

2019-03-26 Thread Noralf Trønnes
This prepares the modeset code so it can be moved out as-is in the next
patch.

Signed-off-by: Noralf Trønnes 
---
 drivers/gpu/drm/drm_fb_helper.c | 75 +
 include/drm/drm_fb_helper.h |  4 --
 2 files changed, 57 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index de805956849d..afe4d4220e4d 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -45,6 +45,10 @@
 #include "drm_crtc_internal.h"
 #include "drm_crtc_helper_internal.h"
 
+struct drm_client_offset {
+   int x, y;
+};
+
 static bool drm_fbdev_emulation = true;
 module_param_named(fbdev_emulation, drm_fbdev_emulation, bool, 0600);
 MODULE_PARM_DESC(fbdev_emulation,
@@ -1792,7 +1796,7 @@ static bool drm_client_target_cloned(struct drm_device 
*dev,
 struct drm_connector **connectors,
 unsigned int connector_count,
 struct drm_display_mode **modes,
-struct drm_fb_offset *offsets,
+struct drm_client_offset *offsets,
 bool *enabled, int width, int height)
 {
int count, i, j;
@@ -1871,7 +1875,7 @@ static bool drm_client_target_cloned(struct drm_device 
*dev,
 static int drm_client_get_tile_offsets(struct drm_connector **connectors,
   unsigned int connector_count,
   struct drm_display_mode **modes,
-  struct drm_fb_offset *offsets,
+  struct drm_client_offset *offsets,
   int idx,
   int h_idx, int v_idx)
 {
@@ -1904,7 +1908,7 @@ static int drm_client_get_tile_offsets(struct 
drm_connector **connectors,
 static bool drm_client_target_preferred(struct drm_connector **connectors,
unsigned int connector_count,
struct drm_display_mode **modes,
-   struct drm_fb_offset *offsets,
+   struct drm_client_offset *offsets,
bool *enabled, int width, int height)
 {
const u64 mask = BIT_ULL(connector_count) - 1;
@@ -2068,7 +2072,7 @@ static bool drm_client_firmware_config(struct drm_device 
*dev,
   unsigned int connector_count,
   struct drm_crtc **crtcs,
   struct drm_display_mode **modes,
-  struct drm_fb_offset *offsets,
+  struct drm_client_offset *offsets,
   bool *enabled, int width, int height)
 {
unsigned int count = min_t(unsigned int, connector_count, 
BITS_PER_LONG);
@@ -2236,32 +2240,51 @@ static bool drm_client_firmware_config(struct 
drm_device *dev,
return ret;
 }
 
-static void drm_setup_crtcs(struct drm_fb_helper *fb_helper,
-   u32 width, u32 height)
+/**
+ * drm_client_modesets_probe() - Probe for displays
+ * @dev: DRM device
+ * @width: Maximum display mode width (optional)
+ * @height: Maximum display mode height (optional)
+ *
+ * This function tries to set up pipelines for enabled connectors and returns
+ * the CRTC config as a _mode_set array.
+ *
+ * Use drm_client_modesets_release() to free the array and its resources.
+ *
+ * Returns:
+ * A _mode_set array on success, NULL if no connectors are found
+ * or error pointer on failure.
+ */
+struct drm_mode_set *
+drm_client_modesets_probe(struct drm_device *dev, unsigned int width, unsigned 
int height)
 {
struct drm_connector *connector, **connectors = NULL;
struct drm_connector_list_iter conn_iter;
-   struct drm_device *dev = fb_helper->dev;
struct drm_mode_set *modesets = NULL;
unsigned int total_modes_count = 0;
+   struct drm_client_offset *offsets;
unsigned int connector_count = 0;
struct drm_display_mode **modes;
-   struct drm_fb_offset *offsets;
struct drm_crtc **crtcs;
+   int i, ret = 0;
bool *enabled;
-   int i;
 
DRM_DEBUG_KMS("\n");
-   /* prevent concurrent modification of connector_count by hotplug */
-   lockdep_assert_held(_helper->lock);
+
+   if (!width)
+   width = dev->mode_config.max_width;
+   if (!height)
+   height = dev->mode_config.max_height;
 
drm_connector_list_iter_begin(dev, _iter);
drm_client_for_each_connector_iter(connector, _iter) {
struct drm_connector **tmp;
 
tmp = krealloc(connectors, (connector_cou

[PATCH 10/16] drm/fb-helper: Remove drm_fb_helper_connector

2019-03-26 Thread Noralf Trønnes
All drivers add all their connectors so there's no need to keep around an
array of available connectors.

Rename functions which signature is changed since they will be moved to
drm_client in a later patch.

Signed-off-by: Noralf Trønnes 
---

checkpatch complains, but I'm unable to satisfy it:

ERROR: Macros with complex values should be enclosed in parentheses
#939: FILE: include/drm/drm_client.h:160:
+#define drm_client_for_each_connector_iter(connector, iter) \
+   drm_for_each_connector_iter(connector, iter) \
+   if (connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK)


 Documentation/gpu/todo.rst  |   3 +
 drivers/gpu/drm/drm_fb_helper.c | 499 ++--
 include/drm/drm_client.h|  15 +
 include/drm/drm_fb_helper.h |  80 ++---
 4 files changed, 194 insertions(+), 403 deletions(-)

diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst
index 8fa08b5feab7..f6cdd1c26788 100644
--- a/Documentation/gpu/todo.rst
+++ b/Documentation/gpu/todo.rst
@@ -306,6 +306,9 @@ drm_fb_helper cleanup tasks
 - The max connector argument for drm_fb_helper_init() and
   drm_fb_helper_fbdev_setup() isn't used anymore and can be removed.
 
+- The helper doesn't keep an array of connectors anymore so these can be
+  removed: drm_fb_helper_single_add_all_connectors(),
+  drm_fb_helper_add_one_connector() and drm_fb_helper_remove_one_connector().
 
 Core refactorings
 =
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index be946d702019..de805956849d 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -92,12 +92,6 @@ static DEFINE_MUTEX(kernel_fb_helper_lock);
  * Setup fbdev emulation by calling drm_fb_helper_fbdev_setup() and tear it
  * down by calling drm_fb_helper_fbdev_teardown().
  *
- * Drivers that need to handle connector hotplugging (e.g. dp mst) can't use
- * the setup helper and will need to do the whole four-step setup process with
- * drm_fb_helper_prepare(), drm_fb_helper_init(),
- * drm_fb_helper_single_add_all_connectors(), enable hotplugging and
- * drm_fb_helper_initial_config() to avoid a possible race window.
- *
  * At runtime drivers should restore the fbdev console by using
  * drm_fb_helper_lastclose() as their _driver.lastclose callback.
  * They should also notify the fb helper code from updates to the output
@@ -120,8 +114,7 @@ static DEFINE_MUTEX(kernel_fb_helper_lock);
  * encoders and connectors. To finish up the fbdev helper initialization, the
  * drm_fb_helper_init() function is called. To probe for all attached displays
  * and set up an initial configuration using the detected hardware, drivers
- * should call drm_fb_helper_single_add_all_connectors() followed by
- * drm_fb_helper_initial_config().
+ * should call drm_fb_helper_initial_config().
  *
  * If _framebuffer_funcs.dirty is set, the
  * drm_fb_helper_{cfb,sys}_{write,fillrect,copyarea,imageblit} functions will
@@ -134,165 +127,6 @@ static DEFINE_MUTEX(kernel_fb_helper_lock);
  * deferred I/O (coupled with drm_fb_helper_fbdev_teardown()).
  */
 
-#define drm_fb_helper_for_each_connector(fbh, i__) \
-   for (({ lockdep_assert_held(&(fbh)->lock); }), \
-i__ = 0; i__ < (fbh)->connector_count; i__++)
-
-static int __drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper,
-struct drm_connector *connector)
-{
-   struct drm_fb_helper_connector *fb_conn;
-   struct drm_fb_helper_connector **temp;
-   unsigned int count;
-
-   if (!drm_fbdev_emulation)
-   return 0;
-
-   lockdep_assert_held(_helper->lock);
-
-   count = fb_helper->connector_count + 1;
-
-   if (count > fb_helper->connector_info_alloc_count) {
-   size_t size = count * sizeof(fb_conn);
-
-   temp = krealloc(fb_helper->connector_info, size, GFP_KERNEL);
-   if (!temp)
-   return -ENOMEM;
-
-   fb_helper->connector_info_alloc_count = count;
-   fb_helper->connector_info = temp;
-   }
-
-   fb_conn = kzalloc(sizeof(*fb_conn), GFP_KERNEL);
-   if (!fb_conn)
-   return -ENOMEM;
-
-   drm_connector_get(connector);
-   fb_conn->connector = connector;
-   fb_helper->connector_info[fb_helper->connector_count++] = fb_conn;
-
-   return 0;
-}
-
-int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper,
-   struct drm_connector *connector)
-{
-   int err;
-
-   if (!fb_helper)
-   return 0;
-
-   mutex_lock(_helper->lock);
-   err = __drm_fb_helper_add_one_connector(fb_helper, connector);
-   mutex_unlock(_helper->lock);
-
-   return err;
-}
-EXPORT_SYMBOL(drm_fb_helper_add_one_connector);
-
-/**
- * drm_fb_helper_single_add_all_connectors() - add all connectors to fbdev
- * 

[PATCH 06/16] drm/i915/fbdev: Move intel_fb_initial_config() to fbdev helper

2019-03-26 Thread Noralf Trønnes
It is generic code and having it in the helper will let other drivers
benefit from it.

One change was necessary assuming this to be true:
INTEL_INFO(dev_priv)->num_pipes == dev->mode_config.num_crtc

Suggested-by: Daniel Vetter 
Cc: Jani Nikula 
Cc: Joonas Lahtinen 
Cc: Rodrigo Vivi 
Cc: intel-...@lists.freedesktop.org
Signed-off-by: Noralf Trønnes 
---
 drivers/gpu/drm/drm_fb_helper.c| 194 -
 drivers/gpu/drm/i915/intel_fbdev.c | 218 -
 include/drm/drm_fb_helper.h|  23 ---
 3 files changed, 190 insertions(+), 245 deletions(-)

diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 36310901e935..634f4dcf0c41 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -2545,6 +2545,194 @@ static int drm_pick_crtcs(struct drm_fb_helper 
*fb_helper,
return best_score;
 }
 
+static struct drm_fb_helper_crtc *
+drm_fb_helper_crtc(struct drm_fb_helper *fb_helper, struct drm_crtc *crtc)
+{
+   int i;
+
+   for (i = 0; i < fb_helper->crtc_count; i++)
+   if (fb_helper->crtc_info[i].mode_set.crtc == crtc)
+   return _helper->crtc_info[i];
+
+   return NULL;
+}
+
+/* Try to read the BIOS display configuration and use it for the initial 
config */
+static bool drm_fb_helper_firmware_config(struct drm_fb_helper *fb_helper,
+ struct drm_fb_helper_crtc **crtcs,
+ struct drm_display_mode **modes,
+ struct drm_fb_offset *offsets,
+ bool *enabled, int width, int height)
+{
+   struct drm_device *dev = fb_helper->dev;
+   unsigned int count = min(fb_helper->connector_count, BITS_PER_LONG);
+   unsigned long conn_configured, conn_seq;
+   int i, j;
+   bool *save_enabled;
+   bool fallback = true, ret = true;
+   int num_connectors_enabled = 0;
+   int num_connectors_detected = 0;
+   struct drm_modeset_acquire_ctx ctx;
+
+   save_enabled = kcalloc(count, sizeof(bool), GFP_KERNEL);
+   if (!save_enabled)
+   return false;
+
+   drm_modeset_acquire_init(, 0);
+
+   while (drm_modeset_lock_all_ctx(dev, ) != 0)
+   drm_modeset_backoff();
+
+   memcpy(save_enabled, enabled, count);
+   conn_seq = GENMASK(count - 1, 0);
+   conn_configured = 0;
+retry:
+   for (i = 0; i < count; i++) {
+   struct drm_fb_helper_connector *fb_conn;
+   struct drm_connector *connector;
+   struct drm_encoder *encoder;
+   struct drm_fb_helper_crtc *new_crtc;
+
+   fb_conn = fb_helper->connector_info[i];
+   connector = fb_conn->connector;
+
+   if (conn_configured & BIT(i))
+   continue;
+
+   /* First pass, only consider tiled connectors */
+   if (conn_seq == GENMASK(count - 1, 0) && !connector->has_tile)
+   continue;
+
+   if (connector->status == connector_status_connected)
+   num_connectors_detected++;
+
+   if (!enabled[i]) {
+   DRM_DEBUG_KMS("connector %s not enabled, skipping\n",
+ connector->name);
+   conn_configured |= BIT(i);
+   continue;
+   }
+
+   if (connector->force == DRM_FORCE_OFF) {
+   DRM_DEBUG_KMS("connector %s is disabled by user, 
skipping\n",
+ connector->name);
+   enabled[i] = false;
+   continue;
+   }
+
+   encoder = connector->state->best_encoder;
+   if (!encoder || WARN_ON(!connector->state->crtc)) {
+   if (connector->force > DRM_FORCE_OFF)
+   goto bail;
+
+   DRM_DEBUG_KMS("connector %s has no encoder or crtc, 
skipping\n",
+ connector->name);
+   enabled[i] = false;
+   conn_configured |= BIT(i);
+   continue;
+   }
+
+   num_connectors_enabled++;
+
+   new_crtc = drm_fb_helper_crtc(fb_helper, 
connector->state->crtc);
+
+   /*
+* Make sure we're not trying to drive multiple connectors
+* with a single CRTC, since our cloning support may not
+* match the BIOS.
+*/
+   for (j = 0; j < count; j++) {
+   if (crtcs[j] == new_crtc) {
+   DRM_DEBUG_KMS("fallback: cloned 
configuration\n");
+ 

[PATCH 09/16] drm/fb-helper: Move out commit code

2019-03-26 Thread Noralf Trønnes
Move the modeset commit code to drm_client.
No changes except exporting API.

Signed-off-by: Noralf Trønnes 
---
 drivers/gpu/drm/drm_client.c| 236 
 drivers/gpu/drm/drm_fb_helper.c | 232 ---
 include/drm/drm_client.h|   3 +
 3 files changed, 239 insertions(+), 232 deletions(-)

diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c
index 84f848f21679..5b199c051960 100644
--- a/drivers/gpu/drm/drm_client.c
+++ b/drivers/gpu/drm/drm_client.c
@@ -9,6 +9,7 @@
 #include 
 #include 
 
+#include 
 #include 
 #include 
 #include 
@@ -485,6 +486,241 @@ struct drm_mode_set *drm_client_find_modeset(struct 
drm_mode_set *modesets, stru
 }
 EXPORT_SYMBOL(drm_client_find_modeset);
 
+/**
+ * drm_client_panel_rotation() - Check panel orientation
+ * @modeset: DRM modeset
+ * @rotation: Returned rotation value
+ *
+ * This function checks if the primary plane in @modeset can hw rotate to match
+ * the panel orientation on its connector.
+ *
+ * Note: Currently only 0 and 180 degrees are supported.
+ *
+ * Return:
+ * True if the plane can do the rotation, false otherwise.
+ */
+bool drm_client_panel_rotation(struct drm_mode_set *modeset, unsigned int 
*rotation)
+{
+   struct drm_connector *connector = modeset->connectors[0];
+   struct drm_plane *plane = modeset->crtc->primary;
+   u64 valid_mask = 0;
+   unsigned int i;
+
+   if (!modeset->num_connectors)
+   return false;
+
+   switch (connector->display_info.panel_orientation) {
+   case DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP:
+   *rotation = DRM_MODE_ROTATE_180;
+   break;
+   case DRM_MODE_PANEL_ORIENTATION_LEFT_UP:
+   *rotation = DRM_MODE_ROTATE_90;
+   break;
+   case DRM_MODE_PANEL_ORIENTATION_RIGHT_UP:
+   *rotation = DRM_MODE_ROTATE_270;
+   break;
+   default:
+   *rotation = DRM_MODE_ROTATE_0;
+   }
+
+   /*
+* TODO: support 90 / 270 degree hardware rotation,
+* depending on the hardware this may require the framebuffer
+* to be in a specific tiling format.
+*/
+   if (*rotation != DRM_MODE_ROTATE_180 || !plane->rotation_property)
+   return false;
+
+   for (i = 0; i < plane->rotation_property->num_values; i++)
+   valid_mask |= (1ULL << plane->rotation_property->values[i]);
+
+   if (!(*rotation & valid_mask))
+   return false;
+
+   return true;
+}
+EXPORT_SYMBOL(drm_client_panel_rotation);
+
+static int drm_client_modesets_commit_atomic(struct drm_device *dev, struct 
drm_mode_set *modesets,
+bool active)
+{
+   struct drm_plane_state *plane_state;
+   struct drm_plane *plane;
+   struct drm_atomic_state *state;
+   struct drm_modeset_acquire_ctx ctx;
+   struct drm_mode_set *mode_set;
+   int ret;
+
+   drm_modeset_acquire_init(, 0);
+
+   state = drm_atomic_state_alloc(dev);
+   if (!state) {
+   ret = -ENOMEM;
+   goto out_ctx;
+   }
+
+   state->acquire_ctx = 
+retry:
+   drm_for_each_plane(plane, dev) {
+   plane_state = drm_atomic_get_plane_state(state, plane);
+   if (IS_ERR(plane_state)) {
+   ret = PTR_ERR(plane_state);
+   goto out_state;
+   }
+
+   plane_state->rotation = DRM_MODE_ROTATE_0;
+
+   /* disable non-primary: */
+   if (plane->type == DRM_PLANE_TYPE_PRIMARY)
+   continue;
+
+   ret = __drm_atomic_helper_disable_plane(plane, plane_state);
+   if (ret != 0)
+   goto out_state;
+   }
+
+   drm_client_for_each_modeset(mode_set, modesets) {
+   struct drm_plane *primary = mode_set->crtc->primary;
+   unsigned int rotation;
+
+   if (drm_client_panel_rotation(mode_set, )) {
+   /* Cannot fail as we've already gotten the plane state 
above */
+   plane_state = drm_atomic_get_new_plane_state(state, 
primary);
+   plane_state->rotation = rotation;
+   }
+
+   ret = __drm_atomic_helper_set_config(mode_set, state);
+   if (ret != 0)
+   goto out_state;
+
+   /*
+* __drm_atomic_helper_set_config() sets active when a
+* mode is set, unconditionally clear it if we force DPMS off
+*/
+   if (!active) {
+   struct drm_crtc *crtc = mode_set->crtc;
+   struct drm_crtc_state *crtc_state = 
drm_atomic_get_new_crtc_state(state, crtc);
+
+   crtc_state->active = false;
+   }
+   }
+
+ 

[PATCH 05/16] drm/fb-helper: Remove drm_fb_helper_crtc->{x, y, desired_mode}

2019-03-26 Thread Noralf Trønnes
The values are already present in the modeset.

This is done in preparation for the removal of struct drm_fb_helper_crtc.

Signed-off-by: Noralf Trønnes 
---
 drivers/gpu/drm/drm_fb_helper.c | 12 
 include/drm/drm_fb_helper.h |  2 --
 2 files changed, 4 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index e1b147fdd3f9..36310901e935 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -2023,16 +2023,16 @@ static int drm_fb_helper_single_fb_probe(struct 
drm_fb_helper *fb_helper,
 */
bool lastv = true, lasth = true;
 
-   desired_mode = fb_helper->crtc_info[i].desired_mode;
mode_set = _helper->crtc_info[i].mode_set;
+   desired_mode = mode_set->mode;
 
if (!desired_mode)
continue;
 
crtc_count++;
 
-   x = fb_helper->crtc_info[i].x;
-   y = fb_helper->crtc_info[i].y;
+   x = mode_set->x;
+   y = mode_set->y;
 
sizes.surface_width  = max_t(u32, desired_mode->hdisplay + x, 
sizes.surface_width);
sizes.surface_height = max_t(u32, desired_mode->vdisplay + y, 
sizes.surface_height);
@@ -2617,11 +2617,7 @@ static void drm_setup_crtcs(struct drm_fb_helper 
*fb_helper,
DRM_DEBUG_KMS("desired mode %s set on crtc %d 
(%d,%d)\n",
  mode->name, 
fb_crtc->mode_set.crtc->base.id, offset->x, offset->y);
 
-   fb_crtc->desired_mode = mode;
-   fb_crtc->x = offset->x;
-   fb_crtc->y = offset->y;
-   modeset->mode = drm_mode_duplicate(dev,
-  
fb_crtc->desired_mode);
+   modeset->mode = drm_mode_duplicate(dev, mode);
drm_connector_get(connector);
modeset->connectors[modeset->num_connectors++] = 
connector;
modeset->x = offset->x;
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
index cff1aa222886..7a095964f6b2 100644
--- a/include/drm/drm_fb_helper.h
+++ b/include/drm/drm_fb_helper.h
@@ -48,8 +48,6 @@ struct drm_fb_offset {
 
 struct drm_fb_helper_crtc {
struct drm_mode_set mode_set;
-   struct drm_display_mode *desired_mode;
-   int x, y;
 };
 
 /**
-- 
2.20.1

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

[PATCH 00/16] drm/fb-helper: Move modesetting code to drm_client

2019-03-26 Thread Noralf Trønnes
This moves the modesetting code from drm_fb_helper to drm_client so it
can be shared by all internal clients.

I have also added a client display abstraction and a bootsplash example
client to show where this might be heading. Hopefully Max Staudt will be
able to pick up his bootsplash work now.

Noralf.

Noralf Trønnes (16):
  drm/fb-helper: Remove unused gamma_size variable
  drm/fb-helper: dpms_legacy(): Only set on connectors in use
  drm/atomic: Move __drm_atomic_helper_disable_plane/set_config()
  drm/fb-helper: No need to cache rotation and sw_rotations
  drm/fb-helper: Remove drm_fb_helper_crtc->{x,y,desired_mode}
  drm/i915/fbdev: Move intel_fb_initial_config() to fbdev helper
  drm/fb-helper: Remove drm_fb_helper_crtc
  drm/fb-helper: Prepare to move out commit code
  drm/fb-helper: Move out commit code
  drm/fb-helper: Remove drm_fb_helper_connector
  drm/fb-helper: Prepare to move out modeset config code
  drm/fb-helper: Move out modeset config code
  drm/fb-helper: Avoid race with DRM userspace
  drm/client: Add display abstraction
  drm/client: Hack: Add bootsplash example
  drm/vc4: Call drm_dev_register() after all setup is done

 Documentation/gpu/todo.rst  |   10 +
 drivers/gpu/drm/Kconfig |5 +
 drivers/gpu/drm/Makefile|1 +
 drivers/gpu/drm/drm_atomic.c|  168 
 drivers/gpu/drm/drm_atomic_helper.c |  164 ---
 drivers/gpu/drm/drm_auth.c  |   20 +
 drivers/gpu/drm/drm_bootsplash.c|  216 
 drivers/gpu/drm/drm_client.c| 1449 +++
 drivers/gpu/drm/drm_crtc_internal.h |5 +
 drivers/gpu/drm/drm_drv.c   |4 +
 drivers/gpu/drm/drm_fb_helper.c | 1151 ++---
 drivers/gpu/drm/drm_internal.h  |2 +
 drivers/gpu/drm/i915/intel_fbdev.c  |  218 
 drivers/gpu/drm/vc4/vc4_drv.c   |6 +-
 include/drm/drm_atomic_helper.h |4 -
 include/drm/drm_client.h|  117 +++
 include/drm/drm_fb_helper.h |  127 +--
 17 files changed, 2128 insertions(+), 1539 deletions(-)
 create mode 100644 drivers/gpu/drm/drm_bootsplash.c

-- 
2.20.1

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

[PATCH 08/16] drm/fb-helper: Prepare to move out commit code

2019-03-26 Thread Noralf Trønnes
This makes the necessary changes so the commit code can be moved out to
drm_client as-is in the next patch. It's split up to ease review.

Signed-off-by: Noralf Trønnes 
---
 drivers/gpu/drm/drm_fb_helper.c | 93 +
 1 file changed, 59 insertions(+), 34 deletions(-)

diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 85bea51e2072..9dcb77dfff0a 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -382,9 +382,20 @@ int drm_fb_helper_debug_leave(struct fb_info *info)
 }
 EXPORT_SYMBOL(drm_fb_helper_debug_leave);
 
-/* Check if the plane can hw rotate to match panel orientation */
-static bool drm_fb_helper_panel_rotation(struct drm_mode_set *modeset,
-unsigned int *rotation)
+/**
+ * drm_client_panel_rotation() - Check panel orientation
+ * @modeset: DRM modeset
+ * @rotation: Returned rotation value
+ *
+ * This function checks if the primary plane in @modeset can hw rotate to match
+ * the panel orientation on its connector.
+ *
+ * Note: Currently only 0 and 180 degrees are supported.
+ *
+ * Return:
+ * True if the plane can do the rotation, false otherwise.
+ */
+bool drm_client_panel_rotation(struct drm_mode_set *modeset, unsigned int 
*rotation)
 {
struct drm_connector *connector = modeset->connectors[0];
struct drm_plane *plane = modeset->crtc->primary;
@@ -425,9 +436,9 @@ static bool drm_fb_helper_panel_rotation(struct 
drm_mode_set *modeset,
return true;
 }
 
-static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool 
active)
+static int drm_client_modesets_commit_atomic(struct drm_device *dev, struct 
drm_mode_set *modesets,
+bool active)
 {
-   struct drm_device *dev = fb_helper->dev;
struct drm_plane_state *plane_state;
struct drm_plane *plane;
struct drm_atomic_state *state;
@@ -463,11 +474,11 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper 
*fb_helper, bool activ
goto out_state;
}
 
-   drm_client_for_each_modeset(mode_set, fb_helper->modesets) {
+   drm_client_for_each_modeset(mode_set, modesets) {
struct drm_plane *primary = mode_set->crtc->primary;
unsigned int rotation;
 
-   if (drm_fb_helper_panel_rotation(mode_set, )) {
+   if (drm_client_panel_rotation(mode_set, )) {
/* Cannot fail as we've already gotten the plane state 
above */
plane_state = drm_atomic_get_new_plane_state(state, 
primary);
plane_state->rotation = rotation;
@@ -509,14 +520,13 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper 
*fb_helper, bool activ
goto retry;
 }
 
-static int restore_fbdev_mode_legacy(struct drm_fb_helper *fb_helper)
+static int drm_client_modesets_commit_legacy(struct drm_device *dev, struct 
drm_mode_set *modesets)
 {
-   struct drm_device *dev = fb_helper->dev;
struct drm_mode_set *mode_set;
struct drm_plane *plane;
int ret = 0;
 
-   drm_modeset_lock_all(fb_helper->dev);
+   drm_modeset_lock_all(dev);
drm_for_each_plane(plane, dev) {
if (plane->type != DRM_PLANE_TYPE_PRIMARY)
drm_plane_force_disable(plane);
@@ -527,7 +537,7 @@ static int restore_fbdev_mode_legacy(struct drm_fb_helper 
*fb_helper)
DRM_MODE_ROTATE_0);
}
 
-   drm_client_for_each_modeset(mode_set, fb_helper->modesets) {
+   drm_client_for_each_modeset(mode_set, modesets) {
struct drm_crtc *crtc = mode_set->crtc;
 
if (crtc->funcs->cursor_set2) {
@@ -545,19 +555,25 @@ static int restore_fbdev_mode_legacy(struct drm_fb_helper 
*fb_helper)
goto out;
}
 out:
-   drm_modeset_unlock_all(fb_helper->dev);
+   drm_modeset_unlock_all(dev);
 
return ret;
 }
 
-static int restore_fbdev_mode(struct drm_fb_helper *fb_helper)
+/**
+ * drm_client_modesets_commit() - Commit CRTC configuration
+ * @dev: DRM device
+ * @modesets: Modeset array
+ *
+ * Returns:
+ * Zero on success or negative error code on failure.
+ */
+int drm_client_modesets_commit(struct drm_device *dev, struct drm_mode_set 
*modesets)
 {
-   struct drm_device *dev = fb_helper->dev;
-
if (drm_drv_uses_atomic_modeset(dev))
-   return restore_fbdev_mode_atomic(fb_helper, true);
+   return drm_client_modesets_commit_atomic(dev, modesets, true);
else
-   return restore_fbdev_mode_legacy(fb_helper);
+   return drm_client_modesets_commit_legacy(dev, modesets);
 }
 
 /**
@@ -583,7 +599,7 @@ int drm_fb_helper_restore_fbdev_mode_unlocked(struct 
drm_fb_helper *fb_helper)
return 

[PATCH 07/16] drm/fb-helper: Remove drm_fb_helper_crtc

2019-03-26 Thread Noralf Trønnes
It now only contains the modeset so use that directly instead. The modeset
code will be moved to drm_client, so add code there.

The modeset connector array size is hardcoded for the cloned case to avoid
having to pass in a value from the driver. A value of 8 is chosen to err
on the safe side. This means that the max connector argument for
drm_fb_helper_init() and drm_fb_helper_fbdev_setup() isn't used anymore,
a todo entry for this is added.

Signed-off-by: Noralf Trønnes 
---
 Documentation/gpu/todo.rst  |   7 +
 drivers/gpu/drm/drm_client.c|  93 
 drivers/gpu/drm/drm_fb_helper.c | 262 +++-
 include/drm/drm_client.h|  16 ++
 include/drm/drm_fb_helper.h |  14 +-
 5 files changed, 207 insertions(+), 185 deletions(-)

diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst
index 1528ad2d598b..8fa08b5feab7 100644
--- a/Documentation/gpu/todo.rst
+++ b/Documentation/gpu/todo.rst
@@ -300,6 +300,13 @@ it to use drm_mode_hsync() instead.
 
 Contact: Sean Paul
 
+drm_fb_helper cleanup tasks
+---
+
+- The max connector argument for drm_fb_helper_init() and
+  drm_fb_helper_fbdev_setup() isn't used anymore and can be removed.
+
+
 Core refactorings
 =
 
diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c
index 9b2bd28dde0a..84f848f21679 100644
--- a/drivers/gpu/drm/drm_client.c
+++ b/drivers/gpu/drm/drm_client.c
@@ -392,6 +392,99 @@ void drm_client_framebuffer_delete(struct 
drm_client_buffer *buffer)
 }
 EXPORT_SYMBOL(drm_client_framebuffer_delete);
 
+/**
+ * drm_client_modesets_create() - Create modeset array
+ * @dev: DRM device
+ *
+ * This function creates a _mode_set array, one entry per CRTC.
+ *
+ * Returns:
+ * A _mode_set array or an error pointer on allocation failure.
+ */
+struct drm_mode_set *drm_client_modesets_create(struct drm_device *dev)
+{
+   unsigned int num_crtc = dev->mode_config.num_crtc;
+   struct drm_mode_set *modeset, *modesets;
+   unsigned int max_connector_count = 1;
+   struct drm_crtc *crtc;
+   unsigned int i = 0;
+
+   /* Add terminating zero entry to enable index less iteration */
+   modesets = kcalloc(num_crtc + 1, sizeof(*modesets), GFP_KERNEL);
+   if (!modesets)
+   return ERR_PTR(-ENOMEM);
+
+   drm_for_each_crtc(crtc, dev)
+   modesets[i++].crtc = crtc;
+
+   /* Cloning is only supported in the single crtc case. */
+   if (num_crtc == 1)
+   max_connector_count = DRM_CLIENT_MAX_CLONED_CONNECTORS;
+
+   drm_client_for_each_modeset(modeset, modesets) {
+   modeset->connectors = kcalloc(max_connector_count,
+ sizeof(*modeset->connectors), 
GFP_KERNEL);
+   if (!modeset->connectors)
+   goto err_free;
+   }
+
+   return modesets;
+
+err_free:
+   drm_client_modesets_release(modesets);
+
+   return ERR_PTR(-ENOMEM);
+}
+EXPORT_SYMBOL(drm_client_modesets_create);
+
+/**
+ * drm_client_modesets_release() - Free modesets
+ * @modesets: Modeset array (can be NULL or error pointer)
+ *
+ * This function destroys any attached display modes, puts connectors and frees
+ * the modeset array.
+ */
+void drm_client_modesets_release(struct drm_mode_set *modesets)
+{
+   struct drm_mode_set *modeset;
+   unsigned int i;
+
+   if (IS_ERR_OR_NULL(modesets))
+   return;
+
+   drm_client_for_each_modeset(modeset, modesets) {
+   drm_mode_destroy(modeset->crtc->dev, modeset->mode);
+
+   for (i = 0; i < modeset->num_connectors; i++)
+   drm_connector_put(modeset->connectors[i]);
+   kfree(modeset->connectors);
+   }
+   kfree(modesets);
+}
+EXPORT_SYMBOL(drm_client_modesets_release);
+
+/**
+ * drm_client_find_modeset() - Find modeset matching a CRTC
+ * @modesets: Modeset array
+ * @crtc: CRTC
+ *
+ * This function looks up the modeset connected to @crtc.
+ *
+ * Returns:
+ * A _mode_set or NULL.
+ */
+struct drm_mode_set *drm_client_find_modeset(struct drm_mode_set *modesets, 
struct drm_crtc *crtc)
+{
+   struct drm_mode_set *modeset;
+
+   drm_client_for_each_modeset(modeset, modesets)
+   if (modeset->crtc == crtc)
+   return modeset;
+
+   return NULL;
+}
+EXPORT_SYMBOL(drm_client_find_modeset);
+
 #ifdef CONFIG_DEBUG_FS
 static int drm_client_debugfs_internal_clients(struct seq_file *m, void *data)
 {
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 634f4dcf0c41..85bea51e2072 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -316,13 +316,10 @@ int drm_fb_helper_debug_enter(struct fb_info *info)
 {
struct drm_fb_helper *helper = info->par;
const struct drm_crtc_helper_funcs *funcs;
-   int i

[PATCH 03/16] drm/atomic: Move __drm_atomic_helper_disable_plane/set_config()

2019-03-26 Thread Noralf Trønnes
Prepare for moving drm_fb_helper modesetting code to drm_client.
drm_client will be linked to drm.ko, so move
__drm_atomic_helper_disable_plane() and __drm_atomic_helper_set_config()
out of drm_kms_helper.ko.

While at it, fix two checkpatch complaints:
- WARNING: Block comments use a trailing */ on a separate line
- CHECK: Alignment should match open parenthesis

Signed-off-by: Noralf Trønnes 
---
 drivers/gpu/drm/drm_atomic.c| 168 
 drivers/gpu/drm/drm_atomic_helper.c | 164 ---
 drivers/gpu/drm/drm_crtc_internal.h |   5 +
 include/drm/drm_atomic_helper.h |   4 -
 4 files changed, 173 insertions(+), 168 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 5eb40130fafb..c3a9ffbf2310 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -1130,6 +1130,174 @@ int drm_atomic_nonblocking_commit(struct 
drm_atomic_state *state)
 }
 EXPORT_SYMBOL(drm_atomic_nonblocking_commit);
 
+/* just used from drm-client and atomic-helper: */
+int __drm_atomic_helper_disable_plane(struct drm_plane *plane,
+ struct drm_plane_state *plane_state)
+{
+   int ret;
+
+   ret = drm_atomic_set_crtc_for_plane(plane_state, NULL);
+   if (ret != 0)
+   return ret;
+
+   drm_atomic_set_fb_for_plane(plane_state, NULL);
+   plane_state->crtc_x = 0;
+   plane_state->crtc_y = 0;
+   plane_state->crtc_w = 0;
+   plane_state->crtc_h = 0;
+   plane_state->src_x = 0;
+   plane_state->src_y = 0;
+   plane_state->src_w = 0;
+   plane_state->src_h = 0;
+
+   return 0;
+}
+EXPORT_SYMBOL(__drm_atomic_helper_disable_plane);
+
+static int update_output_state(struct drm_atomic_state *state,
+  struct drm_mode_set *set)
+{
+   struct drm_device *dev = set->crtc->dev;
+   struct drm_crtc *crtc;
+   struct drm_crtc_state *new_crtc_state;
+   struct drm_connector *connector;
+   struct drm_connector_state *new_conn_state;
+   int ret, i;
+
+   ret = drm_modeset_lock(>mode_config.connection_mutex,
+  state->acquire_ctx);
+   if (ret)
+   return ret;
+
+   /* First disable all connectors on the target crtc. */
+   ret = drm_atomic_add_affected_connectors(state, set->crtc);
+   if (ret)
+   return ret;
+
+   for_each_new_connector_in_state(state, connector, new_conn_state, i) {
+   if (new_conn_state->crtc == set->crtc) {
+   ret = drm_atomic_set_crtc_for_connector(new_conn_state,
+   NULL);
+   if (ret)
+   return ret;
+
+   /* Make sure legacy setCrtc always re-trains */
+   new_conn_state->link_status = DRM_LINK_STATUS_GOOD;
+   }
+   }
+
+   /* Then set all connectors from set->connectors on the target crtc */
+   for (i = 0; i < set->num_connectors; i++) {
+   new_conn_state = drm_atomic_get_connector_state(state,
+   
set->connectors[i]);
+   if (IS_ERR(new_conn_state))
+   return PTR_ERR(new_conn_state);
+
+   ret = drm_atomic_set_crtc_for_connector(new_conn_state,
+   set->crtc);
+   if (ret)
+   return ret;
+   }
+
+   for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
+   /*
+* Don't update ->enable for the CRTC in the set_config request,
+* since a mismatch would indicate a bug in the upper layers.
+* The actual modeset code later on will catch any
+* inconsistencies here.
+*/
+   if (crtc == set->crtc)
+   continue;
+
+   if (!new_crtc_state->connector_mask) {
+   ret = drm_atomic_set_mode_prop_for_crtc(new_crtc_state,
+   NULL);
+   if (ret < 0)
+   return ret;
+
+   new_crtc_state->active = false;
+   }
+   }
+
+   return 0;
+}
+
+/* just used from drm-client and atomic-helper: */
+int __drm_atomic_helper_set_config(struct drm_mode_set *set,
+  struct drm_atomic_state *state)
+{
+   struct drm_crtc_state *crtc_state;
+   struct drm_plane_state *primary_state;
+   struct drm_crtc *crtc = set->crtc;
+   int hdisplay, vdisplay;
+   int ret;
+
+   crtc_state = drm_atomic_get_crtc_state(state, crtc);
+   if (IS_ERR(crtc_state))
+  

[PATCH 01/16] drm/fb-helper: Remove unused gamma_size variable

2019-03-26 Thread Noralf Trønnes
The gamma_size variable has not been used since
commit 4abe35204af8 ("drm/kms/fb: use slow work mechanism for normal hotplug 
also.")

While in the area move a comment back to its code block.
They got separated by
commit d50ba256b5f1 ("drm/kms: start adding command line interface using fb.").

Signed-off-by: Noralf Trønnes 
---
 drivers/gpu/drm/drm_fb_helper.c | 6 +-
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 04d23cb430bf..eea15465da7a 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -1873,7 +1873,6 @@ static int drm_fb_helper_single_fb_probe(struct 
drm_fb_helper *fb_helper,
int crtc_count = 0;
int i;
struct drm_fb_helper_surface_size sizes;
-   int gamma_size = 0;
int best_depth = 0;
 
memset(, 0, sizeof(struct drm_fb_helper_surface_size));
@@ -1889,7 +1888,6 @@ static int drm_fb_helper_single_fb_probe(struct 
drm_fb_helper *fb_helper,
if (preferred_bpp != sizes.surface_bpp)
sizes.surface_depth = sizes.surface_bpp = preferred_bpp;
 
-   /* first up get a count of crtcs now in use and new min/maxes 
width/heights */
drm_fb_helper_for_each_connector(fb_helper, i) {
struct drm_fb_helper_connector *fb_helper_conn = 
fb_helper->connector_info[i];
struct drm_cmdline_mode *cmdline_mode;
@@ -1969,6 +1967,7 @@ static int drm_fb_helper_single_fb_probe(struct 
drm_fb_helper *fb_helper,
sizes.surface_depth = best_depth;
}
 
+   /* first up get a count of crtcs now in use and new min/maxes 
width/heights */
crtc_count = 0;
for (i = 0; i < fb_helper->crtc_count; i++) {
struct drm_display_mode *desired_mode;
@@ -1991,9 +1990,6 @@ static int drm_fb_helper_single_fb_probe(struct 
drm_fb_helper *fb_helper,
x = fb_helper->crtc_info[i].x;
y = fb_helper->crtc_info[i].y;
 
-   if (gamma_size == 0)
-   gamma_size = 
fb_helper->crtc_info[i].mode_set.crtc->gamma_size;
-
sizes.surface_width  = max_t(u32, desired_mode->hdisplay + x, 
sizes.surface_width);
sizes.surface_height = max_t(u32, desired_mode->vdisplay + y, 
sizes.surface_height);
 
-- 
2.20.1

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

[PATCH 04/16] drm/fb-helper: No need to cache rotation and sw_rotations

2019-03-26 Thread Noralf Trønnes
Getting rotation info is cheap so we can do it on demand.

This is done in preparation for the removal of struct drm_fb_helper_crtc.

Cc: Hans de Goede 
Signed-off-by: Noralf Trønnes 
---

Hans, 

You had this comment inline in restore_fbdev_mode_atomic() the last time
I sent this out:

  We want plane_state->rotation to be set to DRM_MODE_ROTATE_0 in the else
  case, AFAIK new_plane_state starts with the current state and rotation
  may have a different value there.
  
  Otherwise this looks good to me.

Rotation is reset for each plane in the code section above the one I'm
changing.

Noralf.

 drivers/gpu/drm/drm_fb_helper.c | 131 
 include/drm/drm_fb_helper.h |   8 --
 2 files changed, 65 insertions(+), 74 deletions(-)

diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index b91df658db59..e1b147fdd3f9 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -387,6 +387,49 @@ int drm_fb_helper_debug_leave(struct fb_info *info)
 }
 EXPORT_SYMBOL(drm_fb_helper_debug_leave);
 
+/* Check if the plane can hw rotate to match panel orientation */
+static bool drm_fb_helper_panel_rotation(struct drm_mode_set *modeset,
+unsigned int *rotation)
+{
+   struct drm_connector *connector = modeset->connectors[0];
+   struct drm_plane *plane = modeset->crtc->primary;
+   u64 valid_mask = 0;
+   unsigned int i;
+
+   if (!modeset->num_connectors)
+   return false;
+
+   switch (connector->display_info.panel_orientation) {
+   case DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP:
+   *rotation = DRM_MODE_ROTATE_180;
+   break;
+   case DRM_MODE_PANEL_ORIENTATION_LEFT_UP:
+   *rotation = DRM_MODE_ROTATE_90;
+   break;
+   case DRM_MODE_PANEL_ORIENTATION_RIGHT_UP:
+   *rotation = DRM_MODE_ROTATE_270;
+   break;
+   default:
+   *rotation = DRM_MODE_ROTATE_0;
+   }
+
+   /*
+* TODO: support 90 / 270 degree hardware rotation,
+* depending on the hardware this may require the framebuffer
+* to be in a specific tiling format.
+*/
+   if (*rotation != DRM_MODE_ROTATE_180 || !plane->rotation_property)
+   return false;
+
+   for (i = 0; i < plane->rotation_property->num_values; i++)
+   valid_mask |= (1ULL << plane->rotation_property->values[i]);
+
+   if (!(*rotation & valid_mask))
+   return false;
+
+   return true;
+}
+
 static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool 
active)
 {
struct drm_device *dev = fb_helper->dev;
@@ -427,10 +470,13 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper 
*fb_helper, bool activ
for (i = 0; i < fb_helper->crtc_count; i++) {
struct drm_mode_set *mode_set = 
_helper->crtc_info[i].mode_set;
struct drm_plane *primary = mode_set->crtc->primary;
+   unsigned int rotation;
 
-   /* Cannot fail as we've already gotten the plane state above */
-   plane_state = drm_atomic_get_new_plane_state(state, primary);
-   plane_state->rotation = fb_helper->crtc_info[i].rotation;
+   if (drm_fb_helper_panel_rotation(mode_set, )) {
+   /* Cannot fail as we've already gotten the plane state 
above */
+   plane_state = drm_atomic_get_new_plane_state(state, 
primary);
+   plane_state->rotation = rotation;
+   }
 
ret = __drm_atomic_helper_set_config(mode_set, state);
if (ret != 0)
@@ -881,7 +927,6 @@ int drm_fb_helper_init(struct drm_device *dev,
if (!fb_helper->crtc_info[i].mode_set.connectors)
goto out_free;
fb_helper->crtc_info[i].mode_set.num_connectors = 0;
-   fb_helper->crtc_info[i].rotation = DRM_MODE_ROTATE_0;
}
 
i = 0;
@@ -2500,62 +2545,6 @@ static int drm_pick_crtcs(struct drm_fb_helper 
*fb_helper,
return best_score;
 }
 
-/*
- * This function checks if rotation is necessary because of panel orientation
- * and if it is, if it is supported.
- * If rotation is necessary and supported, it gets set in fb_crtc.rotation.
- * If rotation is necessary but not supported, a DRM_MODE_ROTATE_* flag gets
- * or-ed into fb_helper->sw_rotations. In drm_setup_crtcs_fb() we check if only
- * one bit is set and then we set fb_info.fbcon_rotate_hint to make fbcon do
- * the unsupported rotation.
- */
-static void drm_setup_crtc_rotation(struct drm_fb_helper *fb_helper,
-   struct drm_fb_helper_crtc *fb_crtc,
-   struct drm_connector *connector)
-{
-   struct drm_plane *plane = fb_c

[PATCH 02/16] drm/fb-helper: dpms_legacy(): Only set on connectors in use

2019-03-26 Thread Noralf Trønnes
For each enabled crtc the functions sets dpms on all registered connectors.
Limit this to only doing it once and on the connectors actually in use.

Signed-off-by: Noralf Trønnes 
---
 drivers/gpu/drm/drm_fb_helper.c | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index eea15465da7a..b91df658db59 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -639,20 +639,19 @@ static struct sysrq_key_op sysrq_drm_fb_helper_restore_op 
= { };
 static void dpms_legacy(struct drm_fb_helper *fb_helper, int dpms_mode)
 {
struct drm_device *dev = fb_helper->dev;
-   struct drm_crtc *crtc;
struct drm_connector *connector;
+   struct drm_mode_set *modeset;
int i, j;
 
drm_modeset_lock_all(dev);
for (i = 0; i < fb_helper->crtc_count; i++) {
-   crtc = fb_helper->crtc_info[i].mode_set.crtc;
+   modeset = _helper->crtc_info[i].mode_set;
 
-   if (!crtc->enabled)
+   if (!modeset->crtc->enabled)
continue;
 
-   /* Walk the connectors & encoders on this fb turning them 
on/off */
-   drm_fb_helper_for_each_connector(fb_helper, j) {
-   connector = fb_helper->connector_info[j]->connector;
+   for (j = 0; j < modeset->num_connectors; j++) {
+   connector = modeset->connectors[j];
connector->funcs->dpms(connector, dpms_mode);
drm_object_property_set_value(>base,
dev->mode_config.dpms_property, dpms_mode);
-- 
2.20.1

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

Re: [PATCH 21/21] drm/fb-helper: Unexport fill_{var,info}

2019-03-26 Thread Noralf Trønnes


Den 26.03.2019 14.20, skrev Daniel Vetter:
> Not used by drivers anymore.
> 
> v2: Rebase
> 
> Signed-off-by: Daniel Vetter 
> ---

Reviewed-by: Noralf Trønnes 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Re: [PATCH 20/21] drm/vboxvideo: Use drm_fb_helper_fill_info

2019-03-26 Thread Noralf Trønnes


Den 26.03.2019 14.20, skrev Daniel Vetter:
> This should not result in any changes.
> 
> v2: Rebase over vbox changes - vbox gained it's own line to fill
> fix.id.
> 
> v3: Rebase
> 
> Reviewed-by: Greg Kroah-Hartman  (v2)
> Signed-off-by: Daniel Vetter 
> Cc: Greg Kroah-Hartman 
> Cc: Hans de Goede 
> Cc: Daniel Vetter 
> Cc: Alexander Kapshuk 
> Cc: Bartlomiej Zolnierkiewicz 
> ---

Reviewed-by: Noralf Trønnes 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Re: [PATCH 19/21] drm/udl: Use drm_fb_helper_fill_info

2019-03-26 Thread Noralf Trønnes


Den 26.03.2019 14.20, skrev Daniel Vetter:
> This should not result in any changes.
> 
> v2: Rebase
> 
> Signed-off-by: Daniel Vetter 
> Cc: Dave Airlie 
> Cc: Sean Paul 
> Cc: Mikulas Patocka 
> Cc: Daniel Vetter 
> Cc: Greg Kroah-Hartman 
> Cc: Emil Lundmark 
> ---
>  drivers/gpu/drm/udl/udl_fb.c | 7 ++-
>  1 file changed, 2 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c
> index dd9ffded223b..59e005edf309 100644
> --- a/drivers/gpu/drm/udl/udl_fb.c
> +++ b/drivers/gpu/drm/udl/udl_fb.c
> @@ -32,7 +32,7 @@ module_param(fb_bpp, int, S_IWUSR | S_IRUSR | S_IWGRP | 
> S_IRGRP);
>  module_param(fb_defio, int, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
>  
>  struct udl_fbdev {
> - struct drm_fb_helper helper;
> + struct drm_fb_helper helper; /* must be first */
>   struct udl_framebuffer ufb;
>   int fb_count;
>  };
> @@ -402,15 +402,12 @@ static int udlfb_create(struct drm_fb_helper *helper,
>  

You forgot to remove the info->par assignement here. With that:

Acked-by: Noralf Trønnes 

>   ufbdev->helper.fb = fb;
>  
> - strcpy(info->fix.id, "udldrmfb");
> -
>   info->screen_base = ufbdev->ufb.obj->vmapping;
>   info->fix.smem_len = size;
>   info->fix.smem_start = (unsigned long)ufbdev->ufb.obj->vmapping;
>  
>   info->fbops = _ops;
> - drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth);
> - drm_fb_helper_fill_var(info, >helper, sizes->fb_width, 
> sizes->fb_height);
> + drm_fb_helper_fill_info(info, >helper, sizes);
>  
>   DRM_DEBUG_KMS("allocated %dx%d vmal %p\n",
> fb->width, fb->height,
> 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Re: [PATCH 18/21] drm/tegra: Use drm_fb_helper_fill_info

2019-03-26 Thread Noralf Trønnes


Den 26.03.2019 14.20, skrev Daniel Vetter:
> Another driver that didn't set fbinfo->fix.id before.
> 
> v2: Fix subject and rebase
> 
> Acked-by: Thierry Reding 
> Signed-off-by: Daniel Vetter 
> Cc: Thierry Reding 
> Cc: Jonathan Hunter 
> Cc: linux-te...@vger.kernel.org
> ---

Reviewed-by: Noralf Trønnes 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Re: [PATCH 17/21] drm/rockchip: Use drm_fb_helper_fill_info

2019-03-26 Thread Noralf Trønnes


Den 26.03.2019 14.20, skrev Daniel Vetter:
> This will set an fb name for the first time!
> 
> v2: Rebase
> 
> Reviewed-by: Heiko Stuebner 
> Signed-off-by: Daniel Vetter 
> Cc: Sandy Huang 
> Cc: "Heiko Stübner" 
> Cc: linux-arm-ker...@lists.infradead.org
> Cc: linux-rockc...@lists.infradead.org
> ---

Reviewed-by: Noralf Trønnes 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Re: [PATCH 16/21] drm/radeon: Use drm_fb_helper_fill_info

2019-03-26 Thread Noralf Trønnes


Den 26.03.2019 14.20, skrev Daniel Vetter:
> This should not result in any changes.
> 
> v2: Rebase
> 
> Signed-off-by: Daniel Vetter 
> Cc: Alex Deucher 
> Cc: "Christian König" 
> Cc: "David (ChunMing) Zhou" 
> Cc: amd-...@lists.freedesktop.org
> ---

Acked-by: Noralf Trønnes 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Re: [PATCH 15/21] drm/omap: Use drm_fb_helper_fill_info

2019-03-26 Thread Noralf Trønnes


Den 26.03.2019 14.20, skrev Daniel Vetter:
> This changes the fb name from "omapdrm" to "omapdrmfb".
> 
> v2: Rebase
> 
> Signed-off-by: Daniel Vetter 
> Cc: Tomi Valkeinen 
> ---

Reviewed-by: Noralf Trønnes 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

<    4   5   6   7   8   9   10   11   12   13   >