repaper / gratis

EPD Source codes and Documentation
238 stars 132 forks source link

Linux kernel driver - re-license code under GPLv2? #68

Closed notro closed 7 years ago

notro commented 7 years ago

I have hacked together a Linux drm graphics driver that (sort of) works with a RePaper 2.7" display I bought from Adafruit 2-3 years back: https://www.adafruit.com/products/1346 I would like to get this included in the Linux kernel, but the Apache 2.0 license is not compatible with the GPLv2 required by the kernel. So before I spend more time on this I need to know if you would allow me to re-license the code in this file under GPLv2: PlatformWithOS/driver-common/V110_G1/epd.c

shawaj commented 7 years ago

@notro - I think that should be fine, I can't see why not, but I'll get in touch with @CharmingSu from Pervasive Displays as it's ultimately them who will decide.

Also just FYI the V110 film I believe has been discontinued. Just the V230 and V231 now I think. Shall I send you the new film screens.

There's also some colour ePaper displays now, and larger ones too... Which also might be worth us sending

repaper commented 7 years ago

Thanks @shawaj. Hi @notro, Yes, it's okay you can re-license the code of V110 under GPLv2 due to they are EOL already. We won't make and supply this model any more. For more latest driver and display models, please refer to Pervasive Displays.

Pervasive FAE- Charming Su.

shawaj commented 7 years ago

@repaper @CharmingSu - could the V230 and V231 and other code on the repaper/gratis be relicensed in this way as well?

And anything for driving the tri-colour and iTC displays?

repaper commented 7 years ago

Current EPDs are driven by the embedded Tcon (iTC). The driving waveform is pre-programmed in the Tcon before shipment, therefore there is no limitation now. The application notes under each of tri-colors and iTC displays on Pervasive Displays website are opened. The source can be found in the EXT2 kit, PaPiRus and Energia now.

shawaj commented 7 years ago

@repaper I meant the eTC with V230 and V231 film?

Hopefully this is OK also?

repaper commented 7 years ago

Yes, eTC with black/white (V230 & V231) film are okay.

shawaj commented 7 years ago

@notro - looks like you're good to go.

Let me know if you want us to send some samples of the newer screens on the house?

You can email me at my GitHub username @gmail.com

notro commented 7 years ago

Thanks @repaper

@shawaj I'm the author of tinydrm which makes it easy to write Linux drivers for displays like these. Currently there's only one tinydrm driver (in mainline) which shows how to support RGB565 displays and now I wanted a driver that showed how to do monochrome displays. The drm subsystem doesn't have monochrome support, so I'm doing this to level the playing field for the next guy with a monochrome display. Since I had an e-ink display on my shelf that I never got around writing a driver for, I chose that one as the monochrome "example" driver. I'm not looking to write drivers for lots of displays, just to give examples of different types of displays. This is to make it easy for others to write drivers for "their" display.

That being said, I'm part of the Raspberry Pi community, so I would love to add support for the PaPiRus HATs. I'll drop you an email.

shawaj commented 7 years ago

@notro - OK thanks very much. Have sent you an email reply :-)

notro commented 7 years ago

I have commited my work so far: https://github.com/notro/tinydrm/blob/master/repaper.h https://github.com/notro/tinydrm/blob/master/repaper-drv.c https://github.com/notro/tinydrm/blob/master/repaper-v110g1.c

It won't work out of the box on the Pi because of a pwm issue as mentioned here: https://github.com/notro/tinydrm/blob/master/rpi-overlays/repaper27-overlay.dts I probably won't address this issue since the papirus doesn't use pwm afaict.

Let me know if there's something that doesn't look right.

I need to make a tool to test this monochrome display under drm...

notro commented 7 years ago

I have the papirus 2.7 sort of working now. https://github.com/notro/tinydrm/blob/master/repaper-v231g2.c

There's one problem: the panel greys out if I don't disable the controller at once. Anyone know what this could be?

notro commented 7 years ago

I've published a library that makes it easy to port the repaper demoes: https://github.com/notro/pydrm It's easy to build and test the driver: https://github.com/notro/tinydrm/wiki/board:-Raspberry-Pi#development This is the DT overlay for a 2.7" panel on the big papirus HAT: https://github.com/notro/tinydrm/blob/master/rpi-overlays/papirus-overlay.dts

The driver treats 0 as background color and 1 as foreground color, regardless of the actual colors.

Issues:

francesco-vannini commented 7 years ago

Hi @notro fantastic work! I'll try to have a go at testing this but I am pretty unfamiliar with this level of stuff so I might need some help. Keep you posted.

francesco-vannini commented 7 years ago

OK been able to get through your guide https://github.com/notro/tinydrm/wiki/board:-Raspberry-Pi#development now what do I put in config.txt?

notro commented 7 years ago

dtoverlay=papirus

I have adressed the conversion and partial update issues, and added support for 1.44"/1.9"/2.0". I will push it when I have done some more cleanup, maybe later today or tomorrow.

francesco-vannini commented 7 years ago

Thanks for the quick answer and sorry for the dumb questions. I thought the line should have been dtoverlay=papirus-overlay I have tried with either of them but I think I need more guidance. What shall I check to see if things are properly setup after I reboot?

francesco-vannini commented 7 years ago

This is what I get when I load dtoverlay=papirus-overlay lsmod | grep tiny tinydrm2 14758 1 repaper tinydrm 13920 2 tinydrm2,repaper drm_kms_helper 153025 3 tinydrm,tinydrm2,repaper drm 347095 5 tinydrm,tinydrm2,repaper,drm_kms_helper

which makes me think things are promising. If this is correct how do I get to test the screen?

notro commented 7 years ago

Yes, if the repaper module has loaded it should be fine.

I've put together a python drm library:

$ git clone https://github.com/notro/pydrm.git
$ cd pydrm

This test displays a pattern and keeps the controller enabled:

$ python modetest.py -s:@XR24 --pattern=mono

The 2.7" displays greys out gradually, the 2.0" greys out quickly, and on the 1.44" I didn't detect anything. I don't know why it greys out.

I've ported a couple of the demoes:

$ python clock27.py
$ python CounterDemo.py 0

This will enable logging:

$ echo 0xff | sudo tee /sys/module/drm/parameters/debug
$ sudo dmesg -C
$ python modetest.py -s:@XR24 --pattern=mono
$ dmesg
...
francesco-vannini commented 7 years ago

All working thanks, now how do we take this forward? We'll try to find somebody from repaper to possibly help with the outstanding issues.

shawaj commented 7 years ago

Is it just the greying issues or what are the others?

@CharmingSu @repaper @hxw can you help with any of these outstanding issues?

Thanks!

notro commented 7 years ago

I have pushed an update:

repaper: Cleanup, add 1.44/1.9/2.0, drop v110g1

I have dropped v110g1 since it's end of line.
I haven't got the 1.9" panel so I hope someone can test.
I didn't add 2.6" since it's EOL.
Change rpi DT overlay name to repaper.
Drop RGB565 format, no point in emulating 2 formats.
Drop dithering on monochrome conversion.

Still problems with greyout when the controller stays enabled.

Signed-off-by: Noralf Trønnes <noralf@tronnes.org>

The whole driver is in one file now: repaper.c

DT overlay (changed name: papirus -> repaper):

dtoverlay=repaper,model=e1144cs021
dtoverlay=repaper,model=e1190cs021
dtoverlay=repaper,model=e2200cs021
dtoverlay=repaper,model=e2271cs021

Drm doesn't have monochrome support, so I'm emulating it using the well supported XRGB8888 (fourcc=XR24) format and converting to monochrome. Don't know how this will fly with the drm maintainers, so it might change.

tinydrm has fbdev emulation by default, so it's possible to put a console on: con2fbmap 1 1 The problem with fbdev is that we don't have control over when flushing happens, so I'm thinking about disabling it for repaper. Comments anyone?

Is it just the greying issues or what are the others?

Just greyout afaik, but it would be great to have some testing from people who know how these panels should look and behave.

Some details about how the driver works: 3 main functions:

shawaj commented 7 years ago

@notro - I think the 2.6" is being replaced with a 2.66" version.

@repaper @CharmingSu can you confirm?

notro commented 7 years ago

I have made some test cases to try and narrow down the greyout issue: https://gist.github.com/notro/a8c272a5a372da9b69d38a33e9887bb2 The tests was done with the 2.0" panel since it the one that greys out the fastest. All tests except number 3 keep the controller enabled for 5 seconds before quitting. Only test number 1 results in greyout. Test number 10 is similar to 1 except for what is displayed, but doesn't greyout. I'm none the wiser, but maybe someone else can see a pattern?

$ cd pydrm
$ wget -o greyout.py https://gist.github.com/notro/a8c272a5a372da9b69d38a33e9887bb2

# results in greyout
$ python greyout.py 1
cross/circle pattern
flush()
sleep(5)

$ python greyout.py 2
cross/circle pattern
flush()
flush()
sleep(5)

$ python greyout.py 3
cross/circle pattern
flush()
disable()
sleep(5)

$ python greyout.py 4
cross/circle pattern
flush()
disable()
enable()
sleep(5)

$ python greyout.py 10
text: Hello
flush()
sleep(5)
notro commented 7 years ago

I forgot 2 test cases which didn't result in greyout:

$ python greyout.py 20
do nothing (controller is enabled)
sleep(5)

$ python greyout.py 21
flush a blank image
flush()
sleep(5)
notro commented 7 years ago

I have run the tests on the other panels:

Border byte seems to be a key difference between the greyout panels and 1.44":

static int repaper_probe(struct spi_device *spi)
{

    switch (model) {
    case E1144CS021:
        epd->stage_time = 480;
        epd->pre_border_byte = false;
        epd->border_byte = REPAPER_BORDER_BYTE_ZERO;

    case E2200CS021:
        epd->stage_time = 480;
        epd->pre_border_byte = true;
        epd->border_byte = REPAPER_BORDER_BYTE_NONE;

    case E2271CS021:
        epd->stage_time = 630;
        epd->pre_border_byte = true;
        epd->border_byte = REPAPER_BORDER_BYTE_NONE;

static void repaper_one_line(struct repaper_epd *epd, unsigned int line,
                 const u8 *data, u8 fixed_value, const u8 *mask,
                 enum repaper_stage stage)
{
[...]
    if (epd->pre_border_byte) {
        *p++ = 0x00;
    }

[...]

    switch (epd->border_byte) {
    case REPAPER_BORDER_BYTE_NONE:
        break;

    case REPAPER_BORDER_BYTE_ZERO:
        *p++ = 0x00;
        break;

    case REPAPER_BORDER_BYTE_SET:
        switch(stage) {
        case REPAPER_COMPENSATE:
        case REPAPER_WHITE:
        case REPAPER_INVERSE:
            *p++ = 0x00;
            break;
        case REPAPER_NORMAL:
            *p++ = 0xaa;
            break;
        }
        break;
    }

[...]
}
notro commented 7 years ago

When I woke up today I thought "border". Then I realised that the cross/circle pattern I use has a border around the edges. So I added more tests:

# greyout
$ python greyout.py 30
1 px edge border
flush()
sleep(5)

# greyout
$ python greyout.py 31
5 px edge border
flush()
sleep(5)

# No greyout
$ python greyout.py 32
1 px border 1 px inside edge
flush()
sleep(5)

# 2 vertical grey lines emerges
$ python greyout.py 33
one pixel in each corner
flush()
sleep(5)

# greyout
$ python greyout.py 34
1 px edge border
flush()
clear edge border
flush()
1 px edge border
flush()
sleep(5)

# No greyout
$ python greyout.py 35
1 px edge border
flush()
clear edge border
flush()
1 px edge border
flush()
flush()
sleep(5)

So to summarise my findings so far: On 2.0" and 2.7": when toucing the border pixels, flush twice

notro commented 7 years ago

And to further narrow it down:

# no greyout
$ python greyout.py 36
draw lines on left and right edge not touching top/bottom lines
flush()
sleep(5)

# no greyout
$ python greyout.py 37
draw top line only
flush()
sleep(5)

# greyout
$ python greyout.py 38
draw bottom line only
flush()
sleep(5)

# grey lines rises from the dots
$ python greyout.py 39
one pixel every 20th on bottom line
flush()
sleep(5)

So to summarise my findings so far: On 2.0" and 2.7": when toucing the bottom line, flush twice

notro commented 7 years ago

I have pushed a fix for the greyout:

repaper: Fix greyout (almost)

Fix greyout by doing an extra frame write when pixels are set on the bottom line.
But it's not perfect, writing 20px spaced dots on the bottom line, gives grey between the dots and a little above.

Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
---
diff --git a/repaper.c b/repaper.c
index 0668a00..360a302 100644
--- a/repaper.c
+++ b/repaper.c
@@ -599,6 +599,24 @@ static int repaper_fb_dirty(struct drm_framebuffer *fb,

    memcpy(epd->current_buffer, buf, fb->width * fb->height / 8);

+   /*
+    * An extra frame write is needed if pixels are set in the bottom line,
+    * or else grey lines rises up from the pixels
+    */
+   if (epd->pre_border_byte) {
+       bool reflush = false;
+       unsigned int x;
+
+       for (x = 0; x < (fb->width / 8); x++)
+           if (buf[x + (fb->width * (fb->height - 1) / 8)]) {
+               reflush = true;
+               break;
+           }
+
+       if (reflush)
+           repaper_frame_data_repeat(epd, buf, epd->current_buffer, REPAPER_NORMAL);
+   }
+
    DRM_DEBUG("End Flushing [FB:%d]\n", fb->base.id);

 out_unlock:

Test 39 shows the tiny greyout.

notro commented 7 years ago

Looking at the controller datasheet reference circuits, the border gpio is only used on the 2.7" display. Can I drop driving it in the driver for 2.7"?

shawaj commented 7 years ago

Basically if you don't drive it, I believe all that will happen is that you get a 1px black border around the edge of the screen.

@repaper @charmingsu are there any other side effects of not driving this pin?

repaper commented 7 years ago

2.7" has no internal border control pin designed in TFT substrate to refresh the border per update. It needs this external board control circuit to reset the color. Like Aaron (Shawaj) mentioned, if you remove the external border control circuit for 2.7", after several updates, the border will become gray then black finally. The other sizes with eTC driver, there is internal border control.

notro commented 7 years ago

My question came out wrong, I meant if I could driver the border gpio on 2.7" only and not the others, but you gave me the answer anyways. Thanks.

notro commented 7 years ago

I've taken the driver as far as I can on my own now.

Issues:

There's a grey border around the 2.7" panel. I don't know if I've always had or if it has showed up recently. I became aware of it when I was writing the Device Tree binding document and found that only 2.7 used the border gpio.

Greyout status when the controller is left enabled after flushing:

I have not tested the 1.9" panel.

I will ask Rachel Sandeman if she can find someone to review the driver and make sure I haven't introduced any errors.

Edit: It's not possible to set the temperature yet, I have to see if there's an in-kernel API to read temp sensors.

repaper commented 7 years ago

Please make sure you had reset the /BORDER_CONTROL pin (low, delay 100 to 200 ms, then high) at the power off stage. Refer to the COG driving document at page 34 for each size. You can submit your issue on Technical Support with pictures or video attached. Pervasive Displays will help you to check the issues. You sample driving code is also welcome to provide.

PervasiveDisplays commented 7 years ago

Hello notro, I am PDi FAE Hardy, quickly went through your discussion, I guess the greyout is caused by the discharge improperly. May I know what kit/circuit you are using for the EPD test? Have you implement the discharge with VGH/VDH? Can you take a greyout video? It's good to see the whole image update procedure from the beginning to the end of greyout. You can ignore the border control of 2.7" EPD, it won't impact the image display. The border will change to B/W according to the nearby pixels.

Hardy Kuo @ PDi hardy_kuo@pervasivedisplays.com

notro commented 7 years ago

Thanks for looking into this Hardy

My camera isn't very good so I couldn't catch the faint greyout above the bottom line in the 2.0" display, but it shows greyout between pixels.

PaPiRus Zero 2.0"

Product: https://www.pi-supply.com/product/papirus-zero-epaper-screen-phat-pi-zero/

Circuit: https://github.com/PiSupply/PaPiRus/blob/master/hardware/PaPiRus%20Zero/Latest%20Version%20-%20v1.2/2015-032-01-PaPiRus-ZERO-circuit_v1_2.pdf

Video: https://youtu.be/eJp5RUNtnys

The video shows these commands:

# starting image is a blank test 21

$ python greyout.py 39
one pixel every 20th on bottom line
flush()
sleep(5)

$ python greyout.py 1
cross/circle pattern
flush()
sleep(5)

$ python greyout.py 39
one pixel every 20th on bottom line
flush()
sleep(5)

PaPiRus 2.7"

Product: https://www.pi-supply.com/product/papirus-epaper-eink-screen-hat-for-raspberry-pi/

Circuit: https://github.com/PiSupply/PaPiRus/blob/master/hardware/PaPiRus%20HAT/Latest%20Version%20-%20v1.9/2014-035-01-Pi-ePaper-circuit_v1_9.pdf

Video: https://youtu.be/PTSPC5KaVDc

The video shows these commands:

# starting image is test 39

$ python greyout.py 1
cross/circle pattern
flush()
sleep(5)

# camera couldn't focus on this one
$ python greyout.py 39
one pixel every 20th on bottom line
flush()
sleep(5)

$ python greyout.py 21
flush a blank image
flush()
sleep(5)

$ python greyout.py 1
cross/circle pattern
flush()
sleep(5)

$ python greyout.py 39
one pixel every 20th on bottom line
flush()
sleep(5)

If there's no obvious software solution to this, then I'd appreciate if you could look through the driver to make sure I haven't made any errors when converting the driver. I'd like to move on and post the driver to the drm mailing list for review.

Is it ok that i CC you when I post the driver? I might get technical questions and I know very little about e-ink displays/controllers.

You can ignore the border control of 2.7" EPD, it won't impact the image display. The border will change to B/W according to the nearby pixels.

Ok, I'll remove the border gpio.

notro commented 7 years ago

You can ignore the border control of 2.7" EPD, it won't impact the image display. The border will change to B/W according to the nearby pixels.

Ok, I'll remove the border gpio.

I have to drive the border gpio, or else nothing shows up except some greyness. Maybe the interface circuit demands that it'll be driven?

notro commented 7 years ago

The driver has been been accepted and will show up in Linux 4.14. https://cgit.freedesktop.org/drm/drm-misc/tree/drivers/gpu/drm/tinydrm/repaper.c

I'm planning to backport it to 4.9 and get it included in the official Raspeberry Pi Linux kernel. Not sure when I can do that, it depends on a couple of other projects.

notro commented 7 years ago

The driver is now merged in the official rpi kernel and available through rpi-update. It will later be available through the debian kernel package and probably the next Raspian release.

Pull request: https://github.com/raspberrypi/linux/pull/2119 Driver: drivers/gpu/drm/tinydrm/repaper.c DT overlay: https://github.com/raspberrypi/linux/blob/rpi-4.9.y/arch/arm/boot/dts/overlays/papirus-overlay.dts

Here's the DT overlay README entry:

Name:   papirus
Info:   PaPiRus ePaper Screen by Pi Supply (both HAT and pHAT)
Load:   dtoverlay=papirus,<param>=<val>
Params: panel                   Display panel (required):
                                1.44": e1144cs021
                                2.0":  e2200cs021
                                2.7":  e2271cs021

        speed                   Display SPI bus speed

Use one these in /boot/config.txt:

dtoverlay=papirus,panel=e1144cs021
dtoverlay=papirus,panel=e2200cs021
dtoverlay=papirus,panel=e2271cs021

The driver presents the framebuffer as XRGB8888 to userpace and converts it to monochrome using ITU BT.601. This way it can be used with all graphics libraries. See tinydrm_xrgb8888_to_gray8() in drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c.

I've halfmade a library pydrm that might be useful with these displays, time will tell.