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