1 /*
2  * Copyright (c) 2023 Renesas Electronics Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT  renesas_smartbond_mipi_dbi
8 
9 #include <zephyr/drivers/mipi_dbi.h>
10 #include <zephyr/drivers/pinctrl.h>
11 #include <zephyr/drivers/gpio.h>
12 #include <zephyr/irq.h>
13 #include <zephyr/kernel.h>
14 #include <zephyr/device.h>
15 #include <zephyr/pm/device.h>
16 #include <zephyr/pm/policy.h>
17 #include <DA1469xAB.h>
18 #include <zephyr/drivers/clock_control.h>
19 #include <zephyr/drivers/clock_control/smartbond_clock_control.h>
20 #include <zephyr/drivers/display.h>
21 #include <zephyr/sys/util.h>
22 #include <zephyr/drivers/spi.h>
23 #include <da1469x_lcdc.h>
24 #include <da1469x_pd.h>
25 
26 #include <zephyr/logging/log.h>
27 LOG_MODULE_REGISTER(smartbond_mipi_dbi, CONFIG_MIPI_DBI_LOG_LEVEL);
28 
29 #define SMARTBOND_IRQN		DT_INST_IRQN(0)
30 #define SMARTBOND_IRQ_PRIO  DT_INST_IRQ(0, priority)
31 
32 #define PINCTRL_STATE_READ  PINCTRL_STATE_PRIV_START
33 
34 #define MIPI_DBI_SMARTBOND_IS_READ_SUPPORTED \
35 				DT_INST_NODE_HAS_PROP(0, spi_dev)
36 
37 #define LCDC_SMARTBOND_CLK_DIV(_freq)                           \
38 	((32000000U % (_freq)) ? (96000000U / (_freq)) : (32000000U / (_freq)))
39 
40 #define MIPI_DBI_SMARTBOND_IS_PLL_REQUIRED \
41 			!!(32000000U % DT_PROP(DT_CHOSEN(zephyr_display), mipi_max_frequency))
42 
43 #define MIPI_DBI_SMARTBOND_IS_TE_ENABLED \
44 			DT_INST_PROP_OR(0, te_enable, 0)
45 
46 #define MIPI_DBI_SMARTBOND_IS_DMA_PREFETCH_ENABLED \
47 			DT_INST_ENUM_IDX_OR(0, dma_prefetch, 0)
48 
49 #define MIPI_DBI_SMARTBOND_IS_RESET_AVAILABLE \
50 			DT_INST_NODE_HAS_PROP(0, reset_gpios)
51 
52 #define LCDC_LAYER0_OFFSETX_REG_SET_FIELD(_field, _var, _val) \
53 	((_var)) = \
54 	((_var) & ~(LCDC_LCDC_LAYER0_OFFSETX_REG_ ## _field ## _Msk)) |	\
55 	(((_var) << LCDC_LCDC_LAYER0_OFFSETX_REG_ ## _field ## _Pos) & \
56 	LCDC_LCDC_LAYER0_OFFSETX_REG_ ## _field ## _Msk)
57 
58 struct mipi_dbi_smartbond_data {
59 	/* Provide mutual exclusion when a display operation is requested. */
60 	struct k_sem device_sem;
61 	/* Provide synchronization between task return and ISR firing */
62 	struct k_sem sync_sem;
63 	/* Flag indicating whether or not an underflow took place */
64 	volatile bool underflow_flag;
65 	/* Layer settings */
66 	lcdc_smartbond_layer_cfg layer;
67 };
68 
69 struct mipi_dbi_smartbond_config {
70 	/* Reference to device instance's pinctrl configurations */
71 	const struct pinctrl_dev_config *pcfg;
72 	/* Reset GPIO */
73 	const struct gpio_dt_spec reset;
74 	/* Host controller's timing settings */
75 	lcdc_smartbond_timing_cfg timing_cfg;
76 	/* Background default color configuration */
77 	lcdc_smartbond_bgcolor_cfg bgcolor_cfg;
78 };
79 
80 /* Mark the device is progress and so it's not allowed to enter the sleep state. */
mipi_dbi_smartbond_pm_policy_state_lock_get(void)81 static inline void mipi_dbi_smartbond_pm_policy_state_lock_get(void)
82 {
83 	/*
84 	 * Prevent the SoC from etering the normal sleep state as PDC does not support
85 	 * waking up the application core following LCDC events.
86 	 */
87 	pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES);
88 }
89 
90 /* Mark that device is inactive and so it's allowed to enter the sleep state */
mipi_dbi_smartbond_pm_policy_state_lock_put(void)91 static inline void mipi_dbi_smartbond_pm_policy_state_lock_put(void)
92 {
93 	/* Allow the SoC to enter the nornmal sleep state once LCDC is inactive */
94 	pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES);
95 }
96 
97 /* Helper function to trigger the LCDC fetching data from frame buffer to the connected display */
mipi_dbi_smartbond_send_single_frame(const struct device * dev)98 static void mipi_dbi_smartbond_send_single_frame(const struct device *dev)
99 {
100 	struct mipi_dbi_smartbond_data *data = dev->data;
101 
102 #if MIPI_DBI_SMARTBOND_IS_TE_ENABLED
103 	da1469x_lcdc_te_set_status(true, DT_INST_PROP_OR(0, te_polarity, false));
104 	/*
105 	 * Wait for the TE signal to be asserted so display's refresh status can be synchronized
106 	 * with the current frame update.
107 	 */
108 	k_sem_take(&data->sync_sem, K_FOREVER);
109 #endif
110 
111 	LCDC->LCDC_INTERRUPT_REG |= LCDC_LCDC_INTERRUPT_REG_LCDC_VSYNC_IRQ_EN_Msk;
112 
113 	/* Setting this bit will enable the host to start outputing pixel data */
114 	LCDC->LCDC_MODE_REG |= LCDC_LCDC_MODE_REG_LCDC_SFRAME_UPD_Msk;
115 
116 	/* Wait for frame update to complete */
117 	k_sem_take(&data->sync_sem, K_FOREVER);
118 
119 	if (data->underflow_flag) {
120 		LOG_WRN("Underflow took place");
121 		data->underflow_flag = false;
122 	}
123 }
124 
125 #if MIPI_DBI_SMARTBOND_IS_RESET_AVAILABLE
mipi_dbi_smartbond_reset(const struct device * dev,k_timeout_t delay)126 static int mipi_dbi_smartbond_reset(const struct device *dev, k_timeout_t delay)
127 {
128 	const struct mipi_dbi_smartbond_config *config = dev->config;
129 	int ret;
130 
131 	if (!gpio_is_ready_dt(&config->reset)) {
132 		LOG_ERR("Reset signal not available");
133 		return -ENODEV;
134 	}
135 
136 	ret = gpio_pin_set_dt(&config->reset, 1);
137 	if (ret < 0) {
138 		LOG_ERR("Cannot drive reset signal");
139 		return ret;
140 	}
141 	k_sleep(delay);
142 
143 	return gpio_pin_set_dt(&config->reset, 0);
144 }
145 #endif
146 
147 /* Display pixel to output color format translation */
lcdc_smartbond_pixel_to_ocm(enum display_pixel_format pixfmt)148 static inline uint8_t lcdc_smartbond_pixel_to_ocm(enum display_pixel_format pixfmt)
149 {
150 	switch (pixfmt) {
151 	case PIXEL_FORMAT_RGB_565:
152 		return (uint8_t)LCDC_SMARTBOND_OCM_RGB565;
153 	case PIXEL_FORMAT_RGB_888:
154 		return (uint8_t)LCDC_SMARTBOND_OCM_RGB888;
155 	case PIXEL_FORMAT_MONO10:
156 		return (uint8_t)LCDC_SMARTBOND_L0_L1;
157 	default:
158 		LOG_ERR("Unsupported pixel format");
159 		return 0;
160 	};
161 }
162 
lcdc_smartbond_line_mode_translation(uint8_t mode)163 static inline uint8_t lcdc_smartbond_line_mode_translation(uint8_t mode)
164 {
165 	switch (mode) {
166 	case MIPI_DBI_MODE_SPI_3WIRE:
167 		return (uint8_t)LCDC_SMARTBOND_MODE_SPI3;
168 	case MIPI_DBI_MODE_SPI_4WIRE:
169 		return (uint8_t)LCDC_SMARTBOND_MODE_SPI4;
170 	default:
171 		LOG_ERR("Unsupported SPI mode");
172 		return 0;
173 	}
174 }
175 
lcdc_smartbond_pixel_to_lcm(enum display_pixel_format pixfmt)176 static inline uint8_t lcdc_smartbond_pixel_to_lcm(enum display_pixel_format pixfmt)
177 {
178 	switch (pixfmt) {
179 	case PIXEL_FORMAT_RGB_565:
180 		return (uint8_t)LCDC_SMARTBOND_L0_RGB565;
181 	case PIXEL_FORMAT_ARGB_8888:
182 		return (uint8_t)LCDC_SMARTBOND_L0_ARGB8888;
183 	default:
184 		LOG_ERR("Unsupported pixel format");
185 		return 0;
186 	};
187 }
188 
lcdc_smartbond_mipi_dbi_translation(const struct mipi_dbi_config * dbi_config,lcdc_smartbond_mipi_dbi_cfg * mipi_dbi_cfg,enum display_pixel_format pixfmt)189 static void lcdc_smartbond_mipi_dbi_translation(const struct mipi_dbi_config *dbi_config,
190 			lcdc_smartbond_mipi_dbi_cfg *mipi_dbi_cfg,
191 			enum display_pixel_format pixfmt)
192 {
193 	mipi_dbi_cfg->cpha = dbi_config->config.operation & SPI_MODE_CPHA;
194 	mipi_dbi_cfg->cpol = dbi_config->config.operation & SPI_MODE_CPOL;
195 	mipi_dbi_cfg->cs_active_high = dbi_config->config.operation & SPI_CS_ACTIVE_HIGH;
196 	mipi_dbi_cfg->line_mode = lcdc_smartbond_line_mode_translation(dbi_config->mode);
197 	mipi_dbi_cfg->color_mode = lcdc_smartbond_pixel_to_ocm(pixfmt);
198 }
199 
200 #if MIPI_DBI_SMARTBOND_IS_READ_SUPPORTED
mipi_dbi_smartbond_command_read(const struct device * dev,const struct mipi_dbi_config * dbi_config,uint8_t * cmd,size_t num_cmds,uint8_t * response,size_t len)201 static int mipi_dbi_smartbond_command_read(const struct device *dev,
202 				const struct mipi_dbi_config *dbi_config,
203 				uint8_t *cmd, size_t num_cmds,
204 				uint8_t *response, size_t len)
205 {
206 	struct mipi_dbi_smartbond_data *data = dev->data;
207 	const struct mipi_dbi_smartbond_config *config = dev->config;
208 	int ret = 0;
209 	lcdc_smartbond_mipi_dbi_cfg mipi_dbi_cfg;
210 
211 	k_sem_take(&data->device_sem, K_FOREVER);
212 
213 	mipi_dbi_smartbond_pm_policy_state_lock_get();
214 
215 	/*
216 	 * Add an arbitrary valid color format to satisfy subroutine. The MIPI DBI command/data
217 	 * engine should not be affected.
218 	 */
219 	lcdc_smartbond_mipi_dbi_translation(dbi_config, &mipi_dbi_cfg, PIXEL_FORMAT_RGB_565);
220 	ret = da1469x_lcdc_mipi_dbi_interface_configure(&mipi_dbi_cfg);
221 	if (ret < 0) {
222 		goto _mipi_dbi_read_exit;
223 	}
224 
225 	/* Check if the cmd/data engine is busy since the #CS line will be overruled. */
226 	if (da1469x_lcdc_is_busy()) {
227 		LOG_WRN("MIPI DBI host is busy");
228 		ret = -EBUSY;
229 		goto _mipi_dbi_read_exit;
230 	}
231 
232 	/* Force CS line to low. Typically, command and data are bound in the same #CS assertion */
233 	da1469x_lcdc_force_cs_line(true, mipi_dbi_cfg.cs_active_high);
234 
235 	da1469x_lcdc_send_cmd_data(true, cmd, num_cmds);
236 
237 	if (len) {
238 		const struct device *spi_dev = DEVICE_DT_GET(DT_INST_PHANDLE(0, spi_dev));
239 
240 		struct spi_buf buffer = {
241 			.buf = (void *)response,
242 			.len = len,
243 		};
244 		struct spi_buf_set buf_set = {
245 			.buffers = &buffer,
246 			.count = 1,
247 		};
248 
249 		if (!device_is_ready(spi_dev)) {
250 			LOG_ERR("SPI device is not ready");
251 			ret = -ENODEV;
252 			goto _mipi_dbi_read_exit;
253 		}
254 
255 		/* Overwrite CLK and enable DI lines. CS is driven forcefully. */
256 		ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_READ);
257 		if (ret < 0) {
258 			LOG_ERR("Could not apply MIPI DBI pins' SPI read state (%d)", ret);
259 			goto _mipi_dbi_read_exit;
260 		}
261 
262 		/* Get response */
263 		ret = spi_read(spi_dev, &dbi_config->config, &buf_set);
264 		if (ret < 0) {
265 			LOG_ERR("Could not read data from SPI");
266 			goto _mipi_dbi_read_exit;
267 		}
268 	}
269 
270 _mipi_dbi_read_exit:
271 
272 	/* Restore #CS line */
273 	da1469x_lcdc_force_cs_line(false, mipi_dbi_cfg.cs_active_high);
274 
275 	/* Make sure default LCDC pins are applied upon exit */
276 	ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);
277 	if (ret < 0) {
278 		LOG_ERR("Could not apply MIPI DBI pins' default state (%d)", ret);
279 	}
280 
281 	mipi_dbi_smartbond_pm_policy_state_lock_put();
282 
283 	k_sem_give(&data->device_sem);
284 
285 	return ret;
286 }
287 #endif
288 
mipi_dbi_smartbond_command_write(const struct device * dev,const struct mipi_dbi_config * dbi_config,uint8_t cmd,const uint8_t * data_buf,size_t len)289 static int mipi_dbi_smartbond_command_write(const struct device *dev,
290 				const struct mipi_dbi_config *dbi_config,
291 				uint8_t cmd, const uint8_t *data_buf,
292 				size_t len)
293 {
294 	struct mipi_dbi_smartbond_data *data = dev->data;
295 	int ret = 0;
296 	lcdc_smartbond_mipi_dbi_cfg mipi_dbi_cfg;
297 
298 	k_sem_take(&data->device_sem, K_FOREVER);
299 
300 	mipi_dbi_smartbond_pm_policy_state_lock_get();
301 
302 	/*
303 	 * Add an arbitrary valid color format to satisfy subroutine. The MIPI DBI command/data
304 	 * engine should not be affected.
305 	 */
306 	lcdc_smartbond_mipi_dbi_translation(dbi_config, &mipi_dbi_cfg, PIXEL_FORMAT_RGB_565);
307 	ret = da1469x_lcdc_mipi_dbi_interface_configure(&mipi_dbi_cfg);
308 	if (ret < 0) {
309 		goto finish;
310 	}
311 
312 	/* Command and accompanied data should be transmitted via the DBIB interface */
313 	da1469x_lcdc_send_cmd_data(true, &cmd, 1);
314 
315 	if (len) {
316 		/* Data should be transmitted via the DBIB interface */
317 		da1469x_lcdc_send_cmd_data(false, data_buf, len);
318 	}
319 
320 finish:
321 	mipi_dbi_smartbond_pm_policy_state_lock_put();
322 
323 	k_sem_give(&data->device_sem);
324 
325 	return ret;
326 }
327 
mipi_dbi_smartbond_write_display(const struct device * dev,const struct mipi_dbi_config * dbi_config,const uint8_t * framebuf,struct display_buffer_descriptor * desc,enum display_pixel_format pixfmt)328 static int mipi_dbi_smartbond_write_display(const struct device *dev,
329 					const struct mipi_dbi_config *dbi_config,
330 					const uint8_t *framebuf,
331 					struct display_buffer_descriptor *desc,
332 					enum display_pixel_format pixfmt)
333 {
334 	struct mipi_dbi_smartbond_data *data = dev->data;
335 	const struct mipi_dbi_smartbond_config *config = dev->config;
336 	lcdc_smartbond_layer_cfg *layer = &data->layer;
337 	int ret = 0;
338 	lcdc_smartbond_mipi_dbi_cfg mipi_dbi_cfg;
339 	uint8_t layer_color = lcdc_smartbond_pixel_to_lcm(pixfmt);
340 
341 	if (desc->width * desc->height * (DISPLAY_BITS_PER_PIXEL(pixfmt) / BITS_PER_BYTE) !=
342 	    desc->buf_size) {
343 		LOG_ERR("Incorrect buffer size for given width and height");
344 		return -EINVAL;
345 	}
346 
347 	k_sem_take(&data->device_sem, K_FOREVER);
348 
349 	mipi_dbi_smartbond_pm_policy_state_lock_get();
350 
351 	/*
352 	 * Mainly check if the frame generator is busy with a pending frame update (might happen
353 	 * when two frame updates take place one after the other and the display interface is
354 	 * quite slow). VSYNC interrupt line should be asserted when the last line is being
355 	 * outputed.
356 	 */
357 	if (da1469x_lcdc_is_busy()) {
358 		LOG_WRN("MIPI DBI host is busy");
359 		ret = -EBUSY;
360 		goto _mipi_dbi_write_exit;
361 	}
362 
363 	lcdc_smartbond_mipi_dbi_translation(dbi_config, &mipi_dbi_cfg, pixfmt);
364 	ret = da1469x_lcdc_mipi_dbi_interface_configure(&mipi_dbi_cfg);
365 	if (ret < 0) {
366 		goto _mipi_dbi_write_exit;
367 	}
368 
369 	ret = da1469x_lcdc_timings_configure(desc->width, desc->height,
370 			(lcdc_smartbond_timing_cfg *)&config->timing_cfg);
371 	if (ret < 0) {
372 		goto _mipi_dbi_write_exit;
373 	}
374 
375 	LCDC_SMARTBOND_LAYER_CONFIG(layer, framebuf, 0, 0, desc->width, desc->height,
376 					layer_color,
377 					da1469x_lcdc_stride_calculation(layer_color, desc->width));
378 	ret = da1469x_lcdc_layer_configure(layer);
379 	if (ret < 0) {
380 		goto _mipi_dbi_write_exit;
381 	}
382 
383 	/* Trigger single frame update via the LCDC-DMA engine */
384 	mipi_dbi_smartbond_send_single_frame(dev);
385 
386 _mipi_dbi_write_exit:
387 
388 	mipi_dbi_smartbond_pm_policy_state_lock_put();
389 
390 	k_sem_give(&data->device_sem);
391 
392 	return ret;
393 }
394 
mipi_dbi_smartbond_configure(const struct device * dev)395 static int mipi_dbi_smartbond_configure(const struct device *dev)
396 {
397 	uint8_t clk_div =
398 		LCDC_SMARTBOND_CLK_DIV(DT_PROP(DT_CHOSEN(zephyr_display), mipi_max_frequency));
399 	const struct mipi_dbi_smartbond_config *config = dev->config;
400 
401 	/*
402 	 * First enable the controller so registers can be written. In serial interfaces
403 	 * clock divider is further divided by 2.
404 	 */
405 	da1469x_lcdc_set_status(true, MIPI_DBI_SMARTBOND_IS_PLL_REQUIRED,
406 		(clk_div >= 2 ? clk_div / 2 : clk_div));
407 
408 	if (!da1469x_lcdc_check_id()) {
409 		LOG_ERR("Mismatching LCDC ID");
410 		da1469x_lcdc_set_status(false, 0, 0);
411 		return -EINVAL;
412 	}
413 
414 	da1469x_lcdc_te_set_status(false, DT_INST_PROP_OR(0, te_polarity, false));
415 
416 	da1469x_lcdc_bgcolor_configure((lcdc_smartbond_bgcolor_cfg *)&config->bgcolor_cfg);
417 
418 	LCDC_LAYER0_OFFSETX_REG_SET_FIELD(LCDC_L0_DMA_PREFETCH,
419 			LCDC->LCDC_LAYER0_OFFSETX_REG, MIPI_DBI_SMARTBOND_IS_DMA_PREFETCH_ENABLED);
420 
421 	return 0;
422 }
423 
smartbond_mipi_dbi_isr(const void * arg)424 static void smartbond_mipi_dbi_isr(const void *arg)
425 {
426 	struct mipi_dbi_smartbond_data *data =  ((const struct device *)arg)->data;
427 
428 	/*
429 	 * Underflow sticky bit will remain high until cleared by writing
430 	 * any value to LCDC_INTERRUPT_REG.
431 	 */
432 	data->underflow_flag = LCDC_STATUS_REG_GET_FIELD(LCDC_STICKY_UNDERFLOW);
433 
434 	/* Default interrupt mode is level triggering so interrupt should be cleared */
435 	da1469x_lcdc_te_set_status(false, DT_INST_PROP_OR(0, te_polarity, false));
436 
437 	k_sem_give(&data->sync_sem);
438 }
439 
mipi_dbi_smartbond_resume(const struct device * dev)440 static int mipi_dbi_smartbond_resume(const struct device *dev)
441 {
442 	const struct mipi_dbi_smartbond_config *config = dev->config;
443 	int ret;
444 
445 	/* Select default state */
446 	ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);
447 	if (ret < 0) {
448 		LOG_ERR("Could not apply LCDC pins' default state (%d)", ret);
449 		return -EIO;
450 	}
451 
452 #if MIPI_DBI_SMARTBOND_IS_PLL_REQUIRED
453 	const struct device *clock_dev = DEVICE_DT_GET(DT_NODELABEL(osc));
454 
455 	if (!device_is_ready(clock_dev)) {
456 		LOG_WRN("Clock device is not available; PLL cannot be used");
457 	} else {
458 		ret = z_smartbond_select_sys_clk(SMARTBOND_CLK_PLL96M);
459 		if (ret < 0) {
460 			LOG_WRN("Could not switch to PLL. Requested speed should not be achieved.");
461 		}
462 	}
463 #endif
464 
465 	return mipi_dbi_smartbond_configure(dev);
466 }
467 
468 #if defined(CONFIG_PM_DEVICE)
mipi_dbi_smartbond_suspend(const struct device * dev)469 static int mipi_dbi_smartbond_suspend(const struct device *dev)
470 {
471 	const struct mipi_dbi_smartbond_config *config = dev->config;
472 	int ret;
473 
474 	/* Select sleep state; it's OK if settings fails for any reason. */
475 	ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP);
476 	if (ret < 0) {
477 		LOG_WRN("Could not apply MIPI DBI pins' sleep state");
478 	}
479 
480 	/* Disable host controller to minimize power consumption. */
481 	da1469x_lcdc_set_status(false, false, 0);
482 
483 	return 0;
484 }
485 
mipi_dbi_smartbond_pm_action(const struct device * dev,enum pm_device_action action)486 static int mipi_dbi_smartbond_pm_action(const struct device *dev, enum pm_device_action action)
487 {
488 	int ret = 0;
489 
490 	switch (action) {
491 	case PM_DEVICE_ACTION_SUSPEND:
492 		/* A non-zero value should not affect sleep */
493 		(void)mipi_dbi_smartbond_suspend(dev);
494 		break;
495 	case PM_DEVICE_ACTION_RESUME:
496 		/*
497 		 * The resume error code should not be taken into consideration
498 		 * by the PM subsystem.
499 		 */
500 		ret = mipi_dbi_smartbond_resume(dev);
501 		break;
502 	default:
503 		return -ENOTSUP;
504 	}
505 
506 	return ret;
507 }
508 #endif
509 
mipi_dbi_smartbond_init(const struct device * dev)510 static int mipi_dbi_smartbond_init(const struct device *dev)
511 {
512 	__unused const struct mipi_dbi_smartbond_config *config = dev->config;
513 	struct mipi_dbi_smartbond_data *data = dev->data;
514 	int ret;
515 
516 	/* Device should be ready to be acquired */
517 	k_sem_init(&data->device_sem, 1, 1);
518 	/* Event should be signaled by LCDC ISR */
519 	k_sem_init(&data->sync_sem, 0, 1);
520 
521 #if MIPI_DBI_SMARTBOND_IS_RESET_AVAILABLE
522 	if (gpio_is_ready_dt(&config->reset)) {
523 		ret = gpio_pin_configure_dt(&config->reset, GPIO_OUTPUT_INACTIVE);
524 		if (ret < 0) {
525 			LOG_ERR("Could not configure reset line (%d)", ret);
526 			return -EIO;
527 		}
528 	}
529 #endif
530 
531 	IRQ_CONNECT(SMARTBOND_IRQN, SMARTBOND_IRQ_PRIO, smartbond_mipi_dbi_isr,
532 						DEVICE_DT_INST_GET(0), 0);
533 
534 	ret = mipi_dbi_smartbond_resume(dev);
535 
536 	return ret;
537 }
538 
539 static DEVICE_API(mipi_dbi, mipi_dbi_smartbond_driver_api) = {
540 #if MIPI_DBI_SMARTBOND_IS_RESET_AVAILABLE
541 	.reset = mipi_dbi_smartbond_reset,
542 #endif
543 	.command_write = mipi_dbi_smartbond_command_write,
544 	.write_display = mipi_dbi_smartbond_write_display,
545 #if MIPI_DBI_SMARTBOND_IS_READ_SUPPORTED
546 	.command_read = mipi_dbi_smartbond_command_read,
547 #endif
548 };
549 
550 #define SMARTBOND_MIPI_DBI_INIT(inst)	\
551 	PINCTRL_DT_INST_DEFINE(inst);	\
552                                     \
553 	static const struct mipi_dbi_smartbond_config mipi_dbi_smartbond_config_## inst = {	\
554 		.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst),	\
555 		.reset = GPIO_DT_SPEC_INST_GET_OR(inst, reset_gpios, {}),	\
556 		.timing_cfg = { 0 },	\
557 		.bgcolor_cfg = { 0xFF, 0xFF, 0xFF, 0 },	\
558 	};	\
559 												\
560 	static struct mipi_dbi_smartbond_data mipi_dbi_smartbond_data_## inst;	\
561 												\
562 	PM_DEVICE_DT_INST_DEFINE(inst, mipi_dbi_smartbond_pm_action);	\
563 												\
564 	DEVICE_DT_INST_DEFINE(inst, mipi_dbi_smartbond_init,	\
565 						PM_DEVICE_DT_INST_GET(inst),	\
566 						&mipi_dbi_smartbond_data_## inst,	\
567 						&mipi_dbi_smartbond_config_## inst,	\
568 						POST_KERNEL,	\
569 						CONFIG_MIPI_DBI_INIT_PRIORITY,	\
570 						&mipi_dbi_smartbond_driver_api);
571 
572 SMARTBOND_MIPI_DBI_INIT(0);
573