notro / fbtft

Linux Framebuffer drivers for small TFT LCD display modules. Development has moved to https://git.kernel.org/cgit/linux/kernel/git/gregkh/staging.git/tree/drivers/staging/fbtft?h=staging-testing
1.85k stars 496 forks source link

Driver PCD8544 (Nokia 5110 LCD) doesn't work #494

Closed NguyenTrongThinh closed 6 years ago

NguyenTrongThinh commented 6 years ago

I got this error [ 356.616157] fb_pcd8544 spi32766.0: SPI transfer failed: -22 [ 356.622037] spi_master spi32766: failed to transfer one message from queue [ 356.629277] fb_pcd8544 spi32766.0: write failed and returned: -22 [ 356.635646] fb_pcd8544 spi32766.0: fbtft_update_display: write_vmem failed to update display buffer

Platform

Kernel version 4.11 Board: nanopi-neo

I add this to device tree. If the device is incorrect please add support device tree to folder dts. &pio { leds_pcd8544: light_pins@0 { pins = "PA0"; function = "gpio_out"; }; reset_pcd8544: reset_pins@0 { pins = "PA2"; function = "gpio_out"; }; dc_pcd8544: dc_pins@0 { pins = "PA3"; function = "gpio_out"; }; };

&spi0 { status = "okay"; pcd8544@0 { compatible = "philips,pdc8544"; pinctrl-names = "default"; pinctrl-0 = <&leds_pcd8544>, <&reset_pcd8544>, <&dc_pcd8544>; reg = <0>; status = "okay"; spi-max-frequency = <4000000>; buswidth = <8>; fps = <5>; reset-gpios = <&pio 0 2 GPIO_ACTIVE_LOW>; led-gpios = <&pio 0 0 GPIO_ACTIVE_LOW>; dc-gpios = <&pio 0 3 GPIO_ACTIVE_HIGH>; }; };

notro commented 6 years ago

I need to know which spi master/controller driver you are using. Your error (-EINVAL) comes from that driver. The first error message comes from spi_transfer_one_message:

            ret = master->transfer_one(master, msg->spi, xfer);
            if (ret < 0) {
                SPI_STATISTICS_INCREMENT_FIELD(statm,
                                   errors);
                SPI_STATISTICS_INCREMENT_FIELD(stats,
                                   errors);
                dev_err(&msg->spi->dev,
                    "SPI transfer failed: %d\n", ret);
                goto out;
            }

The setup transfers goes fine, one byte at a time, but it fails when the framebuffer is transferred which is 6x48=288 bytes. Driver: http://elixir.free-electrons.com/linux/v4.11/source/drivers/staging/fbtft/fb_pcd8544.c

NguyenTrongThinh commented 6 years ago

Thanks for reply! This is spi master/controller driver which i am using http://elixir.free-electrons.com/linux/v4.11/source/drivers/spi/spi-sun6i.c

notro commented 6 years ago

That driver has this restriction:

static int sun6i_spi_transfer_one(struct spi_master *master,
                  struct spi_device *spi,
                  struct spi_transfer *tfr)
{
    /* We don't support transfer larger than the FIFO */
    if (tfr->len > sspi->fifo_depth)
        return -EINVAL;

And depending on which version you have, these are the fifo_depth values:

#define SUN6I_FIFO_DEPTH        128
#define SUN8I_FIFO_DEPTH        64

Unfortunately the fb_pcd8544 driver doesn't support the fbtft property txbuflen (nor spi_max_transfer_size()), so there's no way to split up the pixel transfer into smaller chunks.

static int write_vmem(struct fbtft_par *par, size_t offset, size_t len)
{
...
    /* Write data */
    gpio_set_value(par->gpio.dc, 1);
    ret = par->fbtftops.write(par, par->txbuf.buf, 6 * 84);
NguyenTrongThinh commented 6 years ago

Thanks for good answer. It saves my day.