brintos

brintos / linux-shallow public Read only

0
0
Text · 29.0 KiB · 8b48bba Raw
707 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Driver for panels based on Himax HX83102 controller, such as:4 *5 * - Starry 10.51" WUXGA MIPI-DSI panel6 *7 * Based on drivers/gpu/drm/panel/panel-himax-hx8394.c8 */9 10#include <linux/delay.h>11#include <linux/gpio/consumer.h>12#include <linux/module.h>13#include <linux/of.h>14#include <linux/regulator/consumer.h>15 16#include <drm/drm_connector.h>17#include <drm/drm_crtc.h>18#include <drm/drm_mipi_dsi.h>19#include <drm/drm_panel.h>20 21#include <video/mipi_display.h>22 23/* Manufacturer specific DSI commands */24#define HX83102_SETPOWER	0xb125#define HX83102_SETDISP		0xb226#define HX83102_SETCYC		0xb427#define HX83102_SETEXTC		0xb928#define HX83102_SETMIPI		0xba29#define HX83102_SETVDC		0xbc30#define HX83102_SETBANK		0xbd31#define HX83102_UNKNOWN_BE	0xbe32#define HX83102_SETPTBA		0xbf33#define HX83102_SETSTBA		0xc034#define HX83102_SETTCON		0xc735#define HX83102_SETRAMDMY	0xc836#define HX83102_SETPWM		0xc937#define HX83102_SETCLOCK	0xcb38#define HX83102_SETPANEL	0xcc39#define HX83102_SETCASCADE	0xd040#define HX83102_SETPCTRL	0xd141#define HX83102_UNKNOWN_D2	0xd242#define HX83102_SETGIP0		0xd343#define HX83102_SETGIP1		0xd544#define HX83102_SETGIP2		0xd645#define HX83102_SETGIP3		0xd846#define HX83102_SETGMA		0xe047#define HX83102_UNKNOWN_E1	0xe148#define HX83102_SETTP1		0xe749#define HX83102_SETSPCCMD	0xe950 51struct hx83102 {52	struct drm_panel base;53	struct mipi_dsi_device *dsi;54 55	const struct hx83102_panel_desc *desc;56 57	enum drm_panel_orientation orientation;58	struct regulator *pp1800;59	struct regulator *avee;60	struct regulator *avdd;61	struct gpio_desc *enable_gpio;62};63 64struct hx83102_panel_desc {65	const struct drm_display_mode *modes;66 67	/**68	 * @width_mm: width of the panel's active display area69	 * @height_mm: height of the panel's active display area70	 */71	struct {72		unsigned int width_mm;73		unsigned int height_mm;74	} size;75 76	int (*init)(struct hx83102 *ctx);77};78 79static inline struct hx83102 *panel_to_hx83102(struct drm_panel *panel)80{81	return container_of(panel, struct hx83102, base);82}83 84static void hx83102_enable_extended_cmds(struct mipi_dsi_multi_context *dsi_ctx, bool enable)85{86	if (enable)87		mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX83102_SETEXTC, 0x83, 0x10, 0x21, 0x55, 0x00);88	else89		mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX83102_SETEXTC, 0x00, 0x00, 0x00);90}91 92static int starry_himax83102_j02_init(struct hx83102 *ctx)93{94	struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi };95 96	hx83102_enable_extended_cmds(&dsi_ctx, true);97	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x2c, 0xb5, 0xb5, 0x31, 0xf1,98				     0x31, 0xd7, 0x2f, 0x36, 0x36, 0x36, 0x36, 0x1a, 0x8b, 0x11,99				     0x65, 0x00, 0x88, 0xfa, 0xff, 0xff, 0x8f, 0xff, 0x08, 0x74,100				     0x33);101	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETDISP, 0x00, 0x47, 0xb0, 0x80, 0x00,102				     0x12, 0x72, 0x3c, 0xa3, 0x03, 0x03, 0x00, 0x00, 0x88, 0xf5);103	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x76, 0x76, 0x76, 0x76, 0x76,104				     0x76, 0x63, 0x5c, 0x63, 0x5c, 0x01, 0x9e);105	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcd);106	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x84);107	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);108	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETVDC, 0x1b, 0x04);109	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_BE, 0x20);110	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPTBA, 0xfc, 0xc4);111	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSTBA, 0x36, 0x36, 0x22, 0x11, 0x22,112				     0xa0, 0x61, 0x08, 0xf5, 0x03);113	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcc);114	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTCON, 0x80);115	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);116	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6);117	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETRAMDMY, 0x97);118	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);119	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPWM, 0x00, 0x1e, 0x13, 0x88, 0x01);120	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x08, 0x13, 0x07, 0x00, 0x0f, 0x33);121	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPANEL, 0x02);122	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4);123	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCASCADE, 0x03);124	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);125	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPCTRL, 0x37, 0x06, 0x00, 0x02, 0x04, 0x0c,126				     0xff);127	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D2, 0x1f, 0x11, 0x1f);128	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,129				     0x08, 0x00, 0x08, 0x37, 0x47, 0x34, 0x3b, 0x12, 0x12, 0x03, 0x03,130				     0x32, 0x10, 0x10, 0x00, 0x10, 0x32, 0x10, 0x08, 0x00, 0x08, 0x32,131				     0x17, 0x94, 0x07, 0x94, 0x00, 0x00);132	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP1, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,133				     0x18, 0x18, 0x18, 0x18, 0x19, 0x19, 0x40, 0x40, 0x1a, 0x1a, 0x1b,134				     0x1b, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x20, 0x21,135				     0x28, 0x29, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,136				     0x18, 0x18, 0x18, 0x18, 0x18);137	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP2, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,138				     0x18, 0x18, 0x18, 0x18, 0x40, 0x40, 0x19, 0x19, 0x1a, 0x1a, 0x1b,139				     0x1b, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x29, 0x28,140				     0x21, 0x20, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,141				     0x18, 0x18, 0x18, 0x18, 0x18);142	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xaa, 0xba, 0xea, 0xaa, 0xaa, 0xa0,143				     0xaa, 0xba, 0xea, 0xaa, 0xaa, 0xa0, 0xaa, 0xba, 0xea, 0xaa, 0xaa,144				     0xa0, 0xaa, 0xba, 0xea, 0xaa, 0xaa, 0xa0, 0xaa, 0xba, 0xea, 0xaa,145				     0xaa, 0xa0, 0xaa, 0xba, 0xea, 0xaa, 0xaa, 0xa0);146	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGMA, 0x00, 0x09, 0x14, 0x1e, 0x26, 0x48,147				     0x61, 0x67, 0x6c, 0x67, 0x7d, 0x7f, 0x80, 0x8b, 0x87, 0x8f, 0x98,148				     0xab, 0xab, 0x55, 0x5c, 0x68, 0x73, 0x00, 0x09, 0x14, 0x1e, 0x26,149				     0x48, 0x61, 0x67, 0x6c, 0x67, 0x7d, 0x7f, 0x80, 0x8b, 0x87, 0x8f,150				     0x98, 0xab, 0xab, 0x55, 0x5c, 0x68, 0x73);151	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x0e, 0x10, 0x10, 0x21, 0x2b, 0x9a,152				     0x02, 0x54, 0x9a, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x12, 0x05,153				     0x02, 0x02, 0x10);154	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01);155	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x01, 0xbf, 0x11);156	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x86);157	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D2, 0x3c, 0xfa);158	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00,159				     0x00, 0x00, 0x80, 0x0c, 0x01);160	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x02, 0x00, 0x28, 0x01, 0x7e, 0x0f,161				     0x7e, 0x10, 0xa0, 0x00, 0x00, 0x20, 0x40, 0x50, 0x40);162	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x02);163	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xff, 0xff, 0xbf, 0xfe, 0xaa, 0xa0,164				     0xff, 0xff, 0xbf, 0xfe, 0xaa, 0xa0);165	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0xfe, 0x04, 0xfe, 0x04, 0xfe, 0x04,166				     0x03, 0x03, 0x03, 0x26, 0x00, 0x26, 0x81, 0x02, 0x40, 0x00, 0x20,167				     0x9e, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00);168	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x03);169	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6);170	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x03, 0xff, 0xf8);171	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);172	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0x00, 0x2a, 0xaa, 0xa8, 0x00, 0x00,173				     0x00, 0x2a, 0xaa, 0xa8, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfc, 0x00,174				     0x00, 0x00, 0x3f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x2a, 0xaa, 0xa8,175				     0x00, 0x00, 0x00, 0x2a, 0xaa, 0xa8, 0x00, 0x00);176	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00);177	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4);178	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x96);179	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);180	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01);181	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc5);182	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x4f);183	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);184	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00);185 186	return dsi_ctx.accum_err;187};188 189static int boe_nv110wum_init(struct hx83102 *ctx)190{191	struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi };192 193	msleep(60);194 195	hx83102_enable_extended_cmds(&dsi_ctx, true);196	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x2c, 0xaf, 0xaf, 0x2b, 0xeb, 0x42,197				     0xe1, 0x4d, 0x36, 0x36, 0x36, 0x36, 0x1a, 0x8b, 0x11, 0x65, 0x00,198				     0x88, 0xfa, 0xff, 0xff, 0x8f, 0xff, 0x08, 0x9a, 0x33);199	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETDISP, 0x00, 0x47, 0xb0, 0x80, 0x00, 0x12,200				     0x71, 0x3c, 0xa3, 0x11, 0x00, 0x00, 0x00, 0x88, 0xf5, 0x22, 0x8f);201	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x49, 0x49, 0x32, 0x32, 0x14, 0x32,202				     0x84, 0x6e, 0x84, 0x6e, 0x01, 0x9c);203	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcd);204	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x84);205	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);206	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETVDC, 0x1b, 0x04);207	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_BE, 0x20);208	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPTBA, 0xfc, 0x84);209	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSTBA, 0x36, 0x36, 0x22, 0x00, 0x00, 0xa0,210				     0x61, 0x08, 0xf5, 0x03);211	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcc);212	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTCON, 0x80);213	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);214	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6);215	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETRAMDMY, 0x97);216	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);217	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPWM, 0x00, 0x1e, 0x30, 0xd4, 0x01);218	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x08, 0x13, 0x07, 0x00, 0x0f, 0x34);219	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPANEL, 0x02, 0x03, 0x44);220	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4);221	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCASCADE, 0x03);222	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);223	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPCTRL, 0x37, 0x06, 0x00, 0x02, 0x04, 0x0c, 0xff);224	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D2, 0x1f, 0x11, 0x1f, 0x11);225	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x06, 0x00, 0x00, 0x00, 0x00, 0x04,226				     0x08, 0x04, 0x08, 0x37, 0x37, 0x64, 0x4b, 0x11, 0x11, 0x03, 0x03, 0x32,227				     0x10, 0x0e, 0x00, 0x0e, 0x32, 0x10, 0x0a, 0x00, 0x0a, 0x32, 0x17, 0x98,228				     0x07, 0x98, 0x00, 0x00);229	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP1, 0x18, 0x18, 0x18, 0x18, 0x1e, 0x1e,230				     0x1e, 0x1e, 0x1f, 0x1f, 0x1f, 0x1f, 0x24, 0x24, 0x24, 0x24, 0x07, 0x06,231				     0x07, 0x06, 0x05, 0x04, 0x05, 0x04, 0x03, 0x02, 0x03, 0x02, 0x01, 0x00,232				     0x01, 0x00, 0x21, 0x20, 0x21, 0x20, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,233				     0x18, 0x18);234	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0,235				     0xaf, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0);236	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGMA, 0x00, 0x05, 0x0d, 0x14, 0x1b, 0x2c,237				     0x44, 0x49, 0x51, 0x4c, 0x67, 0x6c, 0x71, 0x80, 0x7d, 0x84, 0x8d, 0xa0,238				     0xa0, 0x4f, 0x58, 0x64, 0x73, 0x00, 0x05, 0x0d, 0x14, 0x1b, 0x2c, 0x44,239				     0x49, 0x51, 0x4c, 0x67, 0x6c, 0x71, 0x80, 0x7d, 0x84, 0x8d, 0xa0, 0xa0,240				     0x4f, 0x58, 0x64, 0x73);241	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x07, 0x10, 0x10, 0x1a, 0x26, 0x9e,242				     0x00, 0x53, 0x9b, 0x14, 0x14);243	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_E1, 0x11, 0x00, 0x00, 0x89, 0x30, 0x80,244				     0x07, 0x80, 0x02, 0x58, 0x00, 0x14, 0x02, 0x58, 0x02, 0x58, 0x02, 0x00,245				     0x02, 0x2c, 0x00, 0x20, 0x02, 0x02, 0x00, 0x08, 0x00, 0x0c, 0x05, 0x0e,246				     0x04, 0x94, 0x18, 0x00, 0x10, 0xf0, 0x03, 0x0c, 0x20, 0x00, 0x06, 0x0b,247				     0x0b, 0x33, 0x0e);248	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01);249	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xa0,250				     0xff, 0xff, 0xff, 0xff, 0xfa, 0xa0);251	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x01, 0xbf, 0x11);252	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x86);253	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D2, 0x96);254	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc9);255	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x84);256	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);257	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xd1);258	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_E1, 0xf6, 0x2b, 0x34, 0x2b, 0x74, 0x3b,259				     0x74, 0x6b, 0x74);260	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);261	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x02, 0x00, 0x2b, 0x01, 0x7e, 0x0f,262				     0x7e, 0x10, 0xa0, 0x00, 0x00);263	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x02);264	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x02, 0x00, 0xbb, 0x11);265	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xff, 0xaf, 0xff, 0xff, 0xfa, 0xa0,266				     0xff, 0xaf, 0xff, 0xff, 0xfa, 0xa0);267	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01,268				     0x00, 0x00, 0x00, 0x23, 0x00, 0x23, 0x81, 0x02, 0x40, 0x00, 0x20, 0x65,269				     0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00);270	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x03);271	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xaa, 0xaf, 0xaa, 0xaa, 0xa0, 0x00,272				     0xaa, 0xaf, 0xaa, 0xaa, 0xa0, 0x00, 0xaa, 0xaf, 0xaa, 0xaa, 0xa0, 0x00,273				     0xaa, 0xaf, 0xaa, 0xaa, 0xa0, 0x00);274	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6);275	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x03, 0xff, 0xf8);276	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);277	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_E1, 0x00);278	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00);279	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4);280	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x96);281	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);282	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01);283	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc5);284	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x4f);285	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);286	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00);287	hx83102_enable_extended_cmds(&dsi_ctx, false);288 289	mipi_dsi_msleep(&dsi_ctx, 50);290 291	return dsi_ctx.accum_err;292};293 294static int ivo_t109nw41_init(struct hx83102 *ctx)295{296	struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi };297 298	msleep(60);299 300	hx83102_enable_extended_cmds(&dsi_ctx, true);301	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x2c, 0xed, 0xed, 0x27, 0xe7, 0x52,302				     0xf5, 0x39, 0x36, 0x36, 0x36, 0x36, 0x32, 0x8b, 0x11, 0x65, 0x00, 0x88,303				     0xfa, 0xff, 0xff, 0x8f, 0xff, 0x08, 0xd6, 0x33);304	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETDISP, 0x00, 0x47, 0xb0, 0x80, 0x00, 0x12,305				     0x71, 0x3c, 0xa3, 0x22, 0x20, 0x00, 0x00, 0x88, 0x01);306	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x35, 0x35, 0x43, 0x43, 0x35, 0x35,307				     0x30, 0x7a, 0x30, 0x7a, 0x01, 0x9d);308	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcd);309	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x84);310	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);311	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETVDC, 0x1b, 0x04);312	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_BE, 0x20);313	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPTBA, 0xfc, 0xc4);314	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSTBA, 0x34, 0x34, 0x22, 0x11, 0x22, 0xa0,315				     0x31, 0x08, 0xf5, 0x03);316	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xcc);317	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTCON, 0x80);318	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);319	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xd3);320	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTCON, 0x22);321	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);322	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6);323	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETRAMDMY, 0x97);324	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);325	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPWM, 0x00, 0x1e, 0x13, 0x88, 0x01);326	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x08, 0x13, 0x07, 0x00, 0x0f, 0x34);327	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPANEL, 0x02, 0x03, 0x44);328	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4);329	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCASCADE, 0x03);330	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);331	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPCTRL, 0x07, 0x06, 0x00, 0x02, 0x04, 0x2c,332				     0xff);333	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x06, 0x00, 0x00, 0x00, 0x00, 0x08,334				     0x08, 0x08, 0x08, 0x37, 0x07, 0x64, 0x7c, 0x11, 0x11, 0x03, 0x03, 0x32,335				     0x10, 0x0e, 0x00, 0x0e, 0x32, 0x17, 0x97, 0x07, 0x97, 0x32, 0x00, 0x02,336				     0x00, 0x02, 0x00, 0x00);337	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP1, 0x25, 0x24, 0x25, 0x24, 0x18, 0x18,338				     0x18, 0x18, 0x07, 0x06, 0x07, 0x06, 0x05, 0x04, 0x05, 0x04, 0x03, 0x02,339				     0x03, 0x02, 0x01, 0x00, 0x01, 0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x1f, 0x1f,340				     0x1f, 0x1f, 0x21, 0x20, 0x21, 0x20, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,341				     0x18, 0x18);342	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0,343				     0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,344				     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,345				     0x00, 0x00, 0x00, 0x00, 0x00, 0x00);346	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGMA, 0x00, 0x07, 0x10, 0x17, 0x1c, 0x33,347				     0x48, 0x50, 0x57, 0x50, 0x68, 0x6e, 0x71, 0x7f, 0x81, 0x8a, 0x8e, 0x9b,348				     0x9c, 0x4d, 0x56, 0x5d, 0x73, 0x00, 0x07, 0x10, 0x17, 0x1c, 0x33, 0x48,349				     0x50, 0x57, 0x50, 0x68, 0x6e, 0x71, 0x7f, 0x81, 0x8a, 0x8e, 0x9b, 0x9c,350				     0x4d, 0x56, 0x5d, 0x73);351	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x07, 0x10, 0x10, 0x1a, 0x26, 0x9e,352				     0x00, 0x4f, 0xa0, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x12, 0x0a, 0x02,353				     0x02, 0x00, 0x33, 0x02, 0x04, 0x18, 0x01);354	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01);355	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPOWER, 0x01, 0x7f, 0x11, 0xfd);356	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x86);357	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP0, 0x00, 0x00, 0x04, 0x00, 0x00);358	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,359				     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0,360				     0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,361				     0x00, 0x00, 0x00, 0x00, 0x00, 0x00);362	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0x02, 0x00, 0x2b, 0x01, 0x7e, 0x0f,363				     0x7e, 0x10, 0xa0, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00);364	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x02);365	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETPTBA, 0xf2);366	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCLOCK, 0x03, 0x07, 0x00, 0x10, 0x79);367	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETGIP3, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xa0,368				     0xff, 0xff, 0xff, 0xff, 0xfa, 0xa0);369	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETTP1, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01,370				     0x00, 0x00, 0x00, 0x23, 0x00, 0x23, 0x81, 0x02, 0x40, 0x00, 0x20, 0x6e,371				     0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);372	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x03);373	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0,374				     0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xa0,375				     0xff, 0xff, 0xff, 0xff, 0xfa, 0xa0, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0,376				     0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,377				     0x00, 0x00, 0x00, 0x00, 0x00, 0x00);378	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc6);379	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETCYC, 0x03, 0xff, 0xf8);380	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);381	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_E1, 0x00);382	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00);383	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_UNKNOWN_D2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff);384	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc4);385	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x96);386	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);387	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x01);388	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0xc5);389	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETMIPI, 0x4f);390	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETSPCCMD, 0x3f);391	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83102_SETBANK, 0x00);392	hx83102_enable_extended_cmds(&dsi_ctx, false);393 394	mipi_dsi_msleep(&dsi_ctx, 60);395 396	return dsi_ctx.accum_err;397};398 399static const struct drm_display_mode starry_mode = {400	.clock = 162680,401	.hdisplay = 1200,402	.hsync_start = 1200 + 60,403	.hsync_end = 1200 + 60 + 20,404	.htotal = 1200 + 60 + 20 + 40,405	.vdisplay = 1920,406	.vsync_start = 1920 + 116,407	.vsync_end = 1920 + 116 + 8,408	.vtotal = 1920 + 116 + 8 + 12,409	.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,410};411 412static const struct hx83102_panel_desc starry_desc = {413	.modes = &starry_mode,414	.size = {415		.width_mm = 141,416		.height_mm = 226,417	},418	.init = starry_himax83102_j02_init,419};420 421static const struct drm_display_mode boe_tv110wum_default_mode = {422	.clock = 167700,423	.hdisplay = 1200,424	.hsync_start = 1200 + 75,425	.hsync_end = 1200 + 75 + 20,426	.htotal = 1200 + 75 + 20 + 65,427	.vdisplay = 1920,428	.vsync_start = 1920 + 115,429	.vsync_end = 1920 + 115 + 8,430	.vtotal = 1920 + 115 + 8 + 12,431	.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,432};433 434static const struct hx83102_panel_desc boe_nv110wum_desc = {435	.modes = &boe_tv110wum_default_mode,436	.size = {437		.width_mm = 147,438		.height_mm = 235,439	},440	.init = boe_nv110wum_init,441};442 443static const struct drm_display_mode ivo_t109nw41_default_mode = {444	.clock = 167700,445	.hdisplay = 1200,446	.hsync_start = 1200 + 75,447	.hsync_end = 1200 + 75 + 20,448	.htotal = 1200 + 75 + 20 + 65,449	.vdisplay = 1920,450	.vsync_start = 1920 + 115,451	.vsync_end = 1920 + 115 + 8,452	.vtotal = 1920 + 115 + 8 + 12,453	.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,454};455 456static const struct hx83102_panel_desc ivo_t109nw41_desc = {457	.modes = &ivo_t109nw41_default_mode,458	.size = {459		.width_mm = 147,460		.height_mm = 235,461	},462	.init = ivo_t109nw41_init,463};464 465static int hx83102_enable(struct drm_panel *panel)466{467	msleep(130);468	return 0;469}470 471static int hx83102_disable(struct drm_panel *panel)472{473	struct hx83102 *ctx = panel_to_hx83102(panel);474	struct mipi_dsi_device *dsi = ctx->dsi;475	struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };476 477	dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;478 479	mipi_dsi_dcs_set_display_off_multi(&dsi_ctx);480	mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx);481 482	mipi_dsi_msleep(&dsi_ctx, 150);483 484	return dsi_ctx.accum_err;485}486 487static int hx83102_unprepare(struct drm_panel *panel)488{489	struct hx83102 *ctx = panel_to_hx83102(panel);490 491	gpiod_set_value(ctx->enable_gpio, 0);492	usleep_range(1000, 2000);493	regulator_disable(ctx->avee);494	regulator_disable(ctx->avdd);495	usleep_range(5000, 7000);496	regulator_disable(ctx->pp1800);497 498	return 0;499}500 501static int hx83102_prepare(struct drm_panel *panel)502{503	struct hx83102 *ctx = panel_to_hx83102(panel);504	struct mipi_dsi_device *dsi = ctx->dsi;505	struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };506 507	gpiod_set_value(ctx->enable_gpio, 0);508	usleep_range(1000, 1500);509 510	dsi_ctx.accum_err = regulator_enable(ctx->pp1800);511	if (dsi_ctx.accum_err)512		return dsi_ctx.accum_err;513 514	usleep_range(3000, 5000);515 516	dsi_ctx.accum_err = regulator_enable(ctx->avdd);517	if (dsi_ctx.accum_err)518		goto poweroff1v8;519	dsi_ctx.accum_err = regulator_enable(ctx->avee);520	if (dsi_ctx.accum_err)521		goto poweroffavdd;522 523	usleep_range(10000, 11000);524 525	mipi_dsi_dcs_nop_multi(&dsi_ctx);526	if (dsi_ctx.accum_err)527		goto poweroff;528 529	usleep_range(1000, 2000);530 531	gpiod_set_value(ctx->enable_gpio, 1);532	usleep_range(1000, 2000);533	gpiod_set_value(ctx->enable_gpio, 0);534	usleep_range(1000, 2000);535	gpiod_set_value(ctx->enable_gpio, 1);536	usleep_range(6000, 10000);537 538	dsi_ctx.accum_err = ctx->desc->init(ctx);539 540	mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);541	mipi_dsi_msleep(&dsi_ctx, 120);542	mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);543	if (dsi_ctx.accum_err)544		goto poweroff;545 546	return 0;547 548poweroff:549	gpiod_set_value(ctx->enable_gpio, 0);550	regulator_disable(ctx->avee);551poweroffavdd:552	regulator_disable(ctx->avdd);553poweroff1v8:554	usleep_range(5000, 7000);555	regulator_disable(ctx->pp1800);556 557	return dsi_ctx.accum_err;558}559 560static int hx83102_get_modes(struct drm_panel *panel,561			    struct drm_connector *connector)562{563	struct hx83102 *ctx = panel_to_hx83102(panel);564	const struct drm_display_mode *m = ctx->desc->modes;565	struct drm_display_mode *mode;566 567	mode = drm_mode_duplicate(connector->dev, m);568 569	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;570	drm_mode_set_name(mode);571	drm_mode_probed_add(connector, mode);572 573	connector->display_info.width_mm = ctx->desc->size.width_mm;574	connector->display_info.height_mm = ctx->desc->size.height_mm;575	connector->display_info.bpc = 8;576 577	return 1;578}579 580static enum drm_panel_orientation hx83102_get_orientation(struct drm_panel *panel)581{582	struct hx83102 *ctx = panel_to_hx83102(panel);583 584	return ctx->orientation;585}586 587static const struct drm_panel_funcs hx83102_drm_funcs = {588	.disable   = hx83102_disable,589	.unprepare = hx83102_unprepare,590	.prepare   = hx83102_prepare,591	.enable    = hx83102_enable,592	.get_modes = hx83102_get_modes,593	.get_orientation = hx83102_get_orientation,594};595 596static int hx83102_panel_add(struct hx83102 *ctx)597{598	struct device *dev = &ctx->dsi->dev;599	int err;600 601	ctx->avdd = devm_regulator_get(dev, "avdd");602	if (IS_ERR(ctx->avdd))603		return PTR_ERR(ctx->avdd);604 605	ctx->avee = devm_regulator_get(dev, "avee");606	if (IS_ERR(ctx->avee))607		return PTR_ERR(ctx->avee);608 609	ctx->pp1800 = devm_regulator_get(dev, "pp1800");610	if (IS_ERR(ctx->pp1800))611		return PTR_ERR(ctx->pp1800);612 613	ctx->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);614	if (IS_ERR(ctx->enable_gpio))615		return dev_err_probe(dev, PTR_ERR(ctx->enable_gpio), "Cannot get enable GPIO\n");616 617	ctx->base.prepare_prev_first = true;618 619	drm_panel_init(&ctx->base, dev, &hx83102_drm_funcs,620		       DRM_MODE_CONNECTOR_DSI);621	err = of_drm_get_panel_orientation(dev->of_node, &ctx->orientation);622	if (err < 0)623		return dev_err_probe(dev, err, "failed to get orientation\n");624 625	err = drm_panel_of_backlight(&ctx->base);626	if (err)627		return err;628 629	ctx->base.funcs = &hx83102_drm_funcs;630	ctx->base.dev = &ctx->dsi->dev;631 632	drm_panel_add(&ctx->base);633 634	return 0;635}636 637static int hx83102_probe(struct mipi_dsi_device *dsi)638{639	struct hx83102 *ctx;640	int ret;641	const struct hx83102_panel_desc *desc;642 643	ctx = devm_kzalloc(&dsi->dev, sizeof(*ctx), GFP_KERNEL);644	if (!ctx)645		return -ENOMEM;646 647	desc = of_device_get_match_data(&dsi->dev);648	dsi->lanes = 4;649	dsi->format = MIPI_DSI_FMT_RGB888;650	dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |651					  MIPI_DSI_MODE_LPM;652	ctx->desc = desc;653	ctx->dsi = dsi;654	ret = hx83102_panel_add(ctx);655	if (ret < 0)656		return ret;657 658	mipi_dsi_set_drvdata(dsi, ctx);659 660	ret = mipi_dsi_attach(dsi);661	if (ret)662		drm_panel_remove(&ctx->base);663 664	return ret;665}666 667static void hx83102_remove(struct mipi_dsi_device *dsi)668{669	struct hx83102 *ctx = mipi_dsi_get_drvdata(dsi);670	int ret;671 672	ret = mipi_dsi_detach(dsi);673	if (ret < 0)674		dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret);675 676	if (ctx->base.dev)677		drm_panel_remove(&ctx->base);678}679 680static const struct of_device_id hx83102_of_match[] = {681	{ .compatible = "boe,nv110wum-l60",682	.data = &boe_nv110wum_desc683	},684	{ .compatible = "ivo,t109nw41",685	  .data = &ivo_t109nw41_desc686	},687	{ .compatible = "starry,himax83102-j02",688	  .data = &starry_desc689	},690	{ /* sentinel */ }691};692MODULE_DEVICE_TABLE(of, hx83102_of_match);693 694static struct mipi_dsi_driver hx83102_driver = {695	.probe	= hx83102_probe,696	.remove = hx83102_remove,697	.driver = {698		.name = "panel-himax-hx83102",699		.of_match_table = hx83102_of_match,700	},701};702module_mipi_dsi_driver(hx83102_driver);703 704MODULE_AUTHOR("Cong Yang <yangcong5@huaqin.corp-partner.google.com>");705MODULE_DESCRIPTION("DRM driver for Himax HX83102 based MIPI DSI panels");706MODULE_LICENSE("GPL");707