1 /*
2 * Copyright (c) 2022 Beijing OSWare Technology Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include <drm/drm_mipi_dsi.h>
10 #include <video/mipi_display.h>
11 #include <linux/of.h>
12 #include "hdf_base.h"
13 #include "hdf_device_desc.h"
14 #include "hdf_log.h"
15 #include "mipi_dsi_core.h"
16 #include "mipi_dsi_if.h"
17 #include "osal_time.h"
18
19 #define HDF_LOG_TAG mipi_drm_adapter
20
GetLinuxPanel(const struct MipiDsiCntlr * cntlr)21 static struct mipi_dsi_device *GetLinuxPanel(const struct MipiDsiCntlr *cntlr)
22 {
23 if (cntlr == NULL) {
24 HDF_LOGE("%s: dev is NULL!", __func__);
25 return NULL;
26 }
27 if (cntlr->devNo >= MAX_CNTLR_CNT) {
28 HDF_LOGE("%s: dev is NULL!", __func__);
29 return NULL;
30 }
31
32 return (struct mipi_dsi_device *)cntlr->priv;
33 }
34
MipiDsiAdapterSetConfig(struct MipiDsiCntlr * cntlr)35 static int32_t MipiDsiAdapterSetConfig(struct MipiDsiCntlr *cntlr)
36 {
37 (void)cntlr;
38 return HDF_SUCCESS;
39 }
40
41 // "toshiba,panel-tc358775"
MipiDsiAdapterAttach(struct MipiDsiCntlr * cntlr,uint8_t * name)42 static int32_t MipiDsiAdapterAttach(struct MipiDsiCntlr *cntlr, uint8_t *name)
43 {
44 int32_t ret = 0;
45 struct device_node *panelNode = NULL;
46 struct mipi_dsi_device *linuxPanel = NULL;
47
48 if ((cntlr == NULL) || (name == NULL)) {
49 HDF_LOGE("%s: cntlr or name is NULL!", __func__);
50 return HDF_ERR_INVALID_PARAM;
51 }
52 if (cntlr->devNo >= MAX_CNTLR_CNT) {
53 HDF_LOGE("%s: cntlr->devNo is erro!", __func__);
54 return HDF_ERR_INVALID_PARAM;
55 }
56
57 panelNode = of_find_compatible_node(NULL, NULL, name);
58 if (panelNode == NULL) {
59 HDF_LOGE("%s: [of_find_compatible_node] failed!", __func__);
60 return HDF_FAILURE;
61 }
62 linuxPanel = of_find_mipi_dsi_device_by_node(panelNode);
63 if (linuxPanel == NULL) {
64 HDF_LOGE("%s: [of_find_mipi_dsi_device_by_node] failed!", __func__);
65 return HDF_FAILURE;
66 }
67 ret = mipi_dsi_attach(linuxPanel);
68 if (ret < 0) {
69 HDF_LOGE("%s: mipi_dsi_attach failed.", __func__);
70 return HDF_FAILURE;
71 }
72 cntlr->priv = (DevHandle)linuxPanel;
73
74 return HDF_SUCCESS;
75 }
76
77 extern void hdf_drm_mode_to_videomode(void);
MipiDsiAdapterSetCmd(struct MipiDsiCntlr * cntlr,struct DsiCmdDesc * cmd)78 static int32_t MipiDsiAdapterSetCmd(struct MipiDsiCntlr *cntlr, struct DsiCmdDesc *cmd)
79 {
80 int32_t ret = 0;
81 struct mipi_dsi_device *linuxPanel = NULL;
82
83 if (cntlr == NULL || cmd == NULL) {
84 HDF_LOGE("%s: cntlr or cmd is NULL.", __func__);
85 return HDF_ERR_INVALID_OBJECT;
86 }
87 linuxPanel = GetLinuxPanel(cntlr);
88 if (linuxPanel == NULL) {
89 HDF_LOGE("%s: linuxPanel is NULL!", __func__);
90 return HDF_ERR_INVALID_OBJECT;
91 }
92
93 if (cmd->payload == NULL) {
94 HDF_LOGE("%s: payload is NULL!", __func__);
95 return HDF_ERR_INVALID_OBJECT;
96 }
97
98 hdf_drm_mode_to_videomode();
99 if ((cmd->dataType == MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM) || // 0x13,
100 (cmd->dataType == MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM) || // 0x23
101 (cmd->dataType == MIPI_DSI_GENERIC_LONG_WRITE)) { // 0x29
102 ret = mipi_dsi_generic_write(linuxPanel, cmd->payload, cmd->dataLen);
103 if (ret < 0) {
104 HDF_LOGE("%s: [mipi_dsi_generic_write] failed.", __func__);
105 return HDF_FAILURE;
106 }
107 } else if ((cmd->dataType == MIPI_DSI_DCS_SHORT_WRITE) || // 0x05
108 (cmd->dataType == MIPI_DSI_DCS_SHORT_WRITE_PARAM) || // 0x15
109 (cmd->dataType == MIPI_DSI_DCS_LONG_WRITE)) { // 0x39
110 ret = mipi_dsi_dcs_write_buffer(linuxPanel, cmd->payload, cmd->dataLen);
111 HDF_LOGE("%s: [mipi_dsi_dcs_write_buffer] dataType = 0x%x, payload = 0x%x, dataLen = 0x%x",
112 __func__, cmd->dataType, cmd->payload[0], cmd->dataLen);
113 if (ret < 0) {
114 HDF_LOGE("%s: [mipi_dsi_dcs_write_buffer] failed. ret = %d", __func__, ret);
115 return HDF_FAILURE;
116 }
117 } else {
118 if (cmd->dataLen == 0) {
119 cmd->payload = NULL;
120 }
121 ret = mipi_dsi_dcs_write(linuxPanel, cmd->dataType, cmd->payload, cmd->dataLen);
122 HDF_LOGE("%s: [mipi_dsi_dcs_write] dataType = 0x%x, dataLen = 0x%x",
123 __func__, cmd->dataType, cmd->dataLen);
124 if (ret < 0) {
125 HDF_LOGE("%s: [mipi_dsi_dcs_write] failed.", __func__);
126 return HDF_FAILURE;
127 }
128 }
129
130 if (cmd->delay > 0) {
131 OsalMDelay(cmd->delay);
132 }
133
134 return HDF_SUCCESS;
135 }
136
137 static struct MipiDsiCntlr g_mipiTx = {
138 .devNo = 0
139 };
140
141 static struct MipiDsiCntlrMethod g_method = {
142 .setCntlrCfg = MipiDsiAdapterSetConfig,
143 .setCmd = MipiDsiAdapterSetCmd,
144 .getCmd = NULL,
145 .toHs = NULL,
146 .toLp = NULL,
147 .enterUlps = NULL,
148 .exitUlps = NULL,
149 .powerControl = NULL,
150 .attach = MipiDsiAdapterAttach,
151 };
152
MipiDsiAdapterBind(struct HdfDeviceObject * device)153 static int32_t MipiDsiAdapterBind(struct HdfDeviceObject *device)
154 {
155 int32_t ret = 0;
156
157 if (device == NULL) {
158 HDF_LOGE("%s: device is NULL!", __func__);
159 return HDF_ERR_INVALID_OBJECT;
160 }
161
162 HDF_LOGI("%s: enter.", __func__);
163 g_mipiTx.priv = NULL;
164 g_mipiTx.ops = &g_method;
165 ret = MipiDsiRegisterCntlr(&g_mipiTx, device);
166 if (ret != HDF_SUCCESS) {
167 HDF_LOGE("%s: [MipiDsiRegisterCntlr] failed.", __func__);
168 return ret;
169 }
170 HDF_LOGI("%s: success.", __func__);
171
172 return HDF_SUCCESS;
173 }
174
MipiDsiAdapterInit(struct HdfDeviceObject * device)175 static int32_t MipiDsiAdapterInit(struct HdfDeviceObject *device)
176 {
177 (void)device;
178
179 HDF_LOGI("%s: success.", __func__);
180 return HDF_SUCCESS;
181 }
182
MipiDsiAdapterRelease(struct HdfDeviceObject * device)183 static void MipiDsiAdapterRelease(struct HdfDeviceObject *device)
184 {
185 struct MipiDsiCntlr *cntlr = NULL;
186
187 if (device == NULL) {
188 HDF_LOGE("%s: device is NULL.", __func__);
189 return;
190 }
191 cntlr = MipiDsiCntlrFromDevice(device);
192 if (cntlr == NULL) {
193 HDF_LOGE("%s: cntlr is NULL.", __func__);
194 return;
195 }
196 MipiDsiUnregisterCntlr(cntlr);
197 cntlr->priv = NULL;
198
199 HDF_LOGI("%s: success.", __func__);
200 }
201
202 struct HdfDriverEntry g_mipiDsiLinuxDriverEntry = {
203 .moduleVersion = 1,
204 .Bind = MipiDsiAdapterBind,
205 .Init = MipiDsiAdapterInit,
206 .Release = MipiDsiAdapterRelease,
207 .moduleName = "linux_mipi_drm_adapter",
208 };
209 HDF_INIT(g_mipiDsiLinuxDriverEntry);
210