File Index
Files and directories
Sign in
FILE

panel-himax-hx83112b.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/panel/panel-himax-hx83112b.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree.
  4 * Copyright (c) 2025 Luca Weiss <luca@lucaweiss.eu>
  5 */
  6
  7#include <linux/backlight.h>
  8#include <linux/delay.h>
  9#include <linux/gpio/consumer.h>
 10#include <linux/mod_devicetable.h>
 11#include <linux/module.h>
 12#include <linux/regulator/consumer.h>
 13
 14#include <video/mipi_display.h>
 15
 16#include <drm/drm_mipi_dsi.h>
 17#include <drm/drm_modes.h>
 18#include <drm/drm_panel.h>
 19#include <drm/drm_probe_helper.h>
 20
 21/* Manufacturer specific DSI commands */
 22#define HX83112B_SETPOWER1	0xb1
 23#define HX83112B_SETDISP	0xb2
 24#define HX83112B_SETDRV		0xb4
 25#define HX83112B_SETEXTC	0xb9
 26#define HX83112B_SETBANK	0xbd
 27#define HX83112B_SETDGCLUT	0xc1
 28#define HX83112B_SETDISMO	0xc2
 29#define HX83112B_UNKNOWN1	0xc6
 30#define HX83112B_SETPANEL	0xcc
 31#define HX83112B_UNKNOWN2	0xd1
 32#define HX83112B_SETPOWER2	0xd2
 33#define HX83112B_SETGIP0	0xd3
 34#define HX83112B_SETGIP1	0xd5
 35#define HX83112B_SETGIP2	0xd6
 36#define HX83112B_SETGIP3	0xd8
 37#define HX83112B_SETIDLE	0xdd
 38#define HX83112B_UNKNOWN3	0xe7
 39#define HX83112B_UNKNOWN4	0xe9
 40
 41struct hx83112b_panel {
 42	struct drm_panel panel;
 43	struct mipi_dsi_device *dsi;
 44	struct regulator_bulk_data *supplies;
 45	struct gpio_desc *reset_gpio;
 46};
 47
 48static const struct regulator_bulk_data hx83112b_supplies[] = {
 49	{ .supply = "iovcc" },
 50	{ .supply = "vsn" },
 51	{ .supply = "vsp" },
 52};
 53
 54static inline struct hx83112b_panel *to_hx83112b_panel(struct drm_panel *panel)
 55{
 56	return container_of(panel, struct hx83112b_panel, panel);
 57}
 58
 59static void hx83112b_reset(struct hx83112b_panel *ctx)
 60{
 61	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
 62	usleep_range(10000, 11000);
 63	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
 64	usleep_range(10000, 11000);
 65	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
 66	usleep_range(10000, 11000);
 67}
 68
 69static int hx83112b_on(struct hx83112b_panel *ctx)
 70{
 71	struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi };
 72
 73	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETEXTC, 0x83, 0x11, 0x2b);
 74	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETBANK, 0x01);
 75	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETDISMO, 0x08, 0x70);
 76	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETBANK, 0x03);
 77	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETDISP, 0x04, 0x38, 0x08, 0x70);
 78	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETBANK, 0x00);
 79	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETPOWER1,
 80				     0xf8, 0x27, 0x27, 0x00, 0x00, 0x0b, 0x0e,
 81				     0x0b, 0x0e, 0x33);
 82	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETPOWER2, 0x2d, 0x2d);
 83	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETDISP,
 84				     0x80, 0x02, 0x18, 0x80, 0x70, 0x00, 0x08,
 85				     0x1c, 0x08, 0x11, 0x05);
 86	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_UNKNOWN4, 0xd1);
 87	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETDISP, 0x00, 0x08);
 88	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_UNKNOWN4, 0x00);
 89	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETBANK, 0x02);
 90	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETDISP, 0xb5, 0x0a);
 91	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETBANK, 0x00);
 92	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETIDLE,
 93				     0x00, 0x00, 0x08, 0x1c, 0x08, 0x34, 0x34,
 94				     0x88);
 95	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETDRV,
 96				     0x65, 0x6b, 0x00, 0x00, 0xd0, 0xd4, 0x36,
 97				     0xcf, 0x06, 0xce, 0x00, 0xce, 0x00, 0x00,
 98				     0x00, 0x07, 0x00, 0x2a, 0x07, 0x01, 0x07,
 99				     0x00, 0x00, 0x2a);
100	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETBANK, 0x03);
101	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_UNKNOWN4, 0xc3);
102	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETDRV, 0x01, 0x67, 0x2a);
103	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_UNKNOWN4, 0x00);
104	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETBANK, 0x00);
105	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETDGCLUT, 0x01);
106	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETBANK, 0x01);
107	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETDGCLUT,
108				     0xff, 0xfb, 0xf9, 0xf6, 0xf4, 0xf1, 0xef,
109				     0xea, 0xe7, 0xe5, 0xe2, 0xdf, 0xdd, 0xda,
110				     0xd8, 0xd5, 0xd2, 0xcf, 0xcc, 0xc5, 0xbe,
111				     0xb7, 0xb0, 0xa8, 0xa0, 0x98, 0x8e, 0x85,
112				     0x7b, 0x72, 0x69, 0x5e, 0x53, 0x48, 0x3e,
113				     0x35, 0x2b, 0x22, 0x17, 0x0d, 0x09, 0x07,
114				     0x05, 0x01, 0x00, 0x26, 0xf0, 0x86, 0x25,
115				     0x6e, 0xb6, 0xdd, 0xf3, 0xd8, 0xcc, 0x9b,
116				     0x00);
117	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETBANK, 0x02);
118	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETDGCLUT,
119				     0xff, 0xfb, 0xf9, 0xf6, 0xf4, 0xf1, 0xef,
120				     0xea, 0xe7, 0xe5, 0xe2, 0xdf, 0xdd, 0xda,
121				     0xd8, 0xd5, 0xd2, 0xcf, 0xcc, 0xc5, 0xbe,
122				     0xb7, 0xb0, 0xa8, 0xa0, 0x98, 0x8e, 0x85,
123				     0x7b, 0x72, 0x69, 0x5e, 0x53, 0x48, 0x3e,
124				     0x35, 0x2b, 0x22, 0x17, 0x0d, 0x09, 0x07,
125				     0x05, 0x01, 0x00, 0x26, 0xf0, 0x86, 0x25,
126				     0x6e, 0xb6, 0xdd, 0xf3, 0xd8, 0xcc, 0x9b,
127				     0x00);
128	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETBANK, 0x03);
129	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETDGCLUT,
130				     0xff, 0xfb, 0xf9, 0xf6, 0xf4, 0xf1, 0xef,
131				     0xea, 0xe7, 0xe5, 0xe2, 0xdf, 0xdd, 0xda,
132				     0xd8, 0xd5, 0xd2, 0xcf, 0xcc, 0xc5, 0xbe,
133				     0xb7, 0xb0, 0xa8, 0xa0, 0x98, 0x8e, 0x85,
134				     0x7b, 0x72, 0x69, 0x5e, 0x53, 0x48, 0x3e,
135				     0x35, 0x2b, 0x22, 0x17, 0x0d, 0x09, 0x07,
136				     0x05, 0x01, 0x00, 0x26, 0xf0, 0x86, 0x25,
137				     0x6e, 0xb6, 0xdd, 0xf3, 0xd8, 0xcc, 0x9b,
138				     0x00);
139	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETBANK, 0x00);
140	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETDISMO, 0xc8);
141	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETPANEL, 0x08);
142	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETGIP0,
143				     0x81, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
144				     0x04, 0x00, 0x01, 0x13, 0x40, 0x04, 0x09,
145				     0x09, 0x0b, 0x0b, 0x32, 0x10, 0x08, 0x00,
146				     0x08, 0x32, 0x10, 0x08, 0x00, 0x08, 0x32,
147				     0x10, 0x08, 0x00, 0x08, 0x00, 0x00, 0x0a,
148				     0x08, 0x7b);
149	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_UNKNOWN4, 0xc5);
150	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_UNKNOWN1, 0xf7);
151	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_UNKNOWN4, 0x00);
152	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_UNKNOWN4, 0xd4);
153	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_UNKNOWN1, 0x6e);
154	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_UNKNOWN4, 0x00);
155	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_UNKNOWN4, 0xef);
156	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETGIP0, 0x0c);
157	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_UNKNOWN4, 0x00);
158	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETBANK, 0x01);
159	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_UNKNOWN4, 0xc8);
160	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETGIP0, 0xa1);
161	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_UNKNOWN4, 0x00);
162	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETBANK, 0x00);
163	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETGIP1,
164				     0x18, 0x18, 0x19, 0x18, 0x18, 0x20, 0x18,
165				     0x18, 0x18, 0x10, 0x10, 0x18, 0x18, 0x00,
166				     0x00, 0x18, 0x18, 0x01, 0x01, 0x18, 0x18,
167				     0x28, 0x28, 0x18, 0x18, 0x18, 0x18, 0x18,
168				     0x2f, 0x2f, 0x30, 0x30, 0x31, 0x31, 0x35,
169				     0x35, 0x36, 0x36, 0x37, 0x37, 0x18, 0x18,
170				     0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xfc,
171				     0xfc, 0x00, 0x00, 0xfc, 0xfc, 0x00, 0x00);
172	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETGIP2,
173				     0x18, 0x18, 0x19, 0x18, 0x18, 0x20, 0x19,
174				     0x18, 0x18, 0x10, 0x10, 0x18, 0x18, 0x00,
175				     0x00, 0x18, 0x18, 0x01, 0x01, 0x18, 0x18,
176				     0x28, 0x28, 0x18, 0x18, 0x18, 0x18, 0x18,
177				     0x2f, 0x2f, 0x30, 0x30, 0x31, 0x31, 0x35,
178				     0x35, 0x36, 0x36, 0x37, 0x37, 0x18, 0x18,
179				     0x18, 0x18, 0x18, 0x18, 0x18, 0x18);
180	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETGIP3,
181				     0xaa, 0xaa, 0xaa, 0xaf, 0xea, 0xaa, 0xaa,
182				     0xaa, 0xaa, 0xaf, 0xea, 0xaa, 0xaa, 0xaa,
183				     0xab, 0xaf, 0xef, 0xaa, 0xaa, 0xaa, 0xaa,
184				     0xaf, 0xea, 0xaa);
185	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETBANK, 0x01);
186	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETGIP3,
187				     0xaa, 0xaa, 0xab, 0xaf, 0xea, 0xaa, 0xaa,
188				     0xaa, 0xae, 0xaf, 0xea, 0xaa);
189	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETBANK, 0x02);
190	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETGIP3,
191				     0xaa, 0xaa, 0xaa, 0xaf, 0xea, 0xaa, 0xaa,
192				     0xaa, 0xaa, 0xaf, 0xea, 0xaa);
193	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETBANK, 0x03);
194	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETGIP3,
195				     0xba, 0xaa, 0xaa, 0xaf, 0xea, 0xaa, 0xaa,
196				     0xaa, 0xaa, 0xaf, 0xea, 0xaa, 0xba, 0xaa,
197				     0xaa, 0xaf, 0xea, 0xaa, 0xaa, 0xaa, 0xaa,
198				     0xaf, 0xea, 0xaa);
199	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETBANK, 0x00);
200	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_UNKNOWN4, 0xe4);
201	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_UNKNOWN3, 0x17, 0x69);
202	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_UNKNOWN4, 0x00);
203	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_UNKNOWN3,
204				     0x09, 0x09, 0x00, 0x07, 0xe8, 0x00, 0x26,
205				     0x00, 0x07, 0x00, 0x00, 0xe8, 0x32, 0x00,
206				     0xe9, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x01,
207				     0x01, 0x00, 0x12, 0x04);
208	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETBANK, 0x01);
209	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_UNKNOWN3,
210				     0x02, 0x00, 0x01, 0x20, 0x01, 0x18, 0x08,
211				     0xa8, 0x09);
212	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETBANK, 0x02);
213	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_UNKNOWN3, 0x20, 0x20, 0x00);
214	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETBANK, 0x03);
215	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_UNKNOWN3,
216				     0x00, 0xdc, 0x11, 0x70, 0x00, 0x20);
217	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_UNKNOWN4, 0xc9);
218	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_UNKNOWN3,
219				     0x2a, 0xce, 0x02, 0x70, 0x01, 0x04);
220	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_UNKNOWN4, 0x00);
221	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_SETBANK, 0x00);
222	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, HX83112B_UNKNOWN2, 0x27);
223	mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
224	mipi_dsi_msleep(&dsi_ctx, 120);
225	mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);
226	mipi_dsi_msleep(&dsi_ctx, 20);
227	mipi_dsi_dcs_set_display_brightness_multi(&dsi_ctx, 0x0000);
228	mipi_dsi_dcs_write_seq_multi(&dsi_ctx, MIPI_DCS_WRITE_CONTROL_DISPLAY,
229				     0x24);
230	mipi_dsi_dcs_set_tear_on_multi(&dsi_ctx, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
231
232	return dsi_ctx.accum_err;
233}
234
235static int hx83112b_off(struct hx83112b_panel *ctx)
236{
237	struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi };
238
239	mipi_dsi_dcs_set_display_off_multi(&dsi_ctx);
240	mipi_dsi_msleep(&dsi_ctx, 20);
241	mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx);
242	mipi_dsi_msleep(&dsi_ctx, 120);
243
244	return dsi_ctx.accum_err;
245}
246
247static int hx83112b_prepare(struct drm_panel *panel)
248{
249	struct hx83112b_panel *ctx = to_hx83112b_panel(panel);
250	struct device *dev = &ctx->dsi->dev;
251	int ret;
252
253	ret = regulator_bulk_enable(ARRAY_SIZE(hx83112b_supplies), ctx->supplies);
254	if (ret < 0) {
255		dev_err(dev, "Failed to enable regulators: %d\n", ret);
256		return ret;
257	}
258
259	hx83112b_reset(ctx);
260
261	ret = hx83112b_on(ctx);
262	if (ret < 0) {
263		dev_err(dev, "Failed to initialize panel: %d\n", ret);
264		gpiod_set_value_cansleep(ctx->reset_gpio, 1);
265		regulator_bulk_disable(ARRAY_SIZE(hx83112b_supplies), ctx->supplies);
266		return ret;
267	}
268
269	return 0;
270}
271
272static int hx83112b_unprepare(struct drm_panel *panel)
273{
274	struct hx83112b_panel *ctx = to_hx83112b_panel(panel);
275	struct device *dev = &ctx->dsi->dev;
276	int ret;
277
278	ret = hx83112b_off(ctx);
279	if (ret < 0)
280		dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
281
282	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
283	regulator_bulk_disable(ARRAY_SIZE(hx83112b_supplies), ctx->supplies);
284
285	return 0;
286}
287
288static const struct drm_display_mode hx83112b_mode = {
289	.clock = (1080 + 40 + 4 + 12) * (2160 + 32 + 2 + 2) * 60 / 1000,
290	.hdisplay = 1080,
291	.hsync_start = 1080 + 40,
292	.hsync_end = 1080 + 40 + 4,
293	.htotal = 1080 + 40 + 4 + 12,
294	.vdisplay = 2160,
295	.vsync_start = 2160 + 32,
296	.vsync_end = 2160 + 32 + 2,
297	.vtotal = 2160 + 32 + 2 + 2,
298	.width_mm = 65,
299	.height_mm = 128,
300	.type = DRM_MODE_TYPE_DRIVER,
301};
302
303static int hx83112b_get_modes(struct drm_panel *panel,
304			      struct drm_connector *connector)
305{
306	return drm_connector_helper_get_modes_fixed(connector, &hx83112b_mode);
307}
308
309static const struct drm_panel_funcs hx83112b_panel_funcs = {
310	.prepare = hx83112b_prepare,
311	.unprepare = hx83112b_unprepare,
312	.get_modes = hx83112b_get_modes,
313};
314
315static int hx83112b_bl_update_status(struct backlight_device *bl)
316{
317	struct mipi_dsi_device *dsi = bl_get_data(bl);
318	u16 brightness = backlight_get_brightness(bl);
319	int ret;
320
321	dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
322
323	ret = mipi_dsi_dcs_set_display_brightness_large(dsi, brightness);
324	if (ret < 0)
325		return ret;
326
327	dsi->mode_flags |= MIPI_DSI_MODE_LPM;
328
329	return 0;
330}
331
332static const struct backlight_ops hx83112b_bl_ops = {
333	.update_status = hx83112b_bl_update_status,
334};
335
336static struct backlight_device *
337hx83112b_create_backlight(struct mipi_dsi_device *dsi)
338{
339	struct device *dev = &dsi->dev;
340	const struct backlight_properties props = {
341		.type = BACKLIGHT_RAW,
342		.brightness = 4095,
343		.max_brightness = 4095,
344	};
345
346	return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
347					      &hx83112b_bl_ops, &props);
348}
349
350static int hx83112b_probe(struct mipi_dsi_device *dsi)
351{
352	struct device *dev = &dsi->dev;
353	struct hx83112b_panel *ctx;
354	int ret;
355
356	ctx = devm_drm_panel_alloc(dev, struct hx83112b_panel, panel,
357				   &hx83112b_panel_funcs,
358				   DRM_MODE_CONNECTOR_DSI);
359	if (IS_ERR(ctx))
360		return PTR_ERR(ctx);
361
362	ret = devm_regulator_bulk_get_const(dev,
363					    ARRAY_SIZE(hx83112b_supplies),
364					    hx83112b_supplies,
365					    &ctx->supplies);
366	if (ret < 0)
367		return ret;
368
369	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
370	if (IS_ERR(ctx->reset_gpio))
371		return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
372				     "Failed to get reset-gpios\n");
373
374	ctx->dsi = dsi;
375	mipi_dsi_set_drvdata(dsi, ctx);
376
377	dsi->lanes = 4;
378	dsi->format = MIPI_DSI_FMT_RGB888;
379	dsi->mode_flags = MIPI_DSI_MODE_VIDEO_BURST |
380			  MIPI_DSI_CLOCK_NON_CONTINUOUS |
381			  MIPI_DSI_MODE_VIDEO_NO_HSA | MIPI_DSI_MODE_LPM;
382
383	ctx->panel.prepare_prev_first = true;
384
385	ctx->panel.backlight = hx83112b_create_backlight(dsi);
386	if (IS_ERR(ctx->panel.backlight))
387		return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight),
388				     "Failed to create backlight\n");
389
390	drm_panel_add(&ctx->panel);
391
392	ret = mipi_dsi_attach(dsi);
393	if (ret < 0) {
394		drm_panel_remove(&ctx->panel);
395		return dev_err_probe(dev, ret, "Failed to attach to DSI host\n");
396	}
397
398	return 0;
399}
400
401static void hx83112b_remove(struct mipi_dsi_device *dsi)
402{
403	struct hx83112b_panel *ctx = mipi_dsi_get_drvdata(dsi);
404	int ret;
405
406	ret = mipi_dsi_detach(dsi);
407	if (ret < 0)
408		dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
409
410	drm_panel_remove(&ctx->panel);
411}
412
413static const struct of_device_id hx83112b_of_match[] = {
414	{ .compatible = "djn,98-03057-6598b-i" },
415	{ /* sentinel */ }
416};
417MODULE_DEVICE_TABLE(of, hx83112b_of_match);
418
419static struct mipi_dsi_driver hx83112b_driver = {
420	.probe = hx83112b_probe,
421	.remove = hx83112b_remove,
422	.driver = {
423		.name = "panel-himax-hx83112b",
424		.of_match_table = hx83112b_of_match,
425	},
426};
427module_mipi_dsi_driver(hx83112b_driver);
428
429MODULE_DESCRIPTION("DRM driver for hx83112b-equipped DSI panels");
430MODULE_LICENSE("GPL");
~/ Read-only file preview.