All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Noralf Trønnes" <noralf@tronnes.org>
To: Andy Shevchenko <andy.shevchenko@gmail.com>
Cc: dri-devel@lists.freedesktop.org,
	devicetree <devicetree@vger.kernel.org>,
	robh@kernel.org,
	Thomas Petazzoni <thomas.petazzoni@free-electrons.com>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH v4 2/7] drm/tinydrm: Add helper functions
Date: Sun, 12 Feb 2017 16:33:04 +0100	[thread overview]
Message-ID: <2ee54d47-ff7e-2f94-9eea-7d75788b3e1c@tronnes.org> (raw)
In-Reply-To: <CAHp75Vfc+2iUz=2ias5enwbTVd=unu3dEiRgiAwbGFS2KEW+2A@mail.gmail.com>


Den 12.02.2017 12.50, skrev Andy Shevchenko:
> On Sat, Feb 11, 2017 at 8:48 PM, Noralf Trønnes <noralf@tronnes.org> wrote:
>> Add common functionality needed by many tinydrm drivers.
>> +int tinydrm_enable_backlight(struct backlight_device *backlight)
>> +{
>> +       unsigned int old_state;
>> +       int ret;
>> +
>> +       if (!backlight)
>> +               return 0;
>> +
>> +       old_state = backlight->props.state;
>> +       backlight->props.state &= ~BL_CORE_FBBLANK;
>> +       DRM_DEBUG_KMS("Backlight state: 0x%x -> 0x%x\n", old_state,
>> +                     backlight->props.state);
> "%#x" ?
> (And elsewhere)
>
>> +#if IS_ENABLED(CONFIG_SPI)
>> +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);
> I don't get why DMA constrain somehow affects this framework?

The reason is that spi-bcm2835 reverts to PIO on larger buffers.
Looking at __spi_map_msg() and spi_map_buf() it becomes clear that the
core breaks up the buffer into manageable parts. So this must be a bug
in spi-bcm2835 (and spi-pxa2xx) since no other drivers have a upper
limit in the .can_dma() callback.
So you're rightly confused, with drivers fixed, this limit can be lifted.

> What if max_dma_len is zero (imagine SPI master that works only by PIO
> by some reason)?

It can't be zero:

int spi_register_master(struct spi_master *master)
{
...
     if (!master->max_dma_len)
         master->max_dma_len = INT_MAX;

>> +       if (max_len)
>> +               ret = min(ret, max_len);
>> +       if (spi_max)
>> +               ret = min_t(size_t, ret, spi_max);
>> +       ret &= ~0x3;
> Why alignment is that? Why do we need it? Isn't a busyness of SPI
> framework to cope with it?

This minimum capping doesn't look good. I should probably put >16
instead, that would cover the minimum for the 9-bit emulation code.

The reason I let the user change the transfer size, is that some usb
audio card on Raspberry Pi stuttered with 4k fbtft transfers.

>> +       if (ret < 4)
> It's effectively check for 0.
>
>> +               ret = 4;
>> +
>> +       return ret;
>> +}
>> +EXPORT_SYMBOL(tinydrm_spi_max_transfer_size);
>> +static void
>> +tinydrm_dbg_spi_print(struct spi_device *spi, struct spi_transfer *tr,
>> +                     const void *buf, int idx, bool tx)
>> +{
>> +       u32 speed_hz = tr->speed_hz ? tr->speed_hz : spi->max_speed_hz;
>> +       char linebuf[3 * 32];
>> +
>> +       hex_dump_to_buffer(buf, tr->len, 16,
>> +                          DIV_ROUND_UP(tr->bits_per_word, 8),
>> +                          linebuf, sizeof(linebuf), false);
>> +
>> +       printk(KERN_DEBUG
>> +              "    tr(%i): speed=%u%s, bpw=%i, len=%u, %s_buf=[%s%s]\n", idx,
>> +              speed_hz > 1000000 ? speed_hz / 1000000 : speed_hz / 1000,
>> +              speed_hz > 1000000 ? "MHz" : "kHz", tr->bits_per_word, tr->len,
>> +              tx ? "tx" : "rx", linebuf, tr->len > 16 ? " ..." : "");
> I hope at some point we will have some extension to print speeds,
> sizes and so on based on algo in string_get_size().
>
>> +}
>> +int tinydrm_spi_transfer(struct spi_device *spi, u32 speed_hz,
>> +                        struct spi_transfer *header, u8 bpw, const void *buf,
>> +                        size_t len)
>> +{
>> +       struct spi_transfer tr = {
>> +               .bits_per_word = bpw,
>> +               .speed_hz = speed_hz,
>> +       };
>> +       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);
> For all of your dev_dbg() / pr_debug() __func__ argument might be
> redundant. Dynamic Debug may include this by request from user.
>
>> +/**
>> + * tinydrm_machine_little_endian - Machine is little endian
>> + *
>> + * Returns:
>> + * true if *defined(__LITTLE_ENDIAN)*, false otherwise
>> + */
>> +static inline bool tinydrm_machine_little_endian(void)
>> +{
>> +#if defined(__LITTLE_ENDIAN)
>> +       return true;
>> +#else
>> +       return false;
>> +#endif
>> +}
> Hmm... What is the typical code of a caller for this?

If the bus can't do 16-bit natively, it will have to swap the bytes on
little endian machines before transfer as 8-bit (Raspberry Pi can't do
16-bit SPI with it's DMA capable controller).
So this function is to avoid #ifdef's elsewhere.

WARNING: multiple messages have this Message-ID (diff)
From: "Noralf Trønnes" <noralf-L59+Z2yzLopAfugRpC6u6w@public.gmane.org>
To: Andy Shevchenko
	<andy.shevchenko-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org,
	devicetree <devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>,
	robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org,
	Thomas Petazzoni
	<thomas.petazzoni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>,
	"linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org"
	<linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>
Subject: Re: [PATCH v4 2/7] drm/tinydrm: Add helper functions
Date: Sun, 12 Feb 2017 16:33:04 +0100	[thread overview]
Message-ID: <2ee54d47-ff7e-2f94-9eea-7d75788b3e1c@tronnes.org> (raw)
In-Reply-To: <CAHp75Vfc+2iUz=2ias5enwbTVd=unu3dEiRgiAwbGFS2KEW+2A-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>


Den 12.02.2017 12.50, skrev Andy Shevchenko:
> On Sat, Feb 11, 2017 at 8:48 PM, Noralf Trønnes <noralf-L59+Z2yzLopAfugRpC6u6w@public.gmane.org> wrote:
>> Add common functionality needed by many tinydrm drivers.
>> +int tinydrm_enable_backlight(struct backlight_device *backlight)
>> +{
>> +       unsigned int old_state;
>> +       int ret;
>> +
>> +       if (!backlight)
>> +               return 0;
>> +
>> +       old_state = backlight->props.state;
>> +       backlight->props.state &= ~BL_CORE_FBBLANK;
>> +       DRM_DEBUG_KMS("Backlight state: 0x%x -> 0x%x\n", old_state,
>> +                     backlight->props.state);
> "%#x" ?
> (And elsewhere)
>
>> +#if IS_ENABLED(CONFIG_SPI)
>> +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);
> I don't get why DMA constrain somehow affects this framework?

The reason is that spi-bcm2835 reverts to PIO on larger buffers.
Looking at __spi_map_msg() and spi_map_buf() it becomes clear that the
core breaks up the buffer into manageable parts. So this must be a bug
in spi-bcm2835 (and spi-pxa2xx) since no other drivers have a upper
limit in the .can_dma() callback.
So you're rightly confused, with drivers fixed, this limit can be lifted.

> What if max_dma_len is zero (imagine SPI master that works only by PIO
> by some reason)?

It can't be zero:

int spi_register_master(struct spi_master *master)
{
...
     if (!master->max_dma_len)
         master->max_dma_len = INT_MAX;

>> +       if (max_len)
>> +               ret = min(ret, max_len);
>> +       if (spi_max)
>> +               ret = min_t(size_t, ret, spi_max);
>> +       ret &= ~0x3;
> Why alignment is that? Why do we need it? Isn't a busyness of SPI
> framework to cope with it?

This minimum capping doesn't look good. I should probably put >16
instead, that would cover the minimum for the 9-bit emulation code.

The reason I let the user change the transfer size, is that some usb
audio card on Raspberry Pi stuttered with 4k fbtft transfers.

>> +       if (ret < 4)
> It's effectively check for 0.
>
>> +               ret = 4;
>> +
>> +       return ret;
>> +}
>> +EXPORT_SYMBOL(tinydrm_spi_max_transfer_size);
>> +static void
>> +tinydrm_dbg_spi_print(struct spi_device *spi, struct spi_transfer *tr,
>> +                     const void *buf, int idx, bool tx)
>> +{
>> +       u32 speed_hz = tr->speed_hz ? tr->speed_hz : spi->max_speed_hz;
>> +       char linebuf[3 * 32];
>> +
>> +       hex_dump_to_buffer(buf, tr->len, 16,
>> +                          DIV_ROUND_UP(tr->bits_per_word, 8),
>> +                          linebuf, sizeof(linebuf), false);
>> +
>> +       printk(KERN_DEBUG
>> +              "    tr(%i): speed=%u%s, bpw=%i, len=%u, %s_buf=[%s%s]\n", idx,
>> +              speed_hz > 1000000 ? speed_hz / 1000000 : speed_hz / 1000,
>> +              speed_hz > 1000000 ? "MHz" : "kHz", tr->bits_per_word, tr->len,
>> +              tx ? "tx" : "rx", linebuf, tr->len > 16 ? " ..." : "");
> I hope at some point we will have some extension to print speeds,
> sizes and so on based on algo in string_get_size().
>
>> +}
>> +int tinydrm_spi_transfer(struct spi_device *spi, u32 speed_hz,
>> +                        struct spi_transfer *header, u8 bpw, const void *buf,
>> +                        size_t len)
>> +{
>> +       struct spi_transfer tr = {
>> +               .bits_per_word = bpw,
>> +               .speed_hz = speed_hz,
>> +       };
>> +       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);
> For all of your dev_dbg() / pr_debug() __func__ argument might be
> redundant. Dynamic Debug may include this by request from user.
>
>> +/**
>> + * tinydrm_machine_little_endian - Machine is little endian
>> + *
>> + * Returns:
>> + * true if *defined(__LITTLE_ENDIAN)*, false otherwise
>> + */
>> +static inline bool tinydrm_machine_little_endian(void)
>> +{
>> +#if defined(__LITTLE_ENDIAN)
>> +       return true;
>> +#else
>> +       return false;
>> +#endif
>> +}
> Hmm... What is the typical code of a caller for this?

If the bus can't do 16-bit natively, it will have to swap the bytes on
little endian machines before transfer as 8-bit (Raspberry Pi can't do
16-bit SPI with it's DMA capable controller).
So this function is to avoid #ifdef's elsewhere.

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

  reply	other threads:[~2017-02-12 15:33 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-02-11 18:48 [PATCH v4 0/7] drm: Add support for tiny LCD displays Noralf Trønnes
2017-02-11 18:48 ` Noralf Trønnes
2017-02-11 18:48 ` [PATCH v4 1/7] drm: Add DRM " Noralf Trønnes
2017-02-11 18:48   ` Noralf Trønnes
2017-02-12 11:05   ` Andy Shevchenko
2017-02-12 11:05     ` Andy Shevchenko
2017-02-12 13:57     ` Noralf Trønnes
2017-02-12 13:57       ` Noralf Trønnes
2017-02-14 19:54       ` Daniel Vetter
2017-02-14 19:54         ` Daniel Vetter
2017-03-07 22:21   ` Daniel Vetter
2017-03-07 22:21     ` Daniel Vetter
2017-03-08 12:23     ` Noralf Trønnes
2017-03-08 12:23       ` Noralf Trønnes
2017-02-11 18:48 ` [PATCH v4 2/7] drm/tinydrm: Add helper functions Noralf Trønnes
2017-02-11 18:48   ` Noralf Trønnes
2017-02-12 11:50   ` Andy Shevchenko
2017-02-12 11:50     ` Andy Shevchenko
2017-02-12 15:33     ` Noralf Trønnes [this message]
2017-02-12 15:33       ` Noralf Trønnes
2017-02-11 18:48 ` [PATCH v4 3/7] drm/tinydrm: Add MIPI DBI support Noralf Trønnes
2017-02-11 18:48   ` Noralf Trønnes
2017-03-12 18:42   ` Daniel Vetter
2017-03-12 18:42     ` Daniel Vetter
2017-03-12 19:02     ` Daniel Vetter
2017-03-12 19:02       ` Daniel Vetter
2017-02-11 18:48 ` [PATCH v4 4/7] of: Add vendor prefix for Multi-Inno Noralf Trønnes
2017-02-11 18:48   ` Noralf Trønnes
2017-02-11 18:48 ` [PATCH v4 5/7] dt-bindings: display/panel: Add common rotation property Noralf Trønnes
2017-02-11 18:48   ` Noralf Trønnes
2017-02-14 16:19   ` Rob Herring
2017-02-14 16:19     ` Rob Herring
2017-04-11  5:29   ` Laurent Pinchart
2017-04-11  5:29     ` Laurent Pinchart
2017-04-12 11:01     ` Noralf Trønnes
2017-04-12 11:01       ` Noralf Trønnes
2017-02-11 18:48 ` [PATCH v4 6/7] dt-bindings: Add Multi-Inno MI0283QT binding Noralf Trønnes
2017-02-11 18:48   ` Noralf Trønnes
2017-02-11 18:48 ` [PATCH v4 7/7] drm/tinydrm: Add support for Multi-Inno MI0283QT display Noralf Trønnes
2017-02-11 18:48   ` Noralf Trønnes

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=2ee54d47-ff7e-2f94-9eea-7d75788b3e1c@tronnes.org \
    --to=noralf@tronnes.org \
    --cc=andy.shevchenko@gmail.com \
    --cc=devicetree@vger.kernel.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=robh@kernel.org \
    --cc=thomas.petazzoni@free-electrons.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.