diff --git a/Documentation/devicetree/bindings/display/panel/jadard,jd9365da-h3.yaml b/Documentation/devicetree/bindings/display/panel/jadard,jd9365da-h3.yaml index b8783eba3ddc6..6ff79f90e983d 100644 --- a/Documentation/devicetree/bindings/display/panel/jadard,jd9365da-h3.yaml +++ b/Documentation/devicetree/bindings/display/panel/jadard,jd9365da-h3.yaml @@ -21,6 +21,12 @@ properties: - melfas,lmfbx101117480 - radxa,display-10hd-ad001 - radxa,display-8hd-ad002 + - waveshare,3.4-dsi-touch-c + - waveshare,4.0-dsi-touch-c + - waveshare,8.0-dsi-touch-a + - waveshare,9.0-dsi-touch-b + - waveshare,10.1-dsi-touch-a + - waveshare,10.1-dsi-touch-b - const: jadard,jd9365da-h3 reg: diff --git a/Documentation/devicetree/bindings/gpio/waveshare,dsi-touch-gpio.yaml b/Documentation/devicetree/bindings/gpio/waveshare,dsi-touch-gpio.yaml new file mode 100644 index 0000000000000..091e1fffcd476 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/waveshare,dsi-touch-gpio.yaml @@ -0,0 +1,73 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/gpio/waveshare,dsi-touch-gpio.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Waveshare GPIO controller on DSI TOUCH panels + +maintainers: + - Dmitry Baryshkov + +description: + Waveshare DSI TOUCH panel kits contain separate GPIO controller for toggling + power supplies and panel / touchscreen resets. + +properties: + compatible: + const: waveshare,dsi-touch-gpio + + reg: + maxItems: 1 + + gpio-controller: true + + '#gpio-cells': + const: 2 + +required: + - compatible + - reg + - gpio-controller + - "#gpio-cells" + +additionalProperties: false + +examples: + - | + #include + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + wsgpio: gpio@45 { + compatible = "waveshare,dsi-touch-gpio"; + reg = <0x45>; + gpio-controller; + #gpio-cells = <2>; + }; + }; + + panel_avdd: regulator-panel-avdd { + compatible = "regulator-fixed"; + regulator-name = "panel-avdd"; + gpios = <&wsgpio 0 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + panel_iovcc: regulator-panel-iovcc { + compatible = "regulator-fixed"; + regulator-name = "panel-iovcc"; + gpios = <&wsgpio 4 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + panel_vcc: regulator-panel-vcc { + compatible = "regulator-fixed"; + regulator-name = "panel-vcc"; + gpios = <&wsgpio 8 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-always-on; + }; +... diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 3b7284938babf..0d89f93fcb9b2 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -805,6 +805,16 @@ config GPIO_VISCONTI help Say yes here to support GPIO on Tohisba Visconti. +config GPIO_WAVESHARE_DSI_TOUCH + tristate "Waveshare GPIO controller for DSI panels" + depends on BACKLIGHT_CLASS_DEVICE + depends on I2C + select REGMAP_I2C + help + Enable support for the GPIO and PWM controller found on Waveshare DSI + TOUCH panel kits. It provides GPIOs (used for regulator control and + resets) and backlight support. + config GPIO_WCD934X tristate "Qualcomm Technologies Inc WCD9340/WCD9341 GPIO controller driver" depends on MFD_WCD934X && OF_GPIO diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index ec296fa14bfdb..6f31446a528df 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -201,6 +201,7 @@ obj-$(CONFIG_GPIO_VIRTUSER) += gpio-virtuser.o obj-$(CONFIG_GPIO_VIRTIO) += gpio-virtio.o obj-$(CONFIG_GPIO_VISCONTI) += gpio-visconti.o obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o +obj-$(CONFIG_GPIO_WAVESHARE_DSI_TOUCH) += gpio-waveshare-dsi.o obj-$(CONFIG_GPIO_WCD934X) += gpio-wcd934x.o obj-$(CONFIG_GPIO_WHISKEY_COVE) += gpio-wcove.o obj-$(CONFIG_GPIO_WINBOND) += gpio-winbond.o diff --git a/drivers/gpio/gpio-waveshare-dsi.c b/drivers/gpio/gpio-waveshare-dsi.c new file mode 100644 index 0000000000000..38f52351bb584 --- /dev/null +++ b/drivers/gpio/gpio-waveshare-dsi.c @@ -0,0 +1,208 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2024 Waveshare International Limited + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* I2C registers of the microcontroller. */ +#define REG_TP 0x94 +#define REG_LCD 0x95 +#define REG_PWM 0x96 +#define REG_SIZE 0x97 +#define REG_ID 0x98 +#define REG_VERSION 0x99 + +enum { + GPIO_AVDD = 0, + GPIO_PANEL_RESET = 1, + GPIO_BL_ENABLE = 2, + GPIO_IOVCC = 4, + GPIO_VCC = 8, + GPIO_TS_RESET = 9, +}; + +#define NUM_GPIO 16 + +struct waveshare_gpio { + struct mutex dir_lock; + struct mutex pwr_lock; + struct regmap *regmap; + u16 poweron_state; + + struct gpio_chip gc; +}; + +static const struct regmap_config waveshare_gpio_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = REG_VERSION, +}; + +static int waveshare_gpio_get(struct waveshare_gpio *state, unsigned int offset) +{ + u16 pwr_state; + + guard(mutex)(&state->pwr_lock); + pwr_state = state->poweron_state & BIT(offset); + + return !!pwr_state; +} + +static int waveshare_gpio_set(struct waveshare_gpio *state, unsigned int offset, int value) +{ + u16 last_val; + int err; + + guard(mutex)(&state->pwr_lock); + + last_val = state->poweron_state; + if (value) + last_val |= BIT(offset); + else + last_val &= ~BIT(offset); + + state->poweron_state = last_val; + + err = regmap_write(state->regmap, REG_TP, last_val >> 8); + if (!err) + err = regmap_write(state->regmap, REG_LCD, last_val & 0xff); + + return err; +} + +static int waveshare_gpio_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) +{ + return GPIO_LINE_DIRECTION_OUT; +} + +static int waveshare_gpio_gpio_get(struct gpio_chip *gc, unsigned int offset) +{ + struct waveshare_gpio *state = gpiochip_get_data(gc); + + return waveshare_gpio_get(state, offset); +} + +static int waveshare_gpio_gpio_set(struct gpio_chip *gc, unsigned int offset, int value) +{ + struct waveshare_gpio *state = gpiochip_get_data(gc); + + return waveshare_gpio_set(state, offset, value); +} + +static int waveshare_gpio_update_status(struct backlight_device *bl) +{ + struct waveshare_gpio *state = bl_get_data(bl); + int brightness = backlight_get_brightness(bl); + + waveshare_gpio_set(state, GPIO_BL_ENABLE, brightness); + + return regmap_write(state->regmap, REG_PWM, brightness); +} + +static const struct backlight_ops waveshare_gpio_bl = { + .update_status = waveshare_gpio_update_status, +}; + +static int waveshare_gpio_probe(struct i2c_client *i2c) +{ + struct backlight_properties props = {}; + struct waveshare_gpio *state; + struct device *dev = &i2c->dev; + struct backlight_device *bl; + struct regmap *regmap; + unsigned int data; + int ret; + + state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL); + if (!state) + return -ENOMEM; + + ret = devm_mutex_init(dev, &state->dir_lock); + if (ret) + return ret; + + ret = devm_mutex_init(dev, &state->pwr_lock); + if (ret) + return ret; + + regmap = devm_regmap_init_i2c(i2c, &waveshare_gpio_regmap_config); + if (IS_ERR(regmap)) + return dev_err_probe(dev, PTR_ERR(regmap), "Failed to allocate register map\n"); + + state->regmap = regmap; + i2c_set_clientdata(i2c, state); + + ret = regmap_read(regmap, REG_ID, &data); + if (ret < 0) + return dev_err_probe(dev, ret, "Failed to read register\n"); + + dev_dbg(dev, "waveshare panel hw id = 0x%x\n", data); + + ret = regmap_read(regmap, REG_SIZE, &data); + if (ret < 0) + return dev_err_probe(dev, ret, "Failed to read register\n"); + + dev_dbg(dev, "waveshare panel size = %d\n", data); + + ret = regmap_read(regmap, REG_VERSION, &data); + if (ret < 0) + return dev_err_probe(dev, ret, "Failed to read register\n"); + + dev_dbg(dev, "waveshare panel mcu version = 0x%x\n", data); + + ret = waveshare_gpio_set(state, GPIO_TS_RESET, 1); + if (ret) + return dev_err_probe(dev, ret, "Failed to program GPIOs\n"); + + msleep(20); + + state->gc.parent = dev; + state->gc.label = i2c->name; + state->gc.owner = THIS_MODULE; + state->gc.base = -1; + state->gc.ngpio = NUM_GPIO; + + /* it is output only */ + state->gc.get = waveshare_gpio_gpio_get; + state->gc.set = waveshare_gpio_gpio_set; + state->gc.get_direction = waveshare_gpio_gpio_get_direction; + state->gc.can_sleep = true; + + ret = devm_gpiochip_add_data(dev, &state->gc, state); + if (ret) + return dev_err_probe(dev, ret, "Failed to create gpiochip\n"); + + props.type = BACKLIGHT_RAW; + props.max_brightness = 255; + props.brightness = 255; + bl = devm_backlight_device_register(dev, dev_name(dev), dev, state, + &waveshare_gpio_bl, &props); + return PTR_ERR_OR_ZERO(bl); +} + +static const struct of_device_id waveshare_gpio_dt_ids[] = { + { .compatible = "waveshare,dsi-touch-gpio" }, + {}, +}; +MODULE_DEVICE_TABLE(of, waveshare_gpio_dt_ids); + +static struct i2c_driver waveshare_gpio_regulator_driver = { + .driver = { + .name = "waveshare-regulator", + .of_match_table = of_match_ptr(waveshare_gpio_dt_ids), + }, + .probe = waveshare_gpio_probe, +}; + +module_i2c_driver(waveshare_gpio_regulator_driver); + +MODULE_DESCRIPTION("GPIO controller driver for Waveshare DSI touch panels"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c index 4f65ce729a473..ef6b093169637 100644 --- a/drivers/gpu/drm/drm_of.c +++ b/drivers/gpu/drm/drm_of.c @@ -558,6 +558,40 @@ int drm_of_get_data_lanes_count_ep(const struct device_node *port, } EXPORT_SYMBOL_GPL(drm_of_get_data_lanes_count_ep); +/** + * drm_of_get_data_lanes_count_remote - Get DSI/(e)DP data lane count by endpoint + * @port: DT port node of the DSI/(e)DP source or sink + * @port_reg: identifier (value of reg property) of the parent port node + * @reg: identifier (value of reg property) of the endpoint node + * @min: minimum supported number of data lanes + * @max: maximum supported number of data lanes + * + * Count DT "data-lanes" property elements in the remote endpoint and check for + * validity. This variant uses endpoint specifier. + * + * Return: + * * min..max - positive integer count of "data-lanes" elements + * * -EINVAL - the "data-lanes" property is unsupported + * * -ENODEV - the "data-lanes" property is missing + */ +int drm_of_get_data_lanes_count_remote(const struct device_node *port, + int port_reg, int reg, + const unsigned int min, + const unsigned int max) +{ + struct device_node *endpoint, *remote; + int ret; + + endpoint = of_graph_get_endpoint_by_regs(port, port_reg, reg); + remote = of_graph_get_remote_endpoint(endpoint); + of_node_put(endpoint); + ret = drm_of_get_data_lanes_count(remote, min, max); + of_node_put(remote); + + return ret; +} +EXPORT_SYMBOL_GPL(drm_of_get_data_lanes_count_remote); + #if IS_ENABLED(CONFIG_DRM_MIPI_DSI) /** diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index 71cfa3442816f..b449e698eca10 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -321,6 +321,7 @@ config DRM_PANEL_JADARD_JD9365DA_H3 depends on OF depends on DRM_MIPI_DSI depends on BACKLIGHT_CLASS_DEVICE + select DRM_KMS_HELPER help Say Y here if you want to enable support for Jadard JD9365DA-H3 WXGA MIPI DSI panel. The panel support TFT dot matrix LCD with diff --git a/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c b/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c index 5c2530598ddb9..25b4133d5c0b9 100644 --- a/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c +++ b/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c @@ -10,8 +10,10 @@ #include #include +#include #include #include +#include #include #include @@ -22,7 +24,8 @@ struct jadard; struct jadard_panel_desc { - const struct drm_display_mode mode; + const struct drm_display_mode *mode_4ln; + const struct drm_display_mode *mode_2ln; unsigned int lanes; enum mipi_dsi_pixel_format format; int (*init)(struct jadard *jadard); @@ -55,7 +58,10 @@ static void jadard_enable_standard_cmds(struct mipi_dsi_multi_context *dsi_ctx) mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe1, 0x93); mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe2, 0x65); mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xe3, 0xf8); - mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0x80, 0x03); + if (dsi_ctx->dsi->lanes == 2) + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0x80, 0x01); + else + mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0x80, 0x03); } static inline struct jadard *panel_to_jadard(struct drm_panel *panel) @@ -148,24 +154,11 @@ static int jadard_get_modes(struct drm_panel *panel, struct drm_connector *connector) { struct jadard *jadard = panel_to_jadard(panel); - const struct drm_display_mode *desc_mode = &jadard->desc->mode; - struct drm_display_mode *mode; - - mode = drm_mode_duplicate(connector->dev, desc_mode); - if (!mode) { - DRM_DEV_ERROR(&jadard->dsi->dev, "failed to add mode %ux%ux@%u\n", - desc_mode->hdisplay, desc_mode->vdisplay, - drm_mode_vrefresh(desc_mode)); - return -ENOMEM; - } - - drm_mode_set_name(mode); - drm_mode_probed_add(connector, mode); - - connector->display_info.width_mm = mode->width_mm; - connector->display_info.height_mm = mode->height_mm; - return 1; + if (jadard->dsi->lanes == 2) + return drm_connector_helper_get_modes_fixed(connector, jadard->desc->mode_2ln); + else + return drm_connector_helper_get_modes_fixed(connector, jadard->desc->mode_4ln); } static enum drm_panel_orientation jadard_panel_get_orientation(struct drm_panel *panel) @@ -368,7 +361,7 @@ static int radxa_display_8hd_ad002_init_cmds(struct jadard *jadard) }; static const struct jadard_panel_desc radxa_display_8hd_ad002_desc = { - .mode = { + .mode_4ln = &(const struct drm_display_mode) { .clock = 70000, .hdisplay = 800, @@ -600,7 +593,7 @@ static int cz101b4001_init_cmds(struct jadard *jadard) }; static const struct jadard_panel_desc cz101b4001_desc = { - .mode = { + .mode_4ln = &(const struct drm_display_mode) { .clock = 70000, .hdisplay = 800, @@ -833,7 +826,7 @@ static int kingdisplay_kd101ne3_init_cmds(struct jadard *jadard) }; static const struct jadard_panel_desc kingdisplay_kd101ne3_40ti_desc = { - .mode = { + .mode_4ln = &(const struct drm_display_mode) { .clock = (800 + 24 + 24 + 24) * (1280 + 30 + 4 + 8) * 60 / 1000, .hdisplay = 800, @@ -1084,7 +1077,7 @@ static int melfas_lmfbx101117480_init_cmds(struct jadard *jadard) }; static const struct jadard_panel_desc melfas_lmfbx101117480_desc = { - .mode = { + .mode_4ln = &(const struct drm_display_mode) { .clock = (800 + 24 + 24 + 24) * (1280 + 30 + 4 + 8) * 60 / 1000, .hdisplay = 800, @@ -1113,6 +1106,1034 @@ static const struct jadard_panel_desc melfas_lmfbx101117480_desc = { .enter_sleep_to_reset_down_delay_ms = 100, }; +static int waveshare_3_4_c_init(struct jadard *jadard) +{ + struct mipi_dsi_multi_context dsi_ctx = { .dsi = jadard->dsi }; + + jd9365da_switch_page(&dsi_ctx, 0x00); + jadard_enable_standard_cmds(&dsi_ctx); + + jd9365da_switch_page(&dsi_ctx, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x41); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x03, 0x10); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x04, 0x44); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0xd0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1a, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1b, 0xd0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1c, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x24, 0xfe); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x35, 0x26); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x37, 0x09); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x38, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x39, 0x08); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3a, 0x0a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3c, 0x78); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3d, 0xff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3e, 0xff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3f, 0xff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x40, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x41, 0x64); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x42, 0xc7); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x43, 0x18); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x44, 0x0b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x45, 0x14); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x57, 0x49); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x59, 0x0a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5a, 0x1b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5b, 0x19); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5d, 0x7f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5e, 0x56); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5f, 0x43); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x60, 0x37); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x61, 0x33); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x62, 0x25); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x63, 0x2a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x64, 0x16); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x65, 0x30); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x66, 0x2f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x67, 0x32); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x53); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x69, 0x43); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6a, 0x4c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6b, 0x40); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6c, 0x3d); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6d, 0x31); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6e, 0x20); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x0f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x70, 0x7f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x71, 0x56); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x72, 0x43); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x73, 0x37); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x74, 0x33); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x75, 0x25); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x76, 0x2a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0x16); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x30); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x79, 0x2f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7a, 0x32); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7b, 0x53); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7c, 0x43); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7d, 0x4c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7e, 0x40); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7f, 0x3d); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x80, 0x31); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x81, 0x20); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x82, 0x0f); + + jd9365da_switch_page(&dsi_ctx, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x5f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x5f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0x5e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x03, 0x5e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x04, 0x50); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x05, 0x48); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x06, 0x48); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x07, 0x4a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x08, 0x4a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x09, 0x44); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0a, 0x44); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0b, 0x46); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0c, 0x46); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0d, 0x5f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0e, 0x5f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0f, 0x57); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x10, 0x57); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x11, 0x77); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x12, 0x77); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x13, 0x40); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x14, 0x42); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x15, 0x5f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x16, 0x5f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0x5f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0x5e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x5e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1a, 0x50); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1b, 0x49); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1c, 0x49); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1d, 0x4b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1e, 0x4b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1f, 0x45); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x20, 0x45); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x21, 0x47); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x22, 0x47); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x23, 0x5f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x24, 0x5f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x25, 0x57); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x26, 0x57); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x27, 0x77); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x28, 0x77); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x29, 0x41); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2a, 0x43); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2b, 0x5f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2c, 0x1e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2d, 0x1e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2e, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2f, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x30, 0x10); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x31, 0x07); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x32, 0x07); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x33, 0x05); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x34, 0x05); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x35, 0x0b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x36, 0x0b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x37, 0x09); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x38, 0x09); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x39, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3a, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3b, 0x17); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3c, 0x17); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3d, 0x17); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3e, 0x17); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3f, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x40, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x41, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x42, 0x1e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x43, 0x1e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x44, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x45, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x46, 0x10); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x47, 0x06); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x48, 0x06); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x49, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4a, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4b, 0x0a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4c, 0x0a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4d, 0x08); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4e, 0x08); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4f, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x50, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x51, 0x17); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x52, 0x17); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x53, 0x17); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x54, 0x17); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x56, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x57, 0x1f); + + jd9365da_switch_page(&dsi_ctx, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x58, 0x40); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x59, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5a, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5b, 0x30); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5c, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5d, 0x30); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5e, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5f, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x60, 0x30); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x61, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x62, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x63, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x64, 0xa6); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x65, 0x43); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x66, 0x30); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x67, 0x73); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x05); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x69, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6a, 0x7f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6b, 0x08); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6c, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6d, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6e, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x88); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x75, 0xd9); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x76, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0x33); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x43); + + jd9365da_switch_page(&dsi_ctx, 0x00); + + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); + msleep(120); + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); + msleep(5); + mipi_dsi_dcs_set_tear_on_multi(&dsi_ctx, MIPI_DSI_DCS_TEAR_MODE_VBLANK); + + return dsi_ctx.accum_err; +} + +static const struct jadard_panel_desc waveshare_3_4_inch_c_desc = { + .mode_2ln = &(const struct drm_display_mode) { + .clock = (800 + 40 + 20 + 20) * (800 + 24 + 4 + 12) * 60 / 1000, + + .hdisplay = 800, + .hsync_start = 800 + 40, + .hsync_end = 800 + 40 + 20, + .htotal = 800 + 40 + 20 + 20, + + .vdisplay = 800, + .vsync_start = 800 + 24, + .vsync_end = 800 + 24 + 4, + .vtotal = 800 + 24 + 4 + 12, + + .width_mm = 88, + .height_mm = 88, + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, + }, + .lanes = 2, + .format = MIPI_DSI_FMT_RGB888, + .init = waveshare_3_4_c_init, + .mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO | + MIPI_DSI_MODE_LPM | MIPI_DSI_CLOCK_NON_CONTINUOUS, +}; + +static int waveshare_4_0_c_init(struct jadard *jadard) +{ + struct mipi_dsi_multi_context dsi_ctx = { .dsi = jadard->dsi }; + + jd9365da_switch_page(&dsi_ctx, 0x00); + jadard_enable_standard_cmds(&dsi_ctx); + + jd9365da_switch_page(&dsi_ctx, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x41); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x03, 0x10); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x04, 0x44); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0xd0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1a, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1b, 0xd0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1c, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x24, 0xfe); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x35, 0x26); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x37, 0x09); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x38, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x39, 0x08); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3a, 0x0a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3c, 0x78); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3d, 0xff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3e, 0xff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3f, 0xff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x40, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x41, 0x64); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x42, 0xc7); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x43, 0x18); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x44, 0x0b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x45, 0x14); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x57, 0x49); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x59, 0x0a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5a, 0x1b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5b, 0x19); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5d, 0x7f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5e, 0x56); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5f, 0x43); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x60, 0x37); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x61, 0x33); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x62, 0x25); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x63, 0x2a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x64, 0x16); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x65, 0x30); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x66, 0x2f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x67, 0x32); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x53); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x69, 0x43); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6a, 0x4c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6b, 0x40); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6c, 0x3d); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6d, 0x31); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6e, 0x20); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x0f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x70, 0x7f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x71, 0x56); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x72, 0x43); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x73, 0x37); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x74, 0x33); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x75, 0x25); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x76, 0x2a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0x16); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x30); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x79, 0x2f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7a, 0x32); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7b, 0x53); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7c, 0x43); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7d, 0x4c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7e, 0x40); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7f, 0x3d); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x80, 0x31); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x81, 0x20); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x82, 0x0f); + + jd9365da_switch_page(&dsi_ctx, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x5f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x5f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0x5e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x03, 0x5e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x04, 0x50); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x05, 0x48); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x06, 0x48); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x07, 0x4a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x08, 0x4a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x09, 0x44); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0a, 0x44); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0b, 0x46); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0c, 0x46); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0d, 0x5f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0e, 0x5f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0f, 0x57); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x10, 0x57); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x11, 0x77); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x12, 0x77); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x13, 0x40); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x14, 0x42); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x15, 0x5f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x16, 0x5f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0x5f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0x5e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x5e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1a, 0x50); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1b, 0x49); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1c, 0x49); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1d, 0x4b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1e, 0x4b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1f, 0x45); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x20, 0x45); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x21, 0x47); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x22, 0x47); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x23, 0x5f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x24, 0x5f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x25, 0x57); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x26, 0x57); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x27, 0x77); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x28, 0x77); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x29, 0x41); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2a, 0x43); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2b, 0x5f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2c, 0x1e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2d, 0x1e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2e, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2f, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x30, 0x10); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x31, 0x07); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x32, 0x07); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x33, 0x05); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x34, 0x05); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x35, 0x0b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x36, 0x0b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x37, 0x09); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x38, 0x09); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x39, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3a, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3b, 0x17); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3c, 0x17); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3d, 0x17); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3e, 0x17); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3f, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x40, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x41, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x42, 0x1e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x43, 0x1e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x44, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x45, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x46, 0x10); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x47, 0x06); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x48, 0x06); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x49, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4a, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4b, 0x0a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4c, 0x0a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4d, 0x08); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4e, 0x08); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4f, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x50, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x51, 0x17); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x52, 0x17); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x53, 0x17); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x54, 0x17); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x56, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x57, 0x1f); + + jd9365da_switch_page(&dsi_ctx, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x58, 0x40); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x59, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5a, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5b, 0x30); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5c, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5d, 0x30); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5e, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5f, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x60, 0x30); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x61, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x62, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x63, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x64, 0xa6); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x65, 0x43); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x66, 0x30); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x67, 0x73); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x05); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x69, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6a, 0x7f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6b, 0x08); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6c, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6d, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6e, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x88); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x75, 0xd9); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x76, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0x33); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x43); + + jd9365da_switch_page(&dsi_ctx, 0x00); + + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); + msleep(120); + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); + msleep(5); + mipi_dsi_dcs_set_tear_on_multi(&dsi_ctx, MIPI_DSI_DCS_TEAR_MODE_VBLANK); + + return dsi_ctx.accum_err; +} + +static const struct jadard_panel_desc waveshare_4_0_inch_c_desc = { + .mode_2ln = &(const struct drm_display_mode) { + .clock = (720 + 40 + 20 + 20) * (720 + 24 + 4 + 12) * 60 / 1000, + + .hdisplay = 720, + .hsync_start = 720 + 40, + .hsync_end = 720 + 40 + 20, + .htotal = 720 + 40 + 20 + 20, + + .vdisplay = 720, + .vsync_start = 720 + 24, + .vsync_end = 720 + 24 + 4, + .vtotal = 720 + 24 + 4 + 12, + + .width_mm = 88, + .height_mm = 88, + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, + }, + .lanes = 2, + .format = MIPI_DSI_FMT_RGB888, + .init = waveshare_4_0_c_init, + .mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO | + MIPI_DSI_MODE_LPM | MIPI_DSI_CLOCK_NON_CONTINUOUS, +}; + +static int waveshare_8_0_a_init(struct jadard *jadard) +{ + struct mipi_dsi_multi_context dsi_ctx = { .dsi = jadard->dsi }; + + jd9365da_switch_page(&dsi_ctx, 0x00); + jadard_enable_standard_cmds(&dsi_ctx); + + jd9365da_switch_page(&dsi_ctx, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x00); + if (jadard->dsi->lanes == 4) + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x7e); + else + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x4e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x03, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x04, 0x65); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0c, 0x74); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0xb7); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1a, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1b, 0xb7); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1c, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x24, 0xfe); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x37, 0x19); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x38, 0x05); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x39, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3a, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3b, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3c, 0x70); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3d, 0xff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3e, 0xff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3f, 0xff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x40, 0x06); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x41, 0xa0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x43, 0x1e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x44, 0x0f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x45, 0x28); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4b, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x56, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x57, 0xa9); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x58, 0x0a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x59, 0x0a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5a, 0x37); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5b, 0x19); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5d, 0x78); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5e, 0x63); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5f, 0x54); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x60, 0x49); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x61, 0x45); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x62, 0x38); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x63, 0x3d); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x64, 0x28); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x65, 0x43); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x66, 0x41); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x67, 0x43); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x62); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x69, 0x50); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6a, 0x57); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6b, 0x49); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6c, 0x44); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6d, 0x37); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6e, 0x23); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x10); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x70, 0x78); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x71, 0x63); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x72, 0x54); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x73, 0x49); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x74, 0x45); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x75, 0x38); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x76, 0x3d); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0x28); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x43); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x79, 0x41); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7a, 0x43); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7b, 0x62); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7c, 0x50); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7d, 0x57); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7e, 0x49); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7f, 0x44); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x80, 0x37); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x81, 0x23); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x82, 0x10); + + jd9365da_switch_page(&dsi_ctx, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x47); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x47); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0x45); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x03, 0x45); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x04, 0x4b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x05, 0x4b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x06, 0x49); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x07, 0x49); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x08, 0x41); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x09, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0a, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0b, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0c, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0d, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0e, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0f, 0x5f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x10, 0x5f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x11, 0x57); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x12, 0x77); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x13, 0x35); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x14, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x15, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x16, 0x46); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0x46); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0x44); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x44); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1a, 0x4a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1b, 0x4a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1c, 0x48); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1d, 0x48); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1e, 0x40); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1f, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x20, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x21, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x22, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x23, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x24, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x25, 0x5f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x26, 0x5f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x27, 0x57); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x28, 0x77); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x29, 0x35); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2a, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2b, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x58, 0x40); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x59, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5a, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5b, 0x10); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5c, 0x06); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5d, 0x40); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5e, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5f, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x60, 0x30); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x61, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x62, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x63, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x64, 0x6b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x65, 0x05); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x66, 0x0c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x67, 0x73); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x09); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x69, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6a, 0x56); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6b, 0x08); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6c, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6d, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6e, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x88); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x70, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x71, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x72, 0x06); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x73, 0x7b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x74, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x75, 0xf8); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x76, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0xd5); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x2e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x79, 0x12); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7a, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7b, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7c, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7d, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7e, 0x7b); + + jd9365da_switch_page(&dsi_ctx, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x0e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0xb3); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x09, 0x60); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0e, 0x2a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x36, 0x59); + if (jadard->dsi->lanes != 4) { + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x37, 0x58); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2b, 0x0f); + } + + jd9365da_switch_page(&dsi_ctx, 0x00); + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); + msleep(120); + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); + msleep(60); + + return 0; +} + +static const struct drm_display_mode waveshare_8_0_a_mode = { + .clock = (800 + 40 + 20 + 20) * (1280 + 30 + 12 + 4) * 60 / 1000, + + .hdisplay = 800, + .hsync_start = 800 + 40, + .hsync_end = 800 + 40 + 20, + .htotal = 800 + 40 + 20 + 20, + + .vdisplay = 1280, + .vsync_start = 1280 + 30, + .vsync_end = 1280 + 30 + 12, + .vtotal = 1280 + 30 + 12 + 4, + + .width_mm = 107, + .height_mm = 172, + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, +}; + +static const struct jadard_panel_desc waveshare_8_0_inch_a_desc = { + .mode_4ln = &waveshare_8_0_a_mode, + .mode_2ln = &waveshare_8_0_a_mode, + .format = MIPI_DSI_FMT_RGB888, + .init = waveshare_8_0_a_init, + .mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO | + MIPI_DSI_MODE_LPM | MIPI_DSI_CLOCK_NON_CONTINUOUS, +}; + +static const struct drm_display_mode waveshare_10_1_a_mode = { + .clock = (800 + 40 + 20 + 20) * (1280 + 20 + 20 + 4) * 60 / 1000, + + .hdisplay = 800, + .hsync_start = 800 + 40, + .hsync_end = 800 + 40 + 20, + .htotal = 800 + 40 + 20 + 20, + + .vdisplay = 1280, + .vsync_start = 1280 + 20, + .vsync_end = 1280 + 20 + 20, + .vtotal = 1280 + 20 + 20 + 4, + + .width_mm = 135, + .height_mm = 216, + .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, +}; + +static int waveshare_10_1_a_init(struct jadard *jadard) +{ + struct mipi_dsi_multi_context dsi_ctx = { .dsi = jadard->dsi }; + + jd9365da_switch_page(&dsi_ctx, 0x00); + jadard_enable_standard_cmds(&dsi_ctx); + + jd9365da_switch_page(&dsi_ctx, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x00); + if (jadard->dsi->lanes == 4) { + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x3b); + } else { + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x38); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x03, 0x10); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x04, 0x38); + } + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0c, 0x74); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0xaf); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1a, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1b, 0xaf); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1c, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x35, 0x26); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x37, 0x09); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x38, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x39, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3a, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3c, 0x78); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3d, 0xff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3e, 0xff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3f, 0x7f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x40, 0x06); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x41, 0xa0); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x42, 0x81); + if (jadard->dsi->lanes == 4) { + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x43, 0x14); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x44, 0x23); + } else { + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x43, 0x1e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x44, 0x0d); + } + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x45, 0x28); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x57, 0x69); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x59, 0x0a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5a, 0x2a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5b, 0x17); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5d, 0x7f); + if (jadard->dsi->lanes == 4) { + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5e, 0x6b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5f, 0x5c); + } else { + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5e, 0x6a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5f, 0x5b); + } + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x60, 0x4f); + if (jadard->dsi->lanes == 4) { + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x61, 0x4d); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x62, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x63, 0x42); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x64, 0x2b); + } else { + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x61, 0x4a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x62, 0x3d); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x63, 0x41); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x64, 0x2a); + } + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x65, 0x44); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x66, 0x43); + if (jadard->dsi->lanes == 4) { + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x67, 0x43); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x63); + } else { + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x67, 0x44); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x62); + } + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x69, 0x52); + if (jadard->dsi->lanes == 4) { + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6a, 0x5a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6b, 0x4f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6c, 0x4e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6d, 0x20); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6e, 0x0f); + } else { + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6a, 0x59); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6b, 0x4c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6c, 0x48); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6d, 0x3a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6e, 0x26); + } + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x70, 0x7f); + if (jadard->dsi->lanes == 4) { + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x71, 0x6b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x72, 0x5c); + } else { + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x71, 0x6a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x72, 0x5b); + } + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x73, 0x4f); + if (jadard->dsi->lanes == 4) { + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x74, 0x4d); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x75, 0x3f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x76, 0x42); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0x2b); + } else { + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x74, 0x4a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x75, 0x3d); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x76, 0x41); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0x2a); + } + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x44); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x79, 0x43); + if (jadard->dsi->lanes == 4) { + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7a, 0x43); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7b, 0x63); + } else { + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7a, 0x44); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7b, 0x62); + } + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7c, 0x52); + if (jadard->dsi->lanes == 4) { + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7d, 0x5a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7e, 0x4f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7f, 0x4e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x80, 0x20); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x81, 0x0f); + } else { + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7d, 0x59); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7e, 0x4c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7f, 0x48); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x80, 0x3a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x81, 0x26); + } + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x82, 0x00); + + jd9365da_switch_page(&dsi_ctx, 0x02); + if (jadard->dsi->lanes == 4) { + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x03, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x04, 0x1e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x05, 0x1e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x06, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x07, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x08, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x09, 0x17); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0a, 0x17); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0b, 0x37); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0c, 0x37); + } else { + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x42); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x01, 0x42); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0x40); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x03, 0x40); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x04, 0x5e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x05, 0x5e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x06, 0x5f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x07, 0x5f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x08, 0x5f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x09, 0x57); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0a, 0x57); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0b, 0x77); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0c, 0x77); + } + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0d, 0x47); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0e, 0x47); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0f, 0x45); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x10, 0x45); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x11, 0x4b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x12, 0x4b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x13, 0x49); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x14, 0x49); + if (jadard->dsi->lanes == 4) { + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x15, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x16, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1a, 0x1e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1b, 0x1e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1c, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1d, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1e, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1f, 0x17); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x20, 0x17); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x21, 0x37); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x22, 0x37); + } else { + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x15, 0x5f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x16, 0x41); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x17, 0x41); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x18, 0x40); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x19, 0x40); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1a, 0x5e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1b, 0x5e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1c, 0x5f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1d, 0x5f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1e, 0x5f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x1f, 0x57); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x20, 0x57); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x21, 0x77); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x22, 0x77); + } + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x23, 0x46); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x24, 0x46); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x25, 0x44); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x26, 0x44); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x27, 0x4a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x28, 0x4a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x29, 0x48); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2a, 0x48); + if (jadard->dsi->lanes == 4) + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2b, 0x1f); + else + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2b, 0x5f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2c, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2d, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2e, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2f, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x30, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x31, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x32, 0x1e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x33, 0x1e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x34, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x35, 0x17); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x36, 0x17); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x37, 0x37); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x38, 0x37); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x39, 0x08); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3a, 0x08); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3b, 0x0a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3c, 0x0a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3d, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3e, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x3f, 0x06); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x40, 0x06); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x41, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x42, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x43, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x44, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x45, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x46, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x47, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x48, 0x1e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x49, 0x1e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4a, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4b, 0x17); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4c, 0x17); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4d, 0x37); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4e, 0x37); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x4f, 0x09); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x50, 0x09); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x51, 0x0b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x52, 0x0b); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x53, 0x05); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x54, 0x05); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x55, 0x07); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x56, 0x07); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x57, 0x1f); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x58, 0x40); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5b, 0x30); + if (jadard->dsi->lanes == 4) + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5c, 0x16); + else + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5c, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5d, 0x34); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5e, 0x05); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x5f, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x63, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x64, 0x6a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x67, 0x73); + if (jadard->dsi->lanes == 4) + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x1d); + else + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x68, 0x07); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x69, 0x08); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6a, 0x6a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6b, 0x08); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6c, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6d, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6e, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x88); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x75, 0xff); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x77, 0xdd); + if (jadard->dsi->lanes == 4) + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x3f); + else + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x78, 0x2c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x79, 0x15); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7a, 0x17); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7d, 0x14); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x7e, 0x82); + + jd9365da_switch_page(&dsi_ctx, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x00, 0x0e); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x02, 0xb3); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x09, 0x61); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x0e, 0x48); + if (jadard->dsi->lanes != 4) { + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x37, 0x58); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x2b, 0x0f); + } + + jd9365da_switch_page(&dsi_ctx, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe6, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe7, 0x0c); + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); + msleep(120); + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); + msleep(60); + + return dsi_ctx.accum_err; +} + +static const struct jadard_panel_desc waveshare_10_1_inch_a_desc = { + .mode_4ln = &waveshare_10_1_a_mode, + .mode_2ln = &waveshare_10_1_a_mode, + .format = MIPI_DSI_FMT_RGB888, + .init = waveshare_10_1_a_init, + .mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO | + MIPI_DSI_MODE_LPM | MIPI_DSI_CLOCK_NON_CONTINUOUS, +}; + static int jadard_dsi_probe(struct mipi_dsi_device *dsi) { struct device *dev = &dsi->dev; @@ -1130,6 +2151,26 @@ static int jadard_dsi_probe(struct mipi_dsi_device *dsi) MIPI_DSI_MODE_NO_EOT_PACKET; dsi->format = desc->format; dsi->lanes = desc->lanes; + if (!dsi->lanes) { + dsi->lanes = drm_of_get_data_lanes_count_remote(dsi->dev.of_node, 0, -1, 2, 4); + if (dsi->lanes < 0) + return dsi->lanes; + if (dsi->lanes == 4) { + if (!desc->mode_4ln) { + dev_err(&dsi->dev, "4-lane config is not supported\n"); + return -EINVAL; + } + } else if (dsi->lanes == 2) { + if (!desc->mode_2ln) { + dev_err(&dsi->dev, "2-lane config is not supported\n"); + return -EINVAL; + } + } else { + dev_err(&dsi->dev, "Unsupported number of lanes, %d\n", dsi->lanes); + return -ENODEV; + } + } + dev_dbg(&dsi->dev, "lanes: %d\n", dsi->lanes); jadard->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(jadard->reset)) { @@ -1157,6 +2198,8 @@ static int jadard_dsi_probe(struct mipi_dsi_device *dsi) if (ret) return ret; + jadard->panel.prepare_prev_first = true; + drm_panel_add(&jadard->panel); mipi_dsi_set_drvdata(dsi, jadard); @@ -1199,6 +2242,22 @@ static const struct of_device_id jadard_of_match[] = { .compatible = "radxa,display-8hd-ad002", .data = &radxa_display_8hd_ad002_desc }, + { + .compatible = "waveshare,3.4-dsi-touch-c", + .data = &waveshare_3_4_inch_c_desc + }, + { + .compatible = "waveshare,4.0-dsi-touch-c", + .data = &waveshare_4_0_inch_c_desc + }, + { + .compatible = "waveshare,8.0-dsi-touch-a", + .data = &waveshare_8_0_inch_a_desc + }, + { + .compatible = "waveshare,10.1-dsi-touch-a", + .data = &waveshare_10_1_inch_a_desc + }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, jadard_of_match); diff --git a/include/drm/drm_of.h b/include/drm/drm_of.h index f3e55ea2174c0..8724866beb573 100644 --- a/include/drm/drm_of.h +++ b/include/drm/drm_of.h @@ -62,6 +62,10 @@ int drm_of_get_data_lanes_count_ep(const struct device_node *port, int port_reg, int reg, const unsigned int min, const unsigned int max); +int drm_of_get_data_lanes_count_remote(const struct device_node *port, + int port_reg, int reg, + const unsigned int min, + const unsigned int max); #else static inline uint32_t drm_of_crtc_port_mask(struct drm_device *dev, struct device_node *port) @@ -140,6 +144,15 @@ drm_of_get_data_lanes_count_ep(const struct device_node *port, { return -EINVAL; } + +static inline int +drm_of_get_data_lanes_count_remote(const struct device_node *port, + int port_reg, int reg, + const unsigned int min, + const unsigned int max) +{ + return -EINVAL; +} #endif #if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_DRM_MIPI_DSI)