source: rtems/c/src/lib/libbsp/arm/shared/arm-pl111-fb.c @ 2d0bc83

5
Last change on this file since 2d0bc83 was b2ed712, checked in by Sebastian Huber <sebastian.huber@…>, on 08/25/17 at 08:58:58

Include missing <string.h>

Update #2133.

  • Property mode set to 100644
File size: 6.2 KB
Line 
1/*
2 * Copyright (c) 2013 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Dornierstr. 4
6 *  82178 Puchheim
7 *  Germany
8 *  <info@embedded-brains.de>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
12 * http://www.rtems.org/license/LICENSE.
13 */
14
15#include <errno.h>
16#include <assert.h>
17#include <stdlib.h>
18#include <string.h>
19
20#include <rtems/framebuffer.h>
21#include <rtems/fb.h>
22#include <rtems/libio.h>
23
24#include <bsp.h>
25#include <bsp/arm-pl111-fb.h>
26#include <bsp/fatal.h>
27
28typedef struct {
29  rtems_id semaphore;
30  void *frame_buffer;
31} pl111_fb_context;
32
33static pl111_fb_context pl111_fb_instance;
34
35static const uint8_t pl111_bits_per_pixel[] = { 1, 2, 4, 8, 16, 24, 16, 12 };
36
37static uint32_t pl111_fb_get_width(const pl111_fb_config *cfg)
38{
39  return 16U * (PL111_LCD_TIMING0_PPL_GET(cfg->timing0) + 1U);
40}
41
42static uint32_t pl111_fb_get_height(const pl111_fb_config *cfg)
43{
44  return PL111_LCD_TIMING1_LPP_GET(cfg->timing1) + 1U;
45}
46
47static uint32_t pl111_fb_get_bits_per_pixel(const pl111_fb_config *cfg)
48{
49  return pl111_bits_per_pixel[PL111_LCD_CONTROL_LCD_BPP_GET(cfg->control)];
50}
51
52static uint32_t pl111_fb_get_line_length_in_bytes(const pl111_fb_config *cfg)
53{
54  uint32_t width = pl111_fb_get_width(cfg);
55  uint32_t bits_per_pixel = pl111_fb_get_bits_per_pixel(cfg);
56
57  return width * ((bits_per_pixel + 7U) / 8U);
58}
59
60static uint32_t pl111_fb_get_frame_buffer_size(const pl111_fb_config *cfg)
61{
62  uint32_t line_length_in_bytes = pl111_fb_get_line_length_in_bytes(cfg);
63  uint32_t height = pl111_fb_get_height(cfg);
64
65  return height * line_length_in_bytes;
66}
67
68static void pl111_fb_power_delay(const pl111_fb_config *cfg)
69{
70  rtems_interval delay = (cfg->power_delay_in_us + 1)
71    / rtems_configuration_get_microseconds_per_tick();
72  rtems_status_code sc = rtems_task_wake_after(delay);
73  assert(sc == RTEMS_SUCCESSFUL);
74}
75
76static rtems_status_code pl111_fb_initialize(pl111_fb_context *ctx)
77{
78  rtems_status_code sc = RTEMS_SUCCESSFUL;
79  const pl111_fb_config *cfg = arm_pl111_fb_get_config();
80
81  ctx->frame_buffer = calloc(1, pl111_fb_get_frame_buffer_size(cfg));
82  if (ctx->frame_buffer != NULL) {
83    volatile pl111 *regs = cfg->regs;
84
85    (*cfg->set_up)(cfg);
86
87    regs->lcd.upbase = (uint32_t) ctx->frame_buffer;
88
89    regs->lcd.timing0 = cfg->timing0;
90    regs->lcd.timing1 = cfg->timing1;
91    regs->lcd.timing2 = cfg->timing2;
92    regs->lcd.timing3 = cfg->timing3;
93    regs->lcd.control = cfg->control;
94
95    (*cfg->pins_set_up)(cfg);
96
97    regs->lcd.control = cfg->control
98      | PL111_LCD_CONTROL_LCD_EN;
99
100    pl111_fb_power_delay(cfg);
101
102    regs->lcd.control = cfg->control
103      | PL111_LCD_CONTROL_LCD_EN
104      | PL111_LCD_CONTROL_LCD_PWR;
105  } else {
106    sc = RTEMS_NO_MEMORY;
107  }
108
109  return sc;
110}
111
112static void pl111_fb_destroy(const pl111_fb_context *ctx)
113{
114  const pl111_fb_config *cfg = arm_pl111_fb_get_config();
115  volatile pl111 *regs = cfg->regs;
116
117  free(ctx->frame_buffer);
118
119  regs->lcd.control = cfg->control
120    | PL111_LCD_CONTROL_LCD_EN;
121
122  pl111_fb_power_delay(cfg);
123
124  regs->lcd.control = cfg->control;
125
126  (*cfg->pins_tear_down)(cfg);
127  (*cfg->tear_down)(cfg);
128}
129
130static void pl111_fb_get_fix_screen_info(struct fb_fix_screeninfo *info)
131{
132  const pl111_fb_config *cfg = arm_pl111_fb_get_config();
133  const pl111_fb_context *ctx = &pl111_fb_instance;
134
135  memset(info, 0, sizeof(*info));
136
137  info->smem_start = ctx->frame_buffer;
138  info->smem_len = pl111_fb_get_frame_buffer_size(cfg);
139  info->type = FB_TYPE_PACKED_PIXELS;
140  info->visual = FB_VISUAL_TRUECOLOR;
141  info->line_length = pl111_fb_get_line_length_in_bytes(cfg);
142}
143
144static void pl111_fb_get_var_screen_info(struct fb_var_screeninfo *info)
145{
146  const pl111_fb_config *cfg = arm_pl111_fb_get_config();
147
148  memset(info, 0, sizeof(*info));
149
150  info->xres = pl111_fb_get_width(cfg);
151  info->yres = pl111_fb_get_height(cfg);
152  info->bits_per_pixel = pl111_fb_get_bits_per_pixel(cfg);
153}
154
155static void pl111_fb_release(const pl111_fb_context *ctx)
156{
157  rtems_status_code sc = rtems_semaphore_release(ctx->semaphore);
158  if (sc != RTEMS_SUCCESSFUL) {
159    bsp_fatal(BSP_ARM_PL111_FATAL_SEM_RELEASE);
160  }
161}
162
163rtems_device_driver frame_buffer_initialize(
164  rtems_device_major_number major,
165  rtems_device_minor_number minor,
166  void *arg
167)
168{
169  rtems_status_code sc;
170  pl111_fb_context *ctx = &pl111_fb_instance;
171
172  sc = rtems_io_register_name(FRAMEBUFFER_DEVICE_0_NAME, major, 0);
173  if (sc != RTEMS_SUCCESSFUL) {
174    bsp_fatal(BSP_ARM_PL111_FATAL_REGISTER_DEV);
175  }
176
177  sc = rtems_semaphore_create(
178    rtems_build_name('F', 'B', ' ', ' '),
179    1,
180    RTEMS_COUNTING_SEMAPHORE,
181    0,
182    &ctx->semaphore
183  );
184  if (sc != RTEMS_SUCCESSFUL) {
185    bsp_fatal(BSP_ARM_PL111_FATAL_SEM_CREATE);
186  }
187
188  return sc;
189}
190
191rtems_device_driver frame_buffer_open(
192  rtems_device_major_number major,
193  rtems_device_minor_number minor,
194  void *arg
195)
196{
197  rtems_status_code sc;
198  pl111_fb_context *ctx = &pl111_fb_instance;
199
200  sc = rtems_semaphore_obtain(
201    ctx->semaphore,
202    RTEMS_WAIT,
203    RTEMS_NO_TIMEOUT
204  );
205  if (sc == RTEMS_SUCCESSFUL) {
206    sc = pl111_fb_initialize(ctx);
207    if (sc != RTEMS_SUCCESSFUL) {
208      pl111_fb_release(ctx);
209    }
210  }
211
212  return sc;
213}
214
215rtems_device_driver frame_buffer_close(
216  rtems_device_major_number major,
217  rtems_device_minor_number minor,
218  void *arg
219)
220{
221  const pl111_fb_context *ctx = &pl111_fb_instance;
222
223  pl111_fb_destroy(ctx);
224  pl111_fb_release(ctx);
225
226  return RTEMS_SUCCESSFUL;
227}
228
229rtems_device_driver frame_buffer_read(
230  rtems_device_major_number major,
231  rtems_device_minor_number minor,
232  void *arg
233)
234{
235  return RTEMS_IO_ERROR;
236}
237
238rtems_device_driver frame_buffer_write(
239  rtems_device_major_number major,
240  rtems_device_minor_number minor,
241  void *arg
242)
243{
244  return RTEMS_IO_ERROR;
245}
246
247rtems_device_driver frame_buffer_control(
248  rtems_device_major_number major,
249  rtems_device_minor_number minor,
250  void *arg
251)
252{
253  rtems_libio_ioctl_args_t *ioctl_arg = arg;
254  int eno = 0;
255
256  switch (ioctl_arg->command) {
257    case FBIOGET_FSCREENINFO:
258      pl111_fb_get_fix_screen_info(ioctl_arg->buffer);
259      break;
260    case FBIOGET_VSCREENINFO:
261      pl111_fb_get_var_screen_info(ioctl_arg->buffer);
262      break;
263    default:
264      eno = EINVAL;
265      break;
266  }
267
268  if (eno == 0) {
269    ioctl_arg->ioctl_return = 0;
270  } else {
271    ioctl_arg->ioctl_return = -1;
272    errno = eno;
273  }
274
275  return RTEMS_SUCCESSFUL;
276}
Note: See TracBrowser for help on using the repository browser.