diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index f4dab34339f7b5..4d0e923f834150 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -87,6 +87,7 @@ dtb-$(CONFIG_ARCH_QCOM) += msm8916-samsung-on7.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-samsung-serranove.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-thwc-uf896.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-thwc-ufi001c.dtb +dtb-$(CONFIG_ARCH_QCOM) += msm8916-vivo-pd1505f.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-vivo-y21l.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-wiko-chuppito.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-wingtech-wt86518.dtb diff --git a/arch/arm64/boot/dts/qcom/msm8916-vivo-pd1505f.dts b/arch/arm64/boot/dts/qcom/msm8916-vivo-pd1505f.dts new file mode 100644 index 00000000000000..48b79ea5c16690 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm8916-vivo-pd1505f.dts @@ -0,0 +1,316 @@ +// SPDX-License-Identifier: GPL-2.0-only + +/dts-v1/; + +#include "msm8916-pm8916.dtsi" +#include +#include +#include +#include +#include +#include +#include + +/ { + model = "Vivo Y31A (PD1505F)"; + compatible = "pd1505f", "qcom,msm8916"; + chassis-type = "handset"; + + aliases { + mmc0 = &sdhc_1; + mmc1 = &sdhc_2; + serial0 = &blsp_uart2; + }; + + chosen { + stdout-path = "serial0"; + }; + + gpio-keys { + compatible = "gpio-keys"; + pinctrl-0 = <&gpio_keys_default>; + pinctrl-names = "default"; + label = "GPIO Buttons"; + + button-volume-up { + label = "Volume Up"; + gpios = <&tlmm 107 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + usb_id: usb-id { + compatible = "linux,extcon-usb-gpio"; + id-gpios = <&tlmm 110 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&usb_id_default>; + pinctrl-names = "default"; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + pwms = <&pm8916_pwm 0 40000>; + brightness-levels = <0 255>; + num-interpolated-steps = <255>; + default-brightness-level = <255>; + enable-gpios = <&tlmm 8 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&lcd_bl_en_default>; + post-pwm-on-delay-ms = <10>; + pwm-off-delay-ms = <10>; + }; + + battery: battery-cell { + compatible = "simple-battery"; + voltage-min-design-microvolt = <3450000>; + voltage-max-design-microvolt = <4350000>; + energy-full-design-microwatt-hours = <8470000>; + charge-full-design-microamp-hours = <2200000>; + + ocv-capacity-celsius = <25>; + ocv-capacity-table-0 = <4350000 100>, <4300000 95>, <4250000 90>, + <4200000 85>, <4150000 80>, <4100000 75>, + <4050000 70>, <4000000 65>, <3950000 60>, + <3900000 55>, <3850000 50>, <3820000 45>, + <3800000 40>, <3780000 35>, <3760000 30>, + <3740000 25>, <3720000 20>, <3700000 16>, + <3690000 13>, <3680000 11>, <3670000 10>, + <3660000 9>, <3650000 8>, <3640000 7>, + <3600000 6>, <3550000 5>, <3500000 4>, + <3450000 3>, <3400000 2>, <3300000 1>, + <3000000 0>; + }; +}; + +&blsp_i2c2 { + status = "okay"; + + accelerometer@18 { + compatible = "st,lis3dh-accel"; + reg = <0x18>; + interrupts-extended = <&tlmm 21 IRQ_TYPE_EDGE_RISING>; + vdd-supply = <&pm8916_l17>; + vddio-supply = <&pm8916_l6>; + pinctrl-0 = <&accel_int_default>; + pinctrl-names = "default"; + mount-matrix = "-1", "0", "0", + "0", "1", "0", + "0", "0", "1"; + }; + + magnetormeter@2e { + compatible = "yamaha,yas533"; + reg = <0x2e>; + vdd-supply = <&pm8916_l17>; + vddio-supply = <&pm8916_l6>; + }; + + light-sensor@39 { + compatible = "amstaos,tmd2772"; + reg = <0x39>; + interrupts-extended = <&tlmm 113 IRQ_TYPE_EDGE_FALLING>; + vdd-supply = <&pm8916_l17>; + vddio-supply = <&pm8916_l6>; + pinctrl-0 = <&light_int_default>; + pinctrl-names = "default"; + }; +}; + +&blsp_i2c5 { + status = "okay"; + + touchscreen@14 { + compatible = "goodix,gt928"; + reg = <0x14>; + + interrupt-parent = <&tlmm>; + interrupts = <13 IRQ_TYPE_EDGE_FALLING>; + irq-gpios = <&tlmm 13 GPIO_ACTIVE_LOW>; + reset-gpios = <&tlmm 12 GPIO_ACTIVE_LOW>; + + AVDD28-supply = <&pm8916_l16>; + touchscreen-size-x = <540>; + touchscreen-size-y = <960>; + + pinctrl-names = "default"; + pinctrl-0 = <&ts_int_default &ts_rst_default>; + }; +}; + +&blsp_uart2 { + status = "okay"; +}; + +&pm8916_bms { + monitored-battery = <&battery>; + status = "okay"; +}; + +&pm8916_resin { + linux,code = ; + status = "okay"; +}; + +&pm8916_rpm_regulators { + pm8916_l2: l2 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-always-on; /* 可能需要保持常开 */ + }; + pm8916_l17: l17 { + regulator-min-microvolt = <2850000>; + regulator-max-microvolt = <2850000>; + }; + pm8916_l16: l16 { + regulator-min-microvolt = <2850000>; + regulator-max-microvolt = <2850000>; + }; +}; + +&sdhc_1 { + status = "okay"; +}; + +&sdhc_2 { + non-removable; + status = "okay"; +}; + +&usb { + extcon = <&usb_id>, <&usb_id>; + status = "okay"; +}; + +&usb_hs_phy { + extcon = <&usb_id>; +}; + +&wcnss { + status = "okay"; +}; + +&wcnss_iris { + compatible = "qcom,wcn3620"; +}; + +&wcnss_mem { + status = "okay"; +}; + +&tlmm { + accel_int_default: accel-int-default-state { + pins = "gpio21"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + gpio_keys_default: gpio-keys-default-state { + pins = "gpio107"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + + light_int_default: light-int-default-state { + pins = "gpio113"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + lcd_bl_en_default: lcd-bl-en-default-state { + pins = "gpio8"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + mdss_default: mdss-default-state { + pins = "gpio25"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + }; + + mdss_sleep: mdss-sleep-state { + pins = "gpio25"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; + + usb_id_default: usb-id-default-state { + pins = "gpio110"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; + ts_int_default: ts-int-default-state { + pins = "gpio13"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + ts_rst_default: ts-rst-default-state { + pins = "gpio12"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; +}; + +&pm8916_pwm { + status = "okay"; +}; + +&pm8916_mpps { + pwm_out: mpp4-state { + pins = "mpp4"; + function = "digital"; + power-source = ; + output-low; + qcom,dtest = <1>; + }; +}; + +&gpu { + status = "okay"; + vdd-supply = <&pm8916_l2>; + vddcx-supply = <&rpmpd MSM8916_VDDCX>; +}; + +&mdss { + status = "okay"; +}; + +&mdss_dsi0 { + pinctrl-0 = <&mdss_default>; + pinctrl-1 = <&mdss_sleep>; + pinctrl-names = "default", "sleep"; + + panel@0 { + compatible = "vivo,pd1505f-panel"; + reg = <0>; + + backlight = <&backlight>; + vdd-supply = <&pm8916_l17>; + vddio-supply = <&pm8916_l6>; + reset-gpios = <&tlmm 25 GPIO_ACTIVE_LOW>; + + port { + panel_in: endpoint { + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + }; +}; + +&mdss_dsi0_out { + data-lanes = <0 1>; + remote-endpoint = <&panel_in>; +}; + +&mdss_dsi0_phy { + qcom,dsi-phy-regulator-ldo-mode; +}; diff --git a/drivers/gpu/drm/panel/msm8916-generated/Kconfig b/drivers/gpu/drm/panel/msm8916-generated/Kconfig index 5dd3292b370f4f..ef12df61665cd3 100644 --- a/drivers/gpu/drm/panel/msm8916-generated/Kconfig +++ b/drivers/gpu/drm/panel/msm8916-generated/Kconfig @@ -193,4 +193,4 @@ config DRM_PANEL_WINGTECH_YASSY_ILI9881 tristate "Wingtech YASSY ILI9881" default DRM_PANEL_MSM8916_GENERATED -endmenu +endmenu \ No newline at end of file diff --git a/drivers/gpu/drm/panel/msm8916-generated/Makefile b/drivers/gpu/drm/panel/msm8916-generated/Makefile index 642983369eba93..d8d2b92a639da7 100644 --- a/drivers/gpu/drm/panel/msm8916-generated/Makefile +++ b/drivers/gpu/drm/panel/msm8916-generated/Makefile @@ -44,4 +44,4 @@ obj-$(CONFIG_DRM_PANEL_WINGTECH_QIMEI_ILI9881) += panel-wingtech-qimei-ili9881.o obj-$(CONFIG_DRM_PANEL_WINGTECH_SHARP_R69431) += panel-wingtech-sharp-r69431.o obj-$(CONFIG_DRM_PANEL_WINGTECH_TIANMA_HX8394D) += panel-wingtech-tianma-hx8394d.o obj-$(CONFIG_DRM_PANEL_WINGTECH_TM_OTM1901A) += panel-wingtech-tm-otm1901a.o -obj-$(CONFIG_DRM_PANEL_WINGTECH_YASSY_ILI9881) += panel-wingtech-yassy-ili9881.o +obj-$(CONFIG_DRM_PANEL_WINGTECH_YASSY_ILI9881) += panel-wingtech-yassy-ili9881.o \ No newline at end of file diff --git a/drivers/gpu/drm/panel/msm8916-generated/panel-pd1505l-otm9605a-baoming.c b/drivers/gpu/drm/panel/msm8916-generated/panel-pd1505l-otm9605a-baoming.c new file mode 100644 index 00000000000000..8cb240e893dd5a --- /dev/null +++ b/drivers/gpu/drm/panel/msm8916-generated/panel-pd1505l-otm9605a-baoming.c @@ -0,0 +1,421 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2026 FIXME +// Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree: +// Copyright (c) 2013, The Linux Foundation. All rights reserved. (FIXME) + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +struct pd1505l_otm9605a_540p_baoming { + struct drm_panel panel; + struct mipi_dsi_device *dsi; + struct regulator_bulk_data *supplies; + struct gpio_desc *reset_gpio; +}; + +static const struct regulator_bulk_data pd1505l_otm9605a_540p_baoming_supplies[] = { + { .supply = "vdd" }, + { .supply = "vddio" }, +}; + +static inline +struct pd1505l_otm9605a_540p_baoming *to_pd1505l_otm9605a_540p_baoming(struct drm_panel *panel) +{ + return container_of_const(panel, struct pd1505l_otm9605a_540p_baoming, panel); +} + +static void pd1505l_otm9605a_540p_baoming_reset(struct pd1505l_otm9605a_540p_baoming *ctx) +{ + gpiod_set_value_cansleep(ctx->reset_gpio, 0); + usleep_range(5000, 6000); + gpiod_set_value_cansleep(ctx->reset_gpio, 1); + usleep_range(1000, 2000); + gpiod_set_value_cansleep(ctx->reset_gpio, 0); + msleep(20); +} + +static int pd1505l_otm9605a_540p_baoming_on(struct pd1505l_otm9605a_540p_baoming *ctx) +{ + struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; + + ctx->dsi->mode_flags |= MIPI_DSI_MODE_LPM; + + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xff, 0x96, 0x05, 0x01); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x80); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xff, 0x96, 0x05); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x92); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xff, 0x10, 0x02); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xa6); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc1, 0x01); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x89); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc0, 0x01); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x80); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc1, 0x36, 0x66); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xb1); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc5, 0x28); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x80); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc4, 0x9a); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xc0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc5, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xb2); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf5, + 0x15, 0x00, 0x15, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x93); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc5, 0x03); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xa0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc1, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xc5); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb0, 0x03); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x91); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc5, 0x19); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x92); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc5, 0x01); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd8, 0x67, 0x67); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xe1, + 0x00, 0x13, 0x1a, 0x0e, 0x07, 0x10, + 0x0b, 0x0b, 0x03, 0x07, 0x0c, 0x08, + 0x0f, 0x0c, 0x08, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xe2, + 0x00, 0x13, 0x1a, 0x0e, 0x07, 0x10, + 0x0c, 0x0a, 0x03, 0x06, 0x0c, 0x09, + 0x10, 0x0c, 0x07, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xec, + 0x40, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x04); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xed, + 0x40, 0x34, 0x44, 0x44, 0x34, 0x44, + 0x44, 0x43, 0x44, 0x34, 0x44, 0x44, + 0x34, 0x44, 0x44, 0x43, 0x44, 0x34, + 0x44, 0x44, 0x34, 0x44, 0x44, 0x43, + 0x44, 0x34, 0x44, 0x44, 0x34, 0x44, + 0x44, 0x43, 0x04); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xee, + 0x40, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x04); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x80); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcb, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x90); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcb, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xa0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcb, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xb0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcb, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xc0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcb, + 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xd0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcb, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x00, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xe0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcb, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xf0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcb, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x80); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcc, + 0x00, 0x00, 0x0b, 0x09, 0x01, 0x25, + 0x26, 0x00, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x90); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcc, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0c, 0x0a, 0x02); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xa0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcc, + 0x25, 0x26, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xb0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcc, + 0x00, 0x00, 0x0a, 0x0c, 0x02, 0x26, + 0x25, 0x00, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xc0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcc, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x0b, 0x01); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xd0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcc, + 0x26, 0x25, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x80); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xce, + 0x86, 0x01, 0x00, 0x85, 0x01, 0x00, + 0x0f, 0x00, 0x00, 0x0f, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x90); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xce, + 0xf0, 0x00, 0x00, 0xf0, 0x00, 0x00, + 0xf0, 0x00, 0x00, 0xf0, 0x00, 0x00, + 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xa0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xce, + 0x18, 0x03, 0x83, 0xc2, 0x87, 0x0b, + 0x00, 0x18, 0x02, 0x83, 0xc4, 0x86, + 0x0b, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xb0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xce, + 0x18, 0x05, 0x83, 0xc3, 0x00, 0x04, + 0x00, 0x18, 0x04, 0x83, 0xc5, 0x00, + 0x04, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xc0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xce, + 0xf0, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0xf0, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xd0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xce, + 0xf0, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0xf0, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xc0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcf, + 0x02, 0x02, 0x20, 0x20, 0x00, 0x00, + 0x01, 0x81, 0x00, 0x07); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xb4); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc0, 0x50, 0x48); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xd2); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb0, 0x04); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x94); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc5, 0x55, 0x55); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x80); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcf, + 0xf0, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0xf0, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x90); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcf, + 0xf0, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0xf0, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xa0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcf, + 0xf0, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0xf0, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xb0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcf, + 0xf0, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0xf0, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x84); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc4, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x86); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc4, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x80); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xff, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xff, 0x00, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x11, 0x00); + mipi_dsi_msleep(&dsi_ctx, 120); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x29, 0x00); + mipi_dsi_msleep(&dsi_ctx, 20); + + return dsi_ctx.accum_err; +} + +static int pd1505l_otm9605a_540p_baoming_off(struct pd1505l_otm9605a_540p_baoming *ctx) +{ + struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; + + ctx->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; + + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 20); + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 120); + + return dsi_ctx.accum_err; +} + +static int pd1505l_otm9605a_540p_baoming_prepare(struct drm_panel *panel) +{ + struct pd1505l_otm9605a_540p_baoming *ctx = to_pd1505l_otm9605a_540p_baoming(panel); + struct device *dev = &ctx->dsi->dev; + int ret; + + ret = regulator_bulk_enable(ARRAY_SIZE(pd1505l_otm9605a_540p_baoming_supplies), ctx->supplies); + if (ret < 0) { + dev_err(dev, "Failed to enable regulators: %d\n", ret); + return ret; + } + + pd1505l_otm9605a_540p_baoming_reset(ctx); + + ret = pd1505l_otm9605a_540p_baoming_on(ctx); + if (ret < 0) { + dev_err(dev, "Failed to initialize panel: %d\n", ret); + gpiod_set_value_cansleep(ctx->reset_gpio, 1); + regulator_bulk_disable(ARRAY_SIZE(pd1505l_otm9605a_540p_baoming_supplies), ctx->supplies); + return ret; + } + + return 0; +} + +static int pd1505l_otm9605a_540p_baoming_unprepare(struct drm_panel *panel) +{ + struct pd1505l_otm9605a_540p_baoming *ctx = to_pd1505l_otm9605a_540p_baoming(panel); + struct device *dev = &ctx->dsi->dev; + int ret; + + ret = pd1505l_otm9605a_540p_baoming_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_bulk_disable(ARRAY_SIZE(pd1505l_otm9605a_540p_baoming_supplies), ctx->supplies); + + return 0; +} + +static const struct drm_display_mode pd1505l_otm9605a_540p_baoming_mode = { + .clock = (540 + 35 + 4 + 100) * (960 + 15 + 4 + 16) * 60 / 1000, + .hdisplay = 540, + .hsync_start = 540 + 35, + .hsync_end = 540 + 35 + 4, + .htotal = 540 + 35 + 4 + 100, + .vdisplay = 960, + .vsync_start = 960 + 15, + .vsync_end = 960 + 15 + 4, + .vtotal = 960 + 15 + 4 + 16, + .width_mm = 58, + .height_mm = 103, + .type = DRM_MODE_TYPE_DRIVER, +}; + +static int pd1505l_otm9605a_540p_baoming_get_modes(struct drm_panel *panel, + struct drm_connector *connector) +{ + return drm_connector_helper_get_modes_fixed(connector, &pd1505l_otm9605a_540p_baoming_mode); +} + +static const struct drm_panel_funcs pd1505l_otm9605a_540p_baoming_panel_funcs = { + .prepare = pd1505l_otm9605a_540p_baoming_prepare, + .unprepare = pd1505l_otm9605a_540p_baoming_unprepare, + .get_modes = pd1505l_otm9605a_540p_baoming_get_modes, +}; + +static int pd1505l_otm9605a_540p_baoming_probe(struct mipi_dsi_device *dsi) +{ + struct device *dev = &dsi->dev; + struct pd1505l_otm9605a_540p_baoming *ctx; + int ret; + + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + drm_panel_init(&ctx->panel, dev, &pd1505l_otm9605a_540p_baoming_panel_funcs, + DRM_MODE_CONNECTOR_DSI); + + ret = devm_regulator_bulk_get_const(dev, + ARRAY_SIZE(pd1505l_otm9605a_540p_baoming_supplies), + pd1505l_otm9605a_540p_baoming_supplies, + &ctx->supplies); + if (ret < 0) + return ret; + + 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 = 2; + dsi->format = MIPI_DSI_FMT_RGB888; + dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | + MIPI_DSI_MODE_VIDEO_HSE | + MIPI_DSI_CLOCK_NON_CONTINUOUS | + MIPI_DSI_MODE_VIDEO_NO_HBP; + + ctx->panel.prepare_prev_first = true; + + ret = drm_panel_of_backlight(&ctx->panel); + if (ret) + return dev_err_probe(dev, ret, "Failed to get backlight\n"); + + drm_panel_add(&ctx->panel); + + ret = mipi_dsi_attach(dsi); + if (ret < 0) { + drm_panel_remove(&ctx->panel); + return dev_err_probe(dev, ret, "Failed to attach to DSI host\n"); + } + + return 0; +} + +static void pd1505l_otm9605a_540p_baoming_remove(struct mipi_dsi_device *dsi) +{ + struct pd1505l_otm9605a_540p_baoming *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 pd1505l_otm9605a_540p_baoming_of_match[] = { + { .compatible = "vivo,otm9605a-baoming" }, // FIXME + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, pd1505l_otm9605a_540p_baoming_of_match); + +static struct mipi_dsi_driver pd1505l_otm9605a_540p_baoming_driver = { + .probe = pd1505l_otm9605a_540p_baoming_probe, + .remove = pd1505l_otm9605a_540p_baoming_remove, + .driver = { + .name = "panel-pd1505l-otm9605a-540p-baoming", + .of_match_table = pd1505l_otm9605a_540p_baoming_of_match, + }, +}; +module_mipi_dsi_driver(pd1505l_otm9605a_540p_baoming_driver); + +MODULE_AUTHOR("linux-mdss-dsi-panel-driver-generator "); // FIXME +MODULE_DESCRIPTION("DRM driver for pd1505l otm9605a 540p video mode baoming dsi panel"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/panel/msm8916-generated/panel-pd1505l-otm9605a-boenew.c b/drivers/gpu/drm/panel/msm8916-generated/panel-pd1505l-otm9605a-boenew.c new file mode 100644 index 00000000000000..94a8fe1b1291fd --- /dev/null +++ b/drivers/gpu/drm/panel/msm8916-generated/panel-pd1505l-otm9605a-boenew.c @@ -0,0 +1,428 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2026 FIXME +// Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree: +// Copyright (c) 2013, The Linux Foundation. All rights reserved. (FIXME) + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +struct pd1505l_otm9605a_540p_boenew { + struct drm_panel panel; + struct mipi_dsi_device *dsi; + struct regulator_bulk_data *supplies; + struct gpio_desc *reset_gpio; +}; + +static const struct regulator_bulk_data pd1505l_otm9605a_540p_boenew_supplies[] = { + { .supply = "vdd" }, + { .supply = "vddio" }, +}; + +static inline +struct pd1505l_otm9605a_540p_boenew *to_pd1505l_otm9605a_540p_boenew(struct drm_panel *panel) +{ + return container_of_const(panel, struct pd1505l_otm9605a_540p_boenew, panel); +} + +static void pd1505l_otm9605a_540p_boenew_reset(struct pd1505l_otm9605a_540p_boenew *ctx) +{ + gpiod_set_value_cansleep(ctx->reset_gpio, 0); + usleep_range(5000, 6000); + gpiod_set_value_cansleep(ctx->reset_gpio, 1); + usleep_range(1000, 2000); + gpiod_set_value_cansleep(ctx->reset_gpio, 0); + msleep(20); +} + +static int pd1505l_otm9605a_540p_boenew_on(struct pd1505l_otm9605a_540p_boenew *ctx) +{ + struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; + + ctx->dsi->mode_flags |= MIPI_DSI_MODE_LPM; + + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xff, 0x96, 0x05, 0x01); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x80); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xff, 0x96, 0x05); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x92); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xff, 0x10, 0x02); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xc5); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb0, 0x03); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xd2); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb0, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x89); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc0, 0x01); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x90); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc0, + 0x00, 0x44, 0x00, 0x00, 0x00, 0x03); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xb4); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc0, 0x50, 0x48); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x80); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc1, 0x36, 0x66); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xa0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc1, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xa6); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc1, 0x01); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x80); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc4, 0x9c); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x84); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc4, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x86); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc4, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x87); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc4, 0x40); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x91); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc5, 0x79); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x92); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc5, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x93); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc5, 0x03); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x94); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc5, 0x55, 0x55); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xb1); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc5, 0x28); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xb2); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc5, 0x21); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xc0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc5, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xb2); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf5, + 0x15, 0x00, 0x15, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd8, 0x67, 0x67); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xe1, + 0x00, 0x07, 0x0f, 0x0e, 0x06, 0x10, + 0x0b, 0x09, 0x04, 0x07, 0x0c, 0x07, + 0x0e, 0x11, 0x0a, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xe2, + 0x00, 0x08, 0x0e, 0x0e, 0x07, 0x0f, + 0x0b, 0x0a, 0x03, 0x07, 0x0c, 0x08, + 0x0f, 0x10, 0x0a, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x80); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcb, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x90); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcb, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xa0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcb, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xb0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcb, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xc0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcb, + 0x00, 0x00, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x00, 0x00, + 0x00, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xd0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcb, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0x14); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xe0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcb, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xf0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcb, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x80); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcc, + 0x00, 0x00, 0x25, 0x09, 0x0b, 0x26, + 0x26, 0x01, 0x25, 0x25); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x90); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcc, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x25, 0x0a, 0x0c); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xa0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcc, + 0x26, 0x26, 0x02, 0x25, 0x25, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xb0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcc, + 0x00, 0x00, 0x25, 0x0c, 0x0a, 0x26, + 0x25, 0x02, 0x26, 0x25); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xc0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcc, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x25, 0x0b, 0x09); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xd0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcc, + 0x26, 0x25, 0x01, 0x26, 0x25, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x80); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xce, + 0x86, 0x01, 0x0d, 0x85, 0x01, 0x0d, + 0x0f, 0x00, 0x00, 0x0f, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x90); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xce, + 0xf0, 0x00, 0x00, 0xf0, 0x00, 0x00, + 0xf0, 0x00, 0x00, 0xf0, 0x00, 0x00, + 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xa0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xce, + 0x18, 0x05, 0x83, 0xc0, 0x87, 0x1d, + 0x0d, 0x18, 0x04, 0x83, 0xc1, 0x86, + 0x1d, 0x0d); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xb0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xce, + 0x18, 0x03, 0x83, 0xc2, 0x87, 0x1d, + 0x0d, 0x18, 0x02, 0x83, 0xc3, 0x86, + 0x1d, 0x0d); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xc0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xce, + 0xf0, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0xf0, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xd0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xce, + 0xf0, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0xf0, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xc0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcf, + 0x3d, 0x3d, 0x20, 0x20, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x80); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcf, + 0xf0, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0xf0, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x90); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcf, + 0xf0, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0xf0, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xa0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcf, + 0xf0, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0xf0, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xb0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcf, + 0xf0, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0xf0, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xec, + 0x40, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x04); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xed, + 0x40, 0x34, 0x44, 0x44, 0x34, 0x44, + 0x44, 0x43, 0x44, 0x34, 0x44, 0x44, + 0x34, 0x44, 0x44, 0x43, 0x44, 0x34, + 0x44, 0x44, 0x34, 0x44, 0x44, 0x43, + 0x44, 0x34, 0x44, 0x44, 0x34, 0x44, + 0x44, 0x43, 0x04); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xee, + 0x40, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x04); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x80); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xff, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xff, 0x00, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x11, 0x00); + mipi_dsi_msleep(&dsi_ctx, 120); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x29, 0x00); + mipi_dsi_msleep(&dsi_ctx, 20); + + return dsi_ctx.accum_err; +} + +static int pd1505l_otm9605a_540p_boenew_off(struct pd1505l_otm9605a_540p_boenew *ctx) +{ + struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; + + ctx->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; + + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 20); + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 120); + + return dsi_ctx.accum_err; +} + +static int pd1505l_otm9605a_540p_boenew_prepare(struct drm_panel *panel) +{ + struct pd1505l_otm9605a_540p_boenew *ctx = to_pd1505l_otm9605a_540p_boenew(panel); + struct device *dev = &ctx->dsi->dev; + int ret; + + ret = regulator_bulk_enable(ARRAY_SIZE(pd1505l_otm9605a_540p_boenew_supplies), ctx->supplies); + if (ret < 0) { + dev_err(dev, "Failed to enable regulators: %d\n", ret); + return ret; + } + + pd1505l_otm9605a_540p_boenew_reset(ctx); + + ret = pd1505l_otm9605a_540p_boenew_on(ctx); + if (ret < 0) { + dev_err(dev, "Failed to initialize panel: %d\n", ret); + gpiod_set_value_cansleep(ctx->reset_gpio, 1); + regulator_bulk_disable(ARRAY_SIZE(pd1505l_otm9605a_540p_boenew_supplies), ctx->supplies); + return ret; + } + + return 0; +} + +static int pd1505l_otm9605a_540p_boenew_unprepare(struct drm_panel *panel) +{ + struct pd1505l_otm9605a_540p_boenew *ctx = to_pd1505l_otm9605a_540p_boenew(panel); + struct device *dev = &ctx->dsi->dev; + int ret; + + ret = pd1505l_otm9605a_540p_boenew_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_bulk_disable(ARRAY_SIZE(pd1505l_otm9605a_540p_boenew_supplies), ctx->supplies); + + return 0; +} + +static const struct drm_display_mode pd1505l_otm9605a_540p_boenew_mode = { + .clock = (540 + 35 + 4 + 100) * (960 + 15 + 4 + 16) * 60 / 1000, + .hdisplay = 540, + .hsync_start = 540 + 35, + .hsync_end = 540 + 35 + 4, + .htotal = 540 + 35 + 4 + 100, + .vdisplay = 960, + .vsync_start = 960 + 15, + .vsync_end = 960 + 15 + 4, + .vtotal = 960 + 15 + 4 + 16, + .width_mm = 58, + .height_mm = 103, + .type = DRM_MODE_TYPE_DRIVER, +}; + +static int pd1505l_otm9605a_540p_boenew_get_modes(struct drm_panel *panel, + struct drm_connector *connector) +{ + return drm_connector_helper_get_modes_fixed(connector, &pd1505l_otm9605a_540p_boenew_mode); +} + +static const struct drm_panel_funcs pd1505l_otm9605a_540p_boenew_panel_funcs = { + .prepare = pd1505l_otm9605a_540p_boenew_prepare, + .unprepare = pd1505l_otm9605a_540p_boenew_unprepare, + .get_modes = pd1505l_otm9605a_540p_boenew_get_modes, +}; + +static int pd1505l_otm9605a_540p_boenew_probe(struct mipi_dsi_device *dsi) +{ + struct device *dev = &dsi->dev; + struct pd1505l_otm9605a_540p_boenew *ctx; + int ret; + + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + drm_panel_init(&ctx->panel, dev, &pd1505l_otm9605a_540p_boenew_panel_funcs, + DRM_MODE_CONNECTOR_DSI); + + ret = devm_regulator_bulk_get_const(dev, + ARRAY_SIZE(pd1505l_otm9605a_540p_boenew_supplies), + pd1505l_otm9605a_540p_boenew_supplies, + &ctx->supplies); + if (ret < 0) + return ret; + + 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 = 2; + dsi->format = MIPI_DSI_FMT_RGB888; + dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | + MIPI_DSI_MODE_VIDEO_HSE | + MIPI_DSI_CLOCK_NON_CONTINUOUS | + MIPI_DSI_MODE_VIDEO_NO_HBP; + + ctx->panel.prepare_prev_first = true; + + ret = drm_panel_of_backlight(&ctx->panel); + if (ret) + return dev_err_probe(dev, ret, "Failed to get backlight\n"); + + drm_panel_add(&ctx->panel); + + ret = mipi_dsi_attach(dsi); + if (ret < 0) { + drm_panel_remove(&ctx->panel); + return dev_err_probe(dev, ret, "Failed to attach to DSI host\n"); + } + + return 0; +} + +static void pd1505l_otm9605a_540p_boenew_remove(struct mipi_dsi_device *dsi) +{ + struct pd1505l_otm9605a_540p_boenew *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 pd1505l_otm9605a_540p_boenew_of_match[] = { + { .compatible = "vivo,otm9605a-boenew" }, // FIXME + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, pd1505l_otm9605a_540p_boenew_of_match); + +static struct mipi_dsi_driver pd1505l_otm9605a_540p_boenew_driver = { + .probe = pd1505l_otm9605a_540p_boenew_probe, + .remove = pd1505l_otm9605a_540p_boenew_remove, + .driver = { + .name = "panel-pd1505l-otm9605a-540p-boenew", + .of_match_table = pd1505l_otm9605a_540p_boenew_of_match, + }, +}; +module_mipi_dsi_driver(pd1505l_otm9605a_540p_boenew_driver); + +MODULE_AUTHOR("linux-mdss-dsi-panel-driver-generator "); // FIXME +MODULE_DESCRIPTION("DRM driver for pd1505l otm9605a 540p boenew video mode dsi panel"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/panel/msm8916-generated/panel-pd1505l-otm9605a.c b/drivers/gpu/drm/panel/msm8916-generated/panel-pd1505l-otm9605a.c new file mode 100644 index 00000000000000..94a9ffcfcae036 --- /dev/null +++ b/drivers/gpu/drm/panel/msm8916-generated/panel-pd1505l-otm9605a.c @@ -0,0 +1,421 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2026 FIXME +// Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree: +// Copyright (c) 2013, The Linux Foundation. All rights reserved. (FIXME) + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +struct pd1505l_otm9605a_540p { + struct drm_panel panel; + struct mipi_dsi_device *dsi; + struct regulator_bulk_data *supplies; + struct gpio_desc *reset_gpio; +}; + +static const struct regulator_bulk_data pd1505l_otm9605a_540p_supplies[] = { + { .supply = "vdd" }, + { .supply = "vddio" }, +}; + +static inline +struct pd1505l_otm9605a_540p *to_pd1505l_otm9605a_540p(struct drm_panel *panel) +{ + return container_of_const(panel, struct pd1505l_otm9605a_540p, panel); +} + +static void pd1505l_otm9605a_540p_reset(struct pd1505l_otm9605a_540p *ctx) +{ + gpiod_set_value_cansleep(ctx->reset_gpio, 0); + usleep_range(5000, 6000); + gpiod_set_value_cansleep(ctx->reset_gpio, 1); + usleep_range(1000, 2000); + gpiod_set_value_cansleep(ctx->reset_gpio, 0); + msleep(20); +} + +static int pd1505l_otm9605a_540p_on(struct pd1505l_otm9605a_540p *ctx) +{ + struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; + + ctx->dsi->mode_flags |= MIPI_DSI_MODE_LPM; + + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xff, 0x96, 0x05, 0x01); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x80); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xff, 0x96, 0x05); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x92); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xff, 0x10, 0x02); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xa6); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc1, 0x01); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x89); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc0, 0x01); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x80); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc1, 0x36, 0x66); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xb1); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc5, 0x28); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x80); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc4, 0x9a); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xc0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc5, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xb2); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf5, + 0x15, 0x00, 0x15, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x93); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc5, 0x03); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xa0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc1, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xc5); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb0, 0x03); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x91); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc5, 0x19); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x92); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc5, 0x01); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd8, 0x67, 0x67); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xe1, + 0x00, 0x13, 0x1a, 0x0e, 0x07, 0x10, + 0x0b, 0x0b, 0x03, 0x07, 0x0c, 0x08, + 0x0f, 0x0c, 0x08, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xe2, + 0x00, 0x13, 0x1a, 0x0e, 0x07, 0x10, + 0x0c, 0x0a, 0x03, 0x06, 0x0c, 0x09, + 0x10, 0x0c, 0x07, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xec, + 0x40, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x04); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xed, + 0x40, 0x34, 0x44, 0x44, 0x34, 0x44, + 0x44, 0x43, 0x44, 0x34, 0x44, 0x44, + 0x34, 0x44, 0x44, 0x43, 0x44, 0x34, + 0x44, 0x44, 0x34, 0x44, 0x44, 0x43, + 0x44, 0x34, 0x44, 0x44, 0x34, 0x44, + 0x44, 0x43, 0x04); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xee, + 0x40, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x04); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x80); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcb, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x90); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcb, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xa0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcb, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xb0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcb, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xc0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcb, + 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xd0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcb, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x00, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xe0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcb, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xf0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcb, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x80); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcc, + 0x00, 0x00, 0x0b, 0x09, 0x01, 0x25, + 0x26, 0x00, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x90); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcc, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0c, 0x0a, 0x02); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xa0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcc, + 0x25, 0x26, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xb0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcc, + 0x00, 0x00, 0x0a, 0x0c, 0x02, 0x26, + 0x25, 0x00, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xc0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcc, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x0b, 0x01); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xd0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcc, + 0x26, 0x25, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x80); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xce, + 0x86, 0x01, 0x00, 0x85, 0x01, 0x00, + 0x0f, 0x00, 0x00, 0x0f, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x90); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xce, + 0xf0, 0x00, 0x00, 0xf0, 0x00, 0x00, + 0xf0, 0x00, 0x00, 0xf0, 0x00, 0x00, + 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xa0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xce, + 0x18, 0x03, 0x83, 0xc2, 0x87, 0x0b, + 0x00, 0x18, 0x02, 0x83, 0xc4, 0x86, + 0x0b, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xb0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xce, + 0x18, 0x05, 0x83, 0xc3, 0x00, 0x04, + 0x00, 0x18, 0x04, 0x83, 0xc5, 0x00, + 0x04, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xc0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xce, + 0xf0, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0xf0, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xd0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xce, + 0xf0, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0xf0, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xc0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcf, + 0x02, 0x02, 0x20, 0x20, 0x00, 0x00, + 0x01, 0x81, 0x00, 0x07); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xb4); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc0, 0x50, 0x48); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xd2); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb0, 0x04); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x94); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc5, 0x55, 0x55); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x80); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcf, + 0xf0, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0xf0, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x90); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcf, + 0xf0, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0xf0, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xa0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcf, + 0xf0, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0xf0, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0xb0); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcf, + 0xf0, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0xf0, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x84); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc4, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x86); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc4, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x80); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xff, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xff, 0x00, 0x00, 0x00); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x11, 0x00); + mipi_dsi_msleep(&dsi_ctx, 120); + mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x29, 0x00); + mipi_dsi_msleep(&dsi_ctx, 20); + + return dsi_ctx.accum_err; +} + +static int pd1505l_otm9605a_540p_off(struct pd1505l_otm9605a_540p *ctx) +{ + struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; + + ctx->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; + + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 20); + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 120); + + return dsi_ctx.accum_err; +} + +static int pd1505l_otm9605a_540p_prepare(struct drm_panel *panel) +{ + struct pd1505l_otm9605a_540p *ctx = to_pd1505l_otm9605a_540p(panel); + struct device *dev = &ctx->dsi->dev; + int ret; + + ret = regulator_bulk_enable(ARRAY_SIZE(pd1505l_otm9605a_540p_supplies), ctx->supplies); + if (ret < 0) { + dev_err(dev, "Failed to enable regulators: %d\n", ret); + return ret; + } + + pd1505l_otm9605a_540p_reset(ctx); + + ret = pd1505l_otm9605a_540p_on(ctx); + if (ret < 0) { + dev_err(dev, "Failed to initialize panel: %d\n", ret); + gpiod_set_value_cansleep(ctx->reset_gpio, 1); + regulator_bulk_disable(ARRAY_SIZE(pd1505l_otm9605a_540p_supplies), ctx->supplies); + return ret; + } + + return 0; +} + +static int pd1505l_otm9605a_540p_unprepare(struct drm_panel *panel) +{ + struct pd1505l_otm9605a_540p *ctx = to_pd1505l_otm9605a_540p(panel); + struct device *dev = &ctx->dsi->dev; + int ret; + + ret = pd1505l_otm9605a_540p_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_bulk_disable(ARRAY_SIZE(pd1505l_otm9605a_540p_supplies), ctx->supplies); + + return 0; +} + +static const struct drm_display_mode pd1505l_otm9605a_540p_mode = { + .clock = (540 + 35 + 4 + 100) * (960 + 15 + 4 + 16) * 60 / 1000, + .hdisplay = 540, + .hsync_start = 540 + 35, + .hsync_end = 540 + 35 + 4, + .htotal = 540 + 35 + 4 + 100, + .vdisplay = 960, + .vsync_start = 960 + 15, + .vsync_end = 960 + 15 + 4, + .vtotal = 960 + 15 + 4 + 16, + .width_mm = 58, + .height_mm = 103, + .type = DRM_MODE_TYPE_DRIVER, +}; + +static int pd1505l_otm9605a_540p_get_modes(struct drm_panel *panel, + struct drm_connector *connector) +{ + return drm_connector_helper_get_modes_fixed(connector, &pd1505l_otm9605a_540p_mode); +} + +static const struct drm_panel_funcs pd1505l_otm9605a_540p_panel_funcs = { + .prepare = pd1505l_otm9605a_540p_prepare, + .unprepare = pd1505l_otm9605a_540p_unprepare, + .get_modes = pd1505l_otm9605a_540p_get_modes, +}; + +static int pd1505l_otm9605a_540p_probe(struct mipi_dsi_device *dsi) +{ + struct device *dev = &dsi->dev; + struct pd1505l_otm9605a_540p *ctx; + int ret; + + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + drm_panel_init(&ctx->panel, dev, &pd1505l_otm9605a_540p_panel_funcs, + DRM_MODE_CONNECTOR_DSI); + + ret = devm_regulator_bulk_get_const(dev, + ARRAY_SIZE(pd1505l_otm9605a_540p_supplies), + pd1505l_otm9605a_540p_supplies, + &ctx->supplies); + if (ret < 0) + return ret; + + 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 = 2; + dsi->format = MIPI_DSI_FMT_RGB888; + dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | + MIPI_DSI_MODE_VIDEO_HSE | + MIPI_DSI_CLOCK_NON_CONTINUOUS | + MIPI_DSI_MODE_VIDEO_NO_HBP; + + ctx->panel.prepare_prev_first = true; + + ret = drm_panel_of_backlight(&ctx->panel); + if (ret) + return dev_err_probe(dev, ret, "Failed to get backlight\n"); + + drm_panel_add(&ctx->panel); + + ret = mipi_dsi_attach(dsi); + if (ret < 0) { + drm_panel_remove(&ctx->panel); + return dev_err_probe(dev, ret, "Failed to attach to DSI host\n"); + } + + return 0; +} + +static void pd1505l_otm9605a_540p_remove(struct mipi_dsi_device *dsi) +{ + struct pd1505l_otm9605a_540p *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 pd1505l_otm9605a_540p_of_match[] = { + { .compatible = "vivo,otm9605a" }, // FIXME + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, pd1505l_otm9605a_540p_of_match); + +static struct mipi_dsi_driver pd1505l_otm9605a_540p_driver = { + .probe = pd1505l_otm9605a_540p_probe, + .remove = pd1505l_otm9605a_540p_remove, + .driver = { + .name = "panel-pd1505l-otm9605a-540p", + .of_match_table = pd1505l_otm9605a_540p_of_match, + }, +}; +module_mipi_dsi_driver(pd1505l_otm9605a_540p_driver); + +MODULE_AUTHOR("linux-mdss-dsi-panel-driver-generator "); // FIXME +MODULE_DESCRIPTION("DRM driver for pd1505l otm9605a 540p video mode dsi panel"); +MODULE_LICENSE("GPL");