• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020-2021 Huawei Device 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 "hdf_drm_panel.h"
10 #include <drm/drmP.h>
11 #include <drm/drm_atomic_helper.h>
12 #include <linux/backlight.h>
13 #include <linux/module.h>
14 #include <linux/of.h>
15 #include <linux/of_gpio.h>
16 #include <linux/pm_runtime.h>
17 #include <linux/regulator/consumer.h>
18 #include <video/mipi_display.h>
19 #include <video/of_display_timing.h>
20 #include <video/videomode.h>
21 #include "osal_mem.h"
22 
ToHdfDrmPanel(const struct drm_panel * panel)23 static inline struct HdfDrmPanel *ToHdfDrmPanel(const struct drm_panel *panel)
24 {
25     return container_of(panel, struct HdfDrmPanel, panel);
26 }
27 
HdfDrmPanelUnprepare(struct drm_panel * panel)28 static int HdfDrmPanelUnprepare(struct drm_panel *panel)
29 {
30     return 0;
31 }
32 
HdfDrmPanelPrepare(struct drm_panel * panel)33 static int HdfDrmPanelPrepare(struct drm_panel *panel)
34 {
35     return 0;
36 }
37 
HdfDrmPanelDisable(struct drm_panel * panel)38 static int HdfDrmPanelDisable(struct drm_panel *panel)
39 {
40     struct HdfDrmPanel *hdfDrmPanel = ToHdfDrmPanel(panel);
41     struct PanelData *panelData;
42 
43     HDF_LOGD("%s line = %d\n", __func__, __LINE__);
44     OsalMutexLock(&hdfDrmPanel->manager->dispMutex);
45     panelData = hdfDrmPanel->manager->panelManager->panel[hdfDrmPanel->index];
46     panelData->off(panelData);
47     OsalMutexUnlock(&hdfDrmPanel->manager->dispMutex);
48     return HDF_SUCCESS;
49 }
50 
HdfDrmPanelEnable(struct drm_panel * panel)51 static int HdfDrmPanelEnable(struct drm_panel *panel)
52 {
53     struct HdfDrmPanel *hdfDrmPanel = ToHdfDrmPanel(panel);
54     struct PanelData *panelData;
55 
56     HDF_LOGD("%s line = %d\n", __func__, __LINE__);
57     panelData = hdfDrmPanel->manager->panelManager->panel[hdfDrmPanel->index];
58     OsalMutexLock(&hdfDrmPanel->manager->dispMutex);
59     panelData->on(panelData);
60     OsalMutexUnlock(&hdfDrmPanel->manager->dispMutex);
61     return HDF_SUCCESS;
62 }
63 
HdfDrmPanelGetModes(struct drm_panel * panel)64 static int HdfDrmPanelGetModes(struct drm_panel *panel)
65 {
66     struct drm_connector *connector = panel->connector;
67     struct HdfDrmPanel *hdfDrmPanel = ToHdfDrmPanel(panel);
68     struct drm_display_mode *mode = NULL;
69     struct PanelInfo *panelInfo = NULL;
70 
71     HDF_LOGD("%s line = %d\n", __func__, __LINE__);
72     panelInfo = hdfDrmPanel->manager->panelManager->panel[hdfDrmPanel->index]->info;
73     mode = drm_mode_duplicate(panel->drm, &hdfDrmPanel->mode);
74     if (!mode) {
75         HDF_LOGE("failed to add mode %ux%ux@%u",
76             hdfDrmPanel->mode.hdisplay, hdfDrmPanel->mode.vdisplay,
77             hdfDrmPanel->mode.vrefresh);
78         return -ENOMEM;
79     }
80     drm_mode_set_name(mode);
81     mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
82     drm_mode_probed_add(connector, mode);
83     connector->display_info.width_mm = panelInfo->pWidth;
84     connector->display_info.height_mm = panelInfo->pHeight;
85     return 1;
86 }
87 
88 static struct drm_panel_funcs g_hdfDrmPanelFuncs = {
89     .get_modes = HdfDrmPanelGetModes,
90     .enable = HdfDrmPanelEnable,
91     .disable = HdfDrmPanelDisable,
92     .prepare = HdfDrmPanelPrepare,
93     .unprepare = HdfDrmPanelUnprepare,
94 };
95 
SuspendStore(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)96 static ssize_t SuspendStore(struct device *dev,
97     struct device_attribute *attr, const char *buf, size_t count)
98 {
99     int32_t ret;
100     struct HdfDrmPanel *hdfDrmPanel = dev_get_drvdata(dev);
101 
102     ret = HdfDrmPanelDisable(&hdfDrmPanel->panel);
103     if (ret != HDF_SUCCESS) {
104         HDF_LOGE("%s HdfDrmPanelDisable fail", __func__);
105         return count;
106     }
107     ret = HdfDrmPanelUnprepare(&hdfDrmPanel->panel);
108     if (ret != HDF_SUCCESS) {
109         HDF_LOGE("%s HdfDrmPanelUnprepare fail", __func__);
110         return count;
111     }
112     return count;
113 }
114 static DEVICE_ATTR(suspend, S_IWUSR, NULL, SuspendStore);
115 
ResumeStore(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)116 static ssize_t ResumeStore(struct device *dev,
117     struct device_attribute *attr, const char *buf, size_t count)
118 {
119     int32_t ret;
120     struct HdfDrmPanel *hdfDrmPanel = dev_get_drvdata(dev);
121 
122     ret = HdfDrmPanelPrepare(&hdfDrmPanel->panel);
123     if (ret != HDF_SUCCESS) {
124         HDF_LOGE("%s HdfDrmPanelPrepare fail", __func__);
125         return count;
126     }
127     ret = HdfDrmPanelEnable(&hdfDrmPanel->panel);
128     if (ret != HDF_SUCCESS) {
129         HDF_LOGE("%s HdfDrmPanelEnable fail", __func__);
130         return count;
131     }
132     return count;
133 }
134 static DEVICE_ATTR(resume, S_IWUSR, NULL, ResumeStore);
135 
BacklightStore(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)136 static ssize_t BacklightStore(struct device *dev,
137     struct device_attribute *attr, const char *buf, size_t count)
138 {
139     int32_t ret;
140     unsigned long level;
141     struct PanelData *panel = NULL;
142     struct HdfDrmPanel *hdfDrmPanel = dev_get_drvdata(dev);
143 
144     ret = kstrtoul(buf, 0, &level);
145     if (ret != 0) {
146         return ret;
147     }
148     HDF_LOGI("%s enter", __func__);
149     OsalMutexLock(&hdfDrmPanel->manager->dispMutex);
150     panel = hdfDrmPanel->manager->panelManager->panel[hdfDrmPanel->index];
151     OsalMutexUnlock(&hdfDrmPanel->manager->dispMutex);
152     ret = UpdateBrightness(panel->blDev, level);
153     if (ret != HDF_SUCCESS) {
154         HDF_LOGE("%s UpdateBrightness fail", __func__);
155     }
156 
157     return count;
158 }
159 static DEVICE_ATTR(backlight, S_IWUSR, NULL, BacklightStore);
160 
161 #define ATTR_NUM  3
162 static struct device_attribute *g_panelAttrs[] = {
163     &dev_attr_suspend,
164     &dev_attr_resume,
165     &dev_attr_backlight,
166     NULL,
167 };
168 
CreateDrmMode(struct HdfDrmPanel * hdfDrmPanel)169 static void CreateDrmMode(struct HdfDrmPanel *hdfDrmPanel)
170 {
171     uint32_t panelIndex;
172     struct PanelInfo *panelInfo = NULL;
173 
174     panelIndex = hdfDrmPanel->index;
175     panelInfo = hdfDrmPanel->manager->panelManager->panel[panelIndex]->info;
176     hdfDrmPanel->mode.clock = panelInfo->clockFreq / 1000;
177     hdfDrmPanel->mode.hdisplay = panelInfo->width;
178     hdfDrmPanel->mode.hsync_start = panelInfo->width + panelInfo->hfp;
179     hdfDrmPanel->mode.hsync_end = panelInfo->width + panelInfo->hfp + panelInfo->hsw;
180     hdfDrmPanel->mode.htotal = panelInfo->width + panelInfo->hfp + panelInfo->hsw + panelInfo->hbp;
181     hdfDrmPanel->mode.vdisplay = panelInfo->height;
182     hdfDrmPanel->mode.vsync_start = panelInfo->height + panelInfo->vfp;
183     hdfDrmPanel->mode.vsync_end = panelInfo->height + panelInfo->vfp + panelInfo->vsw;
184     hdfDrmPanel->mode.vtotal = panelInfo->height + panelInfo->vfp + panelInfo->vsw + panelInfo->vbp;
185     hdfDrmPanel->mode.flags = 0;
186     hdfDrmPanel->mode.vrefresh = drm_mode_vrefresh(&hdfDrmPanel->mode);
187 }
188 
InstanceHdfDrmPanel(struct DispManager * manager,int32_t index)189 static struct HdfDrmPanel *InstanceHdfDrmPanel(struct DispManager *manager, int32_t index)
190 {
191     struct HdfDrmPanel *hdfDrmPanel = NULL;
192 
193     hdfDrmPanel = (struct HdfDrmPanel *)OsalMemCalloc(sizeof(struct HdfDrmPanel));
194     if (hdfDrmPanel == NULL) {
195         HDF_LOGE("%s hdfDrmPanel malloc fail", __func__);
196         return NULL;
197     }
198     hdfDrmPanel->index = index;
199     hdfDrmPanel->manager = manager;
200     CreateDrmMode(hdfDrmPanel);
201     hdfDrmPanel->panel.funcs = &g_hdfDrmPanelFuncs;
202     return hdfDrmPanel;
203 }
204 
HdfDrmPanelEntryInit(struct HdfDeviceObject * object)205 int32_t HdfDrmPanelEntryInit(struct HdfDeviceObject *object)
206 {
207     uint32_t ret;
208     uint32_t panelNum;
209     struct HdfDrmPanel *hdfDrmPanel = NULL;
210     struct mipi_dsi_device *dsiDev = NULL;
211     struct DispManager *manager = NULL;
212 
213     manager = GetDispManager();
214     if (manager == NULL) {
215         HDF_LOGE("%s manager is null", __func__);
216         return HDF_FAILURE;
217     }
218     panelNum = manager->panelManager->panelNum;
219     for (uint32_t i = 0; i < panelNum; i++) {
220         hdfDrmPanel = InstanceHdfDrmPanel(manager, i);
221         if (hdfDrmPanel == NULL) {
222             return HDF_FAILURE;
223         }
224         dsiDev = (struct mipi_dsi_device *)manager->panelManager->panel[i]->priv;
225         hdfDrmPanel->panel.dev = &dsiDev->dev;
226         drm_panel_init(&hdfDrmPanel->panel);
227         ret = drm_panel_add(&hdfDrmPanel->panel);
228         if (ret) {
229             HDF_LOGE("%s drm_panel_add() failed", __func__);
230             return ret;
231         }
232         ret = mipi_dsi_attach(dsiDev);
233         if (ret) {
234             HDF_LOGE("%s mipi_dsi_attach failed", __func__);
235             drm_panel_remove(&hdfDrmPanel->panel);
236             return ret;
237         }
238         mipi_dsi_set_drvdata(dsiDev, hdfDrmPanel);
239         for (uint32_t j = 0; j < ATTR_NUM; j++) {
240             if (device_create_file(&dsiDev->dev, g_panelAttrs[j]) != 0) {
241                 HDF_LOGE("%s line = %d device_create_file fail", __func__, __LINE__);
242             }
243         }
244         HDF_LOGI("%s panel[%d] registered success", i, __func__);
245     }
246     HDF_LOGI("%s success", __func__);
247     return HDF_SUCCESS;
248 }
249 
250 struct HdfDriverEntry g_hdfDrmPanelEntry = {
251     .moduleVersion = 1,
252     .moduleName = "HDF_DRMPANEL",
253     .Init = HdfDrmPanelEntryInit,
254 };
255 
256 HDF_INIT(g_hdfDrmPanelEntry);
257