1 /*
2  * Copyright 2021 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "fsl_display.h"
9 #include "fsl_hx8394.h"
10 
11 /*******************************************************************************
12  * Definitions
13  ******************************************************************************/
14 #define HX8394_DelayMs VIDEO_DelayMs
15 
16 typedef struct
17 {
18     const uint8_t *cmd;
19     uint8_t cmdLen;
20 } hx8394_cmd_t;
21 
22 /*******************************************************************************
23  * Variables
24  ******************************************************************************/
25 const display_operations_t hx8394_ops = {
26     .init   = HX8394_Init,
27     .deinit = HX8394_Deinit,
28     .start  = HX8394_Start,
29     .stop   = HX8394_Stop,
30 };
31 
32 static const hx8394_cmd_t s_hx8394Cmds[] = {
33     {(const uint8_t[]){0x36U, 0x02U}, 2U},
34 
35     {(const uint8_t[]){0xB1U, 0x48U, 0x12U, 0x72U, 0x09U, 0x32U, 0x54U, 0x71U, 0x71U, 0x57U, 0x47U}, 11U},
36 
37     {(const uint8_t[]){0xB2U, 0x00U, 0x80U, 0x64U, 0x0CU, 0x0DU, 0x2FU}, 7U},
38 
39     {(const uint8_t[]){0xB4U, 0x73U, 0x74U, 0x73U, 0x74U, 0x73U, 0x74U, 0x01U, 0x0CU, 0x86U, /* 10 */
40                        0x75U, 0x00U, 0x3FU, 0x73U, 0x74U, 0x73U, 0x74U, 0x73U, 0x74U, 0x01U, /* 20 */
41                        0x0CU, 0x86U},
42      22U},
43 
44     {(const uint8_t[]){0xD3U, 0x00U, 0x00U, 0x07U, 0x07U, 0x40U, 0x07U, 0x0CU, 0x00U, 0x08U, /* 10 */
45                        0x10U, 0x08U, 0x00U, 0x08U, 0x54U, 0x15U, 0x0AU, 0x05U, 0x0AU, 0x02U, /* 20 */
46                        0x15U, 0x06U, 0x05U, 0x06U, 0x47U, 0x44U, 0x0AU, 0x0AU, 0x4BU, 0x10U, /* 30 */
47                        0x07U, 0x07U, 0x0CU, 0x40U},
48      34U},
49 
50     {(const uint8_t[]){0xD5U, 0x1CU, 0x1CU, 0x1DU, 0x1DU, 0x00U, 0x01U, 0x02U, 0x03U, 0x04U, /* 10 */
51                        0x05U, 0x06U, 0x07U, 0x08U, 0x09U, 0x0AU, 0x0BU, 0x24U, 0x25U, 0x18U, /* 20 */
52                        0x18U, 0x26U, 0x27U, 0x18U, 0x18U, 0x18U, 0x18U, 0x18U, 0x18U, 0x18U, /* 30 */
53                        0x18U, 0x18U, 0x18U, 0x18U, 0x18U, 0x18U, 0x18U, 0x18U, 0x18U, 0x20U, /* 40 */
54                        0x21U, 0x18U, 0x18U, 0x18U, 0x18U},
55      45U},
56 
57     {(const uint8_t[]){0xD6U, 0x1CU, 0x1CU, 0x1DU, 0x1DU, 0x07U, 0x06U, 0x05U, 0x04U, 0x03U, /* 10 */
58                        0x02U, 0x01U, 0x00U, 0x0BU, 0x0AU, 0x09U, 0x08U, 0x21U, 0x20U, 0x18U, /* 20 */
59                        0x18U, 0x27U, 0x26U, 0x18U, 0x18U, 0x18U, 0x18U, 0x18U, 0x18U, 0x18U, /* 30 */
60                        0x18U, 0x18U, 0x18U, 0x18U, 0x18U, 0x18U, 0x18U, 0x18U, 0x18U, 0x25U, /* 40 */
61                        0x24U, 0x18U, 0x18U, 0x18U, 0x18U},
62      45U},
63 
64     {(const uint8_t[]){0xB6U, 0x92U, 0x92U}, 3U},
65 
66     {(const uint8_t[]){0xE0U, 0x00U, 0x0AU, 0x15U, 0x1BU, 0x1EU, 0x21U, 0x24U, 0x22U, 0x47U, /* 10 */
67                        0x56U, 0x65U, 0x66U, 0x6EU, 0x82U, 0x88U, 0x8BU, 0x9AU, 0x9DU, 0x98U, /* 20 */
68                        0xA8U, 0xB9U, 0x5DU, 0x5CU, 0x61U, 0x66U, 0x6AU, 0x6FU, 0x7FU, 0x7FU, /* 30 */
69                        0x00U, 0x0AU, 0x15U, 0x1BU, 0x1EU, 0x21U, 0x24U, 0x22U, 0x47U, 0x56U, /* 40 */
70                        0x65U, 0x65U, 0x6EU, 0x81U, 0x87U, 0x8BU, 0x98U, 0x9DU, 0x99U, 0xA8U, /* 50 */
71                        0xBAU, 0x5DU, 0x5DU, 0x62U, 0x67U, 0x6BU, 0x72U, 0x7FU, 0x7FU},
72      59U},
73 
74     {(const uint8_t[]){0xC0U, 0x1FU, 0x31U}, 3U},
75     {(const uint8_t[]){0xCCU, 0x03U}, 2U},
76     {(const uint8_t[]){0xD4U, 0x02U}, 2U},
77     {(const uint8_t[]){0xBDU, 0x02U}, 2U},
78 
79     {(const uint8_t[]){0xD8U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, /* 10 */
80                        0xFFU, 0xFFU, 0xFFU},
81      13U},
82 
83     {(const uint8_t[]){0xBDU, 0x00U}, 2U},
84     {(const uint8_t[]){0xBDU, 0x01U}, 2U},
85     {(const uint8_t[]){0xB1U, 0x00U}, 2U},
86     {(const uint8_t[]){0xBDU, 0x00U}, 2U},
87 
88     {(const uint8_t[]){0xBFU, 0x40U, 0x81U, 0x50U, 0x00U, 0x1AU, 0xFCU, 0x01}, 8U},
89 
90     {(const uint8_t[]){0xC6U, 0xEDU}, 2U},
91 
92     {(const uint8_t[]){0x35U, 0x00U}, 2U},
93 };
94 
95 /*******************************************************************************
96  * Code
97  ******************************************************************************/
98 
HX8394_Init(display_handle_t * handle,const display_config_t * config)99 status_t HX8394_Init(display_handle_t *handle, const display_config_t *config)
100 {
101     uint8_t i;
102     status_t status                   = kStatus_Success;
103     const hx8394_resource_t *resource = (const hx8394_resource_t *)(handle->resource);
104     mipi_dsi_device_t *dsiDevice      = resource->dsiDevice;
105     uint8_t setmipi[7]                = {0xBAU, 0x60U, 0x03U, 0x68U, 0x6BU, 0xB2U, 0xC0U};
106 
107     /* Only support 720 * 1280 */
108     if (config->resolution != FSL_VIDEO_RESOLUTION(720, 1280))
109     {
110         return kStatus_InvalidArgument;
111     }
112 
113     /* Power on. */
114     resource->pullPowerPin(true);
115     HX8394_DelayMs(1);
116 
117     /* Perform reset. */
118     resource->pullResetPin(false);
119     HX8394_DelayMs(1);
120     resource->pullResetPin(true);
121     HX8394_DelayMs(50U);
122 
123     status = MIPI_DSI_GenericWrite(dsiDevice, (const uint8_t[]){0xB9U, 0xFFU, 0x83U, 0x94U}, 4);
124 
125     setmipi[1] |= (config->dsiLanes - 1U);
126 
127     if (kStatus_Success == status)
128     {
129         status = MIPI_DSI_GenericWrite(dsiDevice, setmipi, 7);
130     }
131 
132     if (kStatus_Success == status)
133     {
134         for (i = 0; i < ARRAY_SIZE(s_hx8394Cmds); i++)
135         {
136             status = MIPI_DSI_GenericWrite(dsiDevice, s_hx8394Cmds[i].cmd, (int32_t)s_hx8394Cmds[i].cmdLen);
137 
138             if (kStatus_Success != status)
139             {
140                 break;
141             }
142         }
143     }
144 
145     if (kStatus_Success == status)
146     {
147         status = MIPI_DSI_DCS_EnterSleepMode(dsiDevice, false);
148     }
149 
150     if (kStatus_Success == status)
151     {
152         HX8394_DelayMs(120U);
153 
154         status = MIPI_DSI_DCS_SetDisplayOn(dsiDevice, true);
155     }
156 
157     return status;
158 }
159 
HX8394_Deinit(display_handle_t * handle)160 status_t HX8394_Deinit(display_handle_t *handle)
161 {
162     const hx8394_resource_t *resource = (const hx8394_resource_t *)(handle->resource);
163     mipi_dsi_device_t *dsiDevice      = resource->dsiDevice;
164 
165     (void)MIPI_DSI_DCS_EnterSleepMode(dsiDevice, true);
166 
167     resource->pullResetPin(false);
168     resource->pullPowerPin(false);
169 
170     return kStatus_Success;
171 }
172 
HX8394_Start(display_handle_t * handle)173 status_t HX8394_Start(display_handle_t *handle)
174 {
175     const hx8394_resource_t *resource = (const hx8394_resource_t *)(handle->resource);
176     mipi_dsi_device_t *dsiDevice      = resource->dsiDevice;
177 
178     return MIPI_DSI_DCS_SetDisplayOn(dsiDevice, true);
179 }
180 
HX8394_Stop(display_handle_t * handle)181 status_t HX8394_Stop(display_handle_t *handle)
182 {
183     const hx8394_resource_t *resource = (const hx8394_resource_t *)(handle->resource);
184     mipi_dsi_device_t *dsiDevice      = resource->dsiDevice;
185 
186     return MIPI_DSI_DCS_SetDisplayOn(dsiDevice, false);
187 }
188