* [PATCH v5 5/8] clk: stm32: Fix stm32f429's ltdc driver hang in set clock rate, fix duplicated ltdc clock register to 'clk_core' case ltdc's clock turn off by clk_disable_unused()
From: dillon.minfei @ 2020-05-25 3:45 UTC (permalink / raw)
To: linus.walleij, broonie
Cc: devicetree, linux-arm-kernel, linux-kernel, linux-spi,
linux-stm32, dri-devel, linux-clk, dillon min
In-Reply-To: <1590378348-8115-1-git-send-email-dillon.minfei@gmail.com>
From: dillon min <dillon.minfei@gmail.com>
ltdc set clock rate crashed
'post_div_data[]''s pll_num is PLL_I2S, PLL_SAI (number is 1,2). but,
as pll_num is offset of 'clks[]' input to clk_register_pll_div(), which
is FCLK, CLK_LSI, defined in 'include/dt-bindings/clock/stm32fx-clock.h'
so, this is a null object at the register time.
then, in ltdc's clock is_enabled(), enable(), will call to_clk_gate().
will return a null object, cause kernel crashed.
need change pll_num to PLL_VCO_I2S, PLL_VCO_SAI for 'post_div_data[]'
duplicated ltdc clock
'stm32f429_gates[]' has a member 'ltdc' register to 'clk_core', but no
upper driver use it, ltdc driver use the lcd-tft defined in
'stm32f429_aux_clk[]'. after system startup, as stm32f429_gates[]'s ltdc
enable_count is zero, so turn off by clk_disable_unused()
Changes since V3:
1 drop last wrong changes about 'CLK_IGNORE_UNUSED' patch
2 fix PLL_SAI mismatch with PLL_VCO_SAI
Signed-off-by: dillon min <dillon.minfei@gmail.com>
---
drivers/clk/clk-stm32f4.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/drivers/clk/clk-stm32f4.c b/drivers/clk/clk-stm32f4.c
index 18117ce..fa62e99 100644
--- a/drivers/clk/clk-stm32f4.c
+++ b/drivers/clk/clk-stm32f4.c
@@ -129,7 +129,6 @@ static const struct stm32f4_gate_data stm32f429_gates[] __initconst = {
{ STM32F4_RCC_APB2ENR, 20, "spi5", "apb2_div" },
{ STM32F4_RCC_APB2ENR, 21, "spi6", "apb2_div" },
{ STM32F4_RCC_APB2ENR, 22, "sai1", "apb2_div" },
- { STM32F4_RCC_APB2ENR, 26, "ltdc", "apb2_div" },
};
static const struct stm32f4_gate_data stm32f469_gates[] __initconst = {
@@ -557,13 +556,13 @@ static const struct clk_div_table post_divr_table[] = {
#define MAX_POST_DIV 3
static const struct stm32f4_pll_post_div_data post_div_data[MAX_POST_DIV] = {
- { CLK_I2SQ_PDIV, PLL_I2S, "plli2s-q-div", "plli2s-q",
+ { CLK_I2SQ_PDIV, PLL_VCO_I2S, "plli2s-q-div", "plli2s-q",
CLK_SET_RATE_PARENT, STM32F4_RCC_DCKCFGR, 0, 5, 0, NULL},
- { CLK_SAIQ_PDIV, PLL_SAI, "pllsai-q-div", "pllsai-q",
+ { CLK_SAIQ_PDIV, PLL_VCO_SAI, "pllsai-q-div", "pllsai-q",
CLK_SET_RATE_PARENT, STM32F4_RCC_DCKCFGR, 8, 5, 0, NULL },
- { NO_IDX, PLL_SAI, "pllsai-r-div", "pllsai-r", CLK_SET_RATE_PARENT,
+ { NO_IDX, PLL_VCO_SAI, "pllsai-r-div", "pllsai-r", CLK_SET_RATE_PARENT,
STM32F4_RCC_DCKCFGR, 16, 2, 0, post_divr_table },
};
--
2.7.4
^ permalink raw reply related
* [PATCH v5 3/8] ARM: dts: stm32: enable ltdc binding with ili9341, gyro l3gd20 on stm32429-disco board
From: dillon.minfei @ 2020-05-25 3:45 UTC (permalink / raw)
To: linus.walleij, broonie
Cc: devicetree, linux-arm-kernel, linux-kernel, linux-spi,
linux-stm32, dri-devel, linux-clk, dillon min
In-Reply-To: <1590378348-8115-1-git-send-email-dillon.minfei@gmail.com>
From: dillon min <dillon.minfei@gmail.com>
Enable the ltdc & ili9341, gyro l3gd20 on stm32429-disco board.
Signed-off-by: dillon min <dillon.minfei@gmail.com>
---
arch/arm/boot/dts/stm32f429-disco.dts | 48 +++++++++++++++++++++++++++++++++++
1 file changed, 48 insertions(+)
diff --git a/arch/arm/boot/dts/stm32f429-disco.dts b/arch/arm/boot/dts/stm32f429-disco.dts
index 30c0f67..365d16f 100644
--- a/arch/arm/boot/dts/stm32f429-disco.dts
+++ b/arch/arm/boot/dts/stm32f429-disco.dts
@@ -49,6 +49,8 @@
#include "stm32f429.dtsi"
#include "stm32f429-pinctrl.dtsi"
#include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/gpio/gpio.h>
/ {
model = "STMicroelectronics STM32F429i-DISCO board";
@@ -127,3 +129,49 @@
pinctrl-names = "default";
status = "okay";
};
+
+<dc {
+ status = "okay";
+ pinctrl-0 = <<dc_pins_f429_disco>;
+ pinctrl-names = "default";
+
+ port {
+ ltdc_out_rgb: endpoint {
+ remote-endpoint = <&panel_in_rgb>;
+ };
+ };
+};
+
+&spi5 {
+ status = "okay";
+ pinctrl-0 = <&spi5_pins>;
+ pinctrl-names = "default";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cs-gpios = <&gpioc 1 GPIO_ACTIVE_LOW>, <&gpioc 2 GPIO_ACTIVE_LOW>;
+
+ l3gd20: l3gd20@0 {
+ compatible = "st,l3gd20-gyro";
+ spi-max-frequency = <10000000>;
+ st,drdy-int-pin = <2>;
+ interrupt-parent = <&gpioa>;
+ interrupts = <1 IRQ_TYPE_EDGE_RISING>,
+ <2 IRQ_TYPE_EDGE_RISING>;
+ reg = <0>;
+ status = "okay";
+ };
+
+ display: display@1{
+ /* Connect panel-ilitek-9341 to ltdc */
+ compatible = "st,sf-tc240t-9370-t";
+ reg = <1>;
+ spi-3wire;
+ spi-max-frequency = <10000000>;
+ dc-gpios = <&gpiod 13 0>;
+ port {
+ panel_in_rgb: endpoint {
+ remote-endpoint = <<dc_out_rgb>;
+ };
+ };
+ };
+};
--
2.7.4
^ permalink raw reply related
* [PATCH v5 0/8] Enable ili9341 and l3gd20 on stm32f429-disco
From: dillon.minfei @ 2020-05-25 3:45 UTC (permalink / raw)
To: linus.walleij, broonie
Cc: devicetree, linux-arm-kernel, linux-kernel, linux-spi,
linux-stm32, dri-devel, linux-clk, dillon min
From: dillon min <dillon.minfei@gmail.com>
V5's update based on Mark Brown's suggestion, use 'SPI_MASTER_MUST_RX'
for SPI_SIMPLEX_RX mode on stm32 spi controller.
V5:
1 instead of add send dummy data out under SIMPLEX_RX mode,
add flags 'SPI_CONTROLLER_MUST_TX' for stm32 spi driver
2 bypass 'SPI_CONTROLLER_MUST_TX' and 'SPI_CONTROLLER_MUST_RX' under
'SPI_3WIRE' mode
V4:
According to alexandre torgue's suggestion, combine ili9341 and
l3gd20's modification on stm32f429-disco board to one patchset.
Changes:
ili9341:
1 update ili9341 panel driver according to Linus's suggestion
2 drop V1's No.5 patch, sumbit new changes for clk-stm32f4
3 merge l3gd20's change to this patchset
V3:
1 merge original tiny/ili9341.c driver to panel/panel-ilitek-ili9341.c
to support serial spi & parallel rgb interface in one driver.
2 update ilitek,ili9341.yaml dts binding documentation.
3 update stm32f429-disco dts binding
V2:
1 verify ilitek,ili9341.yaml with make O=../linux-stm32
dt_binding_check
DT_SCHEMA_FILES=Documentation/devicetree/bindings/display/panel/
ilitek,ili9341.yaml
V1:
1 add ili9341 drm panel driver
2 add ltdc, spi5 controller for stm32f429-disco
3 add ltdc, spi5 pin map for stm32f429-disco
4 add docs about ili9341
5 fix ltdc driver loading hang in clk set rate bug
L3gd20:
V3:
1 merge stm32f429-disco dtbs binding with ili9341 part
V2:
1 insert blank line at stm32f420-disco.dts line 143
2 add more description for l3gd20 in commit message
V1:
1 enable spi5 controller on stm32f429-disco (dts)
2 add spi5 pinmap for stm32f429-disco (dts)
3 add SPI_SIMPLEX_RX, SPI_3WIRE_RX support for stm32f4
dillon min (8):
ARM: dts: stm32: Add dma config for spi5
ARM: dts: stm32: Add pin map for ltdc & spi5 on stm32f429-disco board
ARM: dts: stm32: enable ltdc binding with ili9341, gyro l3gd20 on
stm32429-disco board
dt-bindings: display: panel: Add ilitek ili9341 panel bindings
clk: stm32: Fix stm32f429's ltdc driver hang in set clock rate,
fix duplicated ltdc clock register to 'clk_core' case ltdc's clock
turn off by clk_disable_unused()
drm/panel: Add ilitek ili9341 panel driver
spi: stm32: Add 'SPI_SIMPLEX_RX', 'SPI_3WIRE_RX' support for stm32f4
spi: flags 'SPI_CONTROLLER_MUST_RX' and 'SPI_CONTROLLER_MUST_TX' can't
be coexit with 'SPI_3WIRE' mode
.../bindings/display/panel/ilitek,ili9341.yaml | 69 ++
arch/arm/boot/dts/stm32f4-pinctrl.dtsi | 67 +
arch/arm/boot/dts/stm32f429-disco.dts | 48 +
arch/arm/boot/dts/stm32f429.dtsi | 3 +
drivers/clk/clk-stm32f4.c | 7 +-
drivers/gpu/drm/panel/Kconfig | 12 +
drivers/gpu/drm/panel/Makefile | 1 +
drivers/gpu/drm/panel/panel-ilitek-ili9341.c | 1301 ++++++++++++++++++++
drivers/spi/spi-stm32.c | 19 +-
drivers/spi/spi.c | 3 +-
10 files changed, 1521 insertions(+), 9 deletions(-)
create mode 100644 Documentation/devicetree/bindings/display/panel/ilitek,ili9341.yaml
create mode 100644 drivers/gpu/drm/panel/panel-ilitek-ili9341.c
--
2.7.4
^ permalink raw reply
* [PATCH v5 2/8] ARM: dts: stm32: Add pin map for ltdc & spi5 on stm32f429-disco board
From: dillon.minfei @ 2020-05-25 3:45 UTC (permalink / raw)
To: linus.walleij, broonie
Cc: devicetree, linux-arm-kernel, linux-kernel, linux-spi,
linux-stm32, dri-devel, linux-clk, dillon min
In-Reply-To: <1590378348-8115-1-git-send-email-dillon.minfei@gmail.com>
From: dillon min <dillon.minfei@gmail.com>
This patch adds the pin configuration for ltdc and spi5 controller
on stm32f429-disco board.
Signed-off-by: dillon min <dillon.minfei@gmail.com>
---
arch/arm/boot/dts/stm32f4-pinctrl.dtsi | 67 ++++++++++++++++++++++++++++++++++
1 file changed, 67 insertions(+)
diff --git a/arch/arm/boot/dts/stm32f4-pinctrl.dtsi b/arch/arm/boot/dts/stm32f4-pinctrl.dtsi
index 392fa14..0eb107f 100644
--- a/arch/arm/boot/dts/stm32f4-pinctrl.dtsi
+++ b/arch/arm/boot/dts/stm32f4-pinctrl.dtsi
@@ -316,6 +316,73 @@
};
};
+ ltdc_pins_f429_disco: ltdc-1 {
+ pins {
+ pinmux = <STM32_PINMUX('C', 6, AF14)>,
+ /* LCD_HSYNC */
+ <STM32_PINMUX('A', 4, AF14)>,
+ /* LCD_VSYNC */
+ <STM32_PINMUX('G', 7, AF14)>,
+ /* LCD_CLK */
+ <STM32_PINMUX('C', 10, AF14)>,
+ /* LCD_R2 */
+ <STM32_PINMUX('B', 0, AF9)>,
+ /* LCD_R3 */
+ <STM32_PINMUX('A', 11, AF14)>,
+ /* LCD_R4 */
+ <STM32_PINMUX('A', 12, AF14)>,
+ /* LCD_R5 */
+ <STM32_PINMUX('B', 1, AF9)>,
+ /* LCD_R6*/
+ <STM32_PINMUX('G', 6, AF14)>,
+ /* LCD_R7 */
+ <STM32_PINMUX('A', 6, AF14)>,
+ /* LCD_G2 */
+ <STM32_PINMUX('G', 10, AF9)>,
+ /* LCD_G3 */
+ <STM32_PINMUX('B', 10, AF14)>,
+ /* LCD_G4 */
+ <STM32_PINMUX('D', 6, AF14)>,
+ /* LCD_B2 */
+ <STM32_PINMUX('G', 11, AF14)>,
+ /* LCD_B3*/
+ <STM32_PINMUX('B', 11, AF14)>,
+ /* LCD_G5 */
+ <STM32_PINMUX('C', 7, AF14)>,
+ /* LCD_G6 */
+ <STM32_PINMUX('D', 3, AF14)>,
+ /* LCD_G7 */
+ <STM32_PINMUX('G', 12, AF9)>,
+ /* LCD_B4 */
+ <STM32_PINMUX('A', 3, AF14)>,
+ /* LCD_B5 */
+ <STM32_PINMUX('B', 8, AF14)>,
+ /* LCD_B6 */
+ <STM32_PINMUX('B', 9, AF14)>,
+ /* LCD_B7 */
+ <STM32_PINMUX('F', 10, AF14)>;
+ /* LCD_DE */
+ slew-rate = <2>;
+ };
+ };
+
+ spi5_pins: spi5-0 {
+ pins1 {
+ pinmux = <STM32_PINMUX('F', 7, AF5)>,
+ /* SPI5_CLK */
+ <STM32_PINMUX('F', 9, AF5)>;
+ /* SPI5_MOSI */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <0>;
+ };
+ pins2 {
+ pinmux = <STM32_PINMUX('F', 8, AF5)>;
+ /* SPI5_MISO */
+ bias-disable;
+ };
+ };
+
dcmi_pins: dcmi-0 {
pins {
pinmux = <STM32_PINMUX('A', 4, AF13)>, /* DCMI_HSYNC */
--
2.7.4
^ permalink raw reply related
* [PATCH v5 1/8] ARM: dts: stm32: Add dma config for spi5
From: dillon.minfei @ 2020-05-25 3:45 UTC (permalink / raw)
To: linus.walleij, broonie
Cc: devicetree, linux-arm-kernel, linux-kernel, linux-spi,
linux-stm32, dri-devel, linux-clk, dillon min
In-Reply-To: <1590378348-8115-1-git-send-email-dillon.minfei@gmail.com>
From: dillon min <dillon.minfei@gmail.com>
Enable spi5's dma configuration. for graphics data output to
ilitek ili9341 panel via mipi dbi interface
Signed-off-by: dillon min <dillon.minfei@gmail.com>
---
arch/arm/boot/dts/stm32f429.dtsi | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/arm/boot/dts/stm32f429.dtsi b/arch/arm/boot/dts/stm32f429.dtsi
index d777069..5820b11 100644
--- a/arch/arm/boot/dts/stm32f429.dtsi
+++ b/arch/arm/boot/dts/stm32f429.dtsi
@@ -660,6 +660,9 @@
reg = <0x40015000 0x400>;
interrupts = <85>;
clocks = <&rcc 0 STM32F4_APB2_CLOCK(SPI5)>;
+ dmas = <&dma2 3 2 0x400 0x0>,
+ <&dma2 4 2 0x400 0x0>;
+ dma-names = "rx", "tx";
status = "disabled";
};
--
2.7.4
^ permalink raw reply related
* [PATCH v5 8/8] spi: flags 'SPI_CONTROLLER_MUST_RX' and 'SPI_CONTROLLER_MUST_TX' can't be coexit with 'SPI_3WIRE' mode
From: dillon.minfei @ 2020-05-25 3:41 UTC (permalink / raw)
To: robh+dt, p.zabel, mcoquelin.stm32, alexandre.torgue,
thierry.reding, sam, airlied, daniel, mturquette, sboyd
Cc: devicetree, linux-arm-kernel, linux-kernel, linux-spi,
linux-stm32, dri-devel, linux-clk, dillon min
In-Reply-To: <1590378062-7965-1-git-send-email-dillon.minfei@gmail.com>
From: dillon min <dillon.minfei@gmail.com>
since chip spi driver need get the transfer direction by 'tx_buf' and
'rx_buf' of 'struct spi_transfer' in 'SPI_3WIRE' mode.
so, we need bypass 'SPI_CONTROLLER_MUST_RX' and 'SPI_CONTROLLER_MUST_TX'
feature in 'SPI_3WIRE' mode
Signed-off-by: dillon min <dillon.minfei@gmail.com>
---
drivers/spi/spi.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index c92c894..f884411 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -1023,7 +1023,8 @@ static int spi_map_msg(struct spi_controller *ctlr, struct spi_message *msg)
void *tmp;
unsigned int max_tx, max_rx;
- if (ctlr->flags & (SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX)) {
+ if ((ctlr->flags & (SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX))
+ && !(msg->spi->mode & SPI_3WIRE)) {
max_tx = 0;
max_rx = 0;
--
2.7.4
^ permalink raw reply related
* [PATCH v5 7/8] spi: stm32: Add 'SPI_SIMPLEX_RX', 'SPI_3WIRE_RX' support for stm32f4
From: dillon.minfei @ 2020-05-25 3:41 UTC (permalink / raw)
To: robh+dt, p.zabel, mcoquelin.stm32, alexandre.torgue,
thierry.reding, sam, airlied, daniel, mturquette, sboyd
Cc: devicetree, linux-arm-kernel, linux-kernel, linux-spi,
linux-stm32, dri-devel, linux-clk, dillon min
In-Reply-To: <1590378062-7965-1-git-send-email-dillon.minfei@gmail.com>
From: dillon min <dillon.minfei@gmail.com>
in l3gd20 driver startup, there is a setup failed error return from
stm32 spi driver
"
[ 2.687630] st-gyro-spi spi0.0: supply vdd not found, using dummy
regulator
[ 2.696869] st-gyro-spi spi0.0: supply vddio not found, using dummy
regulator
[ 2.706707] spi_stm32 40015000.spi: SPI transfer setup failed
[ 2.713741] st-gyro-spi spi0.0: SPI transfer failed: -22
[ 2.721096] spi_master spi0: failed to transfer one message from queue
[ 2.729268] iio iio:device0: failed to read Who-Am-I register.
[ 2.737504] st-gyro-spi: probe of spi0.0 failed with error -22
"
after debug into spi-stm32 driver, st-gyro-spi split two steps to read
l3gd20 id
first: send command to l3gd20 with read id command in tx_buf, rx_buf
is null.
second: read id with tx_buf is null, rx_buf not null.
so, for second step, stm32 driver recongise this process as 'SPI_SIMPLE_RX'
from stm32_spi_communication_type(), but there is no related process for this
type in stm32f4_spi_set_mode(), then we get error from
stm32_spi_transfer_one_setup().
we can use two method to fix this bug.
1, use stm32 spi's "In unidirectional receive-only mode (BIDIMODE=0 and
RXONLY=1)". but as our code running in sdram, the read latency is too large
to get so many receive overrun error in interrupts handler.
2, use stm32 spi's "In full-duplex (BIDIMODE=0 and RXONLY=0)", as tx_buf is
null, so add flag 'SPI_MASTER_MUST_TX' to spi master.
Change since V4:
1 remove dummy data sent out by stm32 spi driver
2 add flag 'SPI_MASTER_MUST_TX' to spi master
Signed-off-by: dillon min <dillon.minfei@gmail.com>
---
Hi Mark,
This changes add 'SPI_MASTER_MUST_TX' for stm32 spi controller
thanks.
drivers/spi/spi-stm32.c | 19 +++++++++++++++----
1 file changed, 15 insertions(+), 4 deletions(-)
diff --git a/drivers/spi/spi-stm32.c b/drivers/spi/spi-stm32.c
index 44ac6eb3..4c643df 100644
--- a/drivers/spi/spi-stm32.c
+++ b/drivers/spi/spi-stm32.c
@@ -811,7 +811,9 @@ static irqreturn_t stm32f4_spi_irq_event(int irq, void *dev_id)
mask |= STM32F4_SPI_SR_TXE;
}
- if (!spi->cur_usedma && spi->cur_comm == SPI_FULL_DUPLEX) {
+ if (!spi->cur_usedma && (spi->cur_comm == SPI_FULL_DUPLEX ||
+ spi->cur_comm == SPI_SIMPLEX_RX ||
+ spi->cur_comm == SPI_3WIRE_RX)) {
/* TXE flag is set and is handled when RXNE flag occurs */
sr &= ~STM32F4_SPI_SR_TXE;
mask |= STM32F4_SPI_SR_RXNE | STM32F4_SPI_SR_OVR;
@@ -850,7 +852,7 @@ static irqreturn_t stm32f4_spi_irq_event(int irq, void *dev_id)
stm32f4_spi_read_rx(spi);
if (spi->rx_len == 0)
end = true;
- else /* Load data for discontinuous mode */
+ else if (spi->tx_buf)/* Load data for discontinuous mode */
stm32f4_spi_write_tx(spi);
}
@@ -1151,7 +1153,9 @@ static int stm32f4_spi_transfer_one_irq(struct stm32_spi *spi)
/* Enable the interrupts relative to the current communication mode */
if (spi->cur_comm == SPI_SIMPLEX_TX || spi->cur_comm == SPI_3WIRE_TX) {
cr2 |= STM32F4_SPI_CR2_TXEIE;
- } else if (spi->cur_comm == SPI_FULL_DUPLEX) {
+ } else if (spi->cur_comm == SPI_FULL_DUPLEX ||
+ spi->cur_comm == SPI_SIMPLEX_RX ||
+ spi->cur_comm == SPI_3WIRE_RX) {
/* In transmit-only mode, the OVR flag is set in the SR register
* since the received data are never read. Therefore set OVR
* interrupt only when rx buffer is available.
@@ -1462,10 +1466,16 @@ static int stm32f4_spi_set_mode(struct stm32_spi *spi, unsigned int comm_type)
stm32_spi_set_bits(spi, STM32F4_SPI_CR1,
STM32F4_SPI_CR1_BIDIMODE |
STM32F4_SPI_CR1_BIDIOE);
- } else if (comm_type == SPI_FULL_DUPLEX) {
+ } else if (comm_type == SPI_FULL_DUPLEX ||
+ comm_type == SPI_SIMPLEX_RX) {
stm32_spi_clr_bits(spi, STM32F4_SPI_CR1,
STM32F4_SPI_CR1_BIDIMODE |
STM32F4_SPI_CR1_BIDIOE);
+ } else if (comm_type == SPI_3WIRE_RX) {
+ stm32_spi_set_bits(spi, STM32F4_SPI_CR1,
+ STM32F4_SPI_CR1_BIDIMODE);
+ stm32_spi_clr_bits(spi, STM32F4_SPI_CR1,
+ STM32F4_SPI_CR1_BIDIOE);
} else {
return -EINVAL;
}
@@ -1906,6 +1916,7 @@ static int stm32_spi_probe(struct platform_device *pdev)
master->prepare_message = stm32_spi_prepare_msg;
master->transfer_one = stm32_spi_transfer_one;
master->unprepare_message = stm32_spi_unprepare_msg;
+ master->flags = SPI_MASTER_MUST_TX;
spi->dma_tx = dma_request_chan(spi->dev, "tx");
if (IS_ERR(spi->dma_tx)) {
--
2.7.4
^ permalink raw reply related
* [PATCH v5 6/8] drm/panel: Add ilitek ili9341 panel driver
From: dillon.minfei @ 2020-05-25 3:41 UTC (permalink / raw)
To: robh+dt, p.zabel, mcoquelin.stm32, alexandre.torgue,
thierry.reding, sam, airlied, daniel, mturquette, sboyd
Cc: devicetree, linux-arm-kernel, linux-kernel, linux-spi,
linux-stm32, dri-devel, linux-clk, dillon min
In-Reply-To: <1590378062-7965-1-git-send-email-dillon.minfei@gmail.com>
From: dillon min <dillon.minfei@gmail.com>
This driver combine tiny/ili9341.c mipi_dbi_interface driver
with mipi_dpi_interface driver, can support ili9341 with serial
mode or parallel rgb interface mode by register configuration.
Changes since V3:
accoding to Linus Walleij's suggestion.
1 add more comments to driver.
2 reduce magic number usage in the driver.
3 move panel configuration from common place to system configuration.
4 reuse MIPI_DCS_* as more as possible.
Signed-off-by: dillon min <dillon.minfei@gmail.com>
---
drivers/gpu/drm/panel/Kconfig | 12 +
drivers/gpu/drm/panel/Makefile | 1 +
drivers/gpu/drm/panel/panel-ilitek-ili9341.c | 1301 ++++++++++++++++++++++++++
3 files changed, 1314 insertions(+)
create mode 100644 drivers/gpu/drm/panel/panel-ilitek-ili9341.c
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index a1723c1..c938bee 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -95,6 +95,18 @@ config DRM_PANEL_ILITEK_IL9322
Say Y here if you want to enable support for Ilitek IL9322
QVGA (320x240) RGB, YUV and ITU-T BT.656 panels.
+config DRM_PANEL_ILITEK_ILI9341
+ tristate "Ilitek ILI9341 240x320 QVGA panels"
+ depends on OF && SPI
+ depends on DRM_KMS_HELPER
+ depends on DRM_KMS_CMA_HELPER
+ depends on BACKLIGHT_CLASS_DEVICE
+ select DRM_MIPI_DBI
+ help
+ Say Y here if you want to enable support for Ilitek IL9341
+ QVGA (240x320) RGB panels. support serial & parallel rgb
+ interface.
+
config DRM_PANEL_ILITEK_ILI9881C
tristate "Ilitek ILI9881C-based panels"
depends on OF
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index 96a883c..16947d7 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_DRM_PANEL_ELIDA_KD35T133) += panel-elida-kd35t133.o
obj-$(CONFIG_DRM_PANEL_FEIXIN_K101_IM2BA02) += panel-feixin-k101-im2ba02.o
obj-$(CONFIG_DRM_PANEL_FEIYANG_FY07024DI26A30D) += panel-feiyang-fy07024di26a30d.o
obj-$(CONFIG_DRM_PANEL_ILITEK_IL9322) += panel-ilitek-ili9322.o
+obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9341) += panel-ilitek-ili9341.o
obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9881C) += panel-ilitek-ili9881c.o
obj-$(CONFIG_DRM_PANEL_INNOLUX_P079ZCA) += panel-innolux-p079zca.o
obj-$(CONFIG_DRM_PANEL_JDI_LT070ME05000) += panel-jdi-lt070me05000.o
diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9341.c b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c
new file mode 100644
index 0000000..dd6f860
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c
@@ -0,0 +1,1301 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Ilitek ILI9341 TFT LCD drm_panel driver.
+ *
+ * This panel can be configured to support:
+ * - 16-bit parallel RGB interface
+ * - 18-bit parallel RGB interface
+ * - 4-line serial spi interface
+ *
+ * Copyright (C) 2020 Dillon Min <dillon.minfei@gmail.com>
+ * Derived from drivers/drm/gpu/panel/panel-ilitek-ili9322.c
+ */
+
+#include <linux/bitops.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/spi/spi.h>
+#include <linux/delay.h>
+#include <video/mipi_display.h>
+#include <drm/drm_mipi_dbi.h>
+#include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_atomic_helper.h>
+
+#include <drm/drm_drv.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_print.h>
+
+#define ILI9341_RGB_INTERFACE 0xb0 /* RGB Interface Signal Control */
+#define ILI9341_FRC 0xb1 /* Frame Rate Control register */
+#define ILI9341_DFC 0xb6 /* Display Function Control register */
+#define ILI9341_POWER1 0xc0 /* Power Control 1 register */
+#define ILI9341_POWER2 0xc1 /* Power Control 2 register */
+#define ILI9341_VCOM1 0xc5 /* VCOM Control 1 register */
+#define ILI9341_VCOM2 0xc7 /* VCOM Control 2 register */
+#define ILI9341_POWERA 0xcb /* Power control A register */
+#define ILI9341_POWERB 0xcf /* Power control B register */
+#define ILI9341_PGAMMA 0xe0 /* Positive Gamma Correction register */
+#define ILI9341_NGAMMA 0xe1 /* Negative Gamma Correction register */
+#define ILI9341_DTCA 0xe8 /* Driver timing control A */
+#define ILI9341_DTCB 0xea /* Driver timing control B */
+#define ILI9341_POWER_SEQ 0xed /* Power on sequence register */
+#define ILI9341_3GAMMA_EN 0xf2 /* 3 Gamma enable register */
+#define ILI9341_INTERFACE 0xf6 /* Interface control register */
+#define ILI9341_PRC 0xf7 /* Pump ratio control register */
+#define ILI9341_ETMOD 0xb7 /* Entry mode set */
+
+#define ILI9341_MADCTL_BGR BIT(3)
+#define ILI9341_MADCTL_MV BIT(5)
+#define ILI9341_MADCTL_MX BIT(6)
+#define ILI9341_MADCTL_MY BIT(7)
+
+
+#define ILI9341_POWER_B_LEN 3
+#define ILI9341_POWER_SEQ_LEN 4
+#define ILI9341_DTCA_LEN 3
+#define ILI9341_DTCB_LEN 2
+#define ILI9341_POWER_A_LEN 5
+#define ILI9341_DFC_1_LEN 2
+#define ILI9341_FRC_LEN 2
+#define ILI9341_VCOM_1_LEN 2
+#define ILI9341_DFC_2_LEN 4
+#define ILI9341_COLUMN_ADDR_LEN 4
+#define ILI9341_PAGE_ADDR_LEN 4
+#define ILI9341_INTERFACE_LEN 3
+#define ILI9341_PGAMMA_LEN 15
+#define ILI9341_NGAMMA_LEN 15
+#define ILI9341_CA_LEN 3
+
+#define ILI9341_PIXEL_DPI_16_BITS (BIT(6)|BIT(4))
+#define ILI9341_PIXEL_DPI_18_BITS (BIT(6)|BIT(5))
+#define ILI9341_GAMMA_CURVE_1 BIT(0)
+#define ILI9341_IF_WE_MODE BIT(0)
+#define ILI9341_IF_BIG_ENDIAN 0x00
+#define ILI9341_IF_DM_RGB BIT(2)
+#define ILI9341_IF_DM_INTERNAL 0x00
+#define ILI9341_IF_DM_VSYNC BIT(3)
+#define ILI9341_IF_RM_RGB BIT(1)
+#define ILI9341_IF_RIM_RGB 0x00
+
+#define ILI9341_COLUMN_ADDR 0x00ef
+#define ILI9341_PAGE_ADDR 0x013f
+
+#define ILI9341_RGB_EPL BIT(0)
+#define ILI9341_RGB_DPL BIT(1)
+#define ILI9341_RGB_HSPL BIT(2)
+#define ILI9341_RGB_VSPL BIT(3)
+#define ILI9341_RGB_DE_MODE BIT(6)
+#define ILI9341_RGB_DISP_PATH_MEM BIT(7)
+
+#define ILI9341_DBI_VCOMH_4P6V 0x23
+#define ILI9341_DBI_PWR_2_DEFAULT 0x10
+#define ILI9341_DBI_PRC_NORMAL 0x20
+#define ILI9341_DBI_VCOM_1_VMH_4P25V 0x3e
+#define ILI9341_DBI_VCOM_1_VML_1P5V 0x28
+#define ILI9341_DBI_VCOM_2_DEC_58 0x86
+#define ILI9341_DBI_FRC_DIVA 0x00
+#define ILI9341_DBI_FRC_RTNA 0x1b
+#define ILI9341_DBI_EMS_GAS BIT(0)
+#define ILI9341_DBI_EMS_DTS BIT(1)
+#define ILI9341_DBI_EMS_GON BIT(2)
+/**
+ * ili9341_command - ili9341 command with optional parameter(s)
+ * @ili: struct ili9341
+ * @cmd: Command
+ * @seq...: Optional parameter(s)
+ *
+ * Send command to the controller.
+ *
+ * Returns:
+ * Zero on success, negative error code on failure.
+ */
+#define ili9341_command(ili, cmd, seq...) \
+({ \
+ u8 d[] = { seq }; \
+ _ili9341_command(ili, cmd, d, ARRAY_SIZE(d)); \
+})
+
+/**
+ * struct ili9341_config - the system specific ILI9341 configuration
+ * @max_spi_speed: 10000000
+ */
+struct ili9341_config {
+ u32 max_spi_speed;
+
+ const struct drm_display_mode mode;
+ /* TODO: need comments for this register */
+ u8 ca[ILI9341_CA_LEN];
+ /* TODO: need comments for this register */
+ u8 power_b[ILI9341_POWER_B_LEN];
+ /* TODO: need comments for this register */
+ u8 power_seq[ILI9341_POWER_SEQ_LEN];
+ /* TODO: need comments for this register */
+ u8 dtca[ILI9341_DTCA_LEN];
+ /* TODO: need comments for this register */
+ u8 dtcb[ILI9341_DTCB_LEN];
+ /* TODO: need comments for this register */
+ u8 power_a[ILI9341_POWER_A_LEN];
+ /*
+ * Frame Rate Control (In Normal Mode/Full Colors) (B1h)
+ *
+ * Formula to calculate frame frequency:
+ * Frame Rate=fosc/(Clocks per line x Division ratio x
+ * (Lines+VBP+VFP))
+ *
+ * Sets the division ratio for internal clocks of Normal mode at MCU
+ * interface.
+ *
+ * fosc : internal oscillator frequency
+ * Clocks per line : RTNA setting
+ * Division ratio : DIVA setting
+ * Lines : total driving line number
+ * VBP : back porch line number
+ * VFP : front porch line number
+ *
+ * RTNA [4:0] Frame Rate (Hz) RTNA [4:0] Frame Rate (Hz)
+ * 1 0 0 0 0 119 1 1 0 0 0 79
+ * 1 0 0 0 1 112 1 1 0 0 1 76
+ * 1 0 0 1 0 106 1 1 0 1 0 73
+ * 1 0 0 1 1 100 1 1 0 1 1 70(default)
+ * 1 0 1 0 0 95 1 1 1 0 0 68
+ * 1 0 1 0 1 90 1 1 1 0 1 65
+ * 1 0 1 1 0 86 1 1 1 0 1 63
+ * 1 0 1 1 1 83 1 1 1 1 1 61
+ *
+ * DIVA [1:0] : division ratio for internal clocks when Normal mode.
+ *
+ * DIVA [1:0] Division Ratio
+ * 0 0 fosc
+ * 0 1 fosc / 2
+ * 1 0 fosc / 4
+ * 1 1 fosc / 8
+ *
+ */
+ u8 frc[ILI9341_FRC_LEN];
+ /* TODO: need comments for this register */
+ u8 prc;
+ /*
+ * B6h DISCTRL (Display Function Control)
+ * D/CX RDX WRX D17-8 D7 D6 D5 D4 D3 D2 D1 D0 HEX
+ * Command 0 1 M XX 1 0 1 1 0 1 1 0 B6h
+ * 1st Parameter 1 1 M XX 0 0 0 0 PTG[1:0] PT[1:0] 0A
+ * 2nd Parameter 1 1 M XX REV GS SS SM ISC[3:0] 82
+ * 3rd Parameter 1 1 M XX 0 0 NL[5:0] 27
+ * 4th Parameter 1 1 M XX 0 0 PCDIV[5:0] XX
+ *
+ * PTG [1:0]: Set the scan mode in non-display area.
+ * PTG1 | PTG0 | Gate outputs in | Source outputs in | VCOM output
+ * non-display area | non-display area |
+ * 1 0 Interval scan Set with the PT[2:0] bits
+ *
+ * PT [1:0]: Determine source/VCOM output in a non-display area in the
+ * partial display mode.
+ * 1 0 AGND AGND AGND AGND
+ *
+ * REV: Select whether the liquid crystal type is normally white type
+ * or normally black type.
+ * REV Liquid crystal type
+ * 0 Normally black
+ * 1 Normally white
+ *
+ * SS: Select the shift direction of outputs from the source driver.
+ * SS Source Output Scan Direction
+ * 0 S1 -> S720
+ * 1 S720 -> S1
+ *
+ * GS: Sets the direction of scan by the gate driver in the range
+ * determined by SCN [4:0] and NL [4:0]. The scan direction
+ * determined by GS = 0 can be reversed by setting GS = 1.
+ *
+ * GS Gate Output Scan Direction
+ * 0 G1 -> G320
+ * 1 G320 -> G1
+ */
+ u8 dfc_1[ILI9341_DFC_1_LEN];
+ /*
+ * Power Control 1 (C0h)
+ * VRH [5:0]: Set the GVDD level, which is a reference level for the
+ * VCOM level and the grayscale voltage level.
+ *
+ * VRH[5:0] GVDD VRH[5:0] GVDD
+ * 0 0 0 0 0 0 Setting prohibited 1 0 0 0 0 0 4.45 V
+ * 0 0 0 0 0 1 Setting prohibited 1 0 0 0 0 1 4.50 V
+ * 0 0 0 0 1 0 Setting prohibited 1 0 0 0 1 0 4.55 V
+ * 0 0 0 0 1 1 3.00 V 1 0 0 0 1 1 4.60 V
+ * 0 0 0 1 0 0 3.05 V 1 0 0 1 0 0 4.65 V
+ * 0 0 0 1 0 1 3.10 V 1 0 0 1 0 1 4.70 V
+ * 0 0 0 1 1 0 3.15 V 1 0 0 1 1 0 4.75 V
+ * 0 0 0 1 1 1 3.20 V 1 0 0 1 1 1 4.80 V
+ * 0 0 1 0 0 0 3.25 V 1 0 1 0 0 0 4.85 V
+ * 0 0 1 0 0 1 3.30 V 1 0 1 0 0 1 4.90 V
+ * 0 0 1 0 1 0 3.35 V 1 0 1 0 1 0 4.95 V
+ * 0 0 1 0 1 1 3.40 V 1 0 1 0 1 1 5.00 V
+ * 0 0 1 1 0 0 3.45 V 1 0 1 1 0 0 5.05 V
+ * 0 0 1 1 0 1 3.50 V 1 0 1 1 0 1 5.10 V
+ * 0 0 1 1 1 0 3.55 V 1 0 1 1 1 0 5.15 V
+ * 0 0 1 1 1 1 3.60 V 1 0 1 1 1 1 5.20 V
+ * 0 1 0 0 0 0 3.65 V 1 1 0 0 0 0 5.25 V
+ * 0 1 0 0 0 1 3.70 V 1 1 0 0 0 1 5.30 V
+ * 0 1 0 0 1 0 3.75 V 1 1 0 0 1 0 5.35 V
+ * 0 1 0 0 1 1 3.80 V 1 1 0 0 1 1 5.40 V
+ * 0 1 0 1 0 0 3.85 V 1 1 0 1 0 0 5.45 V
+ * 0 1 0 1 0 1 3.90 V 1 1 0 1 0 1 5.50 V
+ * 0 1 0 1 1 0 3.95 V 1 1 0 1 1 0 5.55 V
+ * 0 1 0 1 1 1 4.00 V 1 1 0 1 1 1 5.60 V
+ * 0 1 1 0 0 0 4.05 V 1 1 1 0 0 0 5.65 V
+ * 0 1 1 0 0 1 4.10 V 1 1 1 0 0 1 5.70 V
+ * 0 1 1 0 1 0 4.15 V 1 1 1 0 1 0 5.75 V
+ * 0 1 1 0 1 1 4.20 V 1 1 1 0 1 1 5.80 V
+ * 0 1 1 1 0 0 4.25 V 1 1 1 1 0 0 5.85 V
+ * 0 1 1 1 0 1 4.30 V 1 1 1 1 0 1 5.90 V
+ * 0 1 1 1 1 0 4.35 V 1 1 1 1 1 0 5.95 V
+ * 0 1 1 1 1 1 4.40 V 1 1 1 1 1 1 6.00 V
+ */
+ u8 power_1;
+ /*
+ * Power Control 2 (C1h)
+ *
+ * BT [2:0]: Sets the factor used in the step-up circuits.
+ * Select the optimal step-up factor for the operating voltage. To
+ * reduce power consumption, set a smaller factor.
+ *
+ * BT[2:0] AVDD VGH VGL
+ * 0 0 0 VCI x 2 VCI x 7 VCI x 4
+ * 0 0 1 VCI x 3
+ * 0 1 0 VCI x 6 VCI x 4
+ * 0 1 1 VCI x 3
+ *
+ */
+ u8 power_2;
+ /*
+ * VCOM Control 1(C5h)
+ *
+ * VMH [6:0] : Set the VCOMH voltage
+ *
+ * VMH[6:0] VCOMH(V) VMH[6:0] VCOMH(V) VMH[6:0] VCOMH(V) VMH[6:0] VCOMH
+ * 0000000 2.700 0100000 3.500 1000000 4.300 1100000 5.100
+ * 0000001 2.725 0100001 3.525 1000001 4.325 1100001 5.125
+ * 0000010 2.750 0100010 3.550 1000010 4.350 1100010 5.150
+ * 0000011 2.775 0100011 3.575 1000011 4.375 1100011 5.175
+ * 0000100 2.800 0100100 3.600 1000100 4.400 1100100 5.200
+ * 0000101 2.825 0100101 3.625 1000101 4.425 1100101 5.225
+ * 0000110 2.850 0100110 3.650 1000110 4.450 1100110 5.250
+ * 0000111 2.875 0100111 3.675 1000111 4.475 1100111 5.275
+ * 0001000 2.900 0101000 3.700 1001000 4.500 1101000 5.300
+ * 0001001 2.925 0101001 3.725 1001001 4.525 1101001 5.325
+ * 0001010 2.950 0101010 3.750 1001010 4.550 1101010 5.350
+ * 0001011 2.975 0101011 3.775 1001011 4.575 1101011 5.375
+ * 0001100 3.000 0101100 3.800 1001100 4.600 1101100 5.400
+ * 0001101 3.025 0101101 3.825 1001101 4.625 1101101 5.425
+ * 0001110 3.050 0101110 3.850 1001110 4.650 1101110 5.450
+ * 0001111 3.075 0101111 3.875 1001111 4.675 1101111 5.475
+ * 0010000 3.100 0110000 3.900 1010000 4.700 1110000 5.500
+ * 0010001 3.125 0110001 3.925 1010001 4.725 1110001 5.525
+ * 0010010 3.150 0110010 3.950 1010010 4.750 1110010 5.550
+ * 0010011 3.175 0110011 3.975 1010011 4.775 1110011 5.575
+ * 0010100 3.200 0110100 4.000 1010100 4.800 1110100 5.600
+ * 0010101 3.225 0110101 4.025 1010101 4.825 1110101 5.625
+ * 0010110 3.250 0110110 4.050 1010110 4.850 1110110 5.650
+ * 0010111 3.275 0110111 4.075 1010111 4.875 1110111 5.675
+ * 0011000 3.300 0111000 4.100 1011000 4.900 1111000 5.700
+ * 0011001 3.325 0111001 4.125 1011001 4.925 1111001 5.725
+ * 0011010 3.350 0111010 4.150 1011010 4.950 1111010 5.750
+ * 0011011 3.375 0111011 4.175 1011011 4.975 1111011 5.775
+ * 0011100 3.400 0111100 4.200 1011100 5.000 1111100 5.800
+ * 0011101 3.425 0111101 4.225 1011101 5.025 1111101 5.825
+ * 0011110 3.450 0111110 4.250 1011110 5.050 1111110 5.850
+ * 0011111 3.475 0111111 4.275 1011111 5.075 1111111 5.875
+ *
+ * VML[6:0] : Set the VCOML voltage
+ *
+ * VML[6:0] VCOML(V) VML[6:0] VCOML(V) VML[6:0] VCOML(V) VML[6:0] VCOML
+ * 0000000 -2.500 0100000 -1.700 1000000 -0.900 1100000 -0.100
+ * 0000001 -2.475 0100001 -1.675 1000001 -0.875 1100001 -0.075
+ * 0000010 -2.450 0100010 -1.650 1000010 -0.850 1100010 -0.050
+ * 0000011 -2.425 0100011 -1.625 1000011 -0.825 1100011 -0.025
+ * 0000100 -2.400 0100100 -1.600 1000100 -0.800 1100100 0
+ * 0000101 -2.375 0100101 -1.575 1000101 -0.775 1100101 Reserved
+ * 0000110 -2.350 0100110 -1.550 1000110 -0.750 1100110 Reserved
+ * 0000111 -2.325 0100111 -1.525 1000111 -0.725 1100111 Reserved
+ * 0001000 -2.300 0101000 -1.500 1001000 -0.700 1101000 Reserved
+ * 0001001 -2.275 0101001 -1.475 1001001 -0.675 1101001 Reserved
+ * 0001010 -2.250 0101010 -1.450 1001010 -0.650 1101010 Reserved
+ * 0001011 -2.225 0101011 -1.425 1001011 -0.625 1101011 Reserved
+ * 0001100 -2.200 0101100 -1.400 1001100 -0.600 1101100 Reserved
+ * 0001101 -2.175 0101101 -1.375 1001101 -0.575 1101101 Reserved
+ * 0001110 -2.150 0101110 -1.350 1001110 -0.550 1101110 Reserved
+ * 0001111 -2.125 0101111 -1.325 1001111 -0.525 1101111 Reserved
+ * 0010000 -2.100 0110000 -1.300 1010000 -0.500 1110000 Reserved
+ * 0010001 -2.075 0110001 -1.275 1010001 -0.475 1110001 Reserved
+ * 0010010 -2.050 0110010 -1.250 1010010 -0.450 1110010 Reserved
+ * 0010011 -2.025 0110011 -1.225 1010011 -0.425 1110011 Reserved
+ * 0010100 -2.000 0110100 -1.200 1010100 -0.400 1110100 Reserved
+ * 0010101 -1.975 0110101 -1.175 1010101 -0.375 1110101 Reserved
+ * 0010110 -1.950 0110110 -1.150 1010110 -0.350 1110110 Reserved
+ * 0010111 -1.925 0110111 -1.125 1010111 -0.325 1110111 Reserved
+ * 0011000 -1.900 0111000 -1.100 1011000 -0.300 1111000 Reserved
+ * 0011001 -1.875 0111001 -1.075 1011001 -0.275 1111001 Reserved
+ * 0011010 -1.850 0111010 -1.050 1011010 -0.250 1111010 Reserved
+ * 0011011 -1.825 0111011 -1.025 1011011 -0.225 1111011 Reserved
+ * 0011100 -1.800 0111100 -1.000 1011100 -0.200 1111100 Reserved
+ * 0011101 -1.775 0111101 -0.975 1011101 -0.175 1111101 Reserved
+ * 0011110 -1.750 0111110 -0.950 1011110 -0.150 1111110 Reserved
+ * 0011111 -1.725 0111111 -0.925 1011111 -0.125 1111111 Reserved
+ */
+ u8 vcom_1[ILI9341_VCOM_1_LEN];
+ /*
+ * VCOM Control 2(C7h)
+ *
+ * C7h VMCTRL1 (VCOM Control 1)
+ * D/CX RDX WRX D17-8 D7 D6 D5 D4 D3 D2 D1 D0 HEX
+ * Command 0 1 M XX 1 1 0 0 0 1 1 1 C7h
+ * Parameter 1 1 M XX nVM VMF[6:0] C0
+ *
+ * nVM: nVM equals to “0” after power on reset and VCOM offset
+ * equals to program MTP value. When nVM set to “1”, setting
+ * of VMF [6:0] becomes valid and VCOMH/VCOML can be adjusted.
+ *
+ * VMF [6:0]: Set the VCOM offset voltage.
+ */
+ u8 vcom_2;
+ /*
+ * Memory Access Control (36h)
+ *
+ * 36h MADCTL (Memory Access Control)
+ * D/CX RDX WRX D17-8 D7 D6 D5 D4 D3 D2 D1 D0 HEX
+ * Command 0 1 M XX 0 0 1 1 0 1 1 0 36h
+ * Parameter 1 1 M XX MY MX MV ML BGR MH 0 0 00
+ *
+ * This command defines read/write scanning direction of frame memory.
+ * This command makes no change on the other driver status.
+ *
+ * Bit Name Description
+ * MY Row Address Order
+ * MX Column Address Order
+ * MV Row / Column Exchange These 3 bits control MCU to memory
+ * write/read direction.
+ * ML Vertical Refresh Order LCD vertical refresh direction control.
+ * BGR RGB-BGR Order Color selector switch control
+ * (0=RGB color filter panel, 1=BGR
+ * color filter panel)
+ * MH Horizontal Refresh ORDER LCD horizontal refreshing
+ * direction control.
+ *
+ * Note: When BGR bit is changed, the new setting is active
+ * immediately without update the content in Frame Memory again.
+ *
+ */
+ u8 address_mode;
+ /* TODO: need comments for this register */
+ u8 g3amma_en;
+ /* RGB Interface Signal Control (B0h)
+ *
+ * B0h IFMODE (Interface Mode Control)
+ * D/CX RDX WRX D17-8 D7 D6 D5 D4 D3 D2 D1 D0 HEX
+ * Command 0 1 M XX 1 0 1 1 0 0 0 0 B0h
+ * Parameter 1 1 M XX ByPass_MODE RCM[1] RCM[0] 0 VSPL HSPL DPL EPL 40
+ *
+ * Sets the operation status of the display interface. The setting
+ * becomes effective as soon as the command is received.
+ * EPL: DE polarity (“0”= High enable for RGB interface, “1”= Low
+ * enable for RGB interface)
+ *
+ * DPL: DOTCLK polarity set (“0”= data fetched at the rising time,
+ * “1”= data fetched at the falling time)
+ *
+ * HSPL: HSYNC polarity (“0”= Low level sync clock, “1”= High
+ * level sync clock)
+ *
+ * VSPL: VSYNC polarity (“0”= Low level sync clock, “1”= High
+ * level sync clock)
+ *
+ * RCM [1:0]: RGB interface selection (refer to the RGB interface
+ * section).
+ *
+ * ByPass_MODE: Select display data path whether Memory or Direct to
+ * Shift register when RGB Interface is used.
+ *
+ * ByPass_MODE Display Data Path
+ * 0 Direct to Shift Register (default)
+ * 1 Memory
+ */
+ u8 rgb_interface;
+ /* refer to dfc_1 */
+ u8 dfc_2[ILI9341_DFC_2_LEN];
+ /*
+ * Column Address Set (2Ah)
+ * This command is used to define area of frame memory where MCU can
+ * access. This command makes no change on the
+ * other driver status. The values of SC [15:0] and EC [15:0] are
+ * referred when RAMWR command comes. Each value
+ * represents one column line in the Frame Memory.
+ */
+ u8 column_addr[ILI9341_COLUMN_ADDR_LEN];
+ /*
+ * Page Address Set (2Bh)
+ * This command is used to define area of frame memory where MCU can
+ * access. This command makes no change on the
+ * other driver status. The values of SP [15:0] and EP [15:0] are
+ * referred when RAMWR command comes. Each value
+ * represents one Page line in the Frame Memory.
+ */
+ u8 page_addr[ILI9341_PAGE_ADDR_LEN];
+ /*
+ * Interface Control (F6h)
+ *
+ * F6h IFCTL (16bits Data Format Selection)
+ * D/CX RDX WRX D17-8 D7 D6 D5 D4 D3 D2 D1 D0 HEX
+ * Command 0 1 M XX 1 1 1 1 0 1 1 0 F6h
+ * 1stParameter 1 1 M XX MY MX MV
+ * _EOR _EOR _EOR 0 BGR_EOR 0 0 WE MODE 01
+ * 2ndParameter 1 1 M XX 0 0 EPF[1] EPF[0] 0 0 MDT[1] MDT[0] 00
+ * 3rdParameter 1 1 M XX 0 0 ENDIAN 0 DM[1] DM[0] RM RIM 00
+ *
+ */
+ u8 interface[ILI9341_INTERFACE_LEN];
+ /*
+ * This command sets the pixel format for the RGB image data used by
+ * the interface. DPI [2:0] is the pixel format select of RGB
+ * interface and DBI [2:0] is the pixel format of MCU interface. If a
+ * particular interface, either RGB interface or MCU interface, is
+ * not used then the corresponding bits in the parameter are ignored.
+ * The pixel format is shown in the table below.
+ *
+ * DPI[2:0] RGB Interface Format DBI[2:0] MCU Interface Format
+ * 0 0 0 Reserved 0 0 0 Reserved
+ * 0 0 1 Reserved 0 0 1 Reserved
+ * 0 1 0 Reserved 0 1 0 Reserved
+ * 0 1 1 Reserved 0 1 1 Reserved
+ * 1 0 0 Reserved 1 0 0 Reserved
+ * 1 0 1 16 bits / pixel 1 0 1 16 bits / pixel
+ * 1 1 0 18 bits / pixel 1 1 0 18 bits / pixel
+ * 1 1 1 Reserved 1 1 1 Reserved
+ *
+ */
+ u8 pixel_format;
+ /*
+ * This command is used to select the desired Gamma curve for the
+ * current display. A maximum of 4 fixed gamma curves can
+ * be selected. The curve is selected by setting the appropriate bit
+ * in the parameter as described in the Table:
+ *
+ * GC [7:0] Curve Selected
+ * 01h Gamma curve 1 (G2.2)
+ * 02h ---
+ * 04h ---
+ * 08h ---
+ */
+ u8 gamma_curve;
+ /*
+ * Positive Gamma Correction (E0h)
+ *
+ * Set the gray scale voltage to adjust the gamma characteristics of
+ * the TFT panel.
+ */
+ u8 pgamma[ILI9341_PGAMMA_LEN];
+ /*
+ * Negative Gamma Correction (E1h)
+ *
+ * Set the gray scale voltage to adjust the gamma characteristics of
+ * the TFT panel.
+ */
+ u8 ngamma[ILI9341_NGAMMA_LEN];
+};
+
+struct ili9341 {
+ struct device *dev;
+ const struct ili9341_config *conf;
+ struct drm_panel panel;
+ struct gpio_desc *reset_gpio;
+ struct gpio_desc *dc_gpio;
+ u32 max_spi_speed;
+ struct regulator *vcc;
+};
+
+/*
+ * The Stm32f429-disco board has a panel ili9341 connected to ltdc controller
+ */
+static const struct ili9341_config ili9341_stm32f429_disco_data = {
+ .max_spi_speed = 10000000,
+ .mode = {
+ .clock = 6100,
+ .hdisplay = 240,
+ .hsync_start = 240 + 10,/* hfp 10 */
+ .hsync_end = 240 + 10 + 10,/* hsync 10 */
+ .htotal = 240 + 10 + 10 + 20,/* hbp 20 */
+ .vdisplay = 320,
+ .vsync_start = 320 + 4,/* vfp 4 */
+ .vsync_end = 320 + 4 + 2,/* vsync 2 */
+ .vtotal = 320 + 4 + 2 + 2,/* vbp 2 */
+ .vrefresh = 60,
+ .flags = 0,
+ .width_mm = 65,
+ .height_mm = 50,
+ .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+ },
+ /* TODO: need comments for this register */
+ .ca = {0xc3, 0x08, 0x50},
+ /* TODO: need comments for this register */
+ .power_b = {0x00, 0xc1, 0x30},
+ /* TODO: need comments for this register */
+ .power_seq = {0x64, 0x03, 0x12, 0x81},
+ /* TODO: need comments for this register */
+ .dtca = {0x85, 0x00, 0x78},
+ /* TODO: need comments for this register */
+ .power_a = {0x39, 0x2c, 0x00, 0x34, 0x02},
+ /* TODO: need comments for this register */
+ .prc = 0x20,
+ /* TODO: need comments for this register */
+ .dtcb = {0x00, 0x00},
+ /* 0x00 fosc, 0x1b 70hz */
+ .frc = {0x00, 0x1b},
+ /* 0x0a Interval scan, AGND AGND AGND AGND
+ * 0xa2 Normally white, G1 -> G320, S720 -> S1,
+ * Scan Cycle 5 frames,85ms
+ */
+ .dfc_1 = {0x0a, 0xa2},
+ /* 0x10 3.65v */
+ .power_1 = 0x10,
+ /* 0x10 AVDD=vci*2, VGH=vci*7, VGL=-vci*4 */
+ .power_2 = 0x10,
+ /* 0x45 VCOMH 4.425v, 0x15 VCOML -1.975*/
+ .vcom_1 = {0x45, 0x15},
+ /* 0x90 offset voltage, VMH-48, VML-48 */
+ .vcom_2 = 0x90,
+ /* 0xc8 Row Address Order, Column Address Order
+ * BGR 1
+ */
+ .address_mode = 0xc8,
+ .g3amma_en = 0x00,
+ /* 0xc2
+ * Display Data Path: Memory
+ * RGB: DE mode
+ * DOTCLK polarity set (data fetched at the falling time)
+ */
+ .rgb_interface = ILI9341_RGB_DISP_PATH_MEM |
+ ILI9341_RGB_DE_MODE |
+ ILI9341_RGB_DPL,
+ /*
+ * 0x0a
+ * Gate outputs in non-display area: Interval scan
+ * Determine source/VCOM output in a non-display area in the partial
+ * display mode: AGND AGND AGND AGND
+ *
+ * 0xa7
+ * Scan Cycle: 15 frames
+ * fFLM = 60Hz: 255ms
+ * Liquid crystal type: Normally white
+ * Gate Output Scan Direction: G1 -> G320
+ * Source Output Scan Direction: S720 -> S1
+ *
+ * 0x27
+ * LCD Driver Line: 320 lines
+ *
+ * 0x04
+ * PCDIV: 4
+ */
+ .dfc_2 = {0x0a, 0xa7, 0x27, 0x04},
+ /* column address: 240 */
+ .column_addr = {0x00, 0x00, (ILI9341_COLUMN_ADDR >> 4) & 0xff,
+ ILI9341_COLUMN_ADDR & 0xff},
+ /* page address: 320 */
+ .page_addr = {0x00, 0x00, (ILI9341_PAGE_ADDR >> 4) & 0xff,
+ ILI9341_PAGE_ADDR & 0xff},
+ /* Memory write control: When the transfer number of data exceeds
+ * (EC-SC+1)*(EP-SP+1), the column and page number will be
+ * reset, and the exceeding data will be written into the following
+ * column and page.
+ * Display Operation Mode: RGB Interface Mode
+ * Interface for RAM Access: RGB interface
+ * 16- bit RGB interface (1 transfer/pixel)
+ */
+ .interface = {ILI9341_IF_WE_MODE, 0x00,
+ ILI9341_IF_DM_RGB | ILI9341_IF_RM_RGB},
+ /* DPI: 16 bits / pixel */
+ .pixel_format = ILI9341_PIXEL_DPI_16_BITS,
+ /* Curve Selected: Gamma curve 1 (G2.2) */
+ .gamma_curve = ILI9341_GAMMA_CURVE_1,
+ .pgamma = {0x0f, 0x29, 0x24, 0x0c, 0x0e,
+ 0x09, 0x4e, 0x78, 0x3c, 0x09,
+ 0x13, 0x05, 0x17, 0x11, 0x00},
+ .ngamma = {0x00, 0x16, 0x1b, 0x04, 0x11,
+ 0x07, 0x31, 0x33, 0x42, 0x05,
+ 0x0c, 0x0a, 0x28, 0x2f, 0x0f},
+};
+static inline struct ili9341 *panel_to_ili9341(struct drm_panel *panel)
+{
+ return container_of(panel, struct ili9341, panel);
+}
+
+int ili9341_spi_transfer(struct spi_device *spi, u32 speed_hz,
+ u8 bpw, const void *buf, size_t len)
+{
+ size_t max_chunk = spi_max_transfer_size(spi);
+ struct spi_transfer tr = {
+ .bits_per_word = bpw,
+ .speed_hz = speed_hz,
+ .len = len,
+ };
+ struct spi_message m;
+ size_t chunk;
+ int ret;
+
+ spi_message_init_with_transfers(&m, &tr, 1);
+
+ while (len) {
+ chunk = min(len, max_chunk);
+
+ tr.tx_buf = buf;
+ tr.len = chunk;
+ buf += chunk;
+ len -= chunk;
+
+ ret = spi_sync(spi, &m);
+ if (ret) {
+ dev_err(&spi->dev, "spi_sync error: %d\n", ret);
+ return ret;
+ }
+ }
+ return 0;
+}
+
+static int _ili9341_command(struct ili9341 *ili, u8 cmd, const void *data,
+ size_t count)
+{
+ struct spi_device *spi = to_spi_device(ili->dev);
+ int ret = 0;
+
+ gpiod_set_value_cansleep(ili->dc_gpio, 0);
+
+ ret = ili9341_spi_transfer(spi, ili->max_spi_speed, 8,
+ (const void *)&cmd, 1);
+ if (ret || data == NULL || count == 0)
+ return ret;
+
+ gpiod_set_value_cansleep(ili->dc_gpio, 1);
+
+ return ili9341_spi_transfer(spi, ili->max_spi_speed, 8,
+ data, count);
+}
+
+static int ili9341_dpi_init(struct ili9341 *ili)
+{
+ int ret;
+ ret = _ili9341_command(ili, 0xca,
+ ili->conf->ca,
+ ILI9341_CA_LEN);
+ if (ret)
+ return ret;
+
+ ret = _ili9341_command(ili, ILI9341_POWERB,
+ ili->conf->power_b,
+ ILI9341_POWER_B_LEN);
+ if (ret)
+ return ret;
+
+ ret = _ili9341_command(ili, ILI9341_POWER_SEQ,
+ ili->conf->power_seq,
+ ILI9341_POWER_SEQ_LEN);
+ if (ret)
+ return ret;
+
+ ret = _ili9341_command(ili, ILI9341_DTCA,
+ ili->conf->dtca,
+ ILI9341_DTCA_LEN);
+ if (ret)
+ return ret;
+
+ ret = _ili9341_command(ili, ILI9341_POWERA,
+ ili->conf->power_a,
+ ILI9341_POWER_A_LEN);
+ if (ret)
+ return ret;
+
+ ret = _ili9341_command(ili, ILI9341_PRC,
+ &ili->conf->prc,
+ 1);
+ if (ret)
+ return ret;
+
+ ret = _ili9341_command(ili, ILI9341_DTCB,
+ ili->conf->dtcb,
+ ILI9341_DTCB_LEN);
+ if (ret)
+ return ret;
+
+ ret = _ili9341_command(ili, ILI9341_FRC,
+ ili->conf->frc,
+ ILI9341_FRC_LEN);
+ if (ret)
+ return ret;
+
+ ret = _ili9341_command(ili, ILI9341_DFC,
+ ili->conf->dfc_1,
+ ILI9341_DFC_1_LEN);
+ if (ret)
+ return ret;
+
+ ret = _ili9341_command(ili, ILI9341_POWER1,
+ &ili->conf->power_1,
+ 1);
+ if (ret)
+ return ret;
+
+ ret = _ili9341_command(ili, ILI9341_POWER2,
+ &ili->conf->power_2,
+ 1);
+ if (ret)
+ return ret;
+
+ ret = _ili9341_command(ili, ILI9341_VCOM1,
+ ili->conf->vcom_1,
+ ILI9341_VCOM_1_LEN);
+ if (ret)
+ return ret;
+
+ ret = _ili9341_command(ili, ILI9341_VCOM2,
+ &ili->conf->vcom_2,
+ 1);
+ if (ret)
+ return ret;
+
+ ret = _ili9341_command(ili, MIPI_DCS_SET_ADDRESS_MODE,
+ &ili->conf->address_mode,
+ 1);
+ if (ret)
+ return ret;
+
+ ret = _ili9341_command(ili, ILI9341_3GAMMA_EN,
+ &ili->conf->g3amma_en,
+ 1);
+ if (ret)
+ return ret;
+
+ ret = _ili9341_command(ili, ILI9341_RGB_INTERFACE,
+ &ili->conf->rgb_interface,
+ 1);
+ if (ret)
+ return ret;
+
+ ret = _ili9341_command(ili, ILI9341_DFC,
+ ili->conf->dfc_2,
+ ILI9341_DFC_2_LEN);
+ if (ret)
+ return ret;
+
+ ret = _ili9341_command(ili, MIPI_DCS_SET_COLUMN_ADDRESS,
+ ili->conf->column_addr,
+ ILI9341_COLUMN_ADDR_LEN);
+ if (ret)
+ return ret;
+
+ ret = _ili9341_command(ili, MIPI_DCS_SET_PAGE_ADDRESS,
+ ili->conf->page_addr,
+ ILI9341_PAGE_ADDR_LEN);
+ if (ret)
+ return ret;
+
+ ret = _ili9341_command(ili, ILI9341_INTERFACE,
+ ili->conf->interface,
+ ILI9341_INTERFACE_LEN);
+ if (ret)
+ return ret;
+
+ ret = _ili9341_command(ili, MIPI_DCS_SET_PIXEL_FORMAT,
+ &ili->conf->pixel_format,
+ 1);
+ if (ret)
+ return ret;
+
+ ret = ili9341_command(ili, MIPI_DCS_WRITE_MEMORY_START);
+ if (ret)
+ return ret;
+
+ msleep(200);
+ ret = _ili9341_command(ili, MIPI_DCS_SET_GAMMA_CURVE,
+ &ili->conf->gamma_curve,
+ 1);
+ if (ret)
+ return ret;
+
+ ret = _ili9341_command(ili, ILI9341_PGAMMA,
+ ili->conf->pgamma,
+ ILI9341_PGAMMA_LEN);
+ if (ret)
+ return ret;
+
+ ret = _ili9341_command(ili, ILI9341_NGAMMA,
+ ili->conf->ngamma,
+ ILI9341_NGAMMA_LEN);
+ if (ret)
+ return ret;
+
+ ret = ili9341_command(ili, MIPI_DCS_EXIT_SLEEP_MODE);
+ if (ret)
+ return ret;
+
+ msleep(200);
+ ret = ili9341_command(ili, MIPI_DCS_SET_DISPLAY_ON);
+ if (ret)
+ return ret;
+
+ ret = ili9341_command(ili, MIPI_DCS_WRITE_MEMORY_START);
+ if (ret)
+ return ret;
+
+
+ dev_info(ili->dev, "initialized display rgb interface\n");
+
+ return 0;
+}
+
+static int ili9341_dpi_power_on(struct ili9341 *ili)
+{
+ int ret = 0;
+
+ /* Assert RESET */
+ gpiod_set_value(ili->reset_gpio, 1);
+
+ /* Enable power */
+ if (!IS_ERR(ili->vcc)) {
+ ret = regulator_enable(ili->vcc);
+ if (ret < 0) {
+ dev_err(ili->dev, "unable to enable vcc\n");
+ return ret;
+ }
+ }
+ msleep(20);
+
+ /* De-assert RESET */
+ gpiod_set_value(ili->reset_gpio, 0);
+ msleep(10);
+
+ return 0;
+}
+
+static int ili9341_dpi_power_off(struct ili9341 *ili)
+{
+ /* Assert RESET */
+ gpiod_set_value(ili->reset_gpio, 1);
+
+ /* Disable power */
+ if (!IS_ERR(ili->vcc))
+ return regulator_disable(ili->vcc);
+
+ return 0;
+}
+
+static int ili9341_dpi_disable(struct drm_panel *panel)
+{
+ struct ili9341 *ili = panel_to_ili9341(panel);
+
+ ili9341_command(ili, MIPI_DCS_SET_DISPLAY_OFF);
+
+ return 0;
+}
+
+static int ili9341_dpi_unprepare(struct drm_panel *panel)
+{
+ struct ili9341 *ili = panel_to_ili9341(panel);
+
+ return ili9341_dpi_power_off(ili);
+}
+
+static int ili9341_dpi_prepare(struct drm_panel *panel)
+{
+ struct ili9341 *ili = panel_to_ili9341(panel);
+ int ret;
+
+ ret = ili9341_dpi_power_on(ili);
+ if (ret < 0)
+ return ret;
+
+ ret = ili9341_dpi_init(ili);
+ if (ret < 0)
+ ili9341_dpi_unprepare(panel);
+
+ return ret;
+}
+
+static int ili9341_dpi_enable(struct drm_panel *panel)
+{
+ struct ili9341 *ili = panel_to_ili9341(panel);
+
+ ili9341_command(ili, MIPI_DCS_SET_DISPLAY_ON);
+
+ return 0;
+}
+
+static int ili9341_dpi_get_modes(struct drm_panel *panel,
+ struct drm_connector *connector)
+{
+ struct ili9341 *ili = panel_to_ili9341(panel);
+ struct drm_device *drm = connector->dev;
+ struct drm_display_mode *mode;
+ struct drm_display_info *info;
+
+ info = &connector->display_info;
+ info->width_mm = ili->conf->mode.width_mm;
+ info->height_mm = ili->conf->mode.height_mm;
+
+ if (ili->conf->rgb_interface & ILI9341_RGB_DPL)
+ info->bus_flags |= DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE;
+ else
+ info->bus_flags |= DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE;
+
+ if (ili->conf->rgb_interface & ILI9341_RGB_EPL)
+ info->bus_flags |= DRM_BUS_FLAG_DE_HIGH;
+ else
+ info->bus_flags |= DRM_BUS_FLAG_DE_LOW;
+
+ mode = drm_mode_duplicate(drm, &ili->conf->mode);
+ if (!mode) {
+ DRM_ERROR("bad mode or failed to add mode\n");
+ return -EINVAL;
+ }
+ drm_mode_set_name(mode);
+
+ /* Set up the polarity */
+ if (ili->conf->rgb_interface & ILI9341_RGB_HSPL)
+ mode->flags |= DRM_MODE_FLAG_PHSYNC;
+ else
+ mode->flags |= DRM_MODE_FLAG_NHSYNC;
+
+ if (ili->conf->rgb_interface & ILI9341_RGB_VSPL)
+ mode->flags |= DRM_MODE_FLAG_PVSYNC;
+ else
+ mode->flags |= DRM_MODE_FLAG_NVSYNC;
+
+ drm_mode_probed_add(connector, mode);
+
+ return 1; /* Number of modes */
+}
+
+static const struct drm_panel_funcs ili9341_dpi_funcs = {
+ .disable = ili9341_dpi_disable,
+ .unprepare = ili9341_dpi_unprepare,
+ .prepare = ili9341_dpi_prepare,
+ .enable = ili9341_dpi_enable,
+ .get_modes = ili9341_dpi_get_modes,
+};
+
+static int ili9341_dpi_probe(struct spi_device *spi)
+{
+ int ret;
+ struct device *dev = &spi->dev;
+ struct ili9341 *ili;
+
+ ili = devm_kzalloc(dev, sizeof(struct ili9341), GFP_KERNEL);
+ if (!ili)
+ return -ENOMEM;
+
+ spi_set_drvdata(spi, ili);
+
+ ili->dev = dev;
+ /*
+ * Every new incarnation of this display must have a unique
+ * data entry for the system in this driver.
+ */
+ ili->conf = of_device_get_match_data(dev);
+ if (!ili->conf) {
+ dev_err(dev, "missing device configuration\n");
+ return -ENODEV;
+ }
+
+ ili->vcc = devm_regulator_get_optional(dev, "vcc");
+ if (IS_ERR(ili->vcc))
+ dev_err(dev, "get optional vcc failed\n");
+
+ ili->reset_gpio = devm_gpiod_get_optional(dev, "reset",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(ili->reset_gpio)) {
+ dev_err(dev, "failed to get RESET GPIO\n");
+ return PTR_ERR(ili->reset_gpio);
+ }
+
+ ili->dc_gpio = devm_gpiod_get(dev, "dc", GPIOD_OUT_LOW);
+ if (IS_ERR(ili->dc_gpio)) {
+ dev_err(dev, "failed to get DC GPIO\n");
+ return PTR_ERR(ili->dc_gpio);
+ }
+
+ spi->bits_per_word = 8;
+ ret = spi_setup(spi);
+ if (ret < 0) {
+ dev_err(dev, "spi setup failed.\n");
+ return ret;
+ }
+
+ ili->max_spi_speed = ili->conf->max_spi_speed;
+
+ drm_panel_init(&ili->panel, dev, &ili9341_dpi_funcs,
+ DRM_MODE_CONNECTOR_DPI);
+
+ return drm_panel_add(&ili->panel);
+}
+
+
+
+static void ili9341_dbi_enable(struct drm_simple_display_pipe *pipe,
+ struct drm_crtc_state *crtc_state,
+ struct drm_plane_state *plane_state)
+{
+ struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev);
+ struct mipi_dbi *dbi = &dbidev->dbi;
+ u8 addr_mode;
+ int ret, idx;
+
+ if (!drm_dev_enter(pipe->crtc.dev, &idx))
+ return;
+
+ DRM_DEBUG_KMS("\n");
+
+ ret = mipi_dbi_poweron_conditional_reset(dbidev);
+ if (ret < 0)
+ goto out_exit;
+ if (ret == 1)
+ goto out_enable;
+
+ mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_OFF);
+
+ mipi_dbi_command(dbi, ILI9341_POWERB, 0x00, 0xc1, 0x30);
+ mipi_dbi_command(dbi, ILI9341_POWER_SEQ, 0x64, 0x03, 0x12, 0x81);
+ mipi_dbi_command(dbi, ILI9341_DTCA, 0x85, 0x00, 0x78);
+ mipi_dbi_command(dbi, ILI9341_POWERA, 0x39, 0x2c, 0x00, 0x34, 0x02);
+ mipi_dbi_command(dbi, ILI9341_PRC, ILI9341_DBI_PRC_NORMAL);
+ mipi_dbi_command(dbi, ILI9341_DTCB, 0x00, 0x00);
+
+ /* Power Control */
+ mipi_dbi_command(dbi, ILI9341_POWER1, ILI9341_DBI_VCOMH_4P6V);
+ mipi_dbi_command(dbi, ILI9341_POWER2, ILI9341_DBI_PWR_2_DEFAULT);
+ /* VCOM */
+ mipi_dbi_command(dbi, ILI9341_VCOM1, ILI9341_DBI_VCOM_1_VMH_4P25V,
+ ILI9341_DBI_VCOM_1_VML_1P5V);
+ mipi_dbi_command(dbi, ILI9341_VCOM2, ILI9341_DBI_VCOM_2_DEC_58);
+
+ /* Memory Access Control */
+ mipi_dbi_command(dbi, MIPI_DCS_SET_PIXEL_FORMAT,
+ MIPI_DCS_PIXEL_FMT_16BIT);
+
+ /* Frame Rate */
+ mipi_dbi_command(dbi, ILI9341_FRC, ILI9341_DBI_FRC_DIVA & 0x03,
+ ILI9341_DBI_FRC_RTNA & 0x1f);
+
+ /* Gamma */
+ mipi_dbi_command(dbi, ILI9341_3GAMMA_EN, 0x00);
+ mipi_dbi_command(dbi, MIPI_DCS_SET_GAMMA_CURVE, ILI9341_GAMMA_CURVE_1);
+ mipi_dbi_command(dbi, ILI9341_PGAMMA,
+ 0x0f, 0x31, 0x2b, 0x0c, 0x0e, 0x08, 0x4e, 0xf1,
+ 0x37, 0x07, 0x10, 0x03, 0x0e, 0x09, 0x00);
+ mipi_dbi_command(dbi, ILI9341_NGAMMA,
+ 0x00, 0x0e, 0x14, 0x03, 0x11, 0x07, 0x31, 0xc1,
+ 0x48, 0x08, 0x0f, 0x0c, 0x31, 0x36, 0x0f);
+
+ /* DDRAM */
+ mipi_dbi_command(dbi, ILI9341_ETMOD, ILI9341_DBI_EMS_GAS |
+ ILI9341_DBI_EMS_DTS |
+ ILI9341_DBI_EMS_GON);
+
+ /* Display */
+ mipi_dbi_command(dbi, ILI9341_DFC, 0x08, 0x82, 0x27, 0x00);
+ mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE);
+ msleep(100);
+
+ mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON);
+ msleep(100);
+
+out_enable:
+ switch (dbidev->rotation) {
+ default:
+ addr_mode = ILI9341_MADCTL_MX;
+ break;
+ case 90:
+ addr_mode = ILI9341_MADCTL_MV;
+ break;
+ case 180:
+ addr_mode = ILI9341_MADCTL_MY;
+ break;
+ case 270:
+ addr_mode = ILI9341_MADCTL_MV | ILI9341_MADCTL_MY |
+ ILI9341_MADCTL_MX;
+ break;
+ }
+ addr_mode |= ILI9341_MADCTL_BGR;
+ mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode);
+ mipi_dbi_enable_flush(dbidev, crtc_state, plane_state);
+ DRM_DEBUG_KMS("initialized display serial interface\n");
+out_exit:
+ drm_dev_exit(idx);
+}
+
+static const struct drm_simple_display_pipe_funcs ili9341_dbi_funcs = {
+ .enable = ili9341_dbi_enable,
+ .disable = mipi_dbi_pipe_disable,
+ .update = mipi_dbi_pipe_update,
+ .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb,
+};
+
+static const struct drm_display_mode ili9341_dbi_mode = {
+ DRM_SIMPLE_MODE(240, 320, 37, 49),
+};
+
+DEFINE_DRM_GEM_CMA_FOPS(ili9341_dbi_fops);
+
+static struct drm_driver ili9341_dbi_driver = {
+ .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
+ .fops = &ili9341_dbi_fops,
+ .release = mipi_dbi_release,
+ DRM_GEM_CMA_VMAP_DRIVER_OPS,
+ .debugfs_init = mipi_dbi_debugfs_init,
+ .name = "ili9341",
+ .desc = "Ilitek ILI9341",
+ .date = "20180514",
+ .major = 1,
+ .minor = 0,
+};
+static int ili9341_dbi_probe(struct spi_device *spi)
+{
+ struct mipi_dbi_dev *dbidev;
+ struct drm_device *drm;
+ struct mipi_dbi *dbi;
+ struct gpio_desc *dc;
+ struct device *dev = &spi->dev;
+ u32 rotation = 0;
+ int ret;
+
+ dbidev = kzalloc(sizeof(*dbidev), GFP_KERNEL);
+ if (!dbidev)
+ return -ENOMEM;
+
+ dbi = &dbidev->dbi;
+ drm = &dbidev->drm;
+ ret = devm_drm_dev_init(dev, drm, &ili9341_dbi_driver);
+ if (ret) {
+ kfree(dbidev);
+ return ret;
+ }
+
+ drm_mode_config_init(drm);
+
+ dbi->reset = devm_gpiod_get_optional(dev, "reset",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(dbi->reset)) {
+ DRM_DEV_ERROR(dev, "Failed to get gpio 'reset'\n");
+ return PTR_ERR(dbi->reset);
+ }
+
+ dc = devm_gpiod_get_optional(dev, "dc", GPIOD_OUT_LOW);
+ if (IS_ERR(dc)) {
+ DRM_DEV_ERROR(dev, "Failed to get gpio 'dc'\n");
+ return PTR_ERR(dc);
+ }
+
+ dbidev->regulator = devm_regulator_get_optional(dev, "vcc");
+ if (IS_ERR(dbidev->regulator))
+ dev_err(dev, "get optional vcc failed\n");
+
+ dbidev->backlight = devm_of_find_backlight(dev);
+ if (IS_ERR(dbidev->backlight))
+ return PTR_ERR(dbidev->backlight);
+
+ device_property_read_u32(dev, "rotation", &rotation);
+
+ ret = mipi_dbi_spi_init(spi, dbi, dc);
+ if (ret)
+ return ret;
+
+ ret = mipi_dbi_dev_init(dbidev, &ili9341_dbi_funcs,
+ &ili9341_dbi_mode, rotation);
+ if (ret)
+ return ret;
+
+ drm_mode_config_reset(drm);
+
+ ret = drm_dev_register(drm, 0);
+ if (ret)
+ return ret;
+
+ spi_set_drvdata(spi, drm);
+
+ drm_fbdev_generic_setup(drm, 0);
+
+ return 0;
+}
+static int ili9341_probe(struct spi_device *spi)
+{
+ const struct spi_device_id *id = spi_get_device_id(spi);
+
+ if (!strcmp(id->name, "sf-tc240t-9370-t"))
+ return ili9341_dpi_probe(spi);
+ else if (!strcmp(id->name, "yx240qv29"))
+ return ili9341_dbi_probe(spi);
+
+ return -1;
+}
+
+static int ili9341_remove(struct spi_device *spi)
+{
+ const struct spi_device_id *id = spi_get_device_id(spi);
+ struct ili9341 *ili = spi_get_drvdata(spi);
+ struct drm_device *drm = spi_get_drvdata(spi);
+
+ if (!strcmp(id->name, "sf-tc240t-9370-t")) {
+ ili9341_dpi_power_off(ili);
+ drm_panel_remove(&ili->panel);
+ } else if (!strcmp(id->name, "yx240qv29")) {
+ drm_dev_unplug(drm);
+ drm_atomic_helper_shutdown(drm);
+ }
+ return 0;
+}
+
+static void ili9341_shutdown(struct spi_device *spi)
+{
+ const struct spi_device_id *id = spi_get_device_id(spi);
+
+ if (!strcmp(id->name, "yx240qv29"))
+ drm_atomic_helper_shutdown(spi_get_drvdata(spi));
+}
+
+static const struct of_device_id ili9341_of_match[] = {
+ {
+ .compatible = "st,sf-tc240t-9370-t",
+ .data = &ili9341_stm32f429_disco_data,
+ },
+ {
+ /* porting from tiny/ili9341.c
+ * for original mipi dbi compitable
+ */
+ .compatible = "adafruit,yx240qv29",
+ .data = NULL,
+ },
+};
+MODULE_DEVICE_TABLE(of, ili9341_of_match);
+
+static const struct spi_device_id ili9341_id[] = {
+ { "yx240qv29", 0 },
+ { "sf-tc240t-9370-t", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, ili9341_id);
+
+static struct spi_driver ili9341_driver = {
+ .probe = ili9341_probe,
+ .remove = ili9341_remove,
+ .shutdown = ili9341_shutdown,
+ .id_table = ili9341_id,
+ .driver = {
+ .name = "panel-ilitek-ili9341",
+ .of_match_table = ili9341_of_match,
+ },
+};
+module_spi_driver(ili9341_driver);
+
+MODULE_AUTHOR("Dillon Min <dillon.minfei@gmail.com>");
+MODULE_DESCRIPTION("ILI9341 LCD panel driver");
+MODULE_LICENSE("GPL v2");
--
2.7.4
^ permalink raw reply related
* [PATCH v5 5/8] clk: stm32: Fix stm32f429's ltdc driver hang in set clock rate, fix duplicated ltdc clock register to 'clk_core' case ltdc's clock turn off by clk_disable_unused()
From: dillon.minfei @ 2020-05-25 3:40 UTC (permalink / raw)
To: robh+dt, p.zabel, mcoquelin.stm32, alexandre.torgue,
thierry.reding, sam, airlied, daniel, mturquette, sboyd
Cc: devicetree, linux-arm-kernel, linux-kernel, linux-spi,
linux-stm32, dri-devel, linux-clk, dillon min
In-Reply-To: <1590378062-7965-1-git-send-email-dillon.minfei@gmail.com>
From: dillon min <dillon.minfei@gmail.com>
ltdc set clock rate crashed
'post_div_data[]''s pll_num is PLL_I2S, PLL_SAI (number is 1,2). but,
as pll_num is offset of 'clks[]' input to clk_register_pll_div(), which
is FCLK, CLK_LSI, defined in 'include/dt-bindings/clock/stm32fx-clock.h'
so, this is a null object at the register time.
then, in ltdc's clock is_enabled(), enable(), will call to_clk_gate().
will return a null object, cause kernel crashed.
need change pll_num to PLL_VCO_I2S, PLL_VCO_SAI for 'post_div_data[]'
duplicated ltdc clock
'stm32f429_gates[]' has a member 'ltdc' register to 'clk_core', but no
upper driver use it, ltdc driver use the lcd-tft defined in
'stm32f429_aux_clk[]'. after system startup, as stm32f429_gates[]'s ltdc
enable_count is zero, so turn off by clk_disable_unused()
Changes since V3:
1 drop last wrong changes about 'CLK_IGNORE_UNUSED' patch
2 fix PLL_SAI mismatch with PLL_VCO_SAI
Signed-off-by: dillon min <dillon.minfei@gmail.com>
---
drivers/clk/clk-stm32f4.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/drivers/clk/clk-stm32f4.c b/drivers/clk/clk-stm32f4.c
index 18117ce..fa62e99 100644
--- a/drivers/clk/clk-stm32f4.c
+++ b/drivers/clk/clk-stm32f4.c
@@ -129,7 +129,6 @@ static const struct stm32f4_gate_data stm32f429_gates[] __initconst = {
{ STM32F4_RCC_APB2ENR, 20, "spi5", "apb2_div" },
{ STM32F4_RCC_APB2ENR, 21, "spi6", "apb2_div" },
{ STM32F4_RCC_APB2ENR, 22, "sai1", "apb2_div" },
- { STM32F4_RCC_APB2ENR, 26, "ltdc", "apb2_div" },
};
static const struct stm32f4_gate_data stm32f469_gates[] __initconst = {
@@ -557,13 +556,13 @@ static const struct clk_div_table post_divr_table[] = {
#define MAX_POST_DIV 3
static const struct stm32f4_pll_post_div_data post_div_data[MAX_POST_DIV] = {
- { CLK_I2SQ_PDIV, PLL_I2S, "plli2s-q-div", "plli2s-q",
+ { CLK_I2SQ_PDIV, PLL_VCO_I2S, "plli2s-q-div", "plli2s-q",
CLK_SET_RATE_PARENT, STM32F4_RCC_DCKCFGR, 0, 5, 0, NULL},
- { CLK_SAIQ_PDIV, PLL_SAI, "pllsai-q-div", "pllsai-q",
+ { CLK_SAIQ_PDIV, PLL_VCO_SAI, "pllsai-q-div", "pllsai-q",
CLK_SET_RATE_PARENT, STM32F4_RCC_DCKCFGR, 8, 5, 0, NULL },
- { NO_IDX, PLL_SAI, "pllsai-r-div", "pllsai-r", CLK_SET_RATE_PARENT,
+ { NO_IDX, PLL_VCO_SAI, "pllsai-r-div", "pllsai-r", CLK_SET_RATE_PARENT,
STM32F4_RCC_DCKCFGR, 16, 2, 0, post_divr_table },
};
--
2.7.4
^ permalink raw reply related
* [PATCH v5 4/8] dt-bindings: display: panel: Add ilitek ili9341 panel bindings
From: dillon.minfei @ 2020-05-25 3:40 UTC (permalink / raw)
To: robh+dt, p.zabel, mcoquelin.stm32, alexandre.torgue,
thierry.reding, sam, airlied, daniel, mturquette, sboyd
Cc: devicetree, linux-arm-kernel, linux-kernel, linux-spi,
linux-stm32, dri-devel, linux-clk, dillon min
In-Reply-To: <1590378062-7965-1-git-send-email-dillon.minfei@gmail.com>
From: dillon min <dillon.minfei@gmail.com>
Add documentation for "ilitek,ili9341" panel.
Signed-off-by: dillon min <dillon.minfei@gmail.com>
---
.../bindings/display/panel/ilitek,ili9341.yaml | 69 ++++++++++++++++++++++
1 file changed, 69 insertions(+)
create mode 100644 Documentation/devicetree/bindings/display/panel/ilitek,ili9341.yaml
diff --git a/Documentation/devicetree/bindings/display/panel/ilitek,ili9341.yaml b/Documentation/devicetree/bindings/display/panel/ilitek,ili9341.yaml
new file mode 100644
index 0000000..2172f88
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/ilitek,ili9341.yaml
@@ -0,0 +1,69 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/ilitek,ili9341.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Ilitek-9341 Display Panel
+
+maintainers:
+ - Dillon Min <dillon.minfei@gmail.com>
+
+description: |
+ Ilitek ILI9341 TFT panel driver with SPI control bus
+ This is a driver for 320x240 TFT panels, accepting a rgb input
+ streams with 16 bits or 18 bits.
+
+allOf:
+ - $ref: panel-common.yaml#
+
+properties:
+ compatible:
+ items:
+ - enum:
+ # ili9341 240*320 Color on stm32f429-disco board
+ - st,sf-tc240t-9370-t
+ - const: ilitek,ili9341
+
+ reg: true
+
+ dc-gpios:
+ maxItems: 1
+ description: Display data/command selection (D/CX)
+
+ spi-3wire: true
+
+ spi-max-frequency:
+ const: 10000000
+
+ port: true
+
+additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - dc-gpios
+ - port
+
+examples:
+ - |+
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ panel: display@0 {
+ compatible = "st,sf-tc240t-9370-t",
+ "ilitek,ili9341";
+ reg = <0>;
+ spi-3wire;
+ spi-max-frequency = <10000000>;
+ dc-gpios = <&gpiod 13 0>;
+ port {
+ panel_in: endpoint {
+ remote-endpoint = <&display_out>;
+ };
+ };
+ };
+ };
+...
+
--
2.7.4
^ permalink raw reply related
* [PATCH v5 3/8] ARM: dts: stm32: enable ltdc binding with ili9341, gyro l3gd20 on stm32429-disco board
From: dillon.minfei @ 2020-05-25 3:40 UTC (permalink / raw)
To: robh+dt, p.zabel, mcoquelin.stm32, alexandre.torgue,
thierry.reding, sam, airlied, daniel, mturquette, sboyd
Cc: devicetree, linux-arm-kernel, linux-kernel, linux-spi,
linux-stm32, dri-devel, linux-clk, dillon min
In-Reply-To: <1590378062-7965-1-git-send-email-dillon.minfei@gmail.com>
From: dillon min <dillon.minfei@gmail.com>
Enable the ltdc & ili9341, gyro l3gd20 on stm32429-disco board.
Signed-off-by: dillon min <dillon.minfei@gmail.com>
---
arch/arm/boot/dts/stm32f429-disco.dts | 48 +++++++++++++++++++++++++++++++++++
1 file changed, 48 insertions(+)
diff --git a/arch/arm/boot/dts/stm32f429-disco.dts b/arch/arm/boot/dts/stm32f429-disco.dts
index 30c0f67..365d16f 100644
--- a/arch/arm/boot/dts/stm32f429-disco.dts
+++ b/arch/arm/boot/dts/stm32f429-disco.dts
@@ -49,6 +49,8 @@
#include "stm32f429.dtsi"
#include "stm32f429-pinctrl.dtsi"
#include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/gpio/gpio.h>
/ {
model = "STMicroelectronics STM32F429i-DISCO board";
@@ -127,3 +129,49 @@
pinctrl-names = "default";
status = "okay";
};
+
+<dc {
+ status = "okay";
+ pinctrl-0 = <<dc_pins_f429_disco>;
+ pinctrl-names = "default";
+
+ port {
+ ltdc_out_rgb: endpoint {
+ remote-endpoint = <&panel_in_rgb>;
+ };
+ };
+};
+
+&spi5 {
+ status = "okay";
+ pinctrl-0 = <&spi5_pins>;
+ pinctrl-names = "default";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cs-gpios = <&gpioc 1 GPIO_ACTIVE_LOW>, <&gpioc 2 GPIO_ACTIVE_LOW>;
+
+ l3gd20: l3gd20@0 {
+ compatible = "st,l3gd20-gyro";
+ spi-max-frequency = <10000000>;
+ st,drdy-int-pin = <2>;
+ interrupt-parent = <&gpioa>;
+ interrupts = <1 IRQ_TYPE_EDGE_RISING>,
+ <2 IRQ_TYPE_EDGE_RISING>;
+ reg = <0>;
+ status = "okay";
+ };
+
+ display: display@1{
+ /* Connect panel-ilitek-9341 to ltdc */
+ compatible = "st,sf-tc240t-9370-t";
+ reg = <1>;
+ spi-3wire;
+ spi-max-frequency = <10000000>;
+ dc-gpios = <&gpiod 13 0>;
+ port {
+ panel_in_rgb: endpoint {
+ remote-endpoint = <<dc_out_rgb>;
+ };
+ };
+ };
+};
--
2.7.4
^ permalink raw reply related
* [PATCH v5 2/8] ARM: dts: stm32: Add pin map for ltdc & spi5 on stm32f429-disco board
From: dillon.minfei @ 2020-05-25 3:40 UTC (permalink / raw)
To: robh+dt, p.zabel, mcoquelin.stm32, alexandre.torgue,
thierry.reding, sam, airlied, daniel, mturquette, sboyd
Cc: devicetree, linux-arm-kernel, linux-kernel, linux-spi,
linux-stm32, dri-devel, linux-clk, dillon min
In-Reply-To: <1590378062-7965-1-git-send-email-dillon.minfei@gmail.com>
From: dillon min <dillon.minfei@gmail.com>
This patch adds the pin configuration for ltdc and spi5 controller
on stm32f429-disco board.
Signed-off-by: dillon min <dillon.minfei@gmail.com>
---
arch/arm/boot/dts/stm32f4-pinctrl.dtsi | 67 ++++++++++++++++++++++++++++++++++
1 file changed, 67 insertions(+)
diff --git a/arch/arm/boot/dts/stm32f4-pinctrl.dtsi b/arch/arm/boot/dts/stm32f4-pinctrl.dtsi
index 392fa14..0eb107f 100644
--- a/arch/arm/boot/dts/stm32f4-pinctrl.dtsi
+++ b/arch/arm/boot/dts/stm32f4-pinctrl.dtsi
@@ -316,6 +316,73 @@
};
};
+ ltdc_pins_f429_disco: ltdc-1 {
+ pins {
+ pinmux = <STM32_PINMUX('C', 6, AF14)>,
+ /* LCD_HSYNC */
+ <STM32_PINMUX('A', 4, AF14)>,
+ /* LCD_VSYNC */
+ <STM32_PINMUX('G', 7, AF14)>,
+ /* LCD_CLK */
+ <STM32_PINMUX('C', 10, AF14)>,
+ /* LCD_R2 */
+ <STM32_PINMUX('B', 0, AF9)>,
+ /* LCD_R3 */
+ <STM32_PINMUX('A', 11, AF14)>,
+ /* LCD_R4 */
+ <STM32_PINMUX('A', 12, AF14)>,
+ /* LCD_R5 */
+ <STM32_PINMUX('B', 1, AF9)>,
+ /* LCD_R6*/
+ <STM32_PINMUX('G', 6, AF14)>,
+ /* LCD_R7 */
+ <STM32_PINMUX('A', 6, AF14)>,
+ /* LCD_G2 */
+ <STM32_PINMUX('G', 10, AF9)>,
+ /* LCD_G3 */
+ <STM32_PINMUX('B', 10, AF14)>,
+ /* LCD_G4 */
+ <STM32_PINMUX('D', 6, AF14)>,
+ /* LCD_B2 */
+ <STM32_PINMUX('G', 11, AF14)>,
+ /* LCD_B3*/
+ <STM32_PINMUX('B', 11, AF14)>,
+ /* LCD_G5 */
+ <STM32_PINMUX('C', 7, AF14)>,
+ /* LCD_G6 */
+ <STM32_PINMUX('D', 3, AF14)>,
+ /* LCD_G7 */
+ <STM32_PINMUX('G', 12, AF9)>,
+ /* LCD_B4 */
+ <STM32_PINMUX('A', 3, AF14)>,
+ /* LCD_B5 */
+ <STM32_PINMUX('B', 8, AF14)>,
+ /* LCD_B6 */
+ <STM32_PINMUX('B', 9, AF14)>,
+ /* LCD_B7 */
+ <STM32_PINMUX('F', 10, AF14)>;
+ /* LCD_DE */
+ slew-rate = <2>;
+ };
+ };
+
+ spi5_pins: spi5-0 {
+ pins1 {
+ pinmux = <STM32_PINMUX('F', 7, AF5)>,
+ /* SPI5_CLK */
+ <STM32_PINMUX('F', 9, AF5)>;
+ /* SPI5_MOSI */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <0>;
+ };
+ pins2 {
+ pinmux = <STM32_PINMUX('F', 8, AF5)>;
+ /* SPI5_MISO */
+ bias-disable;
+ };
+ };
+
dcmi_pins: dcmi-0 {
pins {
pinmux = <STM32_PINMUX('A', 4, AF13)>, /* DCMI_HSYNC */
--
2.7.4
^ permalink raw reply related
* [PATCH v5 1/8] ARM: dts: stm32: Add dma config for spi5
From: dillon.minfei @ 2020-05-25 3:40 UTC (permalink / raw)
To: robh+dt, p.zabel, mcoquelin.stm32, alexandre.torgue,
thierry.reding, sam, airlied, daniel, mturquette, sboyd
Cc: devicetree, linux-arm-kernel, linux-kernel, linux-spi,
linux-stm32, dri-devel, linux-clk, dillon min
In-Reply-To: <1590378062-7965-1-git-send-email-dillon.minfei@gmail.com>
From: dillon min <dillon.minfei@gmail.com>
Enable spi5's dma configuration. for graphics data output to
ilitek ili9341 panel via mipi dbi interface
Signed-off-by: dillon min <dillon.minfei@gmail.com>
---
arch/arm/boot/dts/stm32f429.dtsi | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/arm/boot/dts/stm32f429.dtsi b/arch/arm/boot/dts/stm32f429.dtsi
index d777069..5820b11 100644
--- a/arch/arm/boot/dts/stm32f429.dtsi
+++ b/arch/arm/boot/dts/stm32f429.dtsi
@@ -660,6 +660,9 @@
reg = <0x40015000 0x400>;
interrupts = <85>;
clocks = <&rcc 0 STM32F4_APB2_CLOCK(SPI5)>;
+ dmas = <&dma2 3 2 0x400 0x0>,
+ <&dma2 4 2 0x400 0x0>;
+ dma-names = "rx", "tx";
status = "disabled";
};
--
2.7.4
^ permalink raw reply related
* [PATCH v5 0/8] Enable ili9341 and l3gd20 on stm32f429-disco
From: dillon.minfei @ 2020-05-25 3:40 UTC (permalink / raw)
To: robh+dt, p.zabel, mcoquelin.stm32, alexandre.torgue,
thierry.reding, sam, airlied, daniel, mturquette, sboyd
Cc: devicetree, linux-arm-kernel, linux-kernel, linux-spi,
linux-stm32, dri-devel, linux-clk, dillon min
In-Reply-To: <broonie@kernel.org>
From: dillon min <dillon.minfei@gmail.com>
V5's update based on Mark Brown's suggestion, use 'SPI_MASTER_MUST_RX'
for SPI_SIMPLEX_RX mode on stm32 spi controller.
V5:
1 instead of add send dummy data out under SIMPLEX_RX mode,
add flags 'SPI_CONTROLLER_MUST_TX' for stm32 spi driver
2 bypass 'SPI_CONTROLLER_MUST_TX' and 'SPI_CONTROLLER_MUST_RX' under
'SPI_3WIRE' mode
V4:
According to alexandre torgue's suggestion, combine ili9341 and
l3gd20's modification on stm32f429-disco board to one patchset.
Changes:
ili9341:
1 update ili9341 panel driver according to Linus's suggestion
2 drop V1's No.5 patch, sumbit new changes for clk-stm32f4
3 merge l3gd20's change to this patchset
V3:
1 merge original tiny/ili9341.c driver to panel/panel-ilitek-ili9341.c
to support serial spi & parallel rgb interface in one driver.
2 update ilitek,ili9341.yaml dts binding documentation.
3 update stm32f429-disco dts binding
V2:
1 verify ilitek,ili9341.yaml with make O=../linux-stm32
dt_binding_check
DT_SCHEMA_FILES=Documentation/devicetree/bindings/display/panel/
ilitek,ili9341.yaml
V1:
1 add ili9341 drm panel driver
2 add ltdc, spi5 controller for stm32f429-disco
3 add ltdc, spi5 pin map for stm32f429-disco
4 add docs about ili9341
5 fix ltdc driver loading hang in clk set rate bug
L3gd20:
V3:
1 merge stm32f429-disco dtbs binding with ili9341 part
V2:
1 insert blank line at stm32f420-disco.dts line 143
2 add more description for l3gd20 in commit message
V1:
1 enable spi5 controller on stm32f429-disco (dts)
2 add spi5 pinmap for stm32f429-disco (dts)
3 add SPI_SIMPLEX_RX, SPI_3WIRE_RX support for stm32f4
dillon min (8):
ARM: dts: stm32: Add dma config for spi5
ARM: dts: stm32: Add pin map for ltdc & spi5 on stm32f429-disco board
ARM: dts: stm32: enable ltdc binding with ili9341, gyro l3gd20 on
stm32429-disco board
dt-bindings: display: panel: Add ilitek ili9341 panel bindings
clk: stm32: Fix stm32f429's ltdc driver hang in set clock rate,
fix duplicated ltdc clock register to 'clk_core' case ltdc's clock
turn off by clk_disable_unused()
drm/panel: Add ilitek ili9341 panel driver
spi: stm32: Add 'SPI_SIMPLEX_RX', 'SPI_3WIRE_RX' support for stm32f4
spi: flags 'SPI_CONTROLLER_MUST_RX' and 'SPI_CONTROLLER_MUST_TX' can't
be coexit with 'SPI_3WIRE' mode
.../bindings/display/panel/ilitek,ili9341.yaml | 69 ++
arch/arm/boot/dts/stm32f4-pinctrl.dtsi | 67 +
arch/arm/boot/dts/stm32f429-disco.dts | 48 +
arch/arm/boot/dts/stm32f429.dtsi | 3 +
drivers/clk/clk-stm32f4.c | 7 +-
drivers/gpu/drm/panel/Kconfig | 12 +
drivers/gpu/drm/panel/Makefile | 1 +
drivers/gpu/drm/panel/panel-ilitek-ili9341.c | 1301 ++++++++++++++++++++
drivers/spi/spi-stm32.c | 19 +-
drivers/spi/spi.c | 3 +-
10 files changed, 1521 insertions(+), 9 deletions(-)
create mode 100644 Documentation/devicetree/bindings/display/panel/ilitek,ili9341.yaml
create mode 100644 drivers/gpu/drm/panel/panel-ilitek-ili9341.c
--
2.7.4
^ permalink raw reply
* Re: [PATCH v5 03/14] PCI: cadence: Convert all r/w accessors to perform only 32-bit accesses
From: Kishon Vijay Abraham I @ 2020-05-25 3:30 UTC (permalink / raw)
To: Rob Herring
Cc: Tom Joseph, Lorenzo Pieralisi, Bjorn Helgaas, PCI,
linux-kernel@vger.kernel.org, Arnd Bergmann, Greg Kroah-Hartman,
devicetree, linux-omap,
moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
In-Reply-To: <CAL_JsqJjXUUgTbSAi83w4Eie-sVTrkLLMGh_PRQsd8k2vuua4Q@mail.gmail.com>
Hi Rob,
On 5/22/2020 9:24 PM, Rob Herring wrote:
> On Thu, May 21, 2020 at 9:37 PM Kishon Vijay Abraham I <kishon@ti.com> wrote:
>>
>> Certain platforms like TI's J721E using Cadence PCIe IP can perform only
>> 32-bit accesses for reading or writing to Cadence registers. Convert all
>> read and write accesses to 32-bit in Cadence PCIe driver in preparation
>> for adding PCIe support in TI's J721E SoC.
>
> Looking more closely I don't think cdns_pcie_ep_assert_intx is okay
> with this and never can be given the PCI_COMMAND and PCI_STATUS
> registers are in the same word (IIRC, that's the main reason 32-bit
> config space accesses are broken). So this isn't going to work at
right, PCI_STATUS has write '1' to clear bits and there's a chance that it
could be reset while raising legacy interrupt. While this cannot be avoided for
TI's J721E, other platforms doesn't have to have this limitation.
> least for EP accesses. And maybe you need a custom .raise_irq() hook
> to minimize any problems (such as making the RMW atomic at least from
> the endpoint's perspective).
This is to make sure EP doesn't update in-consistent state when RC is updating
the PCI_STATUS register? Since this involves two different systems, how do we
make this atomic?
Thanks
Kishon
^ permalink raw reply
* RE: [EXT] Re: [PATCH net 2/4] dt-bindings: fec: update the gpr property
From: Andy Duan @ 2020-05-25 3:16 UTC (permalink / raw)
To: Fuzzey, Martin
Cc: David S. Miller, netdev@vger.kernel.org, Rob Herring, Shawn Guo,
devicetree@vger.kernel.org
In-Reply-To: <CANh8QzxfVtk+3N=5UttjXK6CR9ZQ=qD-Twu7y-zKabLJZGQ2yQ@mail.gmail.com>
From: Fuzzey, Martin <martin.fuzzey@flowbird.group> Sent: Saturday, May 23, 2020 6:16 PM
> > - gpr: phandle of SoC general purpose register mode. Required for
> > wake on LAN
> > - on some SoCs
> > + on some SoCs. Register bits of stop mode control, the format is
> > + <&gpr req_gpr req_bit>.
> > + gpr is the phandle to general purpose register node.
> > + req_gpr is the gpr register offset for ENET stop request.
> > + req_bit is the gpr bit offset for ENET stop request.
> >
>
> More of a DT binding changes policy question, do we care about supporting
> the old no argument binding too?
>
> I don't think it actually matters seeing as the no argument gpr node binding
> was only added recently anyway.
> But it was backported to the stable trees and Documentation/bindings/ABI.txt
> says
>
> "Bindings can be augmented, but the driver shouldn't break when given
> the old binding. ie. add additional properties, but don't change the
> meaning of an existing property. For drivers, default to the original
> behaviour when a newly added property is missing."
>
> Myself I think this is overkill in this case and am fine with just changing the
> binding without the driver handling the old case but that's Rob's call to make I
> think.
The patch set is to add argument binding, and driver also doesn't support wol
without argument binding.
As you know, current driver only wol feature requests the property.
I am not understand why we need to support the old without argument binding.
Welcome to your suggestion for the solution.
And 'gpr' string is not good description for stop mode, I will change it to the string:
' fsl,stop-mode'.
^ permalink raw reply
* RE: [EXT] Re: [PATCH net 1/4] net: ethernet: fec: move GPR register offset and bit into DT
From: Andy Duan @ 2020-05-25 2:36 UTC (permalink / raw)
To: Fuzzey, Martin
Cc: David S. Miller, netdev@vger.kernel.org, Rob Herring, Shawn Guo,
devicetree@vger.kernel.org
In-Reply-To: <CANh8QzxuHAu+L0swPC5V4Oca21Z5zpiULTm22VPShX_T-JVznQ@mail.gmail.com>
From: Fuzzey, Martin <martin.fuzzey@flowbird.group> Sent: Saturday, May 23, 2020 5:56 PM
> Hi Andy,
>
> > Fixes: da722186f654(net: fec: set GPR bit on suspend by DT
> > configuration)
>
> Just a nitpick maybe but I don't really think this need as Fixes: tag.
> That commit didn't actually *break* anything AFAIK.
> It added WoL support for *some* SoCs that didn't have any in mainline and
> didn't hurt the others.
> Of course it turned out to be insufficient for the multiple FEC case so this
> patch series is a welcome improvement.
Sorry, not to hurt you intentionally, I think the commit da722186f654 break multiple instances.
Totally I accept your suggestion, it should be improvement !
>
>
> > struct fec_devinfo {
> > u32 quirks;
> > - u8 stop_gpr_reg;
> > - u8 stop_gpr_bit;
> > };
>
> This structure has become redundant now that it only contains a single
> u32 quirks field.
> So we *could* go back to storing the quirks bitmask directly in .driver_data as
> was done before.
>
> It's a slight wastage to keep the, now unnecessary, indirection, though the
> size impact is small and it's only used at probe() time not on a hot path.
>
> But switching back could be seen as code churn too...
>
> I don't have a strong opinion on this, so just noting it to see what others think.
>
> Martin
To make code clean, we should switch back. I will change it in V2.
Thanks again for your review.
^ permalink raw reply
* RE: [EXT] Re: [PATCH net 3/4] ARM: dts: imx6: update fec gpr property to match new format
From: Andy Duan @ 2020-05-25 2:32 UTC (permalink / raw)
To: Andrew Lunn, Fuzzey, Martin
Cc: David S. Miller, netdev@vger.kernel.org, robh+dt@kernel.org,
shawnguo@kernel.org, devicetree@vger.kernel.org
In-Reply-To: <20200522235016.GB722786@lunn.ch>
From: Andrew Lunn <andrew@lunn.ch> Sent: Saturday, May 23, 2020 7:50 AM
> > Yes, I don't think anyone is saying otherwise.
>
> Correct.
>
> >
> > The problem is just that there are already .dtsi files for i.MX chips
> > having multiple ethernet interfaces in the mainline kernel (at least
> > imx6ui.dtsi, imx6sx.dts, imx7d.dtsi)
>
> Vybrid is one i use a lot with two FECs.
>
> > but that this patch series does not
> > modify those files to use the new DT format.
> >
> > It currently only modifies the dts files that are already supported by
> > hardcoded values in the driver.
>
> Exactly. This patch set itself adds nothing we don't already support.
> So the patch set as is, is pointless.
>
> > As to not knowing which instance it shouldn't matter.
> > The base dtsi can declare both/all ethernet interfaces with the
> > appropriate GPR bits.
>
> I fully agree. All it needs for this patchset to be merged is another patch which
> adds GPR properties to all SoC .dtsi files where appropriate, and optionally to
> a couple of reference designs which support WoL on their ports.
>
> Andrew
Okay, I will add imx6ul/imx6sx/imx7d/imx8mq/imx8mm/imx8mn dts change
into the patch set in v2 version. (before, I plan to submit another patch for them
once the patch set is accepted).
^ permalink raw reply
* RE: [EXT] Re: [PATCH net 3/4] ARM: dts: imx6: update fec gpr property to match new format
From: Andy Duan @ 2020-05-25 2:29 UTC (permalink / raw)
To: Fuzzey, Martin
Cc: Andrew Lunn, David S. Miller, netdev@vger.kernel.org,
robh+dt@kernel.org, shawnguo@kernel.org,
devicetree@vger.kernel.org
In-Reply-To: <CANh8QzwxfnQ1cACz=6dhYujEVtQoTCw8kTgkHi9BnxESptL=xQ@mail.gmail.com>
From: Fuzzey, Martin <martin.fuzzey@flowbird.group> Sent: Saturday, May 23, 2020 2:03 AM
> Hi Andy,
>
> On Fri, 22 May 2020, 03:01 Andy Duan, <fugang.duan@nxp.com> wrote:
> >
> > Andrew, many customers require the wol feature, NXP NPI release always
> > support the wol feature to match customers requirement.
> >
> > And some customers' board only design one ethernet instance based on
> > imx6sx/imx7d/
> > Imx8 serial, but which instance we never know, maybe enet1, maybe
> > enet2. So we should supply different values for gpr.
> >
> > So, it is very necessary to support wol feature for multiple instances.
> >
>
> Yes, I don't think anyone is saying otherwise.
>
> The problem is just that there are already .dtsi files for i.MX chips having
> multiple ethernet interfaces in the mainline kernel (at least imx6ui.dtsi,
> imx6sx.dts, imx7d.dtsi) but that this patch series does not modify those files
> to use the new DT format.
>
For imx6ul/imx6sx/imx7d/imx8mq/imx8mm/imx8mn chips to support wol,
I plan to submit another dts patch after the patch set is accepted.
If you think add the dts patch appending to the patch set, I will add it in v2.
> It currently only modifies the dts files that are already supported by
> hardcoded values in the driver.
>
> As to not knowing which instance it shouldn't matter.
> The base dtsi can declare both/all ethernet interfaces with the appropriate
> GPR bits.
> Both set to status = "disabled".
>
> Then the board specific dts file sets status="okay" and activates wol by adding
> "
> "fsl,magic-packet" if the hardaware supports it (because that depends on
> things beyond the SoC, like how the ethernet PHY is clocked and powered.)
>
> Martin
^ permalink raw reply
* Re: [PATCH v5 09/13] soc: mediatek: cmdq: add write_s value function
From: Dennis-YC Hsieh @ 2020-05-25 2:27 UTC (permalink / raw)
To: Matthias Brugger
Cc: Rob Herring, Mark Rutland, Jassi Brar, Philipp Zabel,
David Airlie, Daniel Vetter, linux-kernel, linux-mediatek,
devicetree, wsd_upstream, dri-devel, Bibby Hsieh, CK Hu,
Houlong Wei, linux-arm-kernel, HS Liao
In-Reply-To: <eb604637-28f0-fa8f-ce4b-3e87f6c944ad@gmail.com>
On Sun, 2020-05-24 at 20:13 +0200, Matthias Brugger wrote:
>
> On 24/05/2020 19:31, Dennis-YC Hsieh wrote:
> > Hi Matthias,
> >
> > Thanks for your comment.
> >
> > On Sat, 2020-05-16 at 20:20 +0200, Matthias Brugger wrote:
> >>
> >> On 08/03/2020 11:52, Dennis YC Hsieh wrote:
> >>> add write_s function in cmdq helper functions which
> >>> writes a constant value to address with large dma
> >>> access support.
> >>>
> >>> Signed-off-by: Dennis YC Hsieh <dennis-yc.hsieh@mediatek.com>
> >>> Reviewed-by: CK Hu <ck.hu@mediatek.com>
> >>> ---
> >>> drivers/soc/mediatek/mtk-cmdq-helper.c | 26 ++++++++++++++++++++++++++
> >>> include/linux/soc/mediatek/mtk-cmdq.h | 14 ++++++++++++++
> >>> 2 files changed, 40 insertions(+)
> >>>
> >>> diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c
> >>> index 03c129230cd7..a9ebbabb7439 100644
> >>> --- a/drivers/soc/mediatek/mtk-cmdq-helper.c
> >>> +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c
> >>> @@ -269,6 +269,32 @@ int cmdq_pkt_write_s(struct cmdq_pkt *pkt, u16 high_addr_reg_idx,
> >>> }
> >>> EXPORT_SYMBOL(cmdq_pkt_write_s);
> >>>
> >>> +int cmdq_pkt_write_s_value(struct cmdq_pkt *pkt, u16 high_addr_reg_idx,
> >>> + u16 addr_low, u32 value, u32 mask)
> >>> +{
> >>> + struct cmdq_instruction inst = { {0} };
> >>> + int err;
> >>> +
> >>> + if (mask != U32_MAX) {
> >>> + inst.op = CMDQ_CODE_MASK;
> >>> + inst.mask = ~mask;
> >>> + err = cmdq_pkt_append_command(pkt, inst);
> >>> + if (err < 0)
> >>> + return err;
> >>> +
> >>> + inst.op = CMDQ_CODE_WRITE_S_MASK;
> >>> + } else {
> >>> + inst.op = CMDQ_CODE_WRITE_S;
> >>> + }
> >>> +
> >>> + inst.sop = high_addr_reg_idx;
> >>
> >> Writing u16 value in a 5 bit wide variable?
> >
> > We need only 5 bits in this case. I'll change high_addr_reg_idx
> > parameter to u8.
> >
>
> Ok, please make sure to mask the value, so that it's explicit in the code that
> we only use the lowest 5 bits of high_addr_reg_idx.
Is it necessary to mask the value?
Since sop already defined as "u8 sop:5;", I thought it is explicit that
only use 5 bits and compiler should do the rest jobs.
Regards,
Dennis
>
> Regards,
> Matthias
>
> >>
> >>> + inst.offset = addr_low;
> >>> + inst.value = value;
> >>> +
> >>> + return cmdq_pkt_append_command(pkt, inst);
> >>> +}
> >>> +EXPORT_SYMBOL(cmdq_pkt_write_s_value);
> >>> +
> >>> int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event)
> >>> {
> >>> struct cmdq_instruction inst = { {0} };
> >>> diff --git a/include/linux/soc/mediatek/mtk-cmdq.h b/include/linux/soc/mediatek/mtk-cmdq.h
> >>> index 01b4184af310..fec292aac83c 100644
> >>> --- a/include/linux/soc/mediatek/mtk-cmdq.h
> >>> +++ b/include/linux/soc/mediatek/mtk-cmdq.h
> >>> @@ -135,6 +135,20 @@ int cmdq_pkt_read_s(struct cmdq_pkt *pkt, u16 high_addr_reg_idx, u16 addr_low,
> >>> int cmdq_pkt_write_s(struct cmdq_pkt *pkt, u16 high_addr_reg_idx,
> >>> u16 addr_low, u16 src_reg_idx, u32 mask);
> >>>
> >>> +/**
> >>> + * cmdq_pkt_write_s_value() - append write_s command with mask to the CMDQ
> >>> + * packet which write value to a physical address
> >>> + * @pkt: the CMDQ packet
> >>> + * @high_addr_reg_idx: internal regisger ID which contains high address of pa
> >>
> >> register
> >
> > will fix
> >
> >
> > Regards,
> > Dennis
> >
> >>
> >>> + * @addr_low: low address of pa
> >>> + * @value: the specified target value
> >>> + * @mask: the specified target mask
> >>> + *
> >>> + * Return: 0 for success; else the error code is returned
> >>> + */
> >>> +int cmdq_pkt_write_s_value(struct cmdq_pkt *pkt, u16 high_addr_reg_idx,
> >>> + u16 addr_low, u32 value, u32 mask);
> >>> +
> >>> /**
> >>> * cmdq_pkt_wfe() - append wait for event command to the CMDQ packet
> >>> * @pkt: the CMDQ packet
> >>>
> >
^ permalink raw reply
* [PATCH v5 3/3] ARM: dts: Add Caninos Loucos Labrador
From: Matheus Castello @ 2020-05-25 1:30 UTC (permalink / raw)
To: afaerber, manivannan.sadhasivam, mark.rutland, robh+dt
Cc: edgar.righi, igor.lima, linux-arm-kernel, devicetree,
linux-kernel, linux-actions, Matheus Castello
In-Reply-To: <20200525013008.108750-1-matheus@castello.eng.br>
Add Device Trees for Caninos Loucos Labrador CoM and base board.
Based on the work of Andreas Färber on Lemaker Guitar device tree.
Signed-off-by: Matheus Castello <matheus@castello.eng.br>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Reviewed-by: Andreas Färber <afaerber@suse.de>
---
arch/arm/boot/dts/Makefile | 1 +
.../arm/boot/dts/owl-s500-labrador-base-m.dts | 34 +++++++++++++++++++
arch/arm/boot/dts/owl-s500-labrador-v2.dtsi | 22 ++++++++++++
3 files changed, 57 insertions(+)
create mode 100644 arch/arm/boot/dts/owl-s500-labrador-base-m.dts
create mode 100644 arch/arm/boot/dts/owl-s500-labrador-v2.dtsi
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index e8dd99201397..0f8c1f255574 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -856,6 +856,7 @@ dtb-$(CONFIG_ARCH_ORION5X) += \
dtb-$(CONFIG_ARCH_ACTIONS) += \
owl-s500-cubieboard6.dtb \
owl-s500-guitar-bb-rev-b.dtb \
+ owl-s500-labrador-base-m.dtb \
owl-s500-sparky.dtb
dtb-$(CONFIG_ARCH_PRIMA2) += \
prima2-evb.dtb
diff --git a/arch/arm/boot/dts/owl-s500-labrador-base-m.dts b/arch/arm/boot/dts/owl-s500-labrador-base-m.dts
new file mode 100644
index 000000000000..044568fec25e
--- /dev/null
+++ b/arch/arm/boot/dts/owl-s500-labrador-base-m.dts
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Caninos Labrador Base Board
+ *
+ * Copyright (c) 2019-2020 Matheus Castello
+ */
+
+/dts-v1/;
+
+#include "owl-s500-labrador-v2.dtsi"
+
+/ {
+ model = "Caninos Labrador Base-M v1.0a";
+ compatible = "caninos,labrador-base-m", "actions,s500";
+
+ aliases {
+ serial3 = &uart3;
+ };
+
+ chosen {
+ stdout-path = "serial3:115200n8";
+ };
+
+ uart3_clk: uart3-clk {
+ compatible = "fixed-clock";
+ clock-frequency = <921600>;
+ #clock-cells = <0>;
+ };
+};
+
+&uart3 {
+ status = "okay";
+ clocks = <&uart3_clk>;
+};
diff --git a/arch/arm/boot/dts/owl-s500-labrador-v2.dtsi b/arch/arm/boot/dts/owl-s500-labrador-v2.dtsi
new file mode 100644
index 000000000000..883ff2f9886d
--- /dev/null
+++ b/arch/arm/boot/dts/owl-s500-labrador-v2.dtsi
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Caninos Labrador SoM V2
+ *
+ * Copyright (c) 2019-2020 Matheus Castello
+ */
+
+#include "owl-s500.dtsi"
+
+/ {
+ model = "Caninos Labrador Core V2.1";
+ compatible = "caninos,labrador-v2", "actions,s500";
+
+ memory@0 {
+ device_type = "memory";
+ reg = <0x0 0x80000000>;
+ };
+};
+
+&timer {
+ clocks = <&hosc>;
+};
--
2.26.2
^ permalink raw reply related
* [PATCH v5 1/3] dt-bindings: Add vendor prefix for Caninos Loucos
From: Matheus Castello @ 2020-05-25 1:30 UTC (permalink / raw)
To: afaerber, manivannan.sadhasivam, mark.rutland, robh+dt
Cc: edgar.righi, igor.lima, linux-arm-kernel, devicetree,
linux-kernel, linux-actions, Matheus Castello, Rob Herring
In-Reply-To: <20200525013008.108750-1-matheus@castello.eng.br>
The Caninos Loucos Program develops Single Board Computers with an open
structure. The Program wants to form a community of developers to use
IoT technologies and disseminate the learning of embedded systems in
Brazil.
It is an initiative of the Technological Integrated Systems Laboratory
(LSI-TEC) with the support of Polytechnic School of the University of
São Paulo (Poli-USP) and Jon "Maddog" Hall.
Signed-off-by: Matheus Castello <matheus@castello.eng.br>
Acked-by: Rob Herring <robh@kernel.org>
Reviewed-by: Andreas Färber <afaerber@suse.de>
---
Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index d3891386d671..a20a05e3deaa 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -167,6 +167,8 @@ patternProperties:
description: CALAO Systems SAS
"^calxeda,.*":
description: Calxeda
+ "^caninos,.*":
+ description: Caninos Loucos Program
"^capella,.*":
description: Capella Microsystems, Inc
"^cascoda,.*":
--
2.26.2
^ permalink raw reply related
* [PATCH v5 2/3] dt-bindings: arm: actions: Document Caninos Loucos Labrador
From: Matheus Castello @ 2020-05-25 1:30 UTC (permalink / raw)
To: afaerber, manivannan.sadhasivam, mark.rutland, robh+dt
Cc: edgar.righi, igor.lima, linux-arm-kernel, devicetree,
linux-kernel, linux-actions, Matheus Castello, Rob Herring
In-Reply-To: <20200525013008.108750-1-matheus@castello.eng.br>
Update the documentation to add the Caninos Loucos Labrador. Labrador
project consists of a computer on module based on the Actions Semi S500
processor and the Labrador base board.
Signed-off-by: Matheus Castello <matheus@castello.eng.br>
Acked-by: Rob Herring <robh@kernel.org>
---
Documentation/devicetree/bindings/arm/actions.yaml | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/Documentation/devicetree/bindings/arm/actions.yaml b/Documentation/devicetree/bindings/arm/actions.yaml
index ace3fdaa8396..2187e1c5bc73 100644
--- a/Documentation/devicetree/bindings/arm/actions.yaml
+++ b/Documentation/devicetree/bindings/arm/actions.yaml
@@ -19,6 +19,11 @@ properties:
- allo,sparky # Allo.com Sparky
- cubietech,cubieboard6 # Cubietech CubieBoard6
- const: actions,s500
+ - items:
+ - enum:
+ - caninos,labrador-v2 # Labrador Core v2
+ - caninos,labrador-base-m # Labrador Base Board M v1
+ - const: actions,s500
- items:
- enum:
- lemaker,guitar-bb-rev-b # LeMaker Guitar Base Board rev. B
--
2.26.2
^ permalink raw reply related
* [PATCH v5 0/3] Add Caninos Loucos Labrador CoM and Base Board Device Tree
From: Matheus Castello @ 2020-05-25 1:30 UTC (permalink / raw)
To: afaerber, manivannan.sadhasivam, mark.rutland, robh+dt
Cc: edgar.righi, igor.lima, linux-arm-kernel, devicetree,
linux-kernel, linux-actions, Matheus Castello
Sorry for the delay.
Thanks Andreas, Mani and Rob for your time reviewing it.
Changes since v4:
(Suggested by Rob Herring)
- Fix issues with yaml indentation
Changes since v3:
(Suggested by Andreas Färber)
- Fix sort on actions.yaml
- Change the file owl-s500-labrador-bb.dts to owl-s500-labrador-base-m.dts
- Add description for both the SoM and Base Board
- Add Model description for both the SoM and Base Board
Matheus Castello (3):
dt-bindings: Add vendor prefix for Caninos Loucos
dt-bindings: arm: actions: Document Caninos Loucos Labrador
ARM: dts: Add Caninos Loucos Labrador
.../devicetree/bindings/arm/actions.yaml | 5 +++
.../devicetree/bindings/vendor-prefixes.yaml | 2 ++
arch/arm/boot/dts/Makefile | 1 +
.../arm/boot/dts/owl-s500-labrador-base-m.dts | 34 +++++++++++++++++++
arch/arm/boot/dts/owl-s500-labrador-v2.dtsi | 22 ++++++++++++
5 files changed, 64 insertions(+)
create mode 100644 arch/arm/boot/dts/owl-s500-labrador-base-m.dts
create mode 100644 arch/arm/boot/dts/owl-s500-labrador-v2.dtsi
--
2.26.2
^ permalink raw reply
* Re: [PATCH v5 10/13] soc: mediatek: cmdq: export finalize function
From: Chun-Kuang Hu @ 2020-05-25 0:23 UTC (permalink / raw)
To: Matthias Brugger
Cc: Dennis YC Hsieh, Rob Herring, Mark Rutland, Jassi Brar,
Philipp Zabel, David Airlie, Daniel Vetter, devicetree,
wsd_upstream, linux-kernel, DRI Development, HS Liao,
moderated list:ARM/Mediatek SoC support, Houlong Wei, Linux ARM
In-Reply-To: <5d6b61b2-23c9-647f-fa22-73e779010bd8@gmail.com>
Hi, Matthias:
Matthias Brugger <matthias.bgg@gmail.com> 於 2020年5月17日 週日 上午2:22寫道:
>
>
>
> On 08/03/2020 11:52, Dennis YC Hsieh wrote:
> > Export finalize function to client which helps append eoc and jump
> > command to pkt. Let client decide call finalize or not.
> >
> > Signed-off-by: Dennis YC Hsieh <dennis-yc.hsieh@mediatek.com>
> > Reviewed-by: CK Hu <ck.hu@mediatek.com>
> > ---
> > drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 1 +
> > drivers/soc/mediatek/mtk-cmdq-helper.c | 7 ++-----
> > include/linux/soc/mediatek/mtk-cmdq.h | 8 ++++++++
> > 3 files changed, 11 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
> > index 0dfcd1787e65..7daaabc26eb1 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
> > +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
> > @@ -490,6 +490,7 @@ static void mtk_drm_crtc_hw_config(struct mtk_drm_crtc *mtk_crtc)
> > cmdq_pkt_clear_event(cmdq_handle, mtk_crtc->cmdq_event);
> > cmdq_pkt_wfe(cmdq_handle, mtk_crtc->cmdq_event);
> > mtk_crtc_ddp_config(crtc, cmdq_handle);
> > + cmdq_pkt_finalize(cmdq_handle);
> > cmdq_pkt_flush_async(cmdq_handle, ddp_cmdq_cb, cmdq_handle);
> > }
> > #endif
>
> This should be a independent patch.
> Other then that patch looks good.
Apply only drm part or only cmdq helpr part, it would be abnormal.
Shall we seperate this patch?
Or seperate it but make sure these two patches be in the same tree?
Regards,
Chun-Kuang.
>
> > diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c
> > index a9ebbabb7439..59bc1164b411 100644
> > --- a/drivers/soc/mediatek/mtk-cmdq-helper.c
> > +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c
> > @@ -372,7 +372,7 @@ int cmdq_pkt_assign(struct cmdq_pkt *pkt, u16 reg_idx, u32 value)
> > }
> > EXPORT_SYMBOL(cmdq_pkt_assign);
> >
> > -static int cmdq_pkt_finalize(struct cmdq_pkt *pkt)
> > +int cmdq_pkt_finalize(struct cmdq_pkt *pkt)
> > {
> > struct cmdq_instruction inst = { {0} };
> > int err;
> > @@ -392,6 +392,7 @@ static int cmdq_pkt_finalize(struct cmdq_pkt *pkt)
> >
> > return err;
> > }
> > +EXPORT_SYMBOL(cmdq_pkt_finalize);
> >
> > static void cmdq_pkt_flush_async_cb(struct cmdq_cb_data data)
> > {
> > @@ -426,10 +427,6 @@ int cmdq_pkt_flush_async(struct cmdq_pkt *pkt, cmdq_async_flush_cb cb,
> > unsigned long flags = 0;
> > struct cmdq_client *client = (struct cmdq_client *)pkt->cl;
> >
> > - err = cmdq_pkt_finalize(pkt);
> > - if (err < 0)
> > - return err;
> > -
> > pkt->cb.cb = cb;
> > pkt->cb.data = data;
> > pkt->async_cb.cb = cmdq_pkt_flush_async_cb;
> > diff --git a/include/linux/soc/mediatek/mtk-cmdq.h b/include/linux/soc/mediatek/mtk-cmdq.h
> > index fec292aac83c..99e77155f967 100644
> > --- a/include/linux/soc/mediatek/mtk-cmdq.h
> > +++ b/include/linux/soc/mediatek/mtk-cmdq.h
> > @@ -213,6 +213,14 @@ int cmdq_pkt_poll_mask(struct cmdq_pkt *pkt, u8 subsys,
> > */
> > int cmdq_pkt_assign(struct cmdq_pkt *pkt, u16 reg_idx, u32 value);
> >
> > +/**
> > + * cmdq_pkt_finalize() - Append EOC and jump command to pkt.
> > + * @pkt: the CMDQ packet
> > + *
> > + * Return: 0 for success; else the error code is returned
> > + */
> > +int cmdq_pkt_finalize(struct cmdq_pkt *pkt);
> > +
> > /**
> > * cmdq_pkt_flush_async() - trigger CMDQ to asynchronously execute the CMDQ
> > * packet and call back at the end of done packet
> >
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox