1/*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "display_layer.h"
17#include <cerrno>
18#include <pthread.h>
19#include <stdio.h>
20#include <unistd.h>
21#include <sys/mman.h>
22#include <securec.h>
23#include "display_type.h"
24#include "hdf_log.h"
25#include "hdf_io_service_if.h"
26#include "hdf_sbuf.h"
27#include "osal_mem.h"
28
29#define DEV_ID                   0
30#define LAYER_ID                 0
31#define FB_PATH                  "/dev/fb0"
32#define DISP_WIDTH               800
33#define DISP_HEIGHT              480
34#define BITS_PER_PIXEL           32
35#define BITS_TO_BYTE             8
36#define DISP_SERVICE_NAME        "hdf_disp"
37#define DISP_CMD_GET_PANELINFO   1
38
39#undef  HDF_LOG_TAG
40#define HDF_LOG_TAG              display_layer_c
41
42/* output timing */
43enum IntfSync {
44    OUTPUT_USER = 0,          /* User timing */
45    OUTPUT_PAL,               /* PAL standard */
46    OUTPUT_NTSC,              /* NTSC standard */
47    OUTPUT_1080P24,           /* 1920 x 1080 at 24 Hz. */
48    OUTPUT_1080P25,           /* 1920 x 1080 at 25 Hz. */
49    OUTPUT_1080P30,           /* 1920 x 1080 at 30 Hz. */
50    OUTPUT_720P50,            /* 1280 x  720 at 50 Hz. */
51    OUTPUT_720P60,            /* 1280 x  720 at 60 Hz. */
52    OUTPUT_1080I50,           /* 1920 x 1080 at 50 Hz, interlace. */
53    OUTPUT_1080I60,           /* 1920 x 1080 at 60 Hz, interlace. */
54    OUTPUT_1080P50,           /* 1920 x 1080 at 50 Hz. */
55    OUTPUT_1080P60,           /* 1920 x 1080 at 60 Hz. */
56    OUTPUT_576P50,            /* 720  x  576 at 50 Hz. */
57    OUTPUT_480P60,            /* 720  x  480 at 60 Hz. */
58    OUTPUT_800X600_60,        /* VESA 800 x 600 at 60 Hz (non-interlaced) */
59    OUTPUT_1024X768_60,       /* VESA 1024 x 768 at 60 Hz (non-interlaced) */
60    OUTPUT_1280X1024_60,      /* VESA 1280 x 1024 at 60 Hz (non-interlaced) */
61    OUTPUT_1366X768_60,       /* VESA 1366 x 768 at 60 Hz (non-interlaced) */
62    OUTPUT_1440X900_60,       /* VESA 1440 x 900 at 60 Hz (non-interlaced) CVT Compliant */
63    OUTPUT_1280X800_60,       /* 1280*800@60Hz VGA@60Hz */
64    OUTPUT_1600X1200_60,      /* VESA 1600 x 1200 at 60 Hz (non-interlaced) */
65    OUTPUT_1680X1050_60,      /* VESA 1680 x 1050 at 60 Hz (non-interlaced) */
66    OUTPUT_1920X1200_60,      /* VESA 1920 x 1600 at 60 Hz (non-interlaced) CVT (Reduced Blanking) */
67    OUTPUT_640X480_60,        /* VESA 640 x 480 at 60 Hz (non-interlaced) CVT */
68    OUTPUT_960H_PAL,          /* ITU-R BT.1302 960 x 576 at 50 Hz (interlaced) */
69    OUTPUT_960H_NTSC,         /* ITU-R BT.1302 960 x 480 at 60 Hz (interlaced) */
70    OUTPUT_1920X2160_30,      /* 1920x2160_30 */
71    OUTPUT_2560X1440_30,      /* 2560x1440_30 */
72    OUTPUT_2560X1440_60,      /* 2560x1440_60 */
73    OUTPUT_2560X1600_60,      /* 2560x1600_60 */
74    OUTPUT_3840X2160_24,      /* 3840x2160_24 */
75    OUTPUT_3840X2160_25,      /* 3840x2160_25 */
76    OUTPUT_3840X2160_30,      /* 3840x2160_30 */
77    OUTPUT_3840X2160_50,      /* 3840x2160_50 */
78    OUTPUT_3840X2160_60,      /* 3840x2160_60 */
79    OUTPUT_4096X2160_24,      /* 4096x2160_24 */
80    OUTPUT_4096X2160_25,      /* 4096x2160_25 */
81    OUTPUT_4096X2160_30,      /* 4096x2160_30 */
82    OUTPUT_4096X2160_50,      /* 4096x2160_50 */
83    OUTPUT_4096X2160_60,      /* 4096x2160_60 */
84    OUTPUT_320X240_60,        /* For ota5182 at 60 Hz (8bit) */
85    OUTPUT_320X240_50,        /* For ili9342 at 50 Hz (6bit) */
86    OUTPUT_240X320_50,        /* Hi3559AV100: For ili9341 at 50 Hz (6bit) */
87    OUTPUT_240X320_60,        /* For ili9341 at 60 Hz (16bit) */
88    OUTPUT_800X600_50,        /* For LCD     at 50 Hz (24bit) */
89    OUTPUT_720X1280_60,       /* For MIPI DSI Tx 720 x1280 at 60 Hz */
90    OUTPUT_1080X1920_60,      /* For MIPI DSI Tx 1080x1920 at 60 Hz */
91    OUTPUT_7680X4320_30,      /* For HDMI2.1 at 30 Hz */
92};
93
94struct DispInfo {
95    uint32_t width;
96    uint32_t hbp;
97    uint32_t hfp;
98    uint32_t hsw;
99    uint32_t height;
100    uint32_t vbp;
101    uint32_t vfp;
102    uint32_t vsw;
103    uint32_t frameRate;
104    uint32_t intfType;
105    enum IntfSync intfSync;
106    uint32_t minLevel;
107    uint32_t maxLevel;
108    uint32_t defLevel;
109};
110
111struct LayerPrivate {
112    int32_t  fd;
113    uint32_t width;
114    uint32_t height;
115    int32_t  pitch;
116    void     *fbAddr;
117    uint32_t fbSize;
118    void     *layerAddr;
119    PixelFormat pixFmt;
120};
121
122struct LayerManager {
123    pthread_mutex_t mutex;
124    pthread_mutexattr_t mutexattr;
125    int32_t count;
126};
127
128static struct LayerManager g_layerManager;
129
130static void GetLayerMgr(void)
131{
132    g_layerManager.count++;
133}
134
135static int32_t PutLayerMgr(void)
136{
137    g_layerManager.count--;
138    return g_layerManager.count;
139}
140
141static void LockLayerMgr(void)
142{
143    pthread_mutex_lock(&g_layerManager.mutex);
144}
145
146static void UnlockLayerMgr(void)
147{
148    pthread_mutex_unlock(&g_layerManager.mutex);
149}
150
151static int32_t DispCmdSend(const uint32_t cmd, struct HdfSBuf *reqData, struct HdfSBuf *respData)
152{
153    struct HdfIoService *dispService = NULL;
154
155    dispService = HdfIoServiceBind(DISP_SERVICE_NAME);
156    if ((dispService == NULL) || (dispService->dispatcher == NULL) || (dispService->dispatcher->Dispatch == NULL)) {
157        HDF_LOGE("%s:bad remote service found", __func__);
158        return DISPLAY_FAILURE;
159    }
160    int32_t ret = dispService->dispatcher->Dispatch(&dispService->object, cmd, reqData, respData);
161    if (ret != DISPLAY_SUCCESS) {
162        HDF_LOGE("%s: cmd=%u, ret=%d", __func__, cmd, ret);
163        HdfIoServiceRecycle(dispService);
164        return DISPLAY_FAILURE;
165    }
166    HdfIoServiceRecycle(dispService);
167    return DISPLAY_SUCCESS;
168}
169
170static int32_t GetInfo(uint32_t devId, struct DispInfo *info)
171{
172    struct DispInfo *tmpInfo = NULL;
173    struct HdfSBuf *data = NULL;
174    struct HdfSBuf *reply = NULL;
175
176    if (info == NULL) {
177        HDF_LOGE("%s: invalid param", __func__);
178        return DISPLAY_FAILURE;
179    }
180    data = HdfSbufObtainDefaultSize();
181    if (data == NULL) {
182        HDF_LOGE("%s: obtain data sbuf fail", __func__);
183        return DISPLAY_FAILURE;
184    }
185    reply = HdfSbufObtainDefaultSize();
186    if (reply == NULL) {
187        HDF_LOGE("%s: obtain reply sbuf fail", __func__);
188        HdfSbufRecycle(data);
189        return DISPLAY_FAILURE;
190    }
191    if (!HdfSbufWriteUint32(data, devId)) {
192        HDF_LOGE("HdfSbufWriteUint32 failure");
193        goto ERR;
194    }
195    if (DispCmdSend(DISP_CMD_GET_PANELINFO, data, reply) != DISPLAY_SUCCESS) {
196        HDF_LOGE("cmd:DISP_CMD_GET_PANEL_INFO failure");
197        goto ERR;
198    }
199    uint32_t dataSize = 0;
200    if (!HdfSbufReadBuffer(reply, (const void **)(&tmpInfo), &dataSize) || dataSize != sizeof(struct DispInfo)) {
201        HDF_LOGE("HdfSbufReadBuffer failure");
202        goto ERR;
203    }
204    if (memcpy_s(info, sizeof(struct DispInfo), tmpInfo, dataSize) != EOK) {
205        HDF_LOGE("memcpy_s failure");
206        goto ERR;
207    }
208    HdfSbufRecycle(data);
209    HdfSbufRecycle(reply);
210    return DISPLAY_SUCCESS;
211
212ERR:
213    HdfSbufRecycle(data);
214    HdfSbufRecycle(reply);
215    return DISPLAY_FAILURE;
216}
217
218static struct LayerPrivate *GetLayerInstance(void)
219{
220    static int32_t count;
221    static struct DispInfo info;
222    static struct LayerPrivate layerPriv = {
223        .fd = -1,
224        .width = DISP_WIDTH,
225        .height = DISP_HEIGHT,
226        .pixFmt = PIXEL_FMT_RGBA_8888,
227    };
228
229    if (count == 0) {
230        count = 1;
231        if (GetInfo(DEV_ID, &info) == DISPLAY_SUCCESS) {
232            layerPriv.width = info.width;
233            layerPriv.height = info.height;
234        } else {
235            HDF_LOGI("%s: GetInfo failed, use default setting", __func__);
236        }
237    }
238    return &layerPriv;
239}
240
241static int32_t InitDisplay(uint32_t devId)
242{
243    if (devId != DEV_ID) {
244        HDF_LOGE("%s: devId invalid", __func__);
245        return DISPLAY_FAILURE;
246    }
247    return DISPLAY_SUCCESS;
248}
249
250static int32_t DeinitDisplay(uint32_t devId)
251{
252    if (devId != DEV_ID) {
253        HDF_LOGE("%s: devId invalid", __func__);
254        return DISPLAY_FAILURE;
255    }
256    return DISPLAY_SUCCESS;
257}
258
259static void SetBackground(void)
260{
261    struct LayerPrivate *priv = GetLayerInstance();
262    uint32_t i;
263    uint32_t j;
264    uint32_t *framebuffer = (uint32_t *)priv->fbAddr;
265    for (j = 0; j < priv->height; j++) {
266        for (i = 0; i < priv->width; i++) {
267            framebuffer[i + j * priv->width] = 0xFF; // Blue background
268        }
269    }
270}
271
272static int32_t CreateLayer(uint32_t devId, const LayerInfo *layerInfo, uint32_t *layerId)
273{
274    if (layerInfo == NULL || layerId == NULL) {
275        HDF_LOGE("%s: pointer is null", __func__);
276        return DISPLAY_NULL_PTR;
277    }
278    if (devId != DEV_ID) {
279        HDF_LOGE("%s: devId invalid", __func__);
280        return DISPLAY_FAILURE;
281    }
282    LockLayerMgr();
283    struct LayerPrivate *priv = GetLayerInstance();
284    priv->fd = open(FB_PATH, O_RDWR, 0);
285    if (priv->fd < 0) {
286        HDF_LOGE("%s: open fb dev failed", __func__);
287        UnlockLayerMgr();
288        return DISPLAY_FD_ERR;
289    }
290    priv->pitch = layerInfo->width * BITS_PER_PIXEL / BITS_TO_BYTE;
291    priv->fbSize = ((priv->pitch * priv->height) + 0xfff) & (~0xfff);
292    priv->fbAddr = (void *)mmap(NULL, priv->fbSize, PROT_READ | PROT_WRITE, MAP_SHARED, priv->fd, 0);
293    if (priv->fbAddr == NULL) {
294        HDF_LOGE("%s: mmap fb address failure, errno: %d", __func__, errno);
295        close(priv->fd);
296        priv->fd = -1;
297        priv->pitch = 0;
298        priv->fbSize = 0;
299        UnlockLayerMgr();
300        return DISPLAY_FAILURE;
301    }
302    SetBackground();
303    *layerId = LAYER_ID;
304    HDF_LOGI("%s: open layer success", __func__);
305    UnlockLayerMgr();
306    return DISPLAY_SUCCESS;
307}
308
309static int32_t CloseLayer(uint32_t devId, uint32_t layerId)
310{
311    if (devId != DEV_ID) {
312        HDF_LOGE("%s: devId invalid", __func__);
313        return DISPLAY_FAILURE;
314    }
315    if (layerId != LAYER_ID) {
316        HDF_LOGE("%s: layerId invalid", __func__);
317        return DISPLAY_FAILURE;
318    }
319    LockLayerMgr();
320    struct LayerPrivate *priv = GetLayerInstance();
321    if (priv->fd >= 0) {
322        close(priv->fd);
323    }
324    if (priv->layerAddr != NULL) {
325        free(priv->layerAddr);
326        priv->layerAddr = NULL;
327    }
328    if (priv->fbAddr != NULL) {
329        munmap(priv->fbAddr, priv->fbSize);
330    }
331    priv->fd = -1;
332    UnlockLayerMgr();
333    return DISPLAY_SUCCESS;
334}
335
336static int32_t GetDisplayInfo(uint32_t devId, DisplayInfo *dispInfo)
337{
338    if (dispInfo == NULL) {
339        HDF_LOGE("%s: dispInfo is null", __func__);
340        return DISPLAY_NULL_PTR;
341    }
342    if (devId != DEV_ID) {
343        HDF_LOGE("%s: devId invalid", __func__);
344        return DISPLAY_FAILURE;
345    }
346    LockLayerMgr();
347    struct LayerPrivate *priv = GetLayerInstance();
348    dispInfo->width = priv->width;
349    dispInfo->height = priv->height;
350    dispInfo->rotAngle = ROTATE_NONE;
351    HDF_LOGD("%s: width = %u, height = %u, rotAngle = %u", __func__, dispInfo->width,
352        dispInfo->height, dispInfo->rotAngle);
353    UnlockLayerMgr();
354    return DISPLAY_SUCCESS;
355}
356
357static int32_t Flush(uint32_t devId, uint32_t layerId, LayerBuffer *buffer)
358{
359    int32_t ret;
360
361    if (devId != DEV_ID) {
362        HDF_LOGE("%s: devId invalid", __func__);
363        return DISPLAY_FAILURE;
364    }
365    if (layerId != LAYER_ID) {
366        HDF_LOGE("%s: layerId invalid", __func__);
367        return DISPLAY_FAILURE;
368    }
369    if (buffer == NULL) {
370        HDF_LOGE("%s: buffer is null", __func__);
371        return DISPLAY_FAILURE;
372    }
373
374    HDF_LOGD("%s: width = %d, height = %d, pixFormat = %d, pitch = %d", __func__, buffer->width,
375        buffer->height, buffer->pixFormat, buffer->pitch);
376    LockLayerMgr();
377    struct LayerPrivate *priv = GetLayerInstance();
378    ret = memcpy_s(priv->fbAddr, priv->fbSize, buffer->data.virAddr, priv->fbSize);
379    if (ret != EOK) {
380        HDF_LOGE("%s: memcpy_s fail, ret %d", __func__, ret);
381        UnlockLayerMgr();
382        return ret;
383    }
384    UnlockLayerMgr();
385    return DISPLAY_SUCCESS;
386}
387
388static int32_t GetLayerBuffer(uint32_t devId, uint32_t layerId, LayerBuffer *buffer)
389{
390    if (buffer == NULL) {
391        HDF_LOGE("%s: buffer is null", __func__);
392        return DISPLAY_NULL_PTR;
393    }
394    if (devId != DEV_ID) {
395        HDF_LOGE("%s: devId invalid", __func__);
396        return DISPLAY_FAILURE;
397    }
398    if (layerId != LAYER_ID) {
399        HDF_LOGE("%s: layerId invalid", __func__);
400        return DISPLAY_FAILURE;
401    }
402    LockLayerMgr();
403    struct LayerPrivate *priv = GetLayerInstance();
404    if (priv->fd < 0) {
405        HDF_LOGE("%s: fd invalid", __func__);
406        UnlockLayerMgr();
407        return DISPLAY_FAILURE;
408    }
409    buffer->fenceId = 0;
410    buffer->width = priv->width;
411    buffer->height = priv->height;
412    buffer->pixFormat = priv->pixFmt;
413    buffer->pitch = priv->pitch;
414    buffer->data.virAddr = malloc(priv->fbSize);
415    if (buffer->data.virAddr == NULL) {
416        HDF_LOGE("%s: malloc failure", __func__);
417        UnlockLayerMgr();
418        return DISPLAY_FAILURE;
419    }
420    priv->layerAddr = buffer->data.virAddr;
421    (void)memset_s(buffer->data.virAddr, priv->fbSize, 0x00, priv->fbSize);
422    HDF_LOGD("%s: fenceId = %d, width = %d, height = %d, pixFormat = %d, pitch = %d", __func__, buffer->fenceId,
423        buffer->width, buffer->height, buffer->pixFormat, buffer->pitch);
424    UnlockLayerMgr();
425    return DISPLAY_SUCCESS;
426}
427
428int32_t LayerInitialize(LayerFuncs **funcs)
429{
430    static LayerFuncs *lFuncs = NULL;
431
432    if (funcs == NULL) {
433        HDF_LOGE("%s: funcs is null", __func__);
434        return DISPLAY_NULL_PTR;
435    }
436    if (lFuncs == NULL) {
437        lFuncs = (LayerFuncs *)OsalMemCalloc(sizeof(LayerFuncs));
438        if (lFuncs == NULL) {
439            HDF_LOGE("%s: lFuncs is null", __func__);
440            return DISPLAY_NULL_PTR;
441        }
442        pthread_mutexattr_init(&g_layerManager.mutexattr);
443        pthread_mutexattr_setpshared(&g_layerManager.mutexattr, PTHREAD_PROCESS_SHARED);
444        pthread_mutex_init(&g_layerManager.mutex, &g_layerManager.mutexattr);
445        lFuncs->InitDisplay = InitDisplay;
446        lFuncs->DeinitDisplay = DeinitDisplay;
447        lFuncs->GetDisplayInfo = GetDisplayInfo;
448        lFuncs->CreateLayer = CreateLayer;
449        lFuncs->CloseLayer = CloseLayer;
450        lFuncs->Flush = Flush;
451        lFuncs->GetLayerBuffer = GetLayerBuffer;
452    }
453    *funcs = lFuncs;
454    GetLayerMgr();
455    HDF_LOGI("%s: success", __func__);
456    return DISPLAY_SUCCESS;
457}
458
459int32_t LayerUninitialize(LayerFuncs *funcs)
460{
461    if (funcs == NULL) {
462        HDF_LOGE("%s: funcs is null", __func__);
463        return DISPLAY_NULL_PTR;
464    }
465    if (PutLayerMgr() == 0) {
466        pthread_mutexattr_destroy(&g_layerManager.mutexattr);
467        pthread_mutex_destroy(&g_layerManager.mutex);
468        OsalMemFree(funcs);
469    }
470    HDF_LOGI("%s: layer uninitialize success", __func__);
471    return DISPLAY_SUCCESS;
472}
473