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_display
8
9 #include <zephyr/drivers/pinctrl.h>
10 #include <zephyr/drivers/gpio.h>
11 #include <zephyr/irq.h>
12 #include <zephyr/kernel.h>
13 #include <zephyr/device.h>
14 #include <zephyr/drivers/clock_control.h>
15 #include <zephyr/drivers/clock_control/smartbond_clock_control.h>
16 #include <zephyr/drivers/display.h>
17 #include <zephyr/sys/util.h>
18 #include <zephyr/drivers/dma.h>
19 #include <da1469x_lcdc.h>
20 #include <DA1469xAB.h>
21 #include <da1469x_pd.h>
22 #include <zephyr/linker/devicetree_regions.h>
23 #include <zephyr/pm/device.h>
24 #include <zephyr/pm/policy.h>
25
26 #include <zephyr/logging/log.h>
27 LOG_MODULE_REGISTER(smartbond_display, CONFIG_DISPLAY_LOG_LEVEL);
28
29 #define SMARTBOND_IRQN DT_INST_IRQN(0)
30 #define SMARTBOND_IRQ_PRIO DT_INST_IRQ(0, priority)
31
32 #define LCDC_SMARTBOND_CLK_DIV(_freq) \
33 ((32000000U % (_freq)) ? (96000000U / (_freq)) : (32000000U / (_freq)))
34
35 #define LCDC_SMARTBOND_IS_PLL_REQUIRED \
36 !!(32000000U % DT_PROP(DT_INST_CHILD(0, display_timings), clock_frequency))
37
38 #define DISPLAY_SMARTBOND_IS_DMA_PREFETCH_ENABLED \
39 DT_INST_ENUM_IDX_OR(0, dma_prefetch, 0)
40
41 #define LCDC_LAYER0_OFFSETX_REG_SET_FIELD(_field, _var, _val)\
42 ((_var)) = \
43 ((_var) & ~(LCDC_LCDC_LAYER0_OFFSETX_REG_ ## _field ## _Msk)) | \
44 (((_val) << LCDC_LCDC_LAYER0_OFFSETX_REG_ ## _field ## _Pos) & \
45 LCDC_LCDC_LAYER0_OFFSETX_REG_ ## _field ## _Msk)
46
47 #define DISPLAY_SMARTBOND_PIXEL_SIZE(inst) \
48 (DISPLAY_BITS_PER_PIXEL(DT_INST_PROP(inst, pixel_format)) / 8)
49
50 #if CONFIG_DISPLAY_RENESAS_LCDC_BUFFER_PSRAM
51 #define DISPLAY_BUFFER_LINKER_SECTION \
52 Z_GENERIC_SECTION(LINKER_DT_NODE_REGION_NAME(DT_NODELABEL(psram)))
53 #else
54 #define DISPLAY_BUFFER_LINKER_SECTION
55 #endif
56
57 struct display_smartbond_data {
58 /* Provide mutual exclusion when a display operation is requested. */
59 struct k_sem device_sem;
60 /* Frame update synchronization token */
61 struct k_sem sync_sem;
62 /* Flag indicating whether or not an underflow took place */
63 volatile bool underflow_flag;
64 /* Layer settings */
65 lcdc_smartbond_layer_cfg layer;
66 /* Frame buffer */
67 uint8_t *buffer;
68 /* DMA device */
69 const struct device *dma;
70 /* DMA configuration structures */
71 struct dma_config dma_cfg;
72 struct dma_block_config dma_block_cfg;
73 /* DMA memory transfer synchronization token */
74 struct k_sem dma_sync_sem;
75 /* Granted DMA channel used for memory transfers */
76 int dma_channel;
77 #if defined(CONFIG_PM_DEVICE)
78 ATOMIC_DEFINE(pm_policy_state_flag, 1);
79 #endif
80 };
81
82 struct display_smartbond_config {
83 /* Reference to device instance's pinctrl configurations */
84 const struct pinctrl_dev_config *pcfg;
85 /* Display ON/OFF GPIO */
86 const struct gpio_dt_spec disp;
87 /* Host controller's timing settings */
88 lcdc_smartbond_timing_cfg timing_cfg;
89 /* Parallel interface settings */
90 lcdc_smartbond_mode_cfg mode;
91 /* Background default color configuration */
92 lcdc_smartbond_bgcolor_cfg bgcolor_cfg;
93 /* Display dimensions */
94 const uint16_t x_res;
95 const uint16_t y_res;
96 /* Pixel size in bytes */
97 uint8_t pixel_size;
98 enum display_pixel_format pixel_format;
99 };
100
lcdc_smartbond_pm_policy_state_lock_get(struct display_smartbond_data * data)101 static inline void lcdc_smartbond_pm_policy_state_lock_get(struct display_smartbond_data *data)
102 {
103 #ifdef CONFIG_PM_DEVICE
104 if (atomic_test_and_set_bit(data->pm_policy_state_flag, 0) == 0) {
105 /*
106 * Prevent the SoC from etering the normal sleep state as PDC does not support
107 * waking up the application core following LCDC events.
108 */
109 pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES);
110 }
111 #endif
112 }
113
lcdc_smartbond_pm_policy_state_lock_put(struct display_smartbond_data * data)114 static inline void lcdc_smartbond_pm_policy_state_lock_put(struct display_smartbond_data *data)
115 {
116 #ifdef CONFIG_PM_DEVICE
117 if (atomic_test_and_clear_bit(data->pm_policy_state_flag, 0) == 1) {
118 /* Allow the SoC to enter the nornmal sleep state once LCDC is inactive */
119 pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES);
120 }
121 #endif
122 }
123
124 /* Display pixel to layer color format translation */
lcdc_smartbond_pixel_to_lcm(enum display_pixel_format pixel_format)125 static uint8_t lcdc_smartbond_pixel_to_lcm(enum display_pixel_format pixel_format)
126 {
127 switch (pixel_format) {
128 case PIXEL_FORMAT_RGB_565:
129 return (uint8_t)LCDC_SMARTBOND_L0_RGB565;
130 case PIXEL_FORMAT_ARGB_8888:
131 return (uint8_t)LCDC_SMARTBOND_L0_ARGB8888;
132 default:
133 LOG_ERR("Unsupported pixel format");
134 return 0;
135 };
136 }
137
display_smartbond_configure(const struct device * dev)138 static int display_smartbond_configure(const struct device *dev)
139 {
140 uint8_t clk_div =
141 LCDC_SMARTBOND_CLK_DIV(DT_PROP(DT_INST_CHILD(0, display_timings), clock_frequency));
142
143 const struct display_smartbond_config *config = dev->config;
144 struct display_smartbond_data *data = dev->data;
145
146 int ret = 0;
147
148 /* First enable the controller so registers can be written. */
149 da1469x_lcdc_set_status(true, LCDC_SMARTBOND_IS_PLL_REQUIRED, clk_div);
150
151 if (!da1469x_lcdc_check_id()) {
152 LOG_ERR("Invalid LCDC ID");
153 da1469x_lcdc_set_status(false, false, 0);
154 return -EINVAL;
155 }
156
157 da1469x_lcdc_parallel_interface_configure((lcdc_smartbond_mode_cfg *)&config->mode);
158 da1469x_lcdc_bgcolor_configure((lcdc_smartbond_bgcolor_cfg *)&config->bgcolor_cfg);
159
160 /*
161 * Partial update is not supported and so timing and layer settings can be configured
162 * once at initialization.
163 */
164 ret = da1469x_lcdc_timings_configure(config->x_res, config->y_res,
165 (lcdc_smartbond_timing_cfg *)&config->timing_cfg);
166 if (ret < 0) {
167 LOG_ERR("Unable to configure timing settings");
168 da1469x_lcdc_set_status(false, false, 0);
169 return ret;
170 }
171
172 /*
173 * Stride should be updated at the end of a frame update (typically in ISR context).
174 * It's OK to update stride here as continuous mode should not be enabled yet.
175 */
176 data->layer.color_format =
177 lcdc_smartbond_pixel_to_lcm(config->pixel_format);
178 data->layer.stride =
179 da1469x_lcdc_stride_calculation(data->layer.color_format, config->x_res);
180
181 ret = da1469x_lcdc_layer_configure(&data->layer);
182 if (ret < 0) {
183 LOG_ERR("Unable to configure layer settings");
184 da1469x_lcdc_set_status(false, false, 0);
185 }
186
187 LCDC_LAYER0_OFFSETX_REG_SET_FIELD(LCDC_L0_DMA_PREFETCH,
188 LCDC->LCDC_LAYER0_OFFSETX_REG, DISPLAY_SMARTBOND_IS_DMA_PREFETCH_ENABLED);
189
190 LCDC->LCDC_MODE_REG |= LCDC_LCDC_MODE_REG_LCDC_MODE_EN_Msk;
191
192 return ret;
193 }
194
smartbond_display_isr(const void * arg)195 static void smartbond_display_isr(const void *arg)
196 {
197 struct display_smartbond_data *data = ((const struct device *)arg)->data;
198
199 data->underflow_flag = LCDC_STATUS_REG_GET_FIELD(LCDC_STICKY_UNDERFLOW);
200
201 /*
202 * Underflow sticky bit will remain high until cleared by writing
203 * any value to LCDC_INTERRUPT_REG.
204 */
205 LCDC->LCDC_INTERRUPT_REG &= ~LCDC_LCDC_INTERRUPT_REG_LCDC_VSYNC_IRQ_EN_Msk;
206
207 /* Notify that current frame update is completed */
208 k_sem_give(&data->sync_sem);
209 }
210
display_smartbond_dma_cb(const struct device * dma,void * arg,uint32_t id,int status)211 static void display_smartbond_dma_cb(const struct device *dma, void *arg,
212 uint32_t id, int status)
213 {
214 struct display_smartbond_data *data = arg;
215
216 if (status < 0) {
217 LOG_WRN("DMA transfer did not complete");
218 }
219
220 k_sem_give(&data->dma_sync_sem);
221 }
222
display_smartbond_dma_config(const struct device * dev)223 static int display_smartbond_dma_config(const struct device *dev)
224 {
225 struct display_smartbond_data *data = dev->data;
226
227 data->dma = DEVICE_DT_GET(DT_NODELABEL(dma));
228 if (!device_is_ready(data->dma)) {
229 LOG_ERR("DMA device is not ready");
230 return -ENODEV;
231 }
232
233 data->dma_cfg.channel_direction = MEMORY_TO_MEMORY;
234 data->dma_cfg.user_data = data;
235 data->dma_cfg.dma_callback = display_smartbond_dma_cb;
236 data->dma_cfg.block_count = 1;
237 data->dma_cfg.head_block = &data->dma_block_cfg;
238 data->dma_cfg.error_callback_dis = 1;
239
240 /* Request an arbitrary DMA channel */
241 data->dma_channel = dma_request_channel(data->dma, NULL);
242 if (data->dma_channel < 0) {
243 LOG_ERR("Could not acquire a DMA channel");
244 return -EIO;
245 }
246
247 return 0;
248 }
249
display_smartbond_resume(const struct device * dev)250 static int display_smartbond_resume(const struct device *dev)
251 {
252 const struct display_smartbond_config *config = dev->config;
253 int ret;
254
255 /* Select default state */
256 ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);
257 if (ret < 0) {
258 LOG_ERR("Could not apply LCDC pins' default state (%d)", ret);
259 return -EIO;
260 }
261
262 #if LCDC_SMARTBOND_IS_PLL_REQUIRED
263 const struct device *clock_dev = DEVICE_DT_GET(DT_NODELABEL(osc));
264
265 if (!device_is_ready(clock_dev)) {
266 LOG_WRN("Clock device is not ready");
267 return -ENODEV;
268 }
269
270 ret = z_smartbond_select_sys_clk(SMARTBOND_CLK_PLL96M);
271 if (ret < 0) {
272 LOG_WRN("Could not switch to PLL");
273 return -EIO;
274 }
275 #endif
276
277 ret = display_smartbond_dma_config(dev);
278 if (ret < 0) {
279 return ret;
280 }
281
282 return display_smartbond_configure(dev);
283 }
284
285 #if defined(CONFIG_PM_DEVICE)
display_smartbond_dma_deconfig(const struct device * dev)286 static void display_smartbond_dma_deconfig(const struct device *dev)
287 {
288 struct display_smartbond_data *data = dev->data;
289
290 __ASSERT(data->dma, "DMA should be already initialized");
291
292 dma_release_channel(data->dma, data->dma_channel);
293 }
294
display_smartbond_suspend(const struct device * dev)295 static int display_smartbond_suspend(const struct device *dev)
296 {
297 const struct display_smartbond_config *config = dev->config;
298 int ret;
299
300 /* Select sleep state; it's OK if settings fails for any reason */
301 ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP);
302 if (ret < 0) {
303 LOG_WRN("Could not apply DISPLAY pins' sleep state");
304 }
305
306 /* Disable host controller to minimize power consumption */
307 da1469x_lcdc_set_status(false, false, 0);
308
309 display_smartbond_dma_deconfig(dev);
310
311 return 0;
312 }
313 #endif
314
display_smartbond_init(const struct device * dev)315 static int display_smartbond_init(const struct device *dev)
316 {
317 const struct display_smartbond_config *config = dev->config;
318 struct display_smartbond_data *data = dev->data;
319 int ret;
320
321 /* Device should be ready to be acquired */
322 k_sem_init(&data->device_sem, 1, 1);
323 /* Event should be signaled by LCDC ISR */
324 k_sem_init(&data->sync_sem, 0, 1);
325 /* Event should be signaled by DMA ISR */
326 k_sem_init(&data->dma_sync_sem, 0, 1);
327
328 /* As per docs, display port should be enabled by default. */
329 if (gpio_is_ready_dt(&config->disp)) {
330 ret = gpio_pin_configure_dt(&config->disp, GPIO_OUTPUT_ACTIVE);
331 if (ret < 0) {
332 LOG_ERR("Could not activate display port");
333 return -EIO;
334 }
335 }
336
337 IRQ_CONNECT(SMARTBOND_IRQN, SMARTBOND_IRQ_PRIO, smartbond_display_isr,
338 DEVICE_DT_INST_GET(0), 0);
339
340 /*
341 * Currently, there is no API to explicitly enable/disable the display controller.
342 * At the same time, the controller is set to continuous mode meaning that
343 * as long as a display panel is turned on, frame updates should happen all
344 * the time (otherwise contents on the display pane will be lost as the latter
345 * does not integrate an SDRAM memory to keep its frame).
346 * As such, resume/suspend operations are bound to blanking operations.
347 * That is, when the display is blanked on we can safely consider that display
348 * is no longer functional and thus, the controller can be suspended (allowing the
349 * SoC to enter the sleep state). Once the display is blanked off, then we consider
350 * that the controller should be resumed and sleep should be prevented at all
351 * (this is because the controller is powered by the same power domain used to
352 * power the application core). Side effect of the above is that the controller
353 * should be configured at initialization phase as display operations might
354 * be requested before the display is blanked off for the very first time.
355 */
356 ret = display_smartbond_resume(dev);
357 if (ret == 0) {
358 /* Display port should be enabled at this moment and so sleep is not allowed. */
359 lcdc_smartbond_pm_policy_state_lock_get(data);
360 }
361
362 return ret;
363 }
364
display_smartbond_blanking_on(const struct device * dev)365 static int display_smartbond_blanking_on(const struct device *dev)
366 {
367 const struct display_smartbond_config *config = dev->config;
368 struct display_smartbond_data *data = dev->data;
369 int ret = 0;
370
371 k_sem_take(&data->device_sem, K_FOREVER);
372
373 /*
374 * This bit will force LCD controller's output to blank that is,
375 * the controller will keep operating without outputting any
376 * pixel data.
377 */
378 LCDC->LCDC_MODE_REG |= LCDC_LCDC_MODE_REG_LCDC_FORCE_BLANK_Msk;
379
380 /* If enabled, disable display port. */
381 if (gpio_is_ready_dt(&config->disp)) {
382 ret = gpio_pin_configure_dt(&config->disp, GPIO_OUTPUT_INACTIVE);
383 if (ret < 0) {
384 LOG_WRN("Display port could not be de-activated");
385 }
386 }
387
388 /*
389 * At this moment the display panel should be turned off and so the device
390 * can enter the suspend state.
391 */
392 lcdc_smartbond_pm_policy_state_lock_put(data);
393
394 k_sem_give(&data->device_sem);
395
396 return ret;
397 }
398
display_smartbond_blanking_off(const struct device * dev)399 static int display_smartbond_blanking_off(const struct device *dev)
400 {
401 const struct display_smartbond_config *config = dev->config;
402 struct display_smartbond_data *data = dev->data;
403 int ret = 0;
404
405 k_sem_take(&data->device_sem, K_FOREVER);
406
407 /* If used, enable display port */
408 if (gpio_is_ready_dt(&config->disp)) {
409 ret = gpio_pin_configure_dt(&config->disp, GPIO_OUTPUT_ACTIVE);
410 if (ret < 0) {
411 LOG_WRN("Display port could not be activated");
412 }
413 }
414
415 /*
416 * This bit will force LCD controller's output to blank that is,
417 * the controller will keep operating without outputting any
418 * pixel data.
419 */
420 LCDC->LCDC_MODE_REG &= ~LCDC_LCDC_MODE_REG_LCDC_FORCE_BLANK_Msk;
421
422 /*
423 * At this moment the display should be turned on and so the device
424 * cannot enter the suspend state.
425 */
426 lcdc_smartbond_pm_policy_state_lock_get(data);
427
428 k_sem_give(&data->device_sem);
429
430 return ret;
431 }
432
display_smartbond_get_framebuffer(const struct device * dev)433 static void *display_smartbond_get_framebuffer(const struct device *dev)
434 {
435 struct display_smartbond_data *data = dev->data;
436
437 return ((void *)data->buffer);
438 }
439
display_smartbond_get_capabilities(const struct device * dev,struct display_capabilities * capabilities)440 static void display_smartbond_get_capabilities(const struct device *dev,
441 struct display_capabilities *capabilities)
442 {
443 memset(capabilities, 0, sizeof(*capabilities));
444
445 /*
446 * Multiple color formats should be supported by LCDC. Currently, RGB56 and ARGB888
447 * exposed by display API are supported. In the future we should consider supporting
448 * more color formats which should require changes in LVGL porting.
449 * Here, only one color format should be supported as the frame buffer is accessed
450 * directly by LCDC and is allocated statically during device initialization. The color
451 * format is defined based on the pixel-format property dictated by lcd-controller
452 * bindings.
453 */
454 capabilities->supported_pixel_formats = DT_INST_PROP(0, pixel_format);
455 capabilities->current_orientation = DISPLAY_ORIENTATION_NORMAL;
456 capabilities->current_pixel_format = DT_INST_PROP(0, pixel_format);
457 capabilities->x_resolution = DT_INST_PROP(0, width);
458 capabilities->y_resolution = DT_INST_PROP(0, height);
459 }
460
display_smartbond_read(const struct device * dev,const uint16_t x,const uint16_t y,const struct display_buffer_descriptor * desc,void * buf)461 static int display_smartbond_read(const struct device *dev,
462 const uint16_t x, const uint16_t y,
463 const struct display_buffer_descriptor *desc,
464 void *buf)
465 {
466 struct display_smartbond_data *data = dev->data;
467 const struct display_smartbond_config *config = dev->config;
468 uint8_t *dst = buf;
469 const uint8_t *src = data->buffer;
470
471 k_sem_take(&data->device_sem, K_FOREVER);
472
473 /* pointer to upper left pixel of the rectangle */
474 src += (x * config->pixel_size);
475 src += (y * data->layer.stride);
476
477 data->dma_block_cfg.block_size = desc->width * config->pixel_size;
478 /*
479 * Source and destination base address is word aligned.
480 * Data size should be selected based on color depth as
481 * cursor is shifted multiple of pixel color depth.
482 */
483 data->dma_cfg.source_data_size = data->dma_cfg.dest_data_size =
484 !(config->pixel_size & 3) ? 4 :
485 !(config->pixel_size & 1) ? 2 : 1;
486
487 data->dma_cfg.dest_burst_length = data->dma_cfg.source_burst_length =
488 !((data->dma_block_cfg.block_size / data->dma_cfg.source_data_size) & 7) ? 8 :
489 !((data->dma_block_cfg.block_size / data->dma_cfg.source_data_size) & 3) ? 4 : 1;
490
491 for (int row = 0; row < desc->height; row++) {
492
493 data->dma_block_cfg.dest_address = (uint32_t)dst;
494 data->dma_block_cfg.source_address = (uint32_t)src;
495
496 if (dma_config(data->dma, data->dma_channel, &data->dma_cfg)) {
497 LOG_ERR("Could not configure DMA");
498 k_sem_give(&data->device_sem);
499 return -EIO;
500 }
501
502 if (dma_start(data->dma, data->dma_channel)) {
503 LOG_ERR("Could not start DMA");
504 k_sem_give(&data->device_sem);
505 return -EIO;
506 }
507
508 k_sem_take(&data->dma_sync_sem, K_FOREVER);
509
510 src += data->layer.stride;
511 dst += (desc->pitch * config->pixel_size);
512 }
513
514 if (dma_stop(data->dma, data->dma_channel)) {
515 LOG_WRN("Could not stop DMA");
516 }
517
518 k_sem_give(&data->device_sem);
519
520 return 0;
521 }
522
display_smartbond_write(const struct device * dev,const uint16_t x,const uint16_t y,const struct display_buffer_descriptor * desc,const void * buf)523 static int display_smartbond_write(const struct device *dev,
524 const uint16_t x, const uint16_t y,
525 const struct display_buffer_descriptor *desc,
526 const void *buf)
527 {
528 struct display_smartbond_data *data = dev->data;
529 const struct display_smartbond_config *config = dev->config;
530 uint8_t *dst = data->buffer;
531 const uint8_t *src = buf;
532
533 k_sem_take(&data->device_sem, K_FOREVER);
534
535 /* pointer to upper left pixel of the rectangle */
536 dst += (x * config->pixel_size);
537 dst += (y * data->layer.stride);
538
539 /*
540 * Wait for the current frame to finish. Do not disable continuous mode as this
541 * will have visual artifacts.
542 */
543 LCDC->LCDC_INTERRUPT_REG |= LCDC_LCDC_INTERRUPT_REG_LCDC_VSYNC_IRQ_EN_Msk;
544 k_sem_take(&data->sync_sem, K_FOREVER);
545
546 data->dma_block_cfg.block_size = desc->width * config->pixel_size;
547 /*
548 * Source and destination base address is word aligned.
549 * Data size should be selected based on color depth as
550 * cursor is shifted multiple of pixel color depth.
551 */
552 data->dma_cfg.source_data_size = data->dma_cfg.dest_data_size =
553 !(config->pixel_size & 3) ? 4 :
554 !(config->pixel_size & 1) ? 2 : 1;
555
556 data->dma_cfg.dest_burst_length = data->dma_cfg.source_burst_length =
557 !((data->dma_block_cfg.block_size / data->dma_cfg.source_data_size) & 7) ? 8 :
558 !((data->dma_block_cfg.block_size / data->dma_cfg.source_data_size) & 3) ? 4 : 1;
559
560 for (int row = 0; row < desc->height; row++) {
561
562 data->dma_block_cfg.dest_address = (uint32_t)dst;
563 data->dma_block_cfg.source_address = (uint32_t)src;
564
565 if (dma_config(data->dma, data->dma_channel, &data->dma_cfg)) {
566 LOG_ERR("Could not configure DMA");
567 k_sem_give(&data->device_sem);
568 return -EIO;
569 }
570
571 if (dma_start(data->dma, data->dma_channel)) {
572 LOG_ERR("Could not start DMA");
573 k_sem_give(&data->device_sem);
574 return -EIO;
575 }
576
577 k_sem_take(&data->dma_sync_sem, K_FOREVER);
578
579 dst += data->layer.stride;
580 src += (desc->pitch * config->pixel_size);
581 }
582
583 if (dma_stop(data->dma, data->dma_channel)) {
584 LOG_WRN("Could not stop DMA");
585 }
586
587 k_sem_give(&data->device_sem);
588
589 return 0;
590 }
591
592 #if defined(CONFIG_PM_DEVICE)
display_smartbond_pm_action(const struct device * dev,enum pm_device_action action)593 static int display_smartbond_pm_action(const struct device *dev, enum pm_device_action action)
594 {
595 int ret = 0;
596
597 switch (action) {
598 case PM_DEVICE_ACTION_SUSPEND:
599 /* A non-zero value should not affect sleep */
600 (void)display_smartbond_suspend(dev);
601 break;
602 case PM_DEVICE_ACTION_RESUME:
603 /*
604 * The resume error code should not be taken into consideration
605 * by the PM subsystem
606 */
607 ret = display_smartbond_resume(dev);
608 break;
609 default:
610 ret = -ENOTSUP;
611 }
612
613 return ret;
614 }
615 #endif
616
617 static const struct display_driver_api display_smartbond_driver_api = {
618 .write = display_smartbond_write,
619 .read = display_smartbond_read,
620 .get_framebuffer = display_smartbond_get_framebuffer,
621 .get_capabilities = display_smartbond_get_capabilities,
622 .blanking_off = display_smartbond_blanking_off,
623 .blanking_on = display_smartbond_blanking_on
624 };
625
626 #define SMARTBOND_DISPLAY_INIT(inst) \
627 PINCTRL_DT_INST_DEFINE(inst); \
628 PM_DEVICE_DT_INST_DEFINE(inst, display_smartbond_pm_action); \
629 \
630 __aligned(4) static uint8_t buffer_ ## inst[(((DT_INST_PROP(inst, width) * \
631 DISPLAY_SMARTBOND_PIXEL_SIZE(inst)) + 0x3) & ~0x3) * \
632 DT_INST_PROP(inst, height)] DISPLAY_BUFFER_LINKER_SECTION; \
633 \
634 static const struct display_smartbond_config display_smartbond_config_## inst = { \
635 .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \
636 .disp = GPIO_DT_SPEC_INST_GET_OR(inst, disp_gpios, {}), \
637 .timing_cfg.vsync_len = \
638 DT_PROP(DT_INST_CHILD(inst, display_timings), vsync_len), \
639 .timing_cfg.hsync_len = \
640 DT_PROP(DT_INST_CHILD(inst, display_timings), hsync_len), \
641 .timing_cfg.hfront_porch = \
642 DT_PROP(DT_INST_CHILD(inst, display_timings), hfront_porch), \
643 .timing_cfg.vfront_porch = \
644 DT_PROP(DT_INST_CHILD(inst, display_timings), vfront_porch), \
645 .timing_cfg.hback_porch = \
646 DT_PROP(DT_INST_CHILD(inst, display_timings), hback_porch), \
647 .timing_cfg.vback_porch = \
648 DT_PROP(DT_INST_CHILD(inst, display_timings), vback_porch), \
649 .bgcolor_cfg = {0xFF, 0xFF, 0xFF, 0}, \
650 .x_res = DT_INST_PROP(inst, width), \
651 .y_res = DT_INST_PROP(inst, height), \
652 .pixel_size = DISPLAY_SMARTBOND_PIXEL_SIZE(inst), \
653 .pixel_format = DT_INST_PROP(0, pixel_format), \
654 .mode.vsync_pol = \
655 DT_PROP(DT_INST_CHILD(inst, display_timings), vsync_active) ? 0 : 1, \
656 .mode.hsync_pol = \
657 DT_PROP(DT_INST_CHILD(inst, display_timings), vsync_active) ? 0 : 1, \
658 .mode.de_pol = \
659 DT_PROP(DT_INST_CHILD(inst, display_timings), de_active) ? 0 : 1, \
660 .mode.pixelclk_pol = \
661 DT_PROP(DT_INST_CHILD(inst, display_timings), pixelclk_active) ? 0 : 1, \
662 }; \
663 \
664 static struct display_smartbond_data display_smartbond_data_## inst = { \
665 .buffer = buffer_ ##inst, \
666 .layer.start_x = 0, \
667 .layer.start_y = 0, \
668 .layer.size_x = DT_INST_PROP(inst, width), \
669 .layer.size_y = DT_INST_PROP(inst, height), \
670 .layer.frame_buf = (uint32_t)buffer_ ## inst, \
671 }; \
672 \
673 \
674 DEVICE_DT_INST_DEFINE(inst, display_smartbond_init, PM_DEVICE_DT_INST_GET(inst), \
675 &display_smartbond_data_## inst, \
676 &display_smartbond_config_## inst, \
677 POST_KERNEL, \
678 CONFIG_DISPLAY_INIT_PRIORITY, \
679 &display_smartbond_driver_api);
680
681 SMARTBOND_DISPLAY_INIT(0);
682