Page 1 of 3

TFT01-2.2S with notro's fbtft module

Posted: Thu Aug 15, 2013 1:05 pm
by Xumpy
Hey guys,

Just to let you know that as a cheap ass I've bought myself a TFT01-2.2S screen.
Package info: http://www.elecfreaks.com/wiki/index.ph ... TFT01-2.2S
Price on ebay: http://www.ebay.com.au/itm/Hot-sale-2-2 ... OC:BE:3160

So now I'm trying to get this to work with Notro's module on my raspberry pi. I've seen that the screen is using the ILI9341 driver. So that's the module I've tried.

First I've downloaded a prebuild kernel: http://tronnes.org/fbtft/download.html

The pinout I've used:

Code: Select all

CS: Pin 26 (CE0 - GPIO 8)
SCL/SCK: Pin 23 (GPIO 11)
SDA/SDI/MOSI: Pin 19 (GPIO 10)
RST: Pin 16 (GPIO 23)
VDD: Pin 1 (3V3)
GND: Pin 6 (GROUND)
LED: Pin 18 (GPIO 24)
SDO/MISO: Pin 21 (GPIO 9)
RS: Pin 22 (GPIO 25)
When everyhing was connected and my raspberry was running I've loaded the module

Code: Select all

sudo modprobe fbtft_device name=ili9341fb
I also tried this with 8mhz

Code: Select all

sudo modprobe fbtft_device name=ili9341fb speed=8000000 
I could find the devices /dev/fb0 and /dev/fb1 so I loaded the driver

Code: Select all

sudo modprobe ili9341fb
The screen went white. I don't know if that's correct but I assume it is...

Then I tried to load X

Code: Select all

FRAMEBUFFER=/dev/fb1 startx
Now here is where I fail. The screen sometimes flicker as if it is trying to load an image but in general it stays white.

Any help is greatly appreciated!

Regards

Xump

Re: TFT01-2.2S with notro's fbtft module

Posted: Thu Aug 15, 2013 7:49 pm
by notro
The ili9341fb driver does only know 3-wire SPI (no RS). Your display uses the 4-wire mode.
I'm currently preparing for a new relase with rewritten drivers that supports all interface modes.
The new fb_ili9341 driver will suit your needs. It will hopefully be out in a week or so.
If you can't wait, this info can be used to build the new drivers: https://github.com/notro/fbtft/wiki/Development

Re: TFT01-2.2S with notro's fbtft module

Posted: Fri Aug 16, 2013 7:24 am
by Xumpy
Thanx Notro, I can wait a week or two, not a problem at all, although I'm interested in building it myself.

I'm going to do some investigation in the meantime. I can only learn from it.

Thanx again mate,

Regards

Xump

Re: TFT01-2.2S with notro's fbtft module

Posted: Fri Aug 16, 2013 9:39 am
by Dutch_Master
I have an interest in the 7" TFT screen from the same company, how did you connect yours to the RPi? It has a different chipset (SSD1963), but I already found it's supported in Linux. I've asked the supplier, but they only have Arduino code :(

Re: TFT01-2.2S with notro's fbtft module

Posted: Fri Aug 16, 2013 10:11 am
by Xumpy
Dutch_Master, I haven't got this working yet.

Notro, I found the fb_ili9341 driver in your master folder of your git repository. Can I use this driver and build it with your tutorial?

Thnx for the help,

Regards

Xump

Re: TFT01-2.2S with notro's fbtft module

Posted: Fri Aug 16, 2013 3:22 pm
by notro
Yes, follow the steps in the link I gave you, but skip the example driver.

The driver will autoload, so you only have to load the device:

Code: Select all

sudo modprobe fbtft_device custom name=fb_ili9341 buswidth=8 gpios=reset:25,dc:24
The documentation is not up to date on fbtft_device, so you have to look to the source code.

Re: TFT01-2.2S with notro's fbtft module

Posted: Fri Aug 16, 2013 5:44 pm
by Xumpy
Hey notro,

Yeah I got these error when trying to import the module.

Code: Select all

[17691.438033] fbtft_device: disagrees about version of symbol fbtft_write_gpio16_wr_latched
[17691.438070] fbtft_device: Unknown symbol fbtft_write_gpio16_wr_latched (err -22)
[17691.438197] fbtft_device: Unknown symbol fbtft_dbg_hex (err 0)
At first I thought that it was because the kernel of the master branch did not match but I also tried branch 3.6.y and it gave me the same error.

Any help is greatly appreciated else I need to search a little more ;)

Regards

Xump

Re: TFT01-2.2S with notro's fbtft module

Posted: Fri Aug 16, 2013 6:57 pm
by i2c
Hey Xump, notro,

I just happen to have that very same display and made it working. Since there seems to
be some interest, I'll write a small tutorial, put it online...

@Xump: Your pinout is correct.
The problem is, that this particular display is configured to use 8bit instead of 9!

@notro: Is there a way to get in touch with you? Email?

Regards,

dk

Re: TFT01-2.2S with notro's fbtft module

Posted: Fri Aug 16, 2013 7:56 pm
by notro
It looks like an old version of fbtft is running? Try unloading it.

Re: TFT01-2.2S with notro's fbtft module

Posted: Sat Aug 17, 2013 9:23 am
by Xumpy
Hey guys,

After some searching I've copied all the ko files to my '/lib/modules/$(uname -r)/kernel/drivers/video/fbtft/'.

Now I load tbtft with 'modprobe tbtft' and then I needed to insert the fb_ili9341.ko manually from the kernel folder. If I didn't do that my display wouldn't even turn itself on.

Now I know that I use the latest tbtft cause following command results in the same 'flickering' but I believe that it was not yet possible in previous versions

Code: Select all

sudo modprobe fbtft_device name=mi0283qt-9a gpios=reset:23,led:24,dc:25
When I try to insert the device 'custom name' (took a while to figure that one out :p) with following line

Code: Select all

sudo modprobe fbtft_device custom name=fb_ili9341 buswidth=8  gpios=reset:23,led:24,dc:25
I receive following error as a dmesg

Code: Select all

[  331.761158] fbtft_device:  SPI devices registered:
[  331.761202] fbtft_device:      spidev spi0.1 500kHz 8 bits mode=0x00
[  331.761213] fbtft_device:  'fb' Platform devices registered:
[  331.761233] fbtft_device:      bcm2708_fb id=-1 pdata? no
[  331.764440] fb_ili9341 fb_ili9341.0: Missing 'wr' gpio. Aborting.
[  331.764552] fb_ili9341: probe of fb_ili9341.0 failed with error -22
[  331.764574] fbtft_device:  GPIOS used by 'fb_ili9341':
[  331.764585] fbtft_device:    'reset' = GPIO23
[  331.764594] fbtft_device:    'dc' = GPIO25
[  331.764602] fbtft_device:  'fb' Platform devices registered:
[  331.764622] fbtft_device:      bcm2708_fb id=-1 pdata? no
[  331.764657] fbtft_device:      fb_ili9341 id=0 pdata? yes
It looks like the wr GPIO is not yet programmed?

Any help is greatly appreciated.

Regards

Xump

Edit: Ok after some more searching I found out that the driver is loaded with different pins. So it wants to load rs, db00, ... How do I say I just want a 4 pin serial connection??

Thnx

Xump

Re: TFT01-2.2S with notro's fbtft module

Posted: Sat Aug 17, 2013 10:04 am
by Xumpy
Woot I did it!!! I added following code to the fbtft_device.c

Code: Select all

{
                .name = "TFT01_22S",
                .spi = &(struct spi_board_info) {
                        .modalias = "fb_ili9341",
                        .max_speed_hz = 32000000,
                        .mode = SPI_MODE_0,
                        .platform_data = &(struct fbtft_platform_data) {
                                .display = {
                                        .buswidth = 8,
                                        .backlight = 1,
                                },
                                .bgr = true,
                                .gpios = (const struct fbtft_gpio []) {
                                        { "reset", 23 },
                                        { "led", 24 },
                                        { "dc", 25 },
                                        {},
                                },
                        }
                }
        }, 
Now when I load this driver with "modprobe fbtft_device name=TFT01_22S" the screen stayed black but my log said that the driver was loaded correctly.

When I started x "FRAMEBUFFER=/dev/fb1 startx" I immediately got myself an image.

Thnx for this great driver notro. Your the man.

Regards

Xump

Re: TFT01-2.2S with notro's fbtft module

Posted: Sat Aug 17, 2013 10:30 am
by notro
Xumpy wrote: When I try to insert the device 'custom name' (took a while to figure that one out :p) with following line

Code: Select all

sudo modprobe fbtft_device custom name=fb_ili9341 buswidth=8  gpios=reset:23,led:24,dc:25
I receive following error as a dmesg

Code: Select all

[  331.764440] fb_ili9341 fb_ili9341.0: Missing 'wr' gpio. Aborting.
It's not easy when documentation is missing. The speed argument will tell fbtft_device that this is a SPI device (parallel bus is the default).

Code: Select all

sudo modprobe fbtft_device custom name=fb_ili9341 speed=32000000 buswidth=8  gpios=reset:23,led:24,dc:25
But you found a way around it I see :-)

Re: TFT01-2.2S with notro's fbtft module

Posted: Sat Aug 17, 2013 10:31 am
by notro
i2c wrote: @notro: Is there a way to get in touch with you? Email?
If it can't be put in a forum post, you can PM me.

Re: TFT01-2.2S with notro's fbtft module

Posted: Mon Aug 19, 2013 7:16 pm
by Keeze
Hi all,

With all the info in this topic I also got my tiny screen working. It took some time to realize that CE0 is not pin 26, but pin 24.

Tnx all!

Cheers,
Kees

Image

Re: TFT01-2.2S with notro's fbtft module

Posted: Wed Aug 21, 2013 1:14 pm
by Gekko
If you wanted to have this display as a console LCD you need to compile the drivers in the kernel (not as modules) making sure to include the BCM2708 SPI too. Then, I understand, you need to pass the parameters to the kernel using cmdline.txt in /boot:

I have this:

fbtft_device.name=fb_ili9341 fbtft_device.custom=1 fbtft_device.speed=12000000 fbtft_device.buswidth=8 fbtft_device.gpios=reset:22 fbtft_device.gpios=led:18 fbtft_device.gpios=dc:25 fbtft_device.rotate=1

But see this in dmesg:


1.921274] fbtft_device: SPI devices registered:
[ 1.921292] fbtft_device: 'fb' Platform devices registered:
[ 1.921312] fbtft_device: bcm2708_fb id=-1 pdata? no
[ 1.921344] fbtft_device: spi_busnum_to_master(0) returned NULL

Has anyone managed to successfully have this work?

G

Re: TFT01-2.2S with notro's fbtft module

Posted: Wed Aug 21, 2013 4:18 pm
by notro
fbtft_device won't work when built into the kernel. It relies on spi_bcm2708 to be loaded.
You need to add the device to the platformfile bcm2708.c: https://github.com/notro/fbtft/wiki/Bui ... re-devices
Find the info for your display in fbtft_device.c

Re: TFT01-2.2S with notro's fbtft module

Posted: Thu Aug 22, 2013 7:29 pm
by Xumpy
Hellow,

I've managed to create myself a kernel and install it so tty1 is the running screen of my tft01-2.2S.

Now I've installed RetroPie and it complains about some stuff

Code: Select all

lvl0: 	Error initializing SDL!
	Unsupported console hardware
Are you in the 'video', 'audio', and 'input' groups? Is X closed? Is your firmware up to date? Are you using at least the 192/64 memory split?
lvl0: 	Renderer failed to initialize!
lvl0: 	Window failed to initialize!
Is this normal for the driver? Can this be resolved at some stage... Really curious about this ;)

Regards

Xump

Re: TFT01-2.2S with notro's fbtft module

Posted: Thu Aug 22, 2013 8:43 pm
by sza2
Hi Noralf,

I have an ILI9341 based display with 4-wire SPI. I was able to wake it up using the flexfb driver appending parameter list with the init data of ILI9341.

However I'd like to use it in kernel boot time, but I can't really follow the "https://github.com/notro/fbtft/wiki/Bui ... re-devices" guide. Is there a real example for some of the displays, I mean a whole, working "bcm2708.c", which includes the mentioned sections? It would be helpful.

I'm not an expert, so please don't blame me if this is a silly question, but why it is necessary / what is the advantage of including these stuff into the platform devices? I also have an ST7735 display, for which I checked out Kamal Mostafa's standalone driver, and it works without any extra magic, just by compiling the SPI and ST7335 stuff into the kernel and there is a boot console.

Thx in advance,

/sza2

Re: TFT01-2.2S with notro's fbtft module

Posted: Fri Aug 23, 2013 6:41 am
by Xumpy
Hey sza2,

This is my bcm2708.c file

Code: Select all

/*
 *  linux/arch/arm/mach-bcm2708/bcm2708.c
 *
 *  Copyright (C) 2010 Broadcom
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <linux/init.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/serial_8250.h>
#include <linux/platform_device.h>
#include <linux/syscore_ops.h>
#include <linux/interrupt.h>
#include <linux/amba/bus.h>
#include <linux/amba/clcd.h>
#include <linux/clockchips.h>
#include <linux/cnt32_to_63.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/spi/spi.h>
#include <linux/w1-gpio.h>

#include <linux/version.h>
#include <linux/clkdev.h>
#include <asm/system.h>
#include <mach/hardware.h>
#include <asm/irq.h>
#include <linux/leds.h>
#include <asm/mach-types.h>
#include <asm/sched_clock.h>

#include <asm/mach/arch.h>
#include <asm/mach/flash.h>
#include <asm/mach/irq.h>
#include <asm/mach/time.h>
#include <asm/mach/map.h>

#include <mach/timex.h>
#include <mach/dma.h>
#include <mach/vcio.h>
#include <mach/system.h>

#include <linux/delay.h>

#include "bcm2708.h"
#include "armctrl.h"
#include "clock.h"

#include <linux/fbtft.h>

#ifdef CONFIG_BCM_VC_CMA
#include <linux/broadcom/vc_cma.h>
#endif


/* Effectively we have an IOMMU (ARM<->VideoCore map) that is set up to
 * give us IO access only to 64Mbytes of physical memory (26 bits).  We could
 * represent this window by setting our dmamasks to 26 bits but, in fact
 * we're not going to use addresses outside this range (they're not in real
 * memory) so we don't bother.
 *
 * In the future we might include code to use this IOMMU to remap other
 * physical addresses onto VideoCore memory then the use of 32-bits would be
 * more legitimate.
 */
#define DMA_MASK_BITS_COMMON 32

// use GPIO 4 for the one-wire GPIO pin, if enabled
#define W1_GPIO 4

/* command line parameters */
static unsigned boardrev, serial;
static unsigned uart_clock;
static unsigned reboot_part = 0;

static void __init bcm2708_init_led(void);

void __init bcm2708_init_irq(void)
{
	armctrl_init(__io_address(ARMCTRL_IC_BASE), 0, 0, 0);
}

static struct map_desc bcm2708_io_desc[] __initdata = {
	{
	 .virtual = IO_ADDRESS(ARMCTRL_BASE),
	 .pfn = __phys_to_pfn(ARMCTRL_BASE),
	 .length = SZ_4K,
	 .type = MT_DEVICE},
	{
	 .virtual = IO_ADDRESS(UART0_BASE),
	 .pfn = __phys_to_pfn(UART0_BASE),
	 .length = SZ_4K,
	 .type = MT_DEVICE},
	{
	 .virtual = IO_ADDRESS(UART1_BASE),
	 .pfn = __phys_to_pfn(UART1_BASE),
	 .length = SZ_4K,
	 .type = MT_DEVICE},
#ifdef CONFIG_MMC_BCM2708	/* broadcom legacy SD */
	{
	 .virtual = IO_ADDRESS(MMCI0_BASE),
	 .pfn = __phys_to_pfn(MMCI0_BASE),
	 .length = SZ_4K,
	 .type = MT_DEVICE},
#endif
	{
	 .virtual = IO_ADDRESS(DMA_BASE),
	 .pfn = __phys_to_pfn(DMA_BASE),
	 .length = SZ_4K,
	 .type = MT_DEVICE},
	{
	 .virtual = IO_ADDRESS(MCORE_BASE),
	 .pfn = __phys_to_pfn(MCORE_BASE),
	 .length = SZ_4K,
	 .type = MT_DEVICE},
	{
	 .virtual = IO_ADDRESS(ST_BASE),
	 .pfn = __phys_to_pfn(ST_BASE),
	 .length = SZ_4K,
	 .type = MT_DEVICE},
	{
	 .virtual = IO_ADDRESS(USB_BASE),
	 .pfn = __phys_to_pfn(USB_BASE),
	 .length = SZ_128K,
	 .type = MT_DEVICE},
	{
	 .virtual = IO_ADDRESS(PM_BASE),
	 .pfn = __phys_to_pfn(PM_BASE),
	 .length = SZ_4K,
	 .type = MT_DEVICE},
	{
	 .virtual = IO_ADDRESS(GPIO_BASE),
	 .pfn = __phys_to_pfn(GPIO_BASE),
	 .length = SZ_4K,
	 .type = MT_DEVICE}
};

void __init bcm2708_map_io(void)
{
	iotable_init(bcm2708_io_desc, ARRAY_SIZE(bcm2708_io_desc));
}

/* The STC is a free running counter that increments at the rate of 1MHz */
#define STC_FREQ_HZ 1000000

static inline uint32_t timer_read(void)
{
	/* STC: a free running counter that increments at the rate of 1MHz */
	return readl(__io_address(ST_BASE + 0x04));
}

#ifdef ARCH_HAS_READ_CURRENT_TIMER
int read_current_timer(unsigned long *timer_val)
{
	*timer_val = timer_read();
	return 0;
}
EXPORT_SYMBOL(read_current_timer);
#endif

static u32 notrace bcm2708_read_sched_clock(void)
{
	return timer_read();
}

static cycle_t clksrc_read(struct clocksource *cs)
{
	return timer_read();
}

static struct clocksource clocksource_stc = {
	.name = "stc",
	.rating = 300,
	.read = clksrc_read,
	.mask = CLOCKSOURCE_MASK(32),
	.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};

unsigned long frc_clock_ticks32(void)
{
	return timer_read();
}

static void __init bcm2708_clocksource_init(void)
{
	if (clocksource_register_hz(&clocksource_stc, STC_FREQ_HZ)) {
		printk(KERN_ERR "timer: failed to initialize clock "
		       "source %s\n", clocksource_stc.name);
	}
}


/*
 * These are fixed clocks.
 */
static struct clk ref24_clk = {
	.rate = UART0_CLOCK,	/* The UART is clocked at 3MHz via APB_CLK */
};

static struct clk osc_clk = {
#ifdef CONFIG_ARCH_BCM2708_CHIPIT
	.rate = 27000000,
#else
	.rate = 500000000,	/* ARM clock is set from the VideoCore booter */
#endif
};

/* warning - the USB needs a clock > 34MHz */

static struct clk sdhost_clk = {
#ifdef CONFIG_ARCH_BCM2708_CHIPIT
	.rate = 4000000,	/* 4MHz */
#else
	.rate = 250000000,	/* 250MHz */
#endif
};

static struct clk_lookup lookups[] = {
	{			/* UART0 */
	 .dev_id = "dev:f1",
	 .clk = &ref24_clk,
	 },
	{			/* USB */
	 .dev_id = "bcm2708_usb",
	 .clk = &osc_clk,
#ifdef CONFIG_MMC_BCM2708
	 },
	{			/* MCI */
	 .dev_id = "bcm2708_mci.0",
	 .clk = &sdhost_clk,
#endif
	 }, {	/* SPI */
		 .dev_id = "bcm2708_spi.0",
		 .clk = &sdhost_clk,
	 }, {	/* BSC0 */
		 .dev_id = "bcm2708_i2c.0",
		 .clk = &sdhost_clk,
	 }, {	/* BSC1 */
		 .dev_id = "bcm2708_i2c.1",
		 .clk = &sdhost_clk,
	 }
};

#define UART0_IRQ	{ IRQ_UART, 0 /*NO_IRQ*/ }
#define UART0_DMA	{ 15, 14 }

AMBA_DEVICE(uart0, "dev:f1", UART0, NULL);

static struct amba_device *amba_devs[] __initdata = {
	&uart0_device,
};

static struct resource bcm2708_dmaman_resources[] = {
	{
	 .start = DMA_BASE,
	 .end = DMA_BASE + SZ_4K - 1,
	 .flags = IORESOURCE_MEM,
	 }
};

static struct platform_device bcm2708_dmaman_device = {
	.name = BCM_DMAMAN_DRIVER_NAME,
	.id = 0,		/* first bcm2708_dma */
	.resource = bcm2708_dmaman_resources,
	.num_resources = ARRAY_SIZE(bcm2708_dmaman_resources),
};

#ifdef CONFIG_MMC_BCM2708
static struct resource bcm2708_mci_resources[] = {
	{
	 .start = MMCI0_BASE,
	 .end = MMCI0_BASE + SZ_4K - 1,
	 .flags = IORESOURCE_MEM,
	 },
	{
	 .start = IRQ_SDIO,
	 .end = IRQ_SDIO,
	 .flags = IORESOURCE_IRQ,
	 }
};

static struct platform_device bcm2708_mci_device = {
	.name = "bcm2708_mci",
	.id = 0,		/* first bcm2708_mci */
	.resource = bcm2708_mci_resources,
	.num_resources = ARRAY_SIZE(bcm2708_mci_resources),
	.dev = {
		.coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON),
		},
};
#endif /* CONFIG_MMC_BCM2708 */

#if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE)
static struct w1_gpio_platform_data w1_gpio_pdata = {
	.pin = W1_GPIO,
	.is_open_drain = 0,
};

static struct platform_device w1_device = {
	.name = "w1-gpio",
	.id = -1,
	.dev.platform_data = &w1_gpio_pdata,
};
#endif

static u64 fb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);

static struct platform_device bcm2708_fb_device = {
	.name = "bcm2708_fb",
	.id = -1,		/* only one bcm2708_fb */
	.resource = NULL,
	.num_resources = 0,
	.dev = {
		.dma_mask = &fb_dmamask,
		.coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON),
		},
};

static struct plat_serial8250_port bcm2708_uart1_platform_data[] = {
	{
	 .mapbase = UART1_BASE + 0x40,
	 .irq = IRQ_AUX,
	 .uartclk = 125000000,
	 .regshift = 2,
	 .iotype = UPIO_MEM,
	 .flags = UPF_FIXED_TYPE | UPF_IOREMAP | UPF_SKIP_TEST,
	 .type = PORT_8250,
	 },
	{},
};

static struct platform_device bcm2708_uart1_device = {
	.name = "serial8250",
	.id = PLAT8250_DEV_PLATFORM,
	.dev = {
		.platform_data = bcm2708_uart1_platform_data,
		},
};

static struct resource bcm2708_usb_resources[] = {
	[0] = {
	       .start = USB_BASE,
	       .end = USB_BASE + SZ_128K - 1,
	       .flags = IORESOURCE_MEM,
	       },
	[1] = {
		.start = MPHI_BASE,
		.end = MPHI_BASE + SZ_4K - 1,
		.flags = IORESOURCE_MEM,
	      },
	[2] = {
	       .start = IRQ_HOSTPORT,
	       .end = IRQ_HOSTPORT,
	       .flags = IORESOURCE_IRQ,
	       },
};

bool fiq_fix_enable = true;

static struct resource bcm2708_usb_resources_no_fiq_fix[] = {
	[0] = {
		.start = USB_BASE,
		.end = USB_BASE + SZ_128K - 1,
		.flags = IORESOURCE_MEM,
		},
	[1] = {
		.start = IRQ_USB,
		.end = IRQ_USB,
		.flags = IORESOURCE_IRQ,
		},
};

static u64 usb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);

static struct platform_device bcm2708_usb_device = {
	.name = "bcm2708_usb",
	.id = -1,		/* only one bcm2708_usb */
	.resource = bcm2708_usb_resources,
	.num_resources = ARRAY_SIZE(bcm2708_usb_resources),
	.dev = {
		.dma_mask = &usb_dmamask,
		.coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON),
		},
};

static struct resource bcm2708_vcio_resources[] = {
	[0] = {			/* mailbox/semaphore/doorbell access */
	       .start = MCORE_BASE,
	       .end = MCORE_BASE + SZ_4K - 1,
	       .flags = IORESOURCE_MEM,
	       },
};

static u64 vcio_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);

static struct platform_device bcm2708_vcio_device = {
	.name = BCM_VCIO_DRIVER_NAME,
	.id = -1,		/* only one VideoCore I/O area */
	.resource = bcm2708_vcio_resources,
	.num_resources = ARRAY_SIZE(bcm2708_vcio_resources),
	.dev = {
		.dma_mask = &vcio_dmamask,
		.coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON),
		},
};

#ifdef CONFIG_BCM2708_GPIO
#define BCM_GPIO_DRIVER_NAME "bcm2708_gpio"

static struct resource bcm2708_gpio_resources[] = {
	[0] = {			/* general purpose I/O */
	       .start = GPIO_BASE,
	       .end = GPIO_BASE + SZ_4K - 1,
	       .flags = IORESOURCE_MEM,
	       },
};

static u64 gpio_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);

static struct platform_device bcm2708_gpio_device = {
	.name = BCM_GPIO_DRIVER_NAME,
	.id = -1,		/* only one VideoCore I/O area */
	.resource = bcm2708_gpio_resources,
	.num_resources = ARRAY_SIZE(bcm2708_gpio_resources),
	.dev = {
		.dma_mask = &gpio_dmamask,
		.coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON),
		},
};
#endif

static struct resource bcm2708_systemtimer_resources[] = {
	[0] = {			/* system timer access */
	       .start = ST_BASE,
	       .end = ST_BASE + SZ_4K - 1,
	       .flags = IORESOURCE_MEM,
	       },
	{
	 .start = IRQ_TIMER3,
	 .end = IRQ_TIMER3,
	 .flags = IORESOURCE_IRQ,
	 }

};

static u64 systemtimer_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);

static struct platform_device bcm2708_systemtimer_device = {
	.name = "bcm2708_systemtimer",
	.id = -1,		/* only one VideoCore I/O area */
	.resource = bcm2708_systemtimer_resources,
	.num_resources = ARRAY_SIZE(bcm2708_systemtimer_resources),
	.dev = {
		.dma_mask = &systemtimer_dmamask,
		.coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON),
		},
};

#ifdef CONFIG_MMC_SDHCI_BCM2708	/* Arasan emmc SD */
static struct resource bcm2708_emmc_resources[] = {
	[0] = {
	       .start = EMMC_BASE,
	       .end = EMMC_BASE + SZ_256 - 1,	/* we only need this area */
	       /* the memory map actually makes SZ_4K available  */
	       .flags = IORESOURCE_MEM,
	       },
	[1] = {
	       .start = IRQ_ARASANSDIO,
	       .end = IRQ_ARASANSDIO,
	       .flags = IORESOURCE_IRQ,
	       },
};

static u64 bcm2708_emmc_dmamask = 0xffffffffUL;

struct platform_device bcm2708_emmc_device = {
	.name = "bcm2708_sdhci",
	.id = 0,
	.num_resources = ARRAY_SIZE(bcm2708_emmc_resources),
	.resource = bcm2708_emmc_resources,
	.dev = {
		.dma_mask = &bcm2708_emmc_dmamask,
		.coherent_dma_mask = 0xffffffffUL},
};
#endif /* CONFIG_MMC_SDHCI_BCM2708 */

static struct resource bcm2708_powerman_resources[] = {
	[0] = {
	       .start = PM_BASE,
	       .end = PM_BASE + SZ_256 - 1,
	       .flags = IORESOURCE_MEM,
	       },
};

static u64 powerman_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);

struct platform_device bcm2708_powerman_device = {
	.name = "bcm2708_powerman",
	.id = 0,
	.num_resources = ARRAY_SIZE(bcm2708_powerman_resources),
	.resource = bcm2708_powerman_resources,
	.dev = {
		.dma_mask = &powerman_dmamask,
		.coherent_dma_mask = 0xffffffffUL},
};

static struct platform_device bcm2708_alsa_devices[] = {
	[0] = {
	       .name = "bcm2835_AUD0",
	       .id = 0,		/* first audio device */
	       .resource = 0,
	       .num_resources = 0,
	       },
	[1] = {
	       .name = "bcm2835_AUD1",
	       .id = 1,		/* second audio device */
	       .resource = 0,
	       .num_resources = 0,
	       },
	[2] = {
	       .name = "bcm2835_AUD2",
	       .id = 2,		/* third audio device */
	       .resource = 0,
	       .num_resources = 0,
	       },
	[3] = {
	       .name = "bcm2835_AUD3",
	       .id = 3,		/* forth audio device */
	       .resource = 0,
	       .num_resources = 0,
	       },
	[4] = {
	       .name = "bcm2835_AUD4",
	       .id = 4,		/* fifth audio device */
	       .resource = 0,
	       .num_resources = 0,
	       },
	[5] = {
	       .name = "bcm2835_AUD5",
	       .id = 5,		/* sixth audio device */
	       .resource = 0,
	       .num_resources = 0,
	       },
	[6] = {
	       .name = "bcm2835_AUD6",
	       .id = 6,		/* seventh audio device */
	       .resource = 0,
	       .num_resources = 0,
	       },
	[7] = {
	       .name = "bcm2835_AUD7",
	       .id = 7,		/* eighth audio device */
	       .resource = 0,
	       .num_resources = 0,
	       },
};

static struct resource bcm2708_spi_resources[] = {
	{
		.start = SPI0_BASE,
		.end = SPI0_BASE + SZ_256 - 1,
		.flags = IORESOURCE_MEM,
	}, {
		.start = IRQ_SPI,
		.end = IRQ_SPI,
		.flags = IORESOURCE_IRQ,
	}
};

static struct platform_device bcm2708_spi_device = {
	.name = "bcm2708_spi",
	.id = 0,
	.num_resources = ARRAY_SIZE(bcm2708_spi_resources),
	.resource = bcm2708_spi_resources,
};

#ifdef CONFIG_BCM2708_SPIDEV
static struct spi_board_info bcm2708_spi_devices[] = {
    {
        .modalias = "fb_ili9341",
        .max_speed_hz = 32000000,
        .bus_num = 0,
        .chip_select = 0,
        .mode = SPI_MODE_0,
        .platform_data = &(struct fbtft_platform_data) {
            .display = {
                    .buswidth = 8,
                    .backlight = 1,
            },
            .bgr = true,
            .gpios = (const struct fbtft_gpio []) {
                    { "reset", 23 },
                    { "led", 24 },
                    { "dc", 25 },
                    {},
            },
        }
    }, {
        .modalias = "spidev",
        .max_speed_hz = 500000,
        .bus_num = 0,
        .chip_select = 1,
        .mode = SPI_MODE_0,
    }
};
#endif

static struct resource bcm2708_bsc0_resources[] = {
	{
		.start = BSC0_BASE,
		.end = BSC0_BASE + SZ_256 - 1,
		.flags = IORESOURCE_MEM,
	}, {
		.start = INTERRUPT_I2C,
		.end = INTERRUPT_I2C,
		.flags = IORESOURCE_IRQ,
	}
};

static struct platform_device bcm2708_bsc0_device = {
	.name = "bcm2708_i2c",
	.id = 0,
	.num_resources = ARRAY_SIZE(bcm2708_bsc0_resources),
	.resource = bcm2708_bsc0_resources,
};


static struct resource bcm2708_bsc1_resources[] = {
	{
		.start = BSC1_BASE,
		.end = BSC1_BASE + SZ_256 - 1,
		.flags = IORESOURCE_MEM,
	}, {
		.start = INTERRUPT_I2C,
		.end = INTERRUPT_I2C,
		.flags = IORESOURCE_IRQ,
	}
};

static struct platform_device bcm2708_bsc1_device = {
	.name = "bcm2708_i2c",
	.id = 1,
	.num_resources = ARRAY_SIZE(bcm2708_bsc1_resources),
	.resource = bcm2708_bsc1_resources,
};

static struct platform_device bcm2835_hwmon_device = {
	.name = "bcm2835_hwmon",
};

static struct platform_device bcm2835_thermal_device = {
	.name = "bcm2835_thermal",
};

int __init bcm_register_device(struct platform_device *pdev)
{
	int ret;

	ret = platform_device_register(pdev);
	if (ret)
		pr_debug("Unable to register platform device '%s': %d\n",
			 pdev->name, ret);

	return ret;
}

int calc_rsts(int partition)
{
	return 0x5a000000 |
		((partition & (1 << 0))  << 0) |
		((partition & (1 << 1))  << 1) |
		((partition & (1 << 2))  << 2) |
		((partition & (1 << 3))  << 3) |
		((partition & (1 << 4))  << 4) |
		((partition & (1 << 5))  << 5);
}

static void bcm2708_restart(char mode, const char *cmd)
{
	uint32_t pm_rstc, pm_wdog;
	uint32_t timeout = 10;
	uint32_t pm_rsts = 0;

	if(mode == 'q')
	{
		// NOOBS < 1.3 booting with reboot=q
		pm_rsts = readl(__io_address(PM_RSTS));
		pm_rsts = PM_PASSWORD | pm_rsts | PM_RSTS_HADWRQ_SET;
	}
	else if(mode == 'p')
	{
		// NOOBS < 1.3 halting
		pm_rsts = readl(__io_address(PM_RSTS));
		pm_rsts = PM_PASSWORD | pm_rsts | PM_RSTS_HADWRH_SET;
	}
	else
	{
		pm_rsts = calc_rsts(reboot_part);
	}

	writel(pm_rsts, __io_address(PM_RSTS));

	/* Setup watchdog for reset */
	pm_rstc = readl(IO_ADDRESS(PM_RSTC));

	pm_wdog = PM_PASSWORD | (timeout & PM_WDOG_TIME_SET); // watchdog timer = timer clock / 16; need password (31:16) + value (11:0)
	pm_rstc = PM_PASSWORD | (pm_rstc & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET;

	writel(pm_wdog, IO_ADDRESS(PM_WDOG));
	writel(pm_rstc, IO_ADDRESS(PM_RSTC));
}

/* We can't really power off, but if we do the normal reset scheme, and indicate to bootcode.bin not to reboot, then most of the chip will be powered off */
static void bcm2708_power_off(void)
{
	extern char reboot_mode;

	if(reboot_mode == 'q')
	{
		// NOOBS < v1.3
		bcm2708_restart('p', "");
	}
	else
	{
		/* partition 63 is special code for HALT the bootloader knows not to boot*/
		reboot_part = 63;
		/* continue with normal reset mechanism */
		bcm2708_restart(0, "");
	}
}

void __init bcm2708_init(void)
{
	int i;

#if defined(CONFIG_BCM_VC_CMA)
	vc_cma_early_init();
#endif
	printk("bcm2708.uart_clock = %d\n", uart_clock);
	pm_power_off = bcm2708_power_off;

	if (uart_clock)
		lookups[0].clk->rate = uart_clock;

	for (i = 0; i < ARRAY_SIZE(lookups); i++)
		clkdev_add(&lookups[i]);

	bcm_register_device(&bcm2708_dmaman_device);
	bcm_register_device(&bcm2708_vcio_device);
#ifdef CONFIG_BCM2708_GPIO
	bcm_register_device(&bcm2708_gpio_device);
#endif
#if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE)
	platform_device_register(&w1_device);
#endif
	bcm_register_device(&bcm2708_systemtimer_device);
#ifdef CONFIG_MMC_BCM2708
	bcm_register_device(&bcm2708_mci_device);
#endif
	bcm_register_device(&bcm2708_fb_device);
	if (!fiq_fix_enable)
	{
		bcm2708_usb_device.resource = bcm2708_usb_resources_no_fiq_fix;
		bcm2708_usb_device.num_resources = ARRAY_SIZE(bcm2708_usb_resources_no_fiq_fix);
	}
	bcm_register_device(&bcm2708_usb_device);
	bcm_register_device(&bcm2708_uart1_device);
	bcm_register_device(&bcm2708_powerman_device);

#ifdef CONFIG_MMC_SDHCI_BCM2708
	bcm_register_device(&bcm2708_emmc_device);
#endif
	bcm2708_init_led();
	for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++)
		bcm_register_device(&bcm2708_alsa_devices[i]);

	bcm_register_device(&bcm2708_spi_device);
	bcm_register_device(&bcm2708_bsc0_device);
	bcm_register_device(&bcm2708_bsc1_device);

	bcm_register_device(&bcm2835_hwmon_device);
	bcm_register_device(&bcm2835_thermal_device);

	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
		struct amba_device *d = amba_devs[i];
		amba_device_register(d, &iomem_resource);
	}
	system_rev = boardrev;
	system_serial_low = serial;

#ifdef CONFIG_BCM2708_SPIDEV
	spi_register_board_info(bcm2708_spi_devices,
			ARRAY_SIZE(bcm2708_spi_devices));
#endif
}

#define TIMER_PERIOD DIV_ROUND_CLOSEST(STC_FREQ_HZ, HZ)

static void timer_set_mode(enum clock_event_mode mode,
			   struct clock_event_device *clk)
{
	switch (mode) {
	case CLOCK_EVT_MODE_ONESHOT: /* Leave the timer disabled, .set_next_event will enable it */
	case CLOCK_EVT_MODE_SHUTDOWN:
		break;
	case CLOCK_EVT_MODE_PERIODIC:

	case CLOCK_EVT_MODE_UNUSED:
	case CLOCK_EVT_MODE_RESUME:

	default:
		printk(KERN_ERR "timer_set_mode: unhandled mode:%d\n",
		       (int)mode);
		break;
	}

}

static int timer_set_next_event(unsigned long cycles,
				struct clock_event_device *unused)
{
	unsigned long stc;

	stc = readl(__io_address(ST_BASE + 0x04));
	writel(stc + cycles, __io_address(ST_BASE + 0x18));	/* stc3 */
	return 0;
}

static struct clock_event_device timer0_clockevent = {
	.name = "timer0",
	.shift = 32,
	.features = CLOCK_EVT_FEAT_ONESHOT,
	.set_mode = timer_set_mode,
	.set_next_event = timer_set_next_event,
};

/*
 * IRQ handler for the timer
 */
static irqreturn_t bcm2708_timer_interrupt(int irq, void *dev_id)
{
	struct clock_event_device *evt = &timer0_clockevent;

	writel(1 << 3, __io_address(ST_BASE + 0x00));	/* stcs clear timer int */

	evt->event_handler(evt);

	return IRQ_HANDLED;
}

static struct irqaction bcm2708_timer_irq = {
	.name = "BCM2708 Timer Tick",
	.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
	.handler = bcm2708_timer_interrupt,
};

/*
 * Set up timer interrupt, and return the current time in seconds.
 */
static void __init bcm2708_timer_init(void)
{
	/* init high res timer */
	bcm2708_clocksource_init();

	/*
	 * Initialise to a known state (all timers off)
	 */
	writel(0, __io_address(ARM_T_CONTROL));
	/*
	 * Make irqs happen for the system timer
	 */
	setup_irq(IRQ_TIMER3, &bcm2708_timer_irq);

	setup_sched_clock(bcm2708_read_sched_clock, 32, STC_FREQ_HZ);

	timer0_clockevent.mult =
	    div_sc(STC_FREQ_HZ, NSEC_PER_SEC, timer0_clockevent.shift);
	timer0_clockevent.max_delta_ns =
	    clockevent_delta2ns(0xffffffff, &timer0_clockevent);
	timer0_clockevent.min_delta_ns =
	    clockevent_delta2ns(0xf, &timer0_clockevent);

	timer0_clockevent.cpumask = cpumask_of(0);
	clockevents_register_device(&timer0_clockevent);
}

struct sys_timer bcm2708_timer = {
	.init = bcm2708_timer_init,
};

#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
#include <linux/leds.h>

static struct gpio_led bcm2708_leds[] = {
	[0] = {
	       .gpio = 16,
	       .name = "led0",
	       .default_trigger = "mmc0",
	       .active_low = 1,
	       },
};

static struct gpio_led_platform_data bcm2708_led_pdata = {
	.num_leds = ARRAY_SIZE(bcm2708_leds),
	.leds = bcm2708_leds,
};

static struct platform_device bcm2708_led_device = {
	.name = "leds-gpio",
	.id = -1,
	.dev = {
		.platform_data = &bcm2708_led_pdata,
		},
};

static void __init bcm2708_init_led(void)
{
	platform_device_register(&bcm2708_led_device);
}
#else
static inline void bcm2708_init_led(void)
{
}
#endif

/* The assembly versions in delay.S don't account for core freq changing in cpufreq driver */
/* Use 1MHz system timer for busy waiting */
static void bcm2708_udelay(unsigned long usecs)
{
	unsigned long start = timer_read();
	unsigned long now;
	do {
		now = timer_read();
	} while ((long)(now - start) <= usecs);
}


static void bcm2708_const_udelay(unsigned long scaled_usecs)
{
	/* want /107374, this is about 3% bigger. We know usecs is less than 2000, so shouldn't overflow */
	const unsigned long usecs = scaled_usecs * 10 >> 20;
	unsigned long start = timer_read();
	unsigned long now;
	do {
		now = timer_read();
	} while ((long)(now - start) <= usecs);
}

extern void bcm2708_delay(unsigned long cycles);

struct arm_delay_ops arm_delay_ops = {
	.delay		= bcm2708_delay,
	.const_udelay	= bcm2708_const_udelay,
	.udelay		= bcm2708_udelay,
};


void __init bcm2708_init_early(void)
{
	/*
	 * Some devices allocate their coherent buffers from atomic
	 * context. Increase size of atomic coherent pool to make sure such
	 * the allocations won't fail.
	 */
	init_dma_coherent_pool_size(SZ_4M);
}

static void __init board_reserve(void)
{
#if defined(CONFIG_BCM_VC_CMA)
	vc_cma_reserve();
#endif
}

MACHINE_START(BCM2708, "BCM2708")
    /* Maintainer: Broadcom Europe Ltd. */
	.map_io = bcm2708_map_io,
	.init_irq = bcm2708_init_irq,
	.timer =&bcm2708_timer,
	.init_machine = bcm2708_init,
	.init_early = bcm2708_init_early,
	.reserve = board_reserve,
	.restart	= bcm2708_restart,
MACHINE_END

module_param(boardrev, uint, 0644);
module_param(serial, uint, 0644);
module_param(uart_clock, uint, 0644);
module_param(reboot_part, uint, 0644);
The thing I did was just add the #include <linux/fbtft.h> line in the header and then find the struct spi_board_info bcm2708_spi_devices and changed it to my needs.

Do you have experience in compiling a kernel. Why do you need to use this in kernel boot time. For me it was cause I wanted to do this but if you don't really have experience then you might just want to load the drivers as a module on boot.

Check this out: https://github.com/notro/fbtft/wiki/Boot-console

Now for my question. I have found that SDL should be compatible with framebuffers. Still I think retropi needs something else... It might be gpu related. I have assigned enough RAM to it but I don't know if fb1 is able to access this. Still if you can load X you should be able to load up something like RetroPi not???

Regards

Xump

Re: TFT01-2.2S with notro's fbtft module

Posted: Fri Aug 23, 2013 9:36 am
by sza2
Hi Xump,

That's great, thanks!

Maybe I tried to solve it too difficult. I was confused by the "Example Platform device" section - I was wondering why and how should I add it (I mean a similar one) to the bcm2708.c. But now it's clear. I only need to extend the bcm2708_spi_devices[] struct, nothing more (no even additional bcm_register_device() ).

So finally it works like a charm. Kernel compiling is not a problem (I cross-compile it on my desktop).

Thanks again,

/sza2

PS: actually I want an embedded system, without modules, that's why I wanted to compile the driver into the kernel.

Re: TFT01-2.2S with notro's fbtft module

Posted: Fri Aug 23, 2013 2:08 pm
by notro
Xumpy wrote: Now for my question. I have found that SDL should be compatible with framebuffers. Still I think retropi needs something else... It might be gpu related. I have assigned enough RAM to it but I don't know if fb1 is able to access this. Still if you can load X you should be able to load up something like RetroPi not???
I think it depends on which SDL library it uses. Isn't there an accelerated version specially crafted for the Pi GPU?
All I have done is to test pygame which relies on SDL: https://github.com/notro/fbtft/wiki/Pygame

Re: TFT01-2.2S with notro's fbtft module

Posted: Mon Aug 26, 2013 1:17 pm
by sza2
Hi Guys,

Is it possible to use 2 same (or eventually different) type of LCDs with these drivers?

I tried to simply add the same device to bcm2708_spi_devices[] using chip_select = 0 and chip_select = 1 but it does not seem to work (drivers compiled into the kernel, no modules, BCM2708 FB disabled).

dmesg output:

fbtft_device: SPI devices registered:
fbtft_device: 'fb' Platform devices registered:
fbtft_device: bcm2708_fb id=-1 pdata? no
fbtft_device: missing module parameter: 'name'
bcm2708_spi bcm2708_spi.0: master is unqueued, this is deprecated
Console: switching to colour frame buffer device 80x40
graphics fb0: fb_ili9341 frame buffer, 320x240, 150 KiB video memory, 16 KiB buffer memory, fps=20, spi0.0 at 32 MHz
bcm2708_spi bcm2708_spi.0: SPI Controller at 0x20204000 (irq 80)

Any idea?

Thanks,

/sza2

Edit: OK, at least I found that GPIOs are used in an exclusive manner, so currently it is not possible to specify the same RESET/DC pins for both displays. Is there any way?

Re: TFT01-2.2S with notro's fbtft module

Posted: Mon Aug 26, 2013 6:56 pm
by Dutch_Master
Multiplexing the signals may work. Effectively you add a 1-of-4 counter to select which ChipSelect (and thus display) should be enabled. Requires a code-rewrite though.

Re: TFT01-2.2S with notro's fbtft module

Posted: Mon Aug 26, 2013 7:35 pm
by notro
sza2 wrote: Is it possible to use 2 same (or eventually different) type of LCDs with these drivers?
Raspberry Pi boots on a small display and shows a movie simultaneously on two displays
sza2 wrote: I tried to simply add the same device to bcm2708_spi_devices[] using chip_select = 0 and chip_select = 1 but it does not seem to work (drivers compiled into the kernel, no modules, BCM2708 FB disabled).

dmesg output:
graphics fb0: fb_ili9341 frame buffer, 320x240, 150 KiB video memory, 16 KiB buffer memory, fps=20, spi0.0 at 32 MHz
Can you post the bcm2708_spi_devices[] you are using? Your dmesg shows only one device.
sza2 wrote: Edit: OK, at least I found that GPIOs are used in an exclusive manner, so currently it is not possible to specify the same RESET/DC pins for both displays. Is there any way?
You can't share reset and dc. dc determines whether the word is an instruction or data. reset can be done in hardware with a resistor and possibly a capacitor if you run out of GPIOs.

Re: TFT01-2.2S with notro's fbtft module

Posted: Tue Aug 27, 2013 8:46 am
by sza2
notro wrote:
sza2 wrote:
dmesg output:
graphics fb0: fb_ili9341 frame buffer, 320x240, 150 KiB video memory, 16 KiB buffer memory, fps=20, spi0.0 at 32 MHz
Can you post the bcm2708_spi_devices[] you are using? Your dmesg shows only one device.
This is the new one (previously both RESET were 25 and DC 24):

Code: Select all

static struct spi_board_info bcm2708_spi_devices[] = {
	{
		.modalias = "fb_ili9341",
		.max_speed_hz = 32000000,
		.bus_num = 0,
		.chip_select = 0,
		.mode = SPI_MODE_0,
		.platform_data = &(struct fbtft_platform_data) {
			.display = {
				.buswidth = 8,
				.backlight = 1,
			},
			.rotate = 270,
			.bgr = true,
			.gpios = (const struct fbtft_gpio []) {
				{ "reset", 25 },
				{ "dc", 24 },
				{},
			},
		}
	},

	{
		.modalias = "fb_ili9341",
		.max_speed_hz = 32000000,
		.bus_num = 0,
		.chip_select = 1,
		.mode = SPI_MODE_0,
		.platform_data = &(struct fbtft_platform_data) {
			.display = {
				.buswidth = 8,
				.backlight = 1,
			},
			.rotate = 270,
			.bgr = true,
			.gpios = (const struct fbtft_gpio []) {
				{ "reset", 23 },
				{ "dc", 18 },
				{},
			},
		}
	}

OK, I think dmesg was wrong. This is the one with same RESET/DC for both display (I understood it is a bad idea):

fbtft_device: SPI devices registered:
fbtft_device: 'fb' Platform devices registered:
fbtft_device: bcm2708_fb id=-1 pdata? no
fbtft_device: missing module parameter: 'name'
bcm2708_spi bcm2708_spi.0: master is unqueued, this is deprecated
Console: switching to colour frame buffer device 45x17
graphics fb0: fb_ili9341 frame buffer, 320x240, 150 KiB video memory, 16 KiB buffer memory, fps=20, spi0.0 at 32 MHz
fb_ili9341 spi0.1: fbtft_request_gpios: gpio_request_one('reset'=25) failed with -16
fb_ili9341: probe of spi0.1 failed with error -16
bcm2708_spi bcm2708_spi.0: SPI Controller at 0x20204000 (irq 80)
sza2 wrote: Edit: OK, at least I found that GPIOs are used in an exclusive manner, so currently it is not possible to specify the same RESET/DC pins for both displays. Is there any way?
notro wrote: You can't share reset and dc. dc determines whether the word is an instruction or data. reset can be done in hardware with a resistor and possibly a capacitor if you run out of GPIOs.
Using different pins dmesg shows:
bcm2708_spi bcm2708_spi.0: master is unqueued, this is deprecated
Console: switching to colour frame buffer device 45x17
graphics fb0: fb_ili9341 frame buffer, 320x240, 150 KiB video memory, 16 KiB buffer memory, fps=20, spi0.0 at 32 MHz
graphics fb1: fb_ili9341 frame buffer, 320x240, 150 KiB video memory, 16 KiB buffer memory, fps=20, spi0.1 at 32 MHz

I still did not have time to modify the hardware, to check whether it works.

Although I finally realized using same pin for RESET makes no sense (since it is asynchronous, and will reset the previously initialized display), I think DC pin could be shared between displays, since its value is read only when the corresponding CS is low. Do you think it would possible?

/sza2

PS: re-wiring the hardware (separate RESET and DC) solved the problem. Now I have a dual-head LCD RaspberryPi :-)

PS2: did someone able to manage Xorg+xrandr to use extended display?

PS3: finally I find a working Xorg configuration for dual display:

/usr/share/X11/xorg.conf.d/20-video.conf

Code: Select all

Section "Device"
        Identifier      "ILI9431B"
        Driver          "fbdev"
        Option          "fbdev"         "/dev/fb0"
EndSection

Section "Device"
        Identifier      "ILI9341T"
        Driver          "fbdev"
        Option          "fbdev"         "/dev/fb1"
EndSection
/usr/share/X11/xorg.conf.d/40-lcd.conf

Code: Select all

Section "Monitor"
        Identifier      "LCD0"
EndSection

Section "Monitor"
        Identifier      "LCD1"
EndSection

Section "Screen"
        Identifier      "LCDB"
        Device          "ILI9341B"
        Monitor         "LCD0"
EndSection

Section "Screen"
        Identifier      "LCDT"
        Device          "ILI9341T"
        Monitor         "LCD1"
EndSection
/usr/share/X11/xorg.conf.d/90-serverlayout.conf

Code: Select all

Section "ServerLayout"
        Identifier      "Main"
        Option          "Xinerama"      "on"
        Option          "Clone"         "off"
        Screen          0 "LCDB"
        Screen          0 "LCDT" Above "LCDB"
EndSection