archive mirror
 help / color / mirror / Atom feed
From: "Jan Sebastian Götte" <>
To: Emil Velikov <>
Cc:, David Airlie <>,
Subject: Re: [PATCH 5/6] drm: uapi: add gdepaper uapi header
Date: Wed, 31 Jul 2019 01:21:50 +0900	[thread overview]
Message-ID: <> (raw)
In-Reply-To: <20190730140852.GB12424@arch-x1c3>

Hi Emil,

thank you for your comments.

On 7/30/19 11:08 PM, Emil Velikov wrote:
> On 2019/07/30, Jan Sebastian Götte wrote:
>> Signed-off-by: Jan Sebastian Götte <>
>> ---
>>  include/uapi/drm/gdepaper_drm.h | 62 +++++++++++++++++++++++++++++++++
>>  1 file changed, 62 insertions(+)
>>  create mode 100644 include/uapi/drm/gdepaper_drm.h
>> diff --git a/include/uapi/drm/gdepaper_drm.h b/include/uapi/drm/gdepaper_drm.h
>> new file mode 100644
>> index 000000000000..84ff6429bef5
>> --- /dev/null
>> +++ b/include/uapi/drm/gdepaper_drm.h
>> @@ -0,0 +1,62 @@
>> +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
>> +/* gdepaper_drm.h
>> + *
>> + * Copyright (c) 2019 Jan Sebastian Götte
>> + */
>> +
> I'm glad to see more devices using upstream KMS interface. Usually
> custom UAPI should not be needed for such devices.
> Can you elaborate why this is required? Is there an open-source
> userspace that uses these?

Not yet. I added this API because I couldn't figure out a way to do that in KMS. What I need is some way for userspace to tell the driver parameters for the display refresh (driving waveforms, refresh speed etc.) on a frame-by-frame basis. These parameters depend on ambient temperature and the displayed content. One has to trade off speed, ghosting and the number of possible partial refreshes until next full one.

Usually, epaper display refresh all pixels at once like an LCD would. This takes about 15s of flickering for b/w/red displays. Since they're bistable, they can also only physically refresh part of the area though. The reason for not having that on-by-default is that epaper partial refresh is really tricky. If you refresh the same area partially a few times, charge builds up, image quality degrades and the picture starts bleeding. If you refresh the same area partially all the time and don't do enough full refresh cycles to balance charges again, eventually the display is going to get permanent burn-in. I think partial refresh should be supported by a driver like this since it's a good tool to alleviate the enormous full refresh times.

For partial hardware refresh you have to customize all these values and the waveform LUTs depending on the displayed content. For example you might want a LUT specifying more inversion cycles for text display to reduce ghosting, or one with less cycles but higher voltages for some spinning loading animation to reduce flickering. If you are displaying a loading bar you might be able to get away with a high drive strength since you know it's going to be done in a few frames, but if you display e.g. a text console you might want to reduce drive strength to do as many partial updates as possible before the next full refresh, to reduce flicker. 

I think what one would like to do from userspace here is along the lines of:
* set voltages depending on content
* set waveforms depending on content
* write framebuffer
* (optional) trigger partial refresh of affected areas

You can get the display up and running with some default values and the factory-programmed OTP LUTs using full hardware refresh, but if you try partial hardware refresh with those you get a irrecognizable mess.

>> +#ifndef _UAPI_GDEPAPER_DRM_H_
>> +#define _UAPI_GDEPAPER_DRM_H_
>> +
>> +#include "drm.h"
>> +
>> +#if defined(__cplusplus)
>> +extern "C" {
>> +#endif
>> +
>> +enum drm_gdepaper_vghl_lv {
>> +	DRM_GDEP_PWR_VGHL_16V = 0,
>> +	DRM_GDEP_PWR_VGHL_15V = 1,
>> +	DRM_GDEP_PWR_VGHL_14V = 2,
>> +	DRM_GDEP_PWR_VGHL_13V = 3,
>> +};
>> +
>> +struct gdepaper_refresh_params {
>> +	enum drm_gdepaper_vghl_lv vg_lv; /* gate voltage level */
> From my experience, kernel drivers aim to avoid exposing voltage control
> to userspace. AFAICT exceptions are present, but generally it's a no-go
I agree with that. FWIW, in this draft these properties are exposed through a DRM_ROOT_ONLY ioctl.

>> +	__u32 vcom_sel; /* VCOM select bit according to datasheet */
>> +	__s32 vdh_bw_mv; /* drive high level, b/w pixel (mV) */
>> +	__s32 vdh_col_mv; /* drive high level, red/yellow pixel (mV) */
>> +	__s32 vdl_mv; /* drive low level (mV) */
>> +	__s32 vcom_dc_mv;
>> +	__u32 vcom_data_ivl_hsync; /* data ivl len in hsync periods */
>> +	__u32 border_data_sel; /* "vbd" in datasheet */
>> +	__u32 data_polarity; /* "ddx" in datasheet */
> These properties look like they should live in the device-tree bindings.

On init they are loaded from dt, but they can be overwritten via ioctl. This would be necessary for anything using the display's partial hardware refresh feature and might change frame-by-frame.

>> +	__u32 use_otp_luts_flag; /* Use OTP LUTs */
>> +	__u8 lut_vcom_dc[44];
>> +	__u8 lut_ww[42];
>> +	__u8 lut_bw[42];
>> +	__u8 lut_bb[42];
>> +	__u8 lut_wb[42];
> There is UAPI to manage LUT (or was it WIP with patches on the list) via
> the atomic API. Is that not flexible enough for your needs?

I had a look around, and I found something in uapi/drm/drm_mode.h for color LUTs. This isn't color LUTs though. The vendor should really have called them "waveform tables". They basically contain a list of voltage levels a pixel transitioning white-black, white-red etc. should be driven at. The format seems to be standardized across different driver chips, but I'd really treat them as device-dependent binary blobs since for some chips they're not even specified and there's no guarantee the format won't suddenly change for some new chip.

>> +};
>> +
>> +/* Force a full display refresh */
>> +
>> +	struct gdepaper_refresh_params)
>> +	struct gdepaper_refresh_params)
>> +
> Similarly to the LUT above, the atomic UAPI has support for partial
> updates. The property is called FB_DAMAGE_CLIPS and there is an example
> in weston how to use it see 009b3cfa6f16bb361eb54efcc7435bfede4524bc.

I do already have support for that. The partial_update_en flag here controls whether the partial hardware refresh is used to implement that. The force_full_refresh thing would be useful to do the periodic (every 10hrs) refresh required by the display's specs without having to re-render the content.

- Jan

  reply	other threads:[~2019-07-30 16:21 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-07-30 13:46 [RFC PATCH 0/6] tiny: Add driver for gooddisplay epaper panels Jan Sebastian Götte
2019-07-30 13:47 ` [PATCH 1/6] drm: tiny: gdepaper: add TINYDRM_GDEPAPER config option Jan Sebastian Götte
2019-07-30 13:48 ` [PATCH 2/6] dt-bindings: add gooddisplay vendor prefix Jan Sebastian Götte
2019-07-30 13:48 ` [PATCH 3/6] dt-bindings: add good display epaper header Jan Sebastian Götte
2019-07-30 13:48 ` [PATCH 4/6] dt-bindings: add gdepaper documentation Jan Sebastian Götte
2019-07-30 13:48 ` [PATCH 5/6] drm: uapi: add gdepaper uapi header Jan Sebastian Götte
2019-07-30 14:08   ` Emil Velikov
2019-07-30 16:21     ` Jan Sebastian Götte [this message]
2019-07-30 16:49       ` Emil Velikov
2019-07-31  2:01         ` Jan Sebastian Götte
2019-07-31  6:47           ` Daniel Vetter
2019-07-30 13:48 ` [PATCH 6/6] drm: tiny: gdepaper: add driver for 2/3 color epaper displays Jan Sebastian Götte
2019-08-06 16:06   ` Noralf Trønnes
2019-08-10  5:17     ` Jan Sebastian Götte
2019-07-30 14:26 ` [RFC PATCH 0/6] tiny: Add driver for gooddisplay epaper panels Daniel Vetter
2019-07-30 16:24   ` Jan Sebastian Götte

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:

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

  git send-email \ \ \ \ \ \ \

* 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).