* [PATCH 0/2] Add support for Lenovo NT36523W BOE panel @ 2023-02-17 11:29 Konrad Dybcio 2023-02-17 11:29 ` [PATCH 1/2] dt-bindings: display/panel: Add " Konrad Dybcio 2023-02-17 11:29 ` [PATCH 2/2] gpu/drm/panel: " Konrad Dybcio 0 siblings, 2 replies; 9+ messages in thread From: Konrad Dybcio @ 2023-02-17 11:29 UTC (permalink / raw) To: Thierry Reding, Sam Ravnborg, David Airlie, Daniel Vetter, Rob Herring, Krzysztof Kozlowski, Neil Armstrong Cc: dri-devel, devicetree, linux-kernel, Konrad Dybcio Add driver and bindings for the NT+BOE display panel found on Lenovo Tab P11 devices. Signed-off-by: Konrad Dybcio <konrad.dybcio@linaro.org> --- Konrad Dybcio (2): dt-bindings: display/panel: Add Lenovo NT36523W BOE panel gpu/drm/panel: Add Lenovo NT36523W BOE panel .../display/panel/lenovo,nt36523w-boe-j606.yaml | 60 ++ drivers/gpu/drm/panel/Kconfig | 12 + drivers/gpu/drm/panel/Makefile | 1 + drivers/gpu/drm/panel/panel-lenovo-nt36523w-boe.c | 751 +++++++++++++++++++++ 4 files changed, 824 insertions(+) --- base-commit: c068f40300a0eaa34f7105d137a5560b86951aa9 change-id: 20230217-topic-lenovo-panel-48c63b84e3f8 Best regards, -- Konrad Dybcio <konrad.dybcio@linaro.org> ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/2] dt-bindings: display/panel: Add Lenovo NT36523W BOE panel 2023-02-17 11:29 [PATCH 0/2] Add support for Lenovo NT36523W BOE panel Konrad Dybcio @ 2023-02-17 11:29 ` Konrad Dybcio 2023-02-21 2:08 ` Rob Herring 2023-02-26 17:41 ` Rob Herring 2023-02-17 11:29 ` [PATCH 2/2] gpu/drm/panel: " Konrad Dybcio 1 sibling, 2 replies; 9+ messages in thread From: Konrad Dybcio @ 2023-02-17 11:29 UTC (permalink / raw) To: Thierry Reding, Sam Ravnborg, David Airlie, Daniel Vetter, Rob Herring, Krzysztof Kozlowski, Neil Armstrong Cc: dri-devel, devicetree, linux-kernel, Konrad Dybcio Add bindings for the 2000x1200px IPS panel found on Lenovo Tab P11/ XiaoXin Pad devices. Signed-off-by: Konrad Dybcio <konrad.dybcio@linaro.org> --- .../display/panel/lenovo,nt36523w-boe-j606.yaml | 60 ++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/Documentation/devicetree/bindings/display/panel/lenovo,nt36523w-boe-j606.yaml b/Documentation/devicetree/bindings/display/panel/lenovo,nt36523w-boe-j606.yaml new file mode 100644 index 000000000000..43dcbe3f9f30 --- /dev/null +++ b/Documentation/devicetree/bindings/display/panel/lenovo,nt36523w-boe-j606.yaml @@ -0,0 +1,60 @@ +# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/panel/lenovo,nt36523w-boe-j606.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NT36523W BOE panel found on Lenovo J606 devices + +maintainers: + - Konrad Dybcio <konrad.dybcio@linaro.org> + +allOf: + - $ref: panel-common.yaml# + +properties: + compatible: + const: lenovo,nt36523w-boe-j606 + + reg: + maxItems: 1 + description: DSI virtual channel + + vddio-supply: true + reset-gpios: true + rotation: true + port: true + +additionalProperties: false + +required: + - compatible + - reg + - vddio-supply + - reset-gpios + - port + +examples: + - | + #include <dt-bindings/gpio/gpio.h> + dsi { + #address-cells = <1>; + #size-cells = <0>; + + panel@0 { + compatible = "lenovo,nt36523w-boe-j606"; + reg = <0>; + + reset-gpios = <&tlmm 82 GPIO_ACTIVE_LOW>; + vddio-supply = <&pm6125_l9>; + + rotation = <180>; + + port { + panel0_in: endpoint { + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + }; + }; +... -- 2.39.1 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] dt-bindings: display/panel: Add Lenovo NT36523W BOE panel 2023-02-17 11:29 ` [PATCH 1/2] dt-bindings: display/panel: Add " Konrad Dybcio @ 2023-02-21 2:08 ` Rob Herring 2023-02-21 2:13 ` Konrad Dybcio 2023-02-26 17:41 ` Rob Herring 1 sibling, 1 reply; 9+ messages in thread From: Rob Herring @ 2023-02-21 2:08 UTC (permalink / raw) To: Konrad Dybcio Cc: Thierry Reding, Sam Ravnborg, David Airlie, Daniel Vetter, Krzysztof Kozlowski, Neil Armstrong, dri-devel, devicetree, linux-kernel On Fri, Feb 17, 2023 at 12:29:07PM +0100, Konrad Dybcio wrote: > Add bindings for the 2000x1200px IPS panel found on Lenovo Tab P11/ > XiaoXin Pad devices. > > Signed-off-by: Konrad Dybcio <konrad.dybcio@linaro.org> > --- > .../display/panel/lenovo,nt36523w-boe-j606.yaml | 60 ++++++++++++++++++++++ > 1 file changed, 60 insertions(+) > > diff --git a/Documentation/devicetree/bindings/display/panel/lenovo,nt36523w-boe-j606.yaml b/Documentation/devicetree/bindings/display/panel/lenovo,nt36523w-boe-j606.yaml > new file mode 100644 > index 000000000000..43dcbe3f9f30 > --- /dev/null > +++ b/Documentation/devicetree/bindings/display/panel/lenovo,nt36523w-boe-j606.yaml > @@ -0,0 +1,60 @@ > +# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause > +%YAML 1.2 > +--- > +$id: http://devicetree.org/schemas/display/panel/lenovo,nt36523w-boe-j606.yaml# > +$schema: http://devicetree.org/meta-schemas/core.yaml# > + > +title: NT36523W BOE panel found on Lenovo J606 devices > + > +maintainers: > + - Konrad Dybcio <konrad.dybcio@linaro.org> > + > +allOf: > + - $ref: panel-common.yaml# > + > +properties: > + compatible: > + const: lenovo,nt36523w-boe-j606 > + > + reg: > + maxItems: 1 > + description: DSI virtual channel > + > + vddio-supply: true If only one supply, why not use panel-simple-dsi.yaml? Though probably there's more than just an IO supply? Rob ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] dt-bindings: display/panel: Add Lenovo NT36523W BOE panel 2023-02-21 2:08 ` Rob Herring @ 2023-02-21 2:13 ` Konrad Dybcio 0 siblings, 0 replies; 9+ messages in thread From: Konrad Dybcio @ 2023-02-21 2:13 UTC (permalink / raw) To: Rob Herring Cc: Thierry Reding, Sam Ravnborg, David Airlie, Daniel Vetter, Krzysztof Kozlowski, Neil Armstrong, dri-devel, devicetree, linux-kernel On 21.02.2023 03:08, Rob Herring wrote: > On Fri, Feb 17, 2023 at 12:29:07PM +0100, Konrad Dybcio wrote: >> Add bindings for the 2000x1200px IPS panel found on Lenovo Tab P11/ >> XiaoXin Pad devices. >> >> Signed-off-by: Konrad Dybcio <konrad.dybcio@linaro.org> >> --- >> .../display/panel/lenovo,nt36523w-boe-j606.yaml | 60 ++++++++++++++++++++++ >> 1 file changed, 60 insertions(+) >> >> diff --git a/Documentation/devicetree/bindings/display/panel/lenovo,nt36523w-boe-j606.yaml b/Documentation/devicetree/bindings/display/panel/lenovo,nt36523w-boe-j606.yaml >> new file mode 100644 >> index 000000000000..43dcbe3f9f30 >> --- /dev/null >> +++ b/Documentation/devicetree/bindings/display/panel/lenovo,nt36523w-boe-j606.yaml >> @@ -0,0 +1,60 @@ >> +# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause >> +%YAML 1.2 >> +--- >> +$id: http://devicetree.org/schemas/display/panel/lenovo,nt36523w-boe-j606.yaml# >> +$schema: http://devicetree.org/meta-schemas/core.yaml# >> + >> +title: NT36523W BOE panel found on Lenovo J606 devices >> + >> +maintainers: >> + - Konrad Dybcio <konrad.dybcio@linaro.org> >> + >> +allOf: >> + - $ref: panel-common.yaml# >> + >> +properties: >> + compatible: >> + const: lenovo,nt36523w-boe-j606 >> + >> + reg: >> + maxItems: 1 >> + description: DSI virtual channel >> + >> + vddio-supply: true > > If only one supply, why not use panel-simple-dsi.yaml? Though probably > there's more than just an IO supply? Display regulators (AB/IBB/AMOLEDB, not to be confused with LAB/IBB) on modern Qualcomm platforms are controlled by the secure firmware layer (yes, you read that correctly). Some panels require additional supplies, but this one just has one positive, one negative and one I/O regulator. Konrad > > Rob ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] dt-bindings: display/panel: Add Lenovo NT36523W BOE panel 2023-02-17 11:29 ` [PATCH 1/2] dt-bindings: display/panel: Add " Konrad Dybcio 2023-02-21 2:08 ` Rob Herring @ 2023-02-26 17:41 ` Rob Herring 1 sibling, 0 replies; 9+ messages in thread From: Rob Herring @ 2023-02-26 17:41 UTC (permalink / raw) To: Konrad Dybcio Cc: linux-kernel, Sam Ravnborg, devicetree, David Airlie, Neil Armstrong, dri-devel, Thierry Reding, Daniel Vetter, Krzysztof Kozlowski, Rob Herring On Fri, 17 Feb 2023 12:29:07 +0100, Konrad Dybcio wrote: > Add bindings for the 2000x1200px IPS panel found on Lenovo Tab P11/ > XiaoXin Pad devices. > > Signed-off-by: Konrad Dybcio <konrad.dybcio@linaro.org> > --- > .../display/panel/lenovo,nt36523w-boe-j606.yaml | 60 ++++++++++++++++++++++ > 1 file changed, 60 insertions(+) > Reviewed-by: Rob Herring <robh@kernel.org> ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 2/2] gpu/drm/panel: Add Lenovo NT36523W BOE panel 2023-02-17 11:29 [PATCH 0/2] Add support for Lenovo NT36523W BOE panel Konrad Dybcio 2023-02-17 11:29 ` [PATCH 1/2] dt-bindings: display/panel: Add " Konrad Dybcio @ 2023-02-17 11:29 ` Konrad Dybcio 2023-03-07 9:16 ` Neil Armstrong 2023-03-07 9:19 ` Neil Armstrong 1 sibling, 2 replies; 9+ messages in thread From: Konrad Dybcio @ 2023-02-17 11:29 UTC (permalink / raw) To: Thierry Reding, Sam Ravnborg, David Airlie, Daniel Vetter, Rob Herring, Krzysztof Kozlowski, Neil Armstrong Cc: dri-devel, devicetree, linux-kernel, Konrad Dybcio Introduce support for the BOE panel with a NT36523W touch/driver IC found on some Lenovo Tab P11 devices. It's a 2000x1200, 24bit RGB MIPI DSI panel with integrated DCS-controlled backlight (that expects big-endian communication). Signed-off-by: Konrad Dybcio <konrad.dybcio@linaro.org> --- drivers/gpu/drm/panel/Kconfig | 12 + drivers/gpu/drm/panel/Makefile | 1 + drivers/gpu/drm/panel/panel-lenovo-nt36523w-boe.c | 751 ++++++++++++++++++++++ 3 files changed, 764 insertions(+) diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index 8eeee71c0000..2abc89284a77 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -297,6 +297,18 @@ config DRM_PANEL_LEADTEK_LTK500HD1829 24 bit RGB per pixel. It provides a MIPI DSI interface to the host and has a built-in LED backlight. +config DRM_PANEL_LENOVO_NT36523W_BOE + tristate "Lenovo NT36523W BOE panel" + depends on OF + depends on DRM_MIPI_DSI + depends on BACKLIGHT_CLASS_DEVICE + help + Say Y here if you want to enable support for BOE display panel with + NT36523W driver/touch IC, found on some Lenovo Tab P11 devices. The + panel has a 2000x1200 resolution and uses 24 bit RGB per pixel. It + provides a MIPI DSI interface to the host and has a built-in LED + backlight. + config DRM_PANEL_SAMSUNG_LD9040 tristate "Samsung LD9040 RGB/SPI panel" depends on OF && SPI diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile index c05aa9e23907..7ed908cc83a6 100644 --- a/drivers/gpu/drm/panel/Makefile +++ b/drivers/gpu/drm/panel/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_DRM_PANEL_KHADAS_TS050) += panel-khadas-ts050.o obj-$(CONFIG_DRM_PANEL_KINGDISPLAY_KD097D04) += panel-kingdisplay-kd097d04.o obj-$(CONFIG_DRM_PANEL_LEADTEK_LTK050H3146W) += panel-leadtek-ltk050h3146w.o obj-$(CONFIG_DRM_PANEL_LEADTEK_LTK500HD1829) += panel-leadtek-ltk500hd1829.o +obj-$(CONFIG_DRM_PANEL_LENOVO_NT36523W_BOE) += panel-lenovo-nt36523w-boe.o obj-$(CONFIG_DRM_PANEL_LG_LB035Q02) += panel-lg-lb035q02.o obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o obj-$(CONFIG_DRM_PANEL_NEC_NL8048HL11) += panel-nec-nl8048hl11.o diff --git a/drivers/gpu/drm/panel/panel-lenovo-nt36523w-boe.c b/drivers/gpu/drm/panel/panel-lenovo-nt36523w-boe.c new file mode 100644 index 000000000000..83478e471493 --- /dev/null +++ b/drivers/gpu/drm/panel/panel-lenovo-nt36523w-boe.c @@ -0,0 +1,751 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2023 Linaro Limited + * + * Generated with linux-mdss-dsi-panel-driver-generator with + * some manual adjustments. + */ +#include <linux/backlight.h> +#include <linux/delay.h> +#include <linux/gpio/consumer.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/regulator/consumer.h> + +#include <video/mipi_display.h> + +#include <drm/drm_mipi_dsi.h> +#include <drm/drm_modes.h> +#include <drm/drm_panel.h> + +struct nt36523w_boe { + struct drm_panel panel; + struct mipi_dsi_device *dsi; + struct regulator *supply; + struct gpio_desc *reset_gpio; + enum drm_panel_orientation orientation; + bool prepared; +}; + +static inline struct nt36523w_boe *to_nt36523w_boe(struct drm_panel *panel) +{ + return container_of(panel, struct nt36523w_boe, panel); +} + +static void nt36523w_boe_reset(struct nt36523w_boe *ctx) +{ + gpiod_set_value_cansleep(ctx->reset_gpio, 0); + usleep_range(10000, 11000); + gpiod_set_value_cansleep(ctx->reset_gpio, 1); + usleep_range(5000, 6000); + gpiod_set_value_cansleep(ctx->reset_gpio, 0); + usleep_range(2000, 3000); +} + +static int nt36523w_boe_on(struct nt36523w_boe *ctx) +{ + struct mipi_dsi_device *dsi = ctx->dsi; + struct device *dev = &dsi->dev; + int ret; + + mipi_dsi_dcs_write_seq(dsi, 0xff, 0x20); + mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); + mipi_dsi_dcs_write_seq(dsi, 0x05, 0xd9); + mipi_dsi_dcs_write_seq(dsi, 0x07, 0x78); + mipi_dsi_dcs_write_seq(dsi, 0x08, 0x5a); + mipi_dsi_dcs_write_seq(dsi, 0x0d, 0x63); + mipi_dsi_dcs_write_seq(dsi, 0x0e, 0x91); + mipi_dsi_dcs_write_seq(dsi, 0x0f, 0x73); + mipi_dsi_dcs_write_seq(dsi, 0x95, 0xeb); + mipi_dsi_dcs_write_seq(dsi, 0x96, 0xeb); + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_PARTIAL_ROWS, 0x11); + mipi_dsi_dcs_write_seq(dsi, 0x6d, 0x66); + mipi_dsi_dcs_write_seq(dsi, 0x75, 0xa2); + mipi_dsi_dcs_write_seq(dsi, 0x77, 0xb3); + mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x00, 0x08, 0x00, 0x23, 0x00, 0x4d, 0x00, 0x6d, 0x00, + 0x89, 0x00, 0xa1, 0x00, 0xb6, 0x00, 0xc9); + mipi_dsi_dcs_write_seq(dsi, 0xb1, 0x00, 0xda, 0x01, 0x13, 0x01, 0x3c, 0x01, 0x7e, 0x01, + 0xab, 0x01, 0xf7, 0x02, 0x2f, 0x02, 0x31); + mipi_dsi_dcs_write_seq(dsi, 0xb2, 0x02, 0x67, 0x02, 0xa6, 0x02, 0xd1, 0x03, 0x08, 0x03, + 0x2e, 0x03, 0x5b, 0x03, 0x6b, 0x03, 0x7b); + mipi_dsi_dcs_write_seq(dsi, 0xb3, 0x03, 0x8e, 0x03, 0xa2, 0x03, 0xb7, 0x03, 0xe7, 0x03, + 0xfd, 0x03, 0xff); + mipi_dsi_dcs_write_seq(dsi, 0xb4, 0x00, 0x08, 0x00, 0x23, 0x00, 0x4d, 0x00, 0x6d, 0x00, + 0x89, 0x00, 0xa1, 0x00, 0xb6, 0x00, 0xc9); + mipi_dsi_dcs_write_seq(dsi, 0xb5, 0x00, 0xda, 0x01, 0x13, 0x01, 0x3c, 0x01, 0x7e, 0x01, + 0xab, 0x01, 0xf7, 0x02, 0x2f, 0x02, 0x31); + mipi_dsi_dcs_write_seq(dsi, 0xb6, 0x02, 0x67, 0x02, 0xa6, 0x02, 0xd1, 0x03, 0x08, 0x03, + 0x2e, 0x03, 0x5b, 0x03, 0x6b, 0x03, 0x7b); + mipi_dsi_dcs_write_seq(dsi, 0xb7, 0x03, 0x8e, 0x03, 0xa2, 0x03, 0xb7, 0x03, 0xe7, 0x03, + 0xfd, 0x03, 0xff); + mipi_dsi_dcs_write_seq(dsi, 0xb8, 0x00, 0x08, 0x00, 0x23, 0x00, 0x4d, 0x00, 0x6d, 0x00, + 0x89, 0x00, 0xa1, 0x00, 0xb6, 0x00, 0xc9); + mipi_dsi_dcs_write_seq(dsi, 0xb9, 0x00, 0xda, 0x01, 0x13, 0x01, 0x3c, 0x01, 0x7e, 0x01, + 0xab, 0x01, 0xf7, 0x02, 0x2f, 0x02, 0x31); + mipi_dsi_dcs_write_seq(dsi, 0xba, 0x02, 0x67, 0x02, 0xa6, 0x02, 0xd1, 0x03, 0x08, 0x03, + 0x2e, 0x03, 0x5b, 0x03, 0x6b, 0x03, 0x7b); + mipi_dsi_dcs_write_seq(dsi, 0xbb, 0x03, 0x8e, 0x03, 0xa2, 0x03, 0xb7, 0x03, 0xe7, 0x03, + 0xfd, 0x03, 0xff); + mipi_dsi_dcs_write_seq(dsi, 0xff, 0x21); + mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); + mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x45, 0x00, 0x65, 0x00, + 0x81, 0x00, 0x99, 0x00, 0xae, 0x00, 0xc1); + mipi_dsi_dcs_write_seq(dsi, 0xb1, 0x00, 0xd2, 0x01, 0x0b, 0x01, 0x34, 0x01, 0x76, 0x01, + 0xa3, 0x01, 0xef, 0x02, 0x27, 0x02, 0x29); + mipi_dsi_dcs_write_seq(dsi, 0xb2, 0x02, 0x5f, 0x02, 0x9e, 0x02, 0xc9, 0x03, 0x00, 0x03, + 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73); + mipi_dsi_dcs_write_seq(dsi, 0xb3, 0x03, 0x86, 0x03, 0x9a, 0x03, 0xaf, 0x03, 0xdf, 0x03, + 0xf5, 0x03, 0xf7); + mipi_dsi_dcs_write_seq(dsi, 0xb4, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x45, 0x00, 0x65, 0x00, + 0x81, 0x00, 0x99, 0x00, 0xae, 0x00, 0xc1); + mipi_dsi_dcs_write_seq(dsi, 0xb5, 0x00, 0xd2, 0x01, 0x0b, 0x01, 0x34, 0x01, 0x76, 0x01, + 0xa3, 0x01, 0xef, 0x02, 0x27, 0x02, 0x29); + mipi_dsi_dcs_write_seq(dsi, 0xb6, 0x02, 0x5f, 0x02, 0x9e, 0x02, 0xc9, 0x03, 0x00, 0x03, + 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73); + mipi_dsi_dcs_write_seq(dsi, 0xb7, 0x03, 0x86, 0x03, 0x9a, 0x03, 0xaf, 0x03, 0xdf, 0x03, + 0xf5, 0x03, 0xf7); + mipi_dsi_dcs_write_seq(dsi, 0xb8, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x45, 0x00, 0x65, 0x00, + 0x81, 0x00, 0x99, 0x00, 0xae, 0x00, 0xc1); + mipi_dsi_dcs_write_seq(dsi, 0xb9, 0x00, 0xd2, 0x01, 0x0b, 0x01, 0x34, 0x01, 0x76, 0x01, + 0xa3, 0x01, 0xef, 0x02, 0x27, 0x02, 0x29); + mipi_dsi_dcs_write_seq(dsi, 0xba, 0x02, 0x5f, 0x02, 0x9e, 0x02, 0xc9, 0x03, 0x00, 0x03, + 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73); + mipi_dsi_dcs_write_seq(dsi, 0xbb, 0x03, 0x86, 0x03, 0x9a, 0x03, 0xaf, 0x03, 0xdf, 0x03, + 0xf5, 0x03, 0xf7); + mipi_dsi_dcs_write_seq(dsi, 0xff, 0x23); + mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); + mipi_dsi_dcs_write_seq(dsi, 0x00, 0x80); + mipi_dsi_dcs_write_seq(dsi, 0x07, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0x11, 0x01); + mipi_dsi_dcs_write_seq(dsi, 0x12, 0x77); + mipi_dsi_dcs_write_seq(dsi, 0x15, 0x07); + mipi_dsi_dcs_write_seq(dsi, 0x16, 0x07); + mipi_dsi_dcs_write_seq(dsi, 0xff, 0x24); + mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); + mipi_dsi_dcs_write_seq(dsi, 0x00, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0x01, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0x02, 0x1c); + mipi_dsi_dcs_write_seq(dsi, 0x03, 0x1c); + mipi_dsi_dcs_write_seq(dsi, 0x04, 0x1d); + mipi_dsi_dcs_write_seq(dsi, 0x05, 0x1d); + mipi_dsi_dcs_write_seq(dsi, 0x06, 0x04); + mipi_dsi_dcs_write_seq(dsi, 0x07, 0x04); + mipi_dsi_dcs_write_seq(dsi, 0x08, 0x0f); + mipi_dsi_dcs_write_seq(dsi, 0x09, 0x0f); + mipi_dsi_dcs_write_seq(dsi, 0x0a, 0x0e); + mipi_dsi_dcs_write_seq(dsi, 0x0b, 0x0e); + mipi_dsi_dcs_write_seq(dsi, 0x0c, 0x0d); + mipi_dsi_dcs_write_seq(dsi, 0x0d, 0x0d); + mipi_dsi_dcs_write_seq(dsi, 0x0e, 0x0c); + mipi_dsi_dcs_write_seq(dsi, 0x0f, 0x0c); + mipi_dsi_dcs_write_seq(dsi, 0x10, 0x08); + mipi_dsi_dcs_write_seq(dsi, 0x11, 0x08); + mipi_dsi_dcs_write_seq(dsi, 0x12, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0x13, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0x14, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0x15, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0x16, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0x17, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0x18, 0x1c); + mipi_dsi_dcs_write_seq(dsi, 0x19, 0x1c); + mipi_dsi_dcs_write_seq(dsi, 0x1a, 0x1d); + mipi_dsi_dcs_write_seq(dsi, 0x1b, 0x1d); + mipi_dsi_dcs_write_seq(dsi, 0x1c, 0x04); + mipi_dsi_dcs_write_seq(dsi, 0x1d, 0x04); + mipi_dsi_dcs_write_seq(dsi, 0x1e, 0x0f); + mipi_dsi_dcs_write_seq(dsi, 0x1f, 0x0f); + mipi_dsi_dcs_write_seq(dsi, 0x20, 0x0e); + mipi_dsi_dcs_write_seq(dsi, 0x21, 0x0e); + mipi_dsi_dcs_write_seq(dsi, 0x22, 0x0d); + mipi_dsi_dcs_write_seq(dsi, 0x23, 0x0d); + mipi_dsi_dcs_write_seq(dsi, 0x24, 0x0c); + mipi_dsi_dcs_write_seq(dsi, 0x25, 0x0c); + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_GAMMA_CURVE, 0x08); + mipi_dsi_dcs_write_seq(dsi, 0x27, 0x08); + mipi_dsi_dcs_write_seq(dsi, 0x28, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0x29, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0x2a, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0x2b, 0x00); + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_LUT, 0x20); + mipi_dsi_dcs_write_seq(dsi, 0x2f, 0x0a); + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_PARTIAL_ROWS, 0x44); + mipi_dsi_dcs_write_seq(dsi, 0x33, 0x0c); + mipi_dsi_dcs_write_seq(dsi, 0x34, 0x32); + mipi_dsi_dcs_write_seq(dsi, 0x37, 0x44); + mipi_dsi_dcs_write_seq(dsi, 0x38, 0x40); + mipi_dsi_dcs_write_seq(dsi, 0x39, 0x00); + + ret = mipi_dsi_dcs_set_pixel_format(dsi, 0x9a); + if (ret < 0) { + dev_err(dev, "Failed to set pixel format: %d\n", ret); + return ret; + } + + mipi_dsi_dcs_write_seq(dsi, 0x3b, 0xa0); + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_3D_CONTROL, 0x42); + mipi_dsi_dcs_write_seq(dsi, 0x3f, 0x06); + mipi_dsi_dcs_write_seq(dsi, 0x43, 0x06); + mipi_dsi_dcs_write_seq(dsi, 0x47, 0x66); + mipi_dsi_dcs_write_seq(dsi, 0x4a, 0x9a); + mipi_dsi_dcs_write_seq(dsi, 0x4b, 0xa0); + mipi_dsi_dcs_write_seq(dsi, 0x4c, 0x91); + mipi_dsi_dcs_write_seq(dsi, 0x4d, 0x21); + mipi_dsi_dcs_write_seq(dsi, 0x4e, 0x43); + + ret = mipi_dsi_dcs_set_display_brightness(dsi, 18); + if (ret < 0) { + dev_err(dev, "Failed to set display brightness: %d\n", ret); + return ret; + } + + mipi_dsi_dcs_write_seq(dsi, 0x52, 0x34); + mipi_dsi_dcs_write_seq(dsi, 0x55, 0x82, 0x02); + mipi_dsi_dcs_write_seq(dsi, 0x56, 0x04); + mipi_dsi_dcs_write_seq(dsi, 0x58, 0x21); + mipi_dsi_dcs_write_seq(dsi, 0x59, 0x30); + mipi_dsi_dcs_write_seq(dsi, 0x5a, 0xba); + mipi_dsi_dcs_write_seq(dsi, 0x5b, 0xa0); + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_CABC_MIN_BRIGHTNESS, 0x00, 0x06); + mipi_dsi_dcs_write_seq(dsi, 0x5f, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0x65, 0x82); + mipi_dsi_dcs_write_seq(dsi, 0x7e, 0x20); + mipi_dsi_dcs_write_seq(dsi, 0x7f, 0x3c); + mipi_dsi_dcs_write_seq(dsi, 0x82, 0x04); + mipi_dsi_dcs_write_seq(dsi, 0x97, 0xc0); + mipi_dsi_dcs_write_seq(dsi, 0xb6, + 0x05, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, + 0x05, 0x00, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0x92, 0xc4); + mipi_dsi_dcs_write_seq(dsi, 0x93, 0x1a); + mipi_dsi_dcs_write_seq(dsi, 0x94, 0x5f); + mipi_dsi_dcs_write_seq(dsi, 0xd7, 0x55); + mipi_dsi_dcs_write_seq(dsi, 0xda, 0x0a); + mipi_dsi_dcs_write_seq(dsi, 0xde, 0x08); + mipi_dsi_dcs_write_seq(dsi, 0xdb, 0x05); + mipi_dsi_dcs_write_seq(dsi, 0xdc, 0xc4); + mipi_dsi_dcs_write_seq(dsi, 0xdd, 0x22); + mipi_dsi_dcs_write_seq(dsi, 0xdf, 0x05); + mipi_dsi_dcs_write_seq(dsi, 0xe0, 0xc4); + mipi_dsi_dcs_write_seq(dsi, 0xe1, 0x05); + mipi_dsi_dcs_write_seq(dsi, 0xe2, 0xc4); + mipi_dsi_dcs_write_seq(dsi, 0xe3, 0x05); + mipi_dsi_dcs_write_seq(dsi, 0xe4, 0xc4); + mipi_dsi_dcs_write_seq(dsi, 0xe5, 0x05); + mipi_dsi_dcs_write_seq(dsi, 0xe6, 0xc4); + mipi_dsi_dcs_write_seq(dsi, 0x5c, 0x88); + mipi_dsi_dcs_write_seq(dsi, 0x5d, 0x08); + mipi_dsi_dcs_write_seq(dsi, 0x8d, 0x88); + mipi_dsi_dcs_write_seq(dsi, 0x8e, 0x08); + mipi_dsi_dcs_write_seq(dsi, 0xb5, 0x90); + mipi_dsi_dcs_write_seq(dsi, 0xff, 0x25); + mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); + mipi_dsi_dcs_write_seq(dsi, 0x05, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0x19, 0x07); + mipi_dsi_dcs_write_seq(dsi, 0x1f, 0xba); + mipi_dsi_dcs_write_seq(dsi, 0x20, 0xa0); + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_GAMMA_CURVE, 0xba); + mipi_dsi_dcs_write_seq(dsi, 0x27, 0xa0); + mipi_dsi_dcs_write_seq(dsi, 0x33, 0xba); + mipi_dsi_dcs_write_seq(dsi, 0x34, 0xa0); + mipi_dsi_dcs_write_seq(dsi, 0x3f, 0xe0); + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_VSYNC_TIMING, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0x44, 0x00); + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_GET_SCANLINE, 0x40); + mipi_dsi_dcs_write_seq(dsi, 0x48, 0xba); + mipi_dsi_dcs_write_seq(dsi, 0x49, 0xa0); + mipi_dsi_dcs_write_seq(dsi, 0x5b, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0x5c, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0x5d, 0x00); + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_CABC_MIN_BRIGHTNESS, 0xd0); + mipi_dsi_dcs_write_seq(dsi, 0x61, 0xba); + mipi_dsi_dcs_write_seq(dsi, 0x62, 0xa0); + mipi_dsi_dcs_write_seq(dsi, 0xf1, 0x10); + mipi_dsi_dcs_write_seq(dsi, 0xff, 0x2a); + mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); + mipi_dsi_dcs_write_seq(dsi, 0x64, 0x16); + mipi_dsi_dcs_write_seq(dsi, 0x67, 0x16); + mipi_dsi_dcs_write_seq(dsi, 0x6a, 0x16); + mipi_dsi_dcs_write_seq(dsi, 0x70, 0x30); + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_READ_PPS_START, 0xf3); + mipi_dsi_dcs_write_seq(dsi, 0xa3, 0xff); + mipi_dsi_dcs_write_seq(dsi, 0xa4, 0xff); + mipi_dsi_dcs_write_seq(dsi, 0xa5, 0xff); + mipi_dsi_dcs_write_seq(dsi, 0xd6, 0x08); + mipi_dsi_dcs_write_seq(dsi, 0xff, 0x26); + mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); + mipi_dsi_dcs_write_seq(dsi, 0x00, 0xa1); + mipi_dsi_dcs_write_seq(dsi, 0x0a, 0xf2); + mipi_dsi_dcs_write_seq(dsi, 0x04, 0x28); + mipi_dsi_dcs_write_seq(dsi, 0x06, 0x30); + mipi_dsi_dcs_write_seq(dsi, 0x0c, 0x13); + mipi_dsi_dcs_write_seq(dsi, 0x0d, 0x0a); + mipi_dsi_dcs_write_seq(dsi, 0x0f, 0x0a); + mipi_dsi_dcs_write_seq(dsi, 0x11, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0x12, 0x50); + mipi_dsi_dcs_write_seq(dsi, 0x13, 0x51); + mipi_dsi_dcs_write_seq(dsi, 0x14, 0x65); + mipi_dsi_dcs_write_seq(dsi, 0x15, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0x16, 0x10); + mipi_dsi_dcs_write_seq(dsi, 0x17, 0xa0); + mipi_dsi_dcs_write_seq(dsi, 0x18, 0x86); + mipi_dsi_dcs_write_seq(dsi, 0x19, 0x11); + mipi_dsi_dcs_write_seq(dsi, 0x1a, 0x7b); + mipi_dsi_dcs_write_seq(dsi, 0x1b, 0x10); + mipi_dsi_dcs_write_seq(dsi, 0x1c, 0xbb); + mipi_dsi_dcs_write_seq(dsi, 0x22, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0x23, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0x2a, 0x11); + mipi_dsi_dcs_write_seq(dsi, 0x2b, 0x7b); + mipi_dsi_dcs_write_seq(dsi, 0x1d, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0x1e, 0xc3); + mipi_dsi_dcs_write_seq(dsi, 0x1f, 0xc3); + mipi_dsi_dcs_write_seq(dsi, 0x24, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0x25, 0xc3); + mipi_dsi_dcs_write_seq(dsi, 0x2f, 0x05); + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_PARTIAL_ROWS, 0xc3); + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_PARTIAL_COLUMNS, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0x32, 0xc3); + mipi_dsi_dcs_write_seq(dsi, 0x39, 0x00); + + ret = mipi_dsi_dcs_set_pixel_format(dsi, 0xc3); + if (ret < 0) { + dev_err(dev, "Failed to set pixel format: %d\n", ret); + return ret; + } + + mipi_dsi_dcs_write_seq(dsi, 0x20, 0x01); + mipi_dsi_dcs_write_seq(dsi, 0x33, 0x11); + mipi_dsi_dcs_write_seq(dsi, 0x34, 0x78); + mipi_dsi_dcs_write_seq(dsi, 0x35, 0x16); + mipi_dsi_dcs_write_seq(dsi, 0xc8, 0x04); + mipi_dsi_dcs_write_seq(dsi, 0xc9, 0x82); + mipi_dsi_dcs_write_seq(dsi, 0xca, 0x4e); + mipi_dsi_dcs_write_seq(dsi, 0xcb, 0x00); + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_READ_PPS_CONTINUE, 0x4c); + mipi_dsi_dcs_write_seq(dsi, 0xaa, 0x47); + mipi_dsi_dcs_write_seq(dsi, 0xff, 0x27); + mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); + mipi_dsi_dcs_write_seq(dsi, 0x56, 0x06); + mipi_dsi_dcs_write_seq(dsi, 0x58, 0x80); + mipi_dsi_dcs_write_seq(dsi, 0x59, 0x53); + mipi_dsi_dcs_write_seq(dsi, 0x5a, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0x5b, 0x14); + mipi_dsi_dcs_write_seq(dsi, 0x5c, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0x5d, 0x01); + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_CABC_MIN_BRIGHTNESS, 0x20); + mipi_dsi_dcs_write_seq(dsi, 0x5f, 0x10); + mipi_dsi_dcs_write_seq(dsi, 0x60, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0x61, 0x1d); + mipi_dsi_dcs_write_seq(dsi, 0x62, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0x63, 0x01); + mipi_dsi_dcs_write_seq(dsi, 0x64, 0x24); + mipi_dsi_dcs_write_seq(dsi, 0x65, 0x1c); + mipi_dsi_dcs_write_seq(dsi, 0x66, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0x67, 0x01); + mipi_dsi_dcs_write_seq(dsi, 0x68, 0x25); + mipi_dsi_dcs_write_seq(dsi, 0x00, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0x78, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0xc3, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0xd1, 0x24); + mipi_dsi_dcs_write_seq(dsi, 0xd2, 0x30); + mipi_dsi_dcs_write_seq(dsi, 0xff, 0x2a); + mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); + mipi_dsi_dcs_write_seq(dsi, 0x22, 0x2f); + mipi_dsi_dcs_write_seq(dsi, 0x23, 0x08); + mipi_dsi_dcs_write_seq(dsi, 0x24, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0x25, 0xc3); + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_GAMMA_CURVE, 0xf8); + mipi_dsi_dcs_write_seq(dsi, 0x27, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0x28, 0x1a); + mipi_dsi_dcs_write_seq(dsi, 0x29, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0x2a, 0x1a); + mipi_dsi_dcs_write_seq(dsi, 0x2b, 0x00); + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_LUT, 0x1a); + mipi_dsi_dcs_write_seq(dsi, 0xff, 0xe0); + mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); + mipi_dsi_dcs_write_seq(dsi, 0x14, 0x60); + mipi_dsi_dcs_write_seq(dsi, 0x16, 0xc0); + mipi_dsi_dcs_write_seq(dsi, 0xff, 0xf0); + mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); + + ret = mipi_dsi_dcs_set_pixel_format(dsi, 0x08); + if (ret < 0) { + dev_err(dev, "Failed to set pixel format: %d\n", ret); + return ret; + } + + mipi_dsi_dcs_write_seq(dsi, 0xff, 0x24); + mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); + + ret = mipi_dsi_dcs_set_pixel_format(dsi, 0x5d); + if (ret < 0) { + dev_err(dev, "Failed to set pixel format: %d\n", ret); + return ret; + } + + mipi_dsi_dcs_write_seq(dsi, 0x3b, 0x60); + mipi_dsi_dcs_write_seq(dsi, 0x4a, 0x5d); + mipi_dsi_dcs_write_seq(dsi, 0x4b, 0x60); + mipi_dsi_dcs_write_seq(dsi, 0x5a, 0x70); + mipi_dsi_dcs_write_seq(dsi, 0x5b, 0x60); + mipi_dsi_dcs_write_seq(dsi, 0x91, 0x44); + mipi_dsi_dcs_write_seq(dsi, 0x92, 0x75); + mipi_dsi_dcs_write_seq(dsi, 0xdb, 0x05); + mipi_dsi_dcs_write_seq(dsi, 0xdc, 0x75); + mipi_dsi_dcs_write_seq(dsi, 0xdd, 0x22); + mipi_dsi_dcs_write_seq(dsi, 0xdf, 0x05); + mipi_dsi_dcs_write_seq(dsi, 0xe0, 0x75); + mipi_dsi_dcs_write_seq(dsi, 0xe1, 0x05); + mipi_dsi_dcs_write_seq(dsi, 0xe2, 0x75); + mipi_dsi_dcs_write_seq(dsi, 0xe3, 0x05); + mipi_dsi_dcs_write_seq(dsi, 0xe4, 0x75); + mipi_dsi_dcs_write_seq(dsi, 0xe5, 0x05); + mipi_dsi_dcs_write_seq(dsi, 0xe6, 0x75); + mipi_dsi_dcs_write_seq(dsi, 0x5c, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0x5d, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0x8d, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0x8e, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0xff, 0x25); + mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); + mipi_dsi_dcs_write_seq(dsi, 0x1f, 0x70); + mipi_dsi_dcs_write_seq(dsi, 0x20, 0x60); + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_GAMMA_CURVE, 0x70); + mipi_dsi_dcs_write_seq(dsi, 0x27, 0x60); + mipi_dsi_dcs_write_seq(dsi, 0x33, 0x70); + mipi_dsi_dcs_write_seq(dsi, 0x34, 0x60); + mipi_dsi_dcs_write_seq(dsi, 0x48, 0x70); + mipi_dsi_dcs_write_seq(dsi, 0x49, 0x60); + mipi_dsi_dcs_write_seq(dsi, 0x5b, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0x61, 0x70); + mipi_dsi_dcs_write_seq(dsi, 0x62, 0x60); + mipi_dsi_dcs_write_seq(dsi, 0xff, 0x26); + mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); + mipi_dsi_dcs_write_seq(dsi, 0x02, 0x31); + mipi_dsi_dcs_write_seq(dsi, 0x19, 0x0a); + mipi_dsi_dcs_write_seq(dsi, 0x1a, 0x7f); + mipi_dsi_dcs_write_seq(dsi, 0x1b, 0x0a); + mipi_dsi_dcs_write_seq(dsi, 0x1c, 0x0c); + mipi_dsi_dcs_write_seq(dsi, 0x2a, 0x0a); + mipi_dsi_dcs_write_seq(dsi, 0x2b, 0x7f); + mipi_dsi_dcs_write_seq(dsi, 0x1e, 0x75); + mipi_dsi_dcs_write_seq(dsi, 0x1f, 0x75); + mipi_dsi_dcs_write_seq(dsi, 0x25, 0x75); + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_PARTIAL_ROWS, 0x75); + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_PARTIAL_COLUMNS, 0x05); + mipi_dsi_dcs_write_seq(dsi, 0x32, 0x8d); + + ret = mipi_dsi_dcs_set_pixel_format(dsi, 0x75); + if (ret < 0) { + dev_err(dev, "Failed to set pixel format: %d\n", ret); + return ret; + } + + mipi_dsi_dcs_write_seq(dsi, 0xff, 0x2a); + mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); + mipi_dsi_dcs_write_seq(dsi, 0x25, 0x75); + mipi_dsi_dcs_write_seq(dsi, 0xff, 0x10); + mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); + mipi_dsi_dcs_write_seq(dsi, 0xb9, 0x01); + mipi_dsi_dcs_write_seq(dsi, 0xff, 0x20); + mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); + mipi_dsi_dcs_write_seq(dsi, 0x18, 0x40); + mipi_dsi_dcs_write_seq(dsi, 0xff, 0x10); + mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); + mipi_dsi_dcs_write_seq(dsi, 0xb9, 0x02); + + ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK); + if (ret < 0) { + dev_err(dev, "Failed to set tear on: %d\n", ret); + return ret; + } + + mipi_dsi_dcs_write_seq(dsi, 0xbb, 0x13); + mipi_dsi_dcs_write_seq(dsi, 0x3b, 0x03, 0x5f, 0x1a, 0x04, 0x04); + mipi_dsi_dcs_write_seq(dsi, 0xff, 0x10); + usleep_range(10000, 11000); + mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); + + ret = mipi_dsi_dcs_set_display_brightness(dsi, 0); + if (ret < 0) { + dev_err(dev, "Failed to set display brightness: %d\n", ret); + return ret; + } + + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x2c); + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0x68, 0x05, 0x01); + + ret = mipi_dsi_dcs_exit_sleep_mode(dsi); + if (ret < 0) { + dev_err(dev, "Failed to exit sleep mode: %d\n", ret); + return ret; + } + msleep(100); + + ret = mipi_dsi_dcs_set_display_on(dsi); + if (ret < 0) { + dev_err(dev, "Failed to set display on: %d\n", ret); + return ret; + } + msleep(30); + + return 0; +} + +static int nt36523w_boe_off(struct nt36523w_boe *ctx) +{ + struct mipi_dsi_device *dsi = ctx->dsi; + struct device *dev = &dsi->dev; + int ret; + + ret = mipi_dsi_dcs_set_display_off(dsi); + if (ret < 0) { + dev_err(dev, "Failed to set display off: %d\n", ret); + return ret; + } + + ret = mipi_dsi_dcs_enter_sleep_mode(dsi); + if (ret < 0) { + dev_err(dev, "Failed to enter sleep mode: %d\n", ret); + return ret; + } + msleep(80); + + return 0; +} + +static int nt36523w_boe_prepare(struct drm_panel *panel) +{ + struct nt36523w_boe *ctx = to_nt36523w_boe(panel); + struct device *dev = &ctx->dsi->dev; + int ret; + + if (ctx->prepared) + return 0; + + ret = regulator_enable(ctx->supply); + if (ret < 0) { + dev_err(dev, "Failed to enable regulator: %d\n", ret); + return ret; + } + + nt36523w_boe_reset(ctx); + + ret = nt36523w_boe_on(ctx); + if (ret < 0) { + dev_err(dev, "Failed to initialize panel: %d\n", ret); + gpiod_set_value_cansleep(ctx->reset_gpio, 1); + regulator_disable(ctx->supply); + return ret; + } + + ctx->prepared = true; + return 0; +} + +static int nt36523w_boe_unprepare(struct drm_panel *panel) +{ + struct nt36523w_boe *ctx = to_nt36523w_boe(panel); + struct device *dev = &ctx->dsi->dev; + int ret; + + if (!ctx->prepared) + return 0; + + ret = nt36523w_boe_off(ctx); + if (ret < 0) + dev_err(dev, "Failed to un-initialize panel: %d\n", ret); + + gpiod_set_value_cansleep(ctx->reset_gpio, 1); + regulator_disable(ctx->supply); + + ctx->prepared = false; + return 0; +} + +static const struct drm_display_mode nt36523w_boe_mode = { + .clock = (1200 + 58 + 2 + 60) * (2000 + 26 + 2 + 93) * 60 / 1000, + .hdisplay = 1200, + .hsync_start = 1200 + 58, + .hsync_end = 1200 + 58 + 2, + .htotal = 1200 + 58 + 2 + 60, + .vdisplay = 2000, + .vsync_start = 2000 + 26, + .vsync_end = 2000 + 26 + 2, + .vtotal = 2000 + 26 + 2 + 93, + .width_mm = 143, + .height_mm = 235, +}; + +static int nt36523w_boe_get_modes(struct drm_panel *panel, struct drm_connector *connector) +{ + struct drm_display_mode *mode; + + mode = drm_mode_duplicate(connector->dev, &nt36523w_boe_mode); + if (!mode) + return -ENOMEM; + + drm_mode_set_name(mode); + + mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; + connector->display_info.width_mm = mode->width_mm; + connector->display_info.height_mm = mode->height_mm; + drm_mode_probed_add(connector, mode); + + return 1; +} + +static enum drm_panel_orientation nt36523w_boe_panel_get_orientation(struct drm_panel *panel) +{ + struct nt36523w_boe *ctx = to_nt36523w_boe(panel); + + return ctx->orientation; +} + +static const struct drm_panel_funcs nt36523w_boe_panel_funcs = { + .prepare = nt36523w_boe_prepare, + .unprepare = nt36523w_boe_unprepare, + .get_modes = nt36523w_boe_get_modes, + .get_orientation = nt36523w_boe_panel_get_orientation, +}; + +static int nt36523w_boe_bl_update_status(struct backlight_device *bl) +{ + struct mipi_dsi_device *dsi = bl_get_data(bl); + u16 brightness = backlight_get_brightness(bl); + int ret; + + brightness = cpu_to_be16(brightness); + + dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; + + ret = mipi_dsi_dcs_set_display_brightness(dsi, brightness); + if (ret < 0) + return ret; + + dsi->mode_flags |= MIPI_DSI_MODE_LPM; + + return 0; +} + +static int nt36523w_boe_bl_get_brightness(struct backlight_device *bl) +{ + struct mipi_dsi_device *dsi = bl_get_data(bl); + u16 brightness; + int ret; + + dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; + + ret = mipi_dsi_dcs_get_display_brightness(dsi, &brightness); + if (ret < 0) + return ret; + + dsi->mode_flags |= MIPI_DSI_MODE_LPM; + + brightness = be16_to_cpu(brightness); + + return brightness; +} + +static const struct backlight_ops nt36523w_boe_bl_ops = { + .update_status = nt36523w_boe_bl_update_status, + .get_brightness = nt36523w_boe_bl_get_brightness, +}; + +static struct backlight_device *nt36523w_boe_create_backlight(struct mipi_dsi_device *dsi) +{ + struct device *dev = &dsi->dev; + const struct backlight_properties props = { + .type = BACKLIGHT_RAW, + .brightness = 512, + .max_brightness = 4095, + }; + + return devm_backlight_device_register(dev, dev_name(dev), dev, dsi, + &nt36523w_boe_bl_ops, &props); +} + +static int nt36523w_boe_probe(struct mipi_dsi_device *dsi) +{ + struct device *dev = &dsi->dev; + struct nt36523w_boe *ctx; + int ret; + + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + ctx->supply = devm_regulator_get(dev, "vddio"); + if (IS_ERR(ctx->supply)) + return dev_err_probe(dev, PTR_ERR(ctx->supply), + "Failed to get vddio regulator\n"); + + ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(ctx->reset_gpio)) + return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), + "Failed to get reset-gpios\n"); + + ctx->dsi = dsi; + mipi_dsi_set_drvdata(dsi, ctx); + + dsi->lanes = 4; + dsi->format = MIPI_DSI_FMT_RGB888; + dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | + MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM; + + drm_panel_init(&ctx->panel, dev, &nt36523w_boe_panel_funcs, + DRM_MODE_CONNECTOR_DSI); + + ret = of_drm_get_panel_orientation(dev->of_node, &ctx->orientation); + if (ret < 0) { + dev_err(dev, "%pOF: failed to get orientation %d\n", dev->of_node, ret); + return ret; + } + + ctx->panel.backlight = nt36523w_boe_create_backlight(dsi); + if (IS_ERR(ctx->panel.backlight)) + return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight), + "Failed to create backlight\n"); + + drm_panel_add(&ctx->panel); + + ret = mipi_dsi_attach(dsi); + if (ret < 0) { + dev_err(dev, "Failed to attach to DSI host: %d\n", ret); + drm_panel_remove(&ctx->panel); + return ret; + } + + return 0; +} + +static void nt36523w_boe_remove(struct mipi_dsi_device *dsi) +{ + struct nt36523w_boe *ctx = mipi_dsi_get_drvdata(dsi); + int ret; + + ret = mipi_dsi_detach(dsi); + if (ret < 0) + dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret); + + drm_panel_remove(&ctx->panel); +} + +static const struct of_device_id nt36523w_boe_of_match[] = { + { .compatible = "lenovo,nt36523w-boe-j606" }, + { } +}; +MODULE_DEVICE_TABLE(of, nt36523w_boe_of_match); + +static struct mipi_dsi_driver nt36523w_boe_driver = { + .probe = nt36523w_boe_probe, + .remove = nt36523w_boe_remove, + .driver = { + .name = "panel-nt36523w-boe-2k", + .of_match_table = nt36523w_boe_of_match, + }, +}; +module_mipi_dsi_driver(nt36523w_boe_driver); + +MODULE_DESCRIPTION("DRM panel driver for Lenovo Tab P11 BOE panel"); +MODULE_LICENSE("GPL"); -- 2.39.1 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] gpu/drm/panel: Add Lenovo NT36523W BOE panel 2023-02-17 11:29 ` [PATCH 2/2] gpu/drm/panel: " Konrad Dybcio @ 2023-03-07 9:16 ` Neil Armstrong 2023-03-07 9:19 ` Neil Armstrong 1 sibling, 0 replies; 9+ messages in thread From: Neil Armstrong @ 2023-03-07 9:16 UTC (permalink / raw) To: Konrad Dybcio, Thierry Reding, Sam Ravnborg, David Airlie, Daniel Vetter, Rob Herring, Krzysztof Kozlowski Cc: dri-devel, devicetree, linux-kernel On 17/02/2023 12:29, Konrad Dybcio wrote: > Introduce support for the BOE panel with a NT36523W touch/driver IC > found on some Lenovo Tab P11 devices. It's a 2000x1200, 24bit RGB > MIPI DSI panel with integrated DCS-controlled backlight (that expects > big-endian communication). > > Signed-off-by: Konrad Dybcio <konrad.dybcio@linaro.org> > --- > drivers/gpu/drm/panel/Kconfig | 12 + > drivers/gpu/drm/panel/Makefile | 1 + > drivers/gpu/drm/panel/panel-lenovo-nt36523w-boe.c | 751 ++++++++++++++++++++++ > 3 files changed, 764 insertions(+) > > diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig > index 8eeee71c0000..2abc89284a77 100644 > --- a/drivers/gpu/drm/panel/Kconfig > +++ b/drivers/gpu/drm/panel/Kconfig > @@ -297,6 +297,18 @@ config DRM_PANEL_LEADTEK_LTK500HD1829 > 24 bit RGB per pixel. It provides a MIPI DSI interface to > the host and has a built-in LED backlight. > > +config DRM_PANEL_LENOVO_NT36523W_BOE > + tristate "Lenovo NT36523W BOE panel" > + depends on OF > + depends on DRM_MIPI_DSI > + depends on BACKLIGHT_CLASS_DEVICE > + help > + Say Y here if you want to enable support for BOE display panel with > + NT36523W driver/touch IC, found on some Lenovo Tab P11 devices. The > + panel has a 2000x1200 resolution and uses 24 bit RGB per pixel. It > + provides a MIPI DSI interface to the host and has a built-in LED > + backlight. > + > config DRM_PANEL_SAMSUNG_LD9040 > tristate "Samsung LD9040 RGB/SPI panel" > depends on OF && SPI > diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile > index c05aa9e23907..7ed908cc83a6 100644 > --- a/drivers/gpu/drm/panel/Makefile > +++ b/drivers/gpu/drm/panel/Makefile > @@ -27,6 +27,7 @@ obj-$(CONFIG_DRM_PANEL_KHADAS_TS050) += panel-khadas-ts050.o > obj-$(CONFIG_DRM_PANEL_KINGDISPLAY_KD097D04) += panel-kingdisplay-kd097d04.o > obj-$(CONFIG_DRM_PANEL_LEADTEK_LTK050H3146W) += panel-leadtek-ltk050h3146w.o > obj-$(CONFIG_DRM_PANEL_LEADTEK_LTK500HD1829) += panel-leadtek-ltk500hd1829.o > +obj-$(CONFIG_DRM_PANEL_LENOVO_NT36523W_BOE) += panel-lenovo-nt36523w-boe.o > obj-$(CONFIG_DRM_PANEL_LG_LB035Q02) += panel-lg-lb035q02.o > obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o > obj-$(CONFIG_DRM_PANEL_NEC_NL8048HL11) += panel-nec-nl8048hl11.o > diff --git a/drivers/gpu/drm/panel/panel-lenovo-nt36523w-boe.c b/drivers/gpu/drm/panel/panel-lenovo-nt36523w-boe.c > new file mode 100644 > index 000000000000..83478e471493 > --- /dev/null > +++ b/drivers/gpu/drm/panel/panel-lenovo-nt36523w-boe.c > @@ -0,0 +1,751 @@ > +// SPDX-License-Identifier: GPL-2.0-only > +/* > + * Copyright (c) 2023 Linaro Limited > + * > + * Generated with linux-mdss-dsi-panel-driver-generator with > + * some manual adjustments. > + */ > +#include <linux/backlight.h> > +#include <linux/delay.h> > +#include <linux/gpio/consumer.h> > +#include <linux/module.h> > +#include <linux/of.h> > +#include <linux/regulator/consumer.h> > + > +#include <video/mipi_display.h> > + > +#include <drm/drm_mipi_dsi.h> > +#include <drm/drm_modes.h> > +#include <drm/drm_panel.h> > + > +struct nt36523w_boe { > + struct drm_panel panel; > + struct mipi_dsi_device *dsi; > + struct regulator *supply; > + struct gpio_desc *reset_gpio; > + enum drm_panel_orientation orientation; > + bool prepared; > +}; > + > +static inline struct nt36523w_boe *to_nt36523w_boe(struct drm_panel *panel) > +{ > + return container_of(panel, struct nt36523w_boe, panel); > +} > + > +static void nt36523w_boe_reset(struct nt36523w_boe *ctx) > +{ > + gpiod_set_value_cansleep(ctx->reset_gpio, 0); > + usleep_range(10000, 11000); > + gpiod_set_value_cansleep(ctx->reset_gpio, 1); > + usleep_range(5000, 6000); > + gpiod_set_value_cansleep(ctx->reset_gpio, 0); > + usleep_range(2000, 3000); > +} > + > +static int nt36523w_boe_on(struct nt36523w_boe *ctx) > +{ > + struct mipi_dsi_device *dsi = ctx->dsi; > + struct device *dev = &dsi->dev; > + int ret; > + > + mipi_dsi_dcs_write_seq(dsi, 0xff, 0x20); > + mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); > + mipi_dsi_dcs_write_seq(dsi, 0x05, 0xd9); > + mipi_dsi_dcs_write_seq(dsi, 0x07, 0x78); > + mipi_dsi_dcs_write_seq(dsi, 0x08, 0x5a); > + mipi_dsi_dcs_write_seq(dsi, 0x0d, 0x63); > + mipi_dsi_dcs_write_seq(dsi, 0x0e, 0x91); > + mipi_dsi_dcs_write_seq(dsi, 0x0f, 0x73); > + mipi_dsi_dcs_write_seq(dsi, 0x95, 0xeb); > + mipi_dsi_dcs_write_seq(dsi, 0x96, 0xeb); > + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_PARTIAL_ROWS, 0x11); > + mipi_dsi_dcs_write_seq(dsi, 0x6d, 0x66); > + mipi_dsi_dcs_write_seq(dsi, 0x75, 0xa2); > + mipi_dsi_dcs_write_seq(dsi, 0x77, 0xb3); > + mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x00, 0x08, 0x00, 0x23, 0x00, 0x4d, 0x00, 0x6d, 0x00, > + 0x89, 0x00, 0xa1, 0x00, 0xb6, 0x00, 0xc9); > + mipi_dsi_dcs_write_seq(dsi, 0xb1, 0x00, 0xda, 0x01, 0x13, 0x01, 0x3c, 0x01, 0x7e, 0x01, > + 0xab, 0x01, 0xf7, 0x02, 0x2f, 0x02, 0x31); > + mipi_dsi_dcs_write_seq(dsi, 0xb2, 0x02, 0x67, 0x02, 0xa6, 0x02, 0xd1, 0x03, 0x08, 0x03, > + 0x2e, 0x03, 0x5b, 0x03, 0x6b, 0x03, 0x7b); > + mipi_dsi_dcs_write_seq(dsi, 0xb3, 0x03, 0x8e, 0x03, 0xa2, 0x03, 0xb7, 0x03, 0xe7, 0x03, > + 0xfd, 0x03, 0xff); > + mipi_dsi_dcs_write_seq(dsi, 0xb4, 0x00, 0x08, 0x00, 0x23, 0x00, 0x4d, 0x00, 0x6d, 0x00, > + 0x89, 0x00, 0xa1, 0x00, 0xb6, 0x00, 0xc9); > + mipi_dsi_dcs_write_seq(dsi, 0xb5, 0x00, 0xda, 0x01, 0x13, 0x01, 0x3c, 0x01, 0x7e, 0x01, > + 0xab, 0x01, 0xf7, 0x02, 0x2f, 0x02, 0x31); > + mipi_dsi_dcs_write_seq(dsi, 0xb6, 0x02, 0x67, 0x02, 0xa6, 0x02, 0xd1, 0x03, 0x08, 0x03, > + 0x2e, 0x03, 0x5b, 0x03, 0x6b, 0x03, 0x7b); > + mipi_dsi_dcs_write_seq(dsi, 0xb7, 0x03, 0x8e, 0x03, 0xa2, 0x03, 0xb7, 0x03, 0xe7, 0x03, > + 0xfd, 0x03, 0xff); > + mipi_dsi_dcs_write_seq(dsi, 0xb8, 0x00, 0x08, 0x00, 0x23, 0x00, 0x4d, 0x00, 0x6d, 0x00, > + 0x89, 0x00, 0xa1, 0x00, 0xb6, 0x00, 0xc9); > + mipi_dsi_dcs_write_seq(dsi, 0xb9, 0x00, 0xda, 0x01, 0x13, 0x01, 0x3c, 0x01, 0x7e, 0x01, > + 0xab, 0x01, 0xf7, 0x02, 0x2f, 0x02, 0x31); > + mipi_dsi_dcs_write_seq(dsi, 0xba, 0x02, 0x67, 0x02, 0xa6, 0x02, 0xd1, 0x03, 0x08, 0x03, > + 0x2e, 0x03, 0x5b, 0x03, 0x6b, 0x03, 0x7b); > + mipi_dsi_dcs_write_seq(dsi, 0xbb, 0x03, 0x8e, 0x03, 0xa2, 0x03, 0xb7, 0x03, 0xe7, 0x03, > + 0xfd, 0x03, 0xff); > + mipi_dsi_dcs_write_seq(dsi, 0xff, 0x21); > + mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); > + mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x45, 0x00, 0x65, 0x00, > + 0x81, 0x00, 0x99, 0x00, 0xae, 0x00, 0xc1); > + mipi_dsi_dcs_write_seq(dsi, 0xb1, 0x00, 0xd2, 0x01, 0x0b, 0x01, 0x34, 0x01, 0x76, 0x01, > + 0xa3, 0x01, 0xef, 0x02, 0x27, 0x02, 0x29); > + mipi_dsi_dcs_write_seq(dsi, 0xb2, 0x02, 0x5f, 0x02, 0x9e, 0x02, 0xc9, 0x03, 0x00, 0x03, > + 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73); > + mipi_dsi_dcs_write_seq(dsi, 0xb3, 0x03, 0x86, 0x03, 0x9a, 0x03, 0xaf, 0x03, 0xdf, 0x03, > + 0xf5, 0x03, 0xf7); > + mipi_dsi_dcs_write_seq(dsi, 0xb4, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x45, 0x00, 0x65, 0x00, > + 0x81, 0x00, 0x99, 0x00, 0xae, 0x00, 0xc1); > + mipi_dsi_dcs_write_seq(dsi, 0xb5, 0x00, 0xd2, 0x01, 0x0b, 0x01, 0x34, 0x01, 0x76, 0x01, > + 0xa3, 0x01, 0xef, 0x02, 0x27, 0x02, 0x29); > + mipi_dsi_dcs_write_seq(dsi, 0xb6, 0x02, 0x5f, 0x02, 0x9e, 0x02, 0xc9, 0x03, 0x00, 0x03, > + 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73); > + mipi_dsi_dcs_write_seq(dsi, 0xb7, 0x03, 0x86, 0x03, 0x9a, 0x03, 0xaf, 0x03, 0xdf, 0x03, > + 0xf5, 0x03, 0xf7); > + mipi_dsi_dcs_write_seq(dsi, 0xb8, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x45, 0x00, 0x65, 0x00, > + 0x81, 0x00, 0x99, 0x00, 0xae, 0x00, 0xc1); > + mipi_dsi_dcs_write_seq(dsi, 0xb9, 0x00, 0xd2, 0x01, 0x0b, 0x01, 0x34, 0x01, 0x76, 0x01, > + 0xa3, 0x01, 0xef, 0x02, 0x27, 0x02, 0x29); > + mipi_dsi_dcs_write_seq(dsi, 0xba, 0x02, 0x5f, 0x02, 0x9e, 0x02, 0xc9, 0x03, 0x00, 0x03, > + 0x26, 0x03, 0x53, 0x03, 0x63, 0x03, 0x73); > + mipi_dsi_dcs_write_seq(dsi, 0xbb, 0x03, 0x86, 0x03, 0x9a, 0x03, 0xaf, 0x03, 0xdf, 0x03, > + 0xf5, 0x03, 0xf7); > + mipi_dsi_dcs_write_seq(dsi, 0xff, 0x23); > + mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); > + mipi_dsi_dcs_write_seq(dsi, 0x00, 0x80); > + mipi_dsi_dcs_write_seq(dsi, 0x07, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0x11, 0x01); > + mipi_dsi_dcs_write_seq(dsi, 0x12, 0x77); > + mipi_dsi_dcs_write_seq(dsi, 0x15, 0x07); > + mipi_dsi_dcs_write_seq(dsi, 0x16, 0x07); > + mipi_dsi_dcs_write_seq(dsi, 0xff, 0x24); > + mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); > + mipi_dsi_dcs_write_seq(dsi, 0x00, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0x01, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0x02, 0x1c); > + mipi_dsi_dcs_write_seq(dsi, 0x03, 0x1c); > + mipi_dsi_dcs_write_seq(dsi, 0x04, 0x1d); > + mipi_dsi_dcs_write_seq(dsi, 0x05, 0x1d); > + mipi_dsi_dcs_write_seq(dsi, 0x06, 0x04); > + mipi_dsi_dcs_write_seq(dsi, 0x07, 0x04); > + mipi_dsi_dcs_write_seq(dsi, 0x08, 0x0f); > + mipi_dsi_dcs_write_seq(dsi, 0x09, 0x0f); > + mipi_dsi_dcs_write_seq(dsi, 0x0a, 0x0e); > + mipi_dsi_dcs_write_seq(dsi, 0x0b, 0x0e); > + mipi_dsi_dcs_write_seq(dsi, 0x0c, 0x0d); > + mipi_dsi_dcs_write_seq(dsi, 0x0d, 0x0d); > + mipi_dsi_dcs_write_seq(dsi, 0x0e, 0x0c); > + mipi_dsi_dcs_write_seq(dsi, 0x0f, 0x0c); > + mipi_dsi_dcs_write_seq(dsi, 0x10, 0x08); > + mipi_dsi_dcs_write_seq(dsi, 0x11, 0x08); > + mipi_dsi_dcs_write_seq(dsi, 0x12, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0x13, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0x14, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0x15, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0x16, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0x17, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0x18, 0x1c); > + mipi_dsi_dcs_write_seq(dsi, 0x19, 0x1c); > + mipi_dsi_dcs_write_seq(dsi, 0x1a, 0x1d); > + mipi_dsi_dcs_write_seq(dsi, 0x1b, 0x1d); > + mipi_dsi_dcs_write_seq(dsi, 0x1c, 0x04); > + mipi_dsi_dcs_write_seq(dsi, 0x1d, 0x04); > + mipi_dsi_dcs_write_seq(dsi, 0x1e, 0x0f); > + mipi_dsi_dcs_write_seq(dsi, 0x1f, 0x0f); > + mipi_dsi_dcs_write_seq(dsi, 0x20, 0x0e); > + mipi_dsi_dcs_write_seq(dsi, 0x21, 0x0e); > + mipi_dsi_dcs_write_seq(dsi, 0x22, 0x0d); > + mipi_dsi_dcs_write_seq(dsi, 0x23, 0x0d); > + mipi_dsi_dcs_write_seq(dsi, 0x24, 0x0c); > + mipi_dsi_dcs_write_seq(dsi, 0x25, 0x0c); > + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_GAMMA_CURVE, 0x08); > + mipi_dsi_dcs_write_seq(dsi, 0x27, 0x08); > + mipi_dsi_dcs_write_seq(dsi, 0x28, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0x29, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0x2a, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0x2b, 0x00); > + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_LUT, 0x20); > + mipi_dsi_dcs_write_seq(dsi, 0x2f, 0x0a); > + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_PARTIAL_ROWS, 0x44); > + mipi_dsi_dcs_write_seq(dsi, 0x33, 0x0c); > + mipi_dsi_dcs_write_seq(dsi, 0x34, 0x32); > + mipi_dsi_dcs_write_seq(dsi, 0x37, 0x44); > + mipi_dsi_dcs_write_seq(dsi, 0x38, 0x40); > + mipi_dsi_dcs_write_seq(dsi, 0x39, 0x00); > + > + ret = mipi_dsi_dcs_set_pixel_format(dsi, 0x9a); > + if (ret < 0) { > + dev_err(dev, "Failed to set pixel format: %d\n", ret); > + return ret; > + } > + > + mipi_dsi_dcs_write_seq(dsi, 0x3b, 0xa0); > + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_3D_CONTROL, 0x42); > + mipi_dsi_dcs_write_seq(dsi, 0x3f, 0x06); > + mipi_dsi_dcs_write_seq(dsi, 0x43, 0x06); > + mipi_dsi_dcs_write_seq(dsi, 0x47, 0x66); > + mipi_dsi_dcs_write_seq(dsi, 0x4a, 0x9a); > + mipi_dsi_dcs_write_seq(dsi, 0x4b, 0xa0); > + mipi_dsi_dcs_write_seq(dsi, 0x4c, 0x91); > + mipi_dsi_dcs_write_seq(dsi, 0x4d, 0x21); > + mipi_dsi_dcs_write_seq(dsi, 0x4e, 0x43); > + > + ret = mipi_dsi_dcs_set_display_brightness(dsi, 18); > + if (ret < 0) { > + dev_err(dev, "Failed to set display brightness: %d\n", ret); > + return ret; > + } > + > + mipi_dsi_dcs_write_seq(dsi, 0x52, 0x34); > + mipi_dsi_dcs_write_seq(dsi, 0x55, 0x82, 0x02); > + mipi_dsi_dcs_write_seq(dsi, 0x56, 0x04); > + mipi_dsi_dcs_write_seq(dsi, 0x58, 0x21); > + mipi_dsi_dcs_write_seq(dsi, 0x59, 0x30); > + mipi_dsi_dcs_write_seq(dsi, 0x5a, 0xba); > + mipi_dsi_dcs_write_seq(dsi, 0x5b, 0xa0); > + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_CABC_MIN_BRIGHTNESS, 0x00, 0x06); > + mipi_dsi_dcs_write_seq(dsi, 0x5f, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0x65, 0x82); > + mipi_dsi_dcs_write_seq(dsi, 0x7e, 0x20); > + mipi_dsi_dcs_write_seq(dsi, 0x7f, 0x3c); > + mipi_dsi_dcs_write_seq(dsi, 0x82, 0x04); > + mipi_dsi_dcs_write_seq(dsi, 0x97, 0xc0); > + mipi_dsi_dcs_write_seq(dsi, 0xb6, > + 0x05, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, > + 0x05, 0x00, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0x92, 0xc4); > + mipi_dsi_dcs_write_seq(dsi, 0x93, 0x1a); > + mipi_dsi_dcs_write_seq(dsi, 0x94, 0x5f); > + mipi_dsi_dcs_write_seq(dsi, 0xd7, 0x55); > + mipi_dsi_dcs_write_seq(dsi, 0xda, 0x0a); > + mipi_dsi_dcs_write_seq(dsi, 0xde, 0x08); > + mipi_dsi_dcs_write_seq(dsi, 0xdb, 0x05); > + mipi_dsi_dcs_write_seq(dsi, 0xdc, 0xc4); > + mipi_dsi_dcs_write_seq(dsi, 0xdd, 0x22); > + mipi_dsi_dcs_write_seq(dsi, 0xdf, 0x05); > + mipi_dsi_dcs_write_seq(dsi, 0xe0, 0xc4); > + mipi_dsi_dcs_write_seq(dsi, 0xe1, 0x05); > + mipi_dsi_dcs_write_seq(dsi, 0xe2, 0xc4); > + mipi_dsi_dcs_write_seq(dsi, 0xe3, 0x05); > + mipi_dsi_dcs_write_seq(dsi, 0xe4, 0xc4); > + mipi_dsi_dcs_write_seq(dsi, 0xe5, 0x05); > + mipi_dsi_dcs_write_seq(dsi, 0xe6, 0xc4); > + mipi_dsi_dcs_write_seq(dsi, 0x5c, 0x88); > + mipi_dsi_dcs_write_seq(dsi, 0x5d, 0x08); > + mipi_dsi_dcs_write_seq(dsi, 0x8d, 0x88); > + mipi_dsi_dcs_write_seq(dsi, 0x8e, 0x08); > + mipi_dsi_dcs_write_seq(dsi, 0xb5, 0x90); > + mipi_dsi_dcs_write_seq(dsi, 0xff, 0x25); > + mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); > + mipi_dsi_dcs_write_seq(dsi, 0x05, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0x19, 0x07); > + mipi_dsi_dcs_write_seq(dsi, 0x1f, 0xba); > + mipi_dsi_dcs_write_seq(dsi, 0x20, 0xa0); > + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_GAMMA_CURVE, 0xba); > + mipi_dsi_dcs_write_seq(dsi, 0x27, 0xa0); > + mipi_dsi_dcs_write_seq(dsi, 0x33, 0xba); > + mipi_dsi_dcs_write_seq(dsi, 0x34, 0xa0); > + mipi_dsi_dcs_write_seq(dsi, 0x3f, 0xe0); > + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_VSYNC_TIMING, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0x44, 0x00); > + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_GET_SCANLINE, 0x40); > + mipi_dsi_dcs_write_seq(dsi, 0x48, 0xba); > + mipi_dsi_dcs_write_seq(dsi, 0x49, 0xa0); > + mipi_dsi_dcs_write_seq(dsi, 0x5b, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0x5c, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0x5d, 0x00); > + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_CABC_MIN_BRIGHTNESS, 0xd0); > + mipi_dsi_dcs_write_seq(dsi, 0x61, 0xba); > + mipi_dsi_dcs_write_seq(dsi, 0x62, 0xa0); > + mipi_dsi_dcs_write_seq(dsi, 0xf1, 0x10); > + mipi_dsi_dcs_write_seq(dsi, 0xff, 0x2a); > + mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); > + mipi_dsi_dcs_write_seq(dsi, 0x64, 0x16); > + mipi_dsi_dcs_write_seq(dsi, 0x67, 0x16); > + mipi_dsi_dcs_write_seq(dsi, 0x6a, 0x16); > + mipi_dsi_dcs_write_seq(dsi, 0x70, 0x30); > + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_READ_PPS_START, 0xf3); > + mipi_dsi_dcs_write_seq(dsi, 0xa3, 0xff); > + mipi_dsi_dcs_write_seq(dsi, 0xa4, 0xff); > + mipi_dsi_dcs_write_seq(dsi, 0xa5, 0xff); > + mipi_dsi_dcs_write_seq(dsi, 0xd6, 0x08); > + mipi_dsi_dcs_write_seq(dsi, 0xff, 0x26); > + mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); > + mipi_dsi_dcs_write_seq(dsi, 0x00, 0xa1); > + mipi_dsi_dcs_write_seq(dsi, 0x0a, 0xf2); > + mipi_dsi_dcs_write_seq(dsi, 0x04, 0x28); > + mipi_dsi_dcs_write_seq(dsi, 0x06, 0x30); > + mipi_dsi_dcs_write_seq(dsi, 0x0c, 0x13); > + mipi_dsi_dcs_write_seq(dsi, 0x0d, 0x0a); > + mipi_dsi_dcs_write_seq(dsi, 0x0f, 0x0a); > + mipi_dsi_dcs_write_seq(dsi, 0x11, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0x12, 0x50); > + mipi_dsi_dcs_write_seq(dsi, 0x13, 0x51); > + mipi_dsi_dcs_write_seq(dsi, 0x14, 0x65); > + mipi_dsi_dcs_write_seq(dsi, 0x15, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0x16, 0x10); > + mipi_dsi_dcs_write_seq(dsi, 0x17, 0xa0); > + mipi_dsi_dcs_write_seq(dsi, 0x18, 0x86); > + mipi_dsi_dcs_write_seq(dsi, 0x19, 0x11); > + mipi_dsi_dcs_write_seq(dsi, 0x1a, 0x7b); > + mipi_dsi_dcs_write_seq(dsi, 0x1b, 0x10); > + mipi_dsi_dcs_write_seq(dsi, 0x1c, 0xbb); > + mipi_dsi_dcs_write_seq(dsi, 0x22, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0x23, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0x2a, 0x11); > + mipi_dsi_dcs_write_seq(dsi, 0x2b, 0x7b); > + mipi_dsi_dcs_write_seq(dsi, 0x1d, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0x1e, 0xc3); > + mipi_dsi_dcs_write_seq(dsi, 0x1f, 0xc3); > + mipi_dsi_dcs_write_seq(dsi, 0x24, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0x25, 0xc3); > + mipi_dsi_dcs_write_seq(dsi, 0x2f, 0x05); > + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_PARTIAL_ROWS, 0xc3); > + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_PARTIAL_COLUMNS, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0x32, 0xc3); > + mipi_dsi_dcs_write_seq(dsi, 0x39, 0x00); > + > + ret = mipi_dsi_dcs_set_pixel_format(dsi, 0xc3); > + if (ret < 0) { > + dev_err(dev, "Failed to set pixel format: %d\n", ret); > + return ret; > + } > + > + mipi_dsi_dcs_write_seq(dsi, 0x20, 0x01); > + mipi_dsi_dcs_write_seq(dsi, 0x33, 0x11); > + mipi_dsi_dcs_write_seq(dsi, 0x34, 0x78); > + mipi_dsi_dcs_write_seq(dsi, 0x35, 0x16); > + mipi_dsi_dcs_write_seq(dsi, 0xc8, 0x04); > + mipi_dsi_dcs_write_seq(dsi, 0xc9, 0x82); > + mipi_dsi_dcs_write_seq(dsi, 0xca, 0x4e); > + mipi_dsi_dcs_write_seq(dsi, 0xcb, 0x00); > + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_READ_PPS_CONTINUE, 0x4c); > + mipi_dsi_dcs_write_seq(dsi, 0xaa, 0x47); > + mipi_dsi_dcs_write_seq(dsi, 0xff, 0x27); > + mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); > + mipi_dsi_dcs_write_seq(dsi, 0x56, 0x06); > + mipi_dsi_dcs_write_seq(dsi, 0x58, 0x80); > + mipi_dsi_dcs_write_seq(dsi, 0x59, 0x53); > + mipi_dsi_dcs_write_seq(dsi, 0x5a, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0x5b, 0x14); > + mipi_dsi_dcs_write_seq(dsi, 0x5c, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0x5d, 0x01); > + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_CABC_MIN_BRIGHTNESS, 0x20); > + mipi_dsi_dcs_write_seq(dsi, 0x5f, 0x10); > + mipi_dsi_dcs_write_seq(dsi, 0x60, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0x61, 0x1d); > + mipi_dsi_dcs_write_seq(dsi, 0x62, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0x63, 0x01); > + mipi_dsi_dcs_write_seq(dsi, 0x64, 0x24); > + mipi_dsi_dcs_write_seq(dsi, 0x65, 0x1c); > + mipi_dsi_dcs_write_seq(dsi, 0x66, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0x67, 0x01); > + mipi_dsi_dcs_write_seq(dsi, 0x68, 0x25); > + mipi_dsi_dcs_write_seq(dsi, 0x00, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0x78, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0xc3, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0xd1, 0x24); > + mipi_dsi_dcs_write_seq(dsi, 0xd2, 0x30); > + mipi_dsi_dcs_write_seq(dsi, 0xff, 0x2a); > + mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); > + mipi_dsi_dcs_write_seq(dsi, 0x22, 0x2f); > + mipi_dsi_dcs_write_seq(dsi, 0x23, 0x08); > + mipi_dsi_dcs_write_seq(dsi, 0x24, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0x25, 0xc3); > + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_GAMMA_CURVE, 0xf8); > + mipi_dsi_dcs_write_seq(dsi, 0x27, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0x28, 0x1a); > + mipi_dsi_dcs_write_seq(dsi, 0x29, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0x2a, 0x1a); > + mipi_dsi_dcs_write_seq(dsi, 0x2b, 0x00); > + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_LUT, 0x1a); > + mipi_dsi_dcs_write_seq(dsi, 0xff, 0xe0); > + mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); > + mipi_dsi_dcs_write_seq(dsi, 0x14, 0x60); > + mipi_dsi_dcs_write_seq(dsi, 0x16, 0xc0); > + mipi_dsi_dcs_write_seq(dsi, 0xff, 0xf0); > + mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); > + > + ret = mipi_dsi_dcs_set_pixel_format(dsi, 0x08); > + if (ret < 0) { > + dev_err(dev, "Failed to set pixel format: %d\n", ret); > + return ret; > + } > + > + mipi_dsi_dcs_write_seq(dsi, 0xff, 0x24); > + mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); > + > + ret = mipi_dsi_dcs_set_pixel_format(dsi, 0x5d); > + if (ret < 0) { > + dev_err(dev, "Failed to set pixel format: %d\n", ret); > + return ret; > + } > + > + mipi_dsi_dcs_write_seq(dsi, 0x3b, 0x60); > + mipi_dsi_dcs_write_seq(dsi, 0x4a, 0x5d); > + mipi_dsi_dcs_write_seq(dsi, 0x4b, 0x60); > + mipi_dsi_dcs_write_seq(dsi, 0x5a, 0x70); > + mipi_dsi_dcs_write_seq(dsi, 0x5b, 0x60); > + mipi_dsi_dcs_write_seq(dsi, 0x91, 0x44); > + mipi_dsi_dcs_write_seq(dsi, 0x92, 0x75); > + mipi_dsi_dcs_write_seq(dsi, 0xdb, 0x05); > + mipi_dsi_dcs_write_seq(dsi, 0xdc, 0x75); > + mipi_dsi_dcs_write_seq(dsi, 0xdd, 0x22); > + mipi_dsi_dcs_write_seq(dsi, 0xdf, 0x05); > + mipi_dsi_dcs_write_seq(dsi, 0xe0, 0x75); > + mipi_dsi_dcs_write_seq(dsi, 0xe1, 0x05); > + mipi_dsi_dcs_write_seq(dsi, 0xe2, 0x75); > + mipi_dsi_dcs_write_seq(dsi, 0xe3, 0x05); > + mipi_dsi_dcs_write_seq(dsi, 0xe4, 0x75); > + mipi_dsi_dcs_write_seq(dsi, 0xe5, 0x05); > + mipi_dsi_dcs_write_seq(dsi, 0xe6, 0x75); > + mipi_dsi_dcs_write_seq(dsi, 0x5c, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0x5d, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0x8d, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0x8e, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0xff, 0x25); > + mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); > + mipi_dsi_dcs_write_seq(dsi, 0x1f, 0x70); > + mipi_dsi_dcs_write_seq(dsi, 0x20, 0x60); > + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_GAMMA_CURVE, 0x70); > + mipi_dsi_dcs_write_seq(dsi, 0x27, 0x60); > + mipi_dsi_dcs_write_seq(dsi, 0x33, 0x70); > + mipi_dsi_dcs_write_seq(dsi, 0x34, 0x60); > + mipi_dsi_dcs_write_seq(dsi, 0x48, 0x70); > + mipi_dsi_dcs_write_seq(dsi, 0x49, 0x60); > + mipi_dsi_dcs_write_seq(dsi, 0x5b, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0x61, 0x70); > + mipi_dsi_dcs_write_seq(dsi, 0x62, 0x60); > + mipi_dsi_dcs_write_seq(dsi, 0xff, 0x26); > + mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); > + mipi_dsi_dcs_write_seq(dsi, 0x02, 0x31); > + mipi_dsi_dcs_write_seq(dsi, 0x19, 0x0a); > + mipi_dsi_dcs_write_seq(dsi, 0x1a, 0x7f); > + mipi_dsi_dcs_write_seq(dsi, 0x1b, 0x0a); > + mipi_dsi_dcs_write_seq(dsi, 0x1c, 0x0c); > + mipi_dsi_dcs_write_seq(dsi, 0x2a, 0x0a); > + mipi_dsi_dcs_write_seq(dsi, 0x2b, 0x7f); > + mipi_dsi_dcs_write_seq(dsi, 0x1e, 0x75); > + mipi_dsi_dcs_write_seq(dsi, 0x1f, 0x75); > + mipi_dsi_dcs_write_seq(dsi, 0x25, 0x75); > + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_PARTIAL_ROWS, 0x75); > + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_PARTIAL_COLUMNS, 0x05); > + mipi_dsi_dcs_write_seq(dsi, 0x32, 0x8d); > + > + ret = mipi_dsi_dcs_set_pixel_format(dsi, 0x75); > + if (ret < 0) { > + dev_err(dev, "Failed to set pixel format: %d\n", ret); > + return ret; > + } > + > + mipi_dsi_dcs_write_seq(dsi, 0xff, 0x2a); > + mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); > + mipi_dsi_dcs_write_seq(dsi, 0x25, 0x75); > + mipi_dsi_dcs_write_seq(dsi, 0xff, 0x10); > + mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); > + mipi_dsi_dcs_write_seq(dsi, 0xb9, 0x01); > + mipi_dsi_dcs_write_seq(dsi, 0xff, 0x20); > + mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); > + mipi_dsi_dcs_write_seq(dsi, 0x18, 0x40); > + mipi_dsi_dcs_write_seq(dsi, 0xff, 0x10); > + mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); > + mipi_dsi_dcs_write_seq(dsi, 0xb9, 0x02); > + > + ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK); > + if (ret < 0) { > + dev_err(dev, "Failed to set tear on: %d\n", ret); > + return ret; > + } > + > + mipi_dsi_dcs_write_seq(dsi, 0xbb, 0x13); > + mipi_dsi_dcs_write_seq(dsi, 0x3b, 0x03, 0x5f, 0x1a, 0x04, 0x04); > + mipi_dsi_dcs_write_seq(dsi, 0xff, 0x10); > + usleep_range(10000, 11000); > + mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01); > + > + ret = mipi_dsi_dcs_set_display_brightness(dsi, 0); > + if (ret < 0) { > + dev_err(dev, "Failed to set display brightness: %d\n", ret); > + return ret; > + } > + > + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x2c); > + mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x00); > + mipi_dsi_dcs_write_seq(dsi, 0x68, 0x05, 0x01); > + > + ret = mipi_dsi_dcs_exit_sleep_mode(dsi); > + if (ret < 0) { > + dev_err(dev, "Failed to exit sleep mode: %d\n", ret); > + return ret; > + } > + msleep(100); > + > + ret = mipi_dsi_dcs_set_display_on(dsi); > + if (ret < 0) { > + dev_err(dev, "Failed to set display on: %d\n", ret); > + return ret; > + } > + msleep(30); > + > + return 0; > +} > + > +static int nt36523w_boe_off(struct nt36523w_boe *ctx) > +{ > + struct mipi_dsi_device *dsi = ctx->dsi; > + struct device *dev = &dsi->dev; > + int ret; > + > + ret = mipi_dsi_dcs_set_display_off(dsi); > + if (ret < 0) { > + dev_err(dev, "Failed to set display off: %d\n", ret); > + return ret; > + } > + > + ret = mipi_dsi_dcs_enter_sleep_mode(dsi); > + if (ret < 0) { > + dev_err(dev, "Failed to enter sleep mode: %d\n", ret); > + return ret; > + } > + msleep(80); > + > + return 0; > +} > + > +static int nt36523w_boe_prepare(struct drm_panel *panel) > +{ > + struct nt36523w_boe *ctx = to_nt36523w_boe(panel); > + struct device *dev = &ctx->dsi->dev; > + int ret; > + > + if (ctx->prepared) > + return 0; > + > + ret = regulator_enable(ctx->supply); > + if (ret < 0) { > + dev_err(dev, "Failed to enable regulator: %d\n", ret); > + return ret; > + } > + > + nt36523w_boe_reset(ctx); > + > + ret = nt36523w_boe_on(ctx); > + if (ret < 0) { > + dev_err(dev, "Failed to initialize panel: %d\n", ret); > + gpiod_set_value_cansleep(ctx->reset_gpio, 1); > + regulator_disable(ctx->supply); > + return ret; > + } > + > + ctx->prepared = true; > + return 0; > +} > + > +static int nt36523w_boe_unprepare(struct drm_panel *panel) > +{ > + struct nt36523w_boe *ctx = to_nt36523w_boe(panel); > + struct device *dev = &ctx->dsi->dev; > + int ret; > + > + if (!ctx->prepared) > + return 0; > + > + ret = nt36523w_boe_off(ctx); > + if (ret < 0) > + dev_err(dev, "Failed to un-initialize panel: %d\n", ret); > + > + gpiod_set_value_cansleep(ctx->reset_gpio, 1); > + regulator_disable(ctx->supply); > + > + ctx->prepared = false; > + return 0; > +} > + > +static const struct drm_display_mode nt36523w_boe_mode = { > + .clock = (1200 + 58 + 2 + 60) * (2000 + 26 + 2 + 93) * 60 / 1000, > + .hdisplay = 1200, > + .hsync_start = 1200 + 58, > + .hsync_end = 1200 + 58 + 2, > + .htotal = 1200 + 58 + 2 + 60, > + .vdisplay = 2000, > + .vsync_start = 2000 + 26, > + .vsync_end = 2000 + 26 + 2, > + .vtotal = 2000 + 26 + 2 + 93, > + .width_mm = 143, > + .height_mm = 235, > +}; > + > +static int nt36523w_boe_get_modes(struct drm_panel *panel, struct drm_connector *connector) > +{ > + struct drm_display_mode *mode; > + > + mode = drm_mode_duplicate(connector->dev, &nt36523w_boe_mode); > + if (!mode) > + return -ENOMEM; > + > + drm_mode_set_name(mode); > + > + mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; > + connector->display_info.width_mm = mode->width_mm; > + connector->display_info.height_mm = mode->height_mm; > + drm_mode_probed_add(connector, mode); > + > + return 1; > +} > + > +static enum drm_panel_orientation nt36523w_boe_panel_get_orientation(struct drm_panel *panel) > +{ > + struct nt36523w_boe *ctx = to_nt36523w_boe(panel); > + > + return ctx->orientation; > +} > + > +static const struct drm_panel_funcs nt36523w_boe_panel_funcs = { > + .prepare = nt36523w_boe_prepare, > + .unprepare = nt36523w_boe_unprepare, > + .get_modes = nt36523w_boe_get_modes, > + .get_orientation = nt36523w_boe_panel_get_orientation, > +}; > + > +static int nt36523w_boe_bl_update_status(struct backlight_device *bl) > +{ > + struct mipi_dsi_device *dsi = bl_get_data(bl); > + u16 brightness = backlight_get_brightness(bl); > + int ret; > + > + brightness = cpu_to_be16(brightness); > + > + dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; > + > + ret = mipi_dsi_dcs_set_display_brightness(dsi, brightness); > + if (ret < 0) > + return ret; > + > + dsi->mode_flags |= MIPI_DSI_MODE_LPM; > + > + return 0; > +} > + > +static int nt36523w_boe_bl_get_brightness(struct backlight_device *bl) > +{ > + struct mipi_dsi_device *dsi = bl_get_data(bl); > + u16 brightness; > + int ret; > + > + dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; > + > + ret = mipi_dsi_dcs_get_display_brightness(dsi, &brightness); > + if (ret < 0) > + return ret; > + > + dsi->mode_flags |= MIPI_DSI_MODE_LPM; > + > + brightness = be16_to_cpu(brightness); > + > + return brightness; > +} > + > +static const struct backlight_ops nt36523w_boe_bl_ops = { > + .update_status = nt36523w_boe_bl_update_status, > + .get_brightness = nt36523w_boe_bl_get_brightness, > +}; > + > +static struct backlight_device *nt36523w_boe_create_backlight(struct mipi_dsi_device *dsi) > +{ > + struct device *dev = &dsi->dev; > + const struct backlight_properties props = { > + .type = BACKLIGHT_RAW, > + .brightness = 512, > + .max_brightness = 4095, > + }; > + > + return devm_backlight_device_register(dev, dev_name(dev), dev, dsi, > + &nt36523w_boe_bl_ops, &props); > +} > + > +static int nt36523w_boe_probe(struct mipi_dsi_device *dsi) > +{ > + struct device *dev = &dsi->dev; > + struct nt36523w_boe *ctx; > + int ret; > + > + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); > + if (!ctx) > + return -ENOMEM; > + > + ctx->supply = devm_regulator_get(dev, "vddio"); > + if (IS_ERR(ctx->supply)) > + return dev_err_probe(dev, PTR_ERR(ctx->supply), > + "Failed to get vddio regulator\n"); > + > + ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); > + if (IS_ERR(ctx->reset_gpio)) > + return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), > + "Failed to get reset-gpios\n"); > + > + ctx->dsi = dsi; > + mipi_dsi_set_drvdata(dsi, ctx); > + > + dsi->lanes = 4; > + dsi->format = MIPI_DSI_FMT_RGB888; > + dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | > + MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM; > + > + drm_panel_init(&ctx->panel, dev, &nt36523w_boe_panel_funcs, > + DRM_MODE_CONNECTOR_DSI); > + > + ret = of_drm_get_panel_orientation(dev->of_node, &ctx->orientation); > + if (ret < 0) { > + dev_err(dev, "%pOF: failed to get orientation %d\n", dev->of_node, ret); > + return ret; > + } > + > + ctx->panel.backlight = nt36523w_boe_create_backlight(dsi); > + if (IS_ERR(ctx->panel.backlight)) > + return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight), > + "Failed to create backlight\n"); > + > + drm_panel_add(&ctx->panel); > + > + ret = mipi_dsi_attach(dsi); > + if (ret < 0) { > + dev_err(dev, "Failed to attach to DSI host: %d\n", ret); > + drm_panel_remove(&ctx->panel); > + return ret; > + } > + > + return 0; > +} > + > +static void nt36523w_boe_remove(struct mipi_dsi_device *dsi) > +{ > + struct nt36523w_boe *ctx = mipi_dsi_get_drvdata(dsi); > + int ret; > + > + ret = mipi_dsi_detach(dsi); > + if (ret < 0) > + dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret); > + > + drm_panel_remove(&ctx->panel); > +} > + > +static const struct of_device_id nt36523w_boe_of_match[] = { > + { .compatible = "lenovo,nt36523w-boe-j606" }, > + { } > +}; > +MODULE_DEVICE_TABLE(of, nt36523w_boe_of_match); > + > +static struct mipi_dsi_driver nt36523w_boe_driver = { > + .probe = nt36523w_boe_probe, > + .remove = nt36523w_boe_remove, > + .driver = { > + .name = "panel-nt36523w-boe-2k", > + .of_match_table = nt36523w_boe_of_match, > + }, > +}; > +module_mipi_dsi_driver(nt36523w_boe_driver); > + > +MODULE_DESCRIPTION("DRM panel driver for Lenovo Tab P11 BOE panel"); > +MODULE_LICENSE("GPL"); > Looks good to me Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org> ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] gpu/drm/panel: Add Lenovo NT36523W BOE panel 2023-02-17 11:29 ` [PATCH 2/2] gpu/drm/panel: " Konrad Dybcio 2023-03-07 9:16 ` Neil Armstrong @ 2023-03-07 9:19 ` Neil Armstrong 2023-03-07 11:13 ` Konrad Dybcio 1 sibling, 1 reply; 9+ messages in thread From: Neil Armstrong @ 2023-03-07 9:19 UTC (permalink / raw) To: Konrad Dybcio, Thierry Reding, Sam Ravnborg, David Airlie, Daniel Vetter, Rob Herring, Krzysztof Kozlowski Cc: dri-devel, devicetree, linux-kernel Hi, On 17/02/2023 12:29, Konrad Dybcio wrote: > Introduce support for the BOE panel with a NT36523W touch/driver IC > found on some Lenovo Tab P11 devices. It's a 2000x1200, 24bit RGB > MIPI DSI panel with integrated DCS-controlled backlight (that expects > big-endian communication). > > Signed-off-by: Konrad Dybcio <konrad.dybcio@linaro.org> > --- > drivers/gpu/drm/panel/Kconfig | 12 + > drivers/gpu/drm/panel/Makefile | 1 + > drivers/gpu/drm/panel/panel-lenovo-nt36523w-boe.c | 751 ++++++++++++++++++++++ > 3 files changed, 764 insertions(+) > <snip> > diff --git a/drivers/gpu/drm/panel/panel-lenovo-nt36523w-boe.c b/drivers/gpu/drm/panel/panel-lenovo-nt36523w-boe.c > new file mode 100644 > index 000000000000..83478e471493 > --- /dev/null > +++ b/drivers/gpu/drm/panel/panel-lenovo-nt36523w-boe.c > @@ -0,0 +1,751 @@ > +// SPDX-License-Identifier: GPL-2.0-only > +/* > + * Copyright (c) 2023 Linaro Limited > + * > + * Generated with linux-mdss-dsi-panel-driver-generator with > + * some manual adjustments. > + */ <snip> > +static int nt36523w_boe_bl_update_status(struct backlight_device *bl) > +{ > + struct mipi_dsi_device *dsi = bl_get_data(bl); > + u16 brightness = backlight_get_brightness(bl); > + int ret; > + > + brightness = cpu_to_be16(brightness); > + > + dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; > + > + ret = mipi_dsi_dcs_set_display_brightness(dsi, brightness); > + if (ret < 0) > + return ret; It's not wrong as is, but could you switch to mipi_dsi_dcs_set_display_brightness_large() ? > + > + dsi->mode_flags |= MIPI_DSI_MODE_LPM; > + > + return 0; > +} > + > +static int nt36523w_boe_bl_get_brightness(struct backlight_device *bl) > +{ > + struct mipi_dsi_device *dsi = bl_get_data(bl); > + u16 brightness; > + int ret; > + > + dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; > + > + ret = mipi_dsi_dcs_get_display_brightness(dsi, &brightness); And here to mipi_dsi_dcs_get_display_brightness_large() ? > + if (ret < 0) > + return ret; > + > + dsi->mode_flags |= MIPI_DSI_MODE_LPM; > + > + brightness = be16_to_cpu(brightness); > + > + return brightness; > +} > + Please send a v2 with those changes and keep my reviewed-by Thanks! Neil ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] gpu/drm/panel: Add Lenovo NT36523W BOE panel 2023-03-07 9:19 ` Neil Armstrong @ 2023-03-07 11:13 ` Konrad Dybcio 0 siblings, 0 replies; 9+ messages in thread From: Konrad Dybcio @ 2023-03-07 11:13 UTC (permalink / raw) To: neil.armstrong, Thierry Reding, Sam Ravnborg, David Airlie, Daniel Vetter, Rob Herring, Krzysztof Kozlowski Cc: dri-devel, devicetree, linux-kernel On 7.03.2023 10:19, Neil Armstrong wrote: > Hi, > > On 17/02/2023 12:29, Konrad Dybcio wrote: >> Introduce support for the BOE panel with a NT36523W touch/driver IC >> found on some Lenovo Tab P11 devices. It's a 2000x1200, 24bit RGB >> MIPI DSI panel with integrated DCS-controlled backlight (that expects >> big-endian communication). >> >> Signed-off-by: Konrad Dybcio <konrad.dybcio@linaro.org> >> --- >> drivers/gpu/drm/panel/Kconfig | 12 + >> drivers/gpu/drm/panel/Makefile | 1 + >> drivers/gpu/drm/panel/panel-lenovo-nt36523w-boe.c | 751 ++++++++++++++++++++++ >> 3 files changed, 764 insertions(+) >> > > <snip> > >> diff --git a/drivers/gpu/drm/panel/panel-lenovo-nt36523w-boe.c b/drivers/gpu/drm/panel/panel-lenovo-nt36523w-boe.c >> new file mode 100644 >> index 000000000000..83478e471493 >> --- /dev/null >> +++ b/drivers/gpu/drm/panel/panel-lenovo-nt36523w-boe.c >> @@ -0,0 +1,751 @@ >> +// SPDX-License-Identifier: GPL-2.0-only >> +/* >> + * Copyright (c) 2023 Linaro Limited >> + * >> + * Generated with linux-mdss-dsi-panel-driver-generator with >> + * some manual adjustments. >> + */ > > <snip> > >> +static int nt36523w_boe_bl_update_status(struct backlight_device *bl) >> +{ >> + struct mipi_dsi_device *dsi = bl_get_data(bl); >> + u16 brightness = backlight_get_brightness(bl); >> + int ret; >> + >> + brightness = cpu_to_be16(brightness); >> + >> + dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; >> + >> + ret = mipi_dsi_dcs_set_display_brightness(dsi, brightness); >> + if (ret < 0) >> + return ret; > > It's not wrong as is, but could you switch to mipi_dsi_dcs_set_display_brightness_large() ? Sure! Recent-ish panels only talk BE brightness data, very cool that somebody made a wrapper for this! Konrad > >> + >> + dsi->mode_flags |= MIPI_DSI_MODE_LPM; >> + >> + return 0; >> +} >> + >> +static int nt36523w_boe_bl_get_brightness(struct backlight_device *bl) >> +{ >> + struct mipi_dsi_device *dsi = bl_get_data(bl); >> + u16 brightness; >> + int ret; >> + >> + dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; >> + >> + ret = mipi_dsi_dcs_get_display_brightness(dsi, &brightness); > > And here to mipi_dsi_dcs_get_display_brightness_large() ? >> + if (ret < 0) >> + return ret; >> + >> + dsi->mode_flags |= MIPI_DSI_MODE_LPM; >> + >> + brightness = be16_to_cpu(brightness); >> + >> + return brightness; >> +} >> + > Please send a v2 with those changes and keep my reviewed-by > > Thanks! > Neil ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2023-03-07 11:16 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2023-02-17 11:29 [PATCH 0/2] Add support for Lenovo NT36523W BOE panel Konrad Dybcio 2023-02-17 11:29 ` [PATCH 1/2] dt-bindings: display/panel: Add " Konrad Dybcio 2023-02-21 2:08 ` Rob Herring 2023-02-21 2:13 ` Konrad Dybcio 2023-02-26 17:41 ` Rob Herring 2023-02-17 11:29 ` [PATCH 2/2] gpu/drm/panel: " Konrad Dybcio 2023-03-07 9:16 ` Neil Armstrong 2023-03-07 9:19 ` Neil Armstrong 2023-03-07 11:13 ` Konrad Dybcio
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).