1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Hisilicon Hibmc SoC drm driver
3 *
4 * Based on the bochs drm driver.
5 *
6 * Copyright (c) 2016 Huawei Limited.
7 *
8 * Author:
9 * Rongrong Zou <zourongrong@huawei.com>
10 * Rongrong Zou <zourongrong@gmail.com>
11 * Jianhua Li <lijianhua@huawei.com>
12 */
13
14 #include <linux/aperture.h>
15 #include <linux/module.h>
16 #include <linux/pci.h>
17
18 #include <drm/clients/drm_client_setup.h>
19 #include <drm/drm_atomic_helper.h>
20 #include <drm/drm_drv.h>
21 #include <drm/drm_fbdev_ttm.h>
22 #include <drm/drm_gem_framebuffer_helper.h>
23 #include <drm/drm_gem_vram_helper.h>
24 #include <drm/drm_managed.h>
25 #include <drm/drm_module.h>
26 #include <drm/drm_vblank.h>
27
28 #include "hibmc_drm_drv.h"
29 #include "hibmc_drm_regs.h"
30
31 #define HIBMC_DP_HOST_SERDES_CTRL 0x1f001c
32 #define HIBMC_DP_HOST_SERDES_CTRL_VAL 0x8a00
33 #define HIBMC_DP_HOST_SERDES_CTRL_MASK 0x7ffff
34
35 DEFINE_DRM_GEM_FOPS(hibmc_fops);
36
hibmc_interrupt(int irq,void * arg)37 static irqreturn_t hibmc_interrupt(int irq, void *arg)
38 {
39 struct drm_device *dev = (struct drm_device *)arg;
40 struct hibmc_drm_private *priv = to_hibmc_drm_private(dev);
41 u32 status;
42
43 status = readl(priv->mmio + HIBMC_RAW_INTERRUPT);
44
45 if (status & HIBMC_RAW_INTERRUPT_VBLANK(1)) {
46 writel(HIBMC_RAW_INTERRUPT_VBLANK(1),
47 priv->mmio + HIBMC_RAW_INTERRUPT);
48 drm_handle_vblank(dev, 0);
49 }
50
51 return IRQ_HANDLED;
52 }
53
hibmc_dumb_create(struct drm_file * file,struct drm_device * dev,struct drm_mode_create_dumb * args)54 static int hibmc_dumb_create(struct drm_file *file, struct drm_device *dev,
55 struct drm_mode_create_dumb *args)
56 {
57 return drm_gem_vram_fill_create_dumb(file, dev, 0, 128, args);
58 }
59
60 static const struct drm_driver hibmc_driver = {
61 .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
62 .fops = &hibmc_fops,
63 .name = "hibmc",
64 .desc = "hibmc drm driver",
65 .major = 1,
66 .minor = 0,
67 .debugfs_init = drm_vram_mm_debugfs_init,
68 .dumb_create = hibmc_dumb_create,
69 .dumb_map_offset = drm_gem_ttm_dumb_map_offset,
70 DRM_FBDEV_TTM_DRIVER_OPS,
71 };
72
hibmc_pm_suspend(struct device * dev)73 static int __maybe_unused hibmc_pm_suspend(struct device *dev)
74 {
75 struct drm_device *drm_dev = dev_get_drvdata(dev);
76
77 return drm_mode_config_helper_suspend(drm_dev);
78 }
79
hibmc_pm_resume(struct device * dev)80 static int __maybe_unused hibmc_pm_resume(struct device *dev)
81 {
82 struct drm_device *drm_dev = dev_get_drvdata(dev);
83
84 return drm_mode_config_helper_resume(drm_dev);
85 }
86
87 static const struct dev_pm_ops hibmc_pm_ops = {
88 SET_SYSTEM_SLEEP_PM_OPS(hibmc_pm_suspend,
89 hibmc_pm_resume)
90 };
91
92 static const struct drm_mode_config_funcs hibmc_mode_funcs = {
93 .mode_valid = drm_vram_helper_mode_valid,
94 .atomic_check = drm_atomic_helper_check,
95 .atomic_commit = drm_atomic_helper_commit,
96 .fb_create = drm_gem_fb_create,
97 };
98
hibmc_kms_init(struct hibmc_drm_private * priv)99 static int hibmc_kms_init(struct hibmc_drm_private *priv)
100 {
101 struct drm_device *dev = &priv->dev;
102 int ret;
103
104 ret = drmm_mode_config_init(dev);
105 if (ret)
106 return ret;
107
108 dev->mode_config.min_width = 0;
109 dev->mode_config.min_height = 0;
110 dev->mode_config.max_width = 1920;
111 dev->mode_config.max_height = 1200;
112
113 dev->mode_config.preferred_depth = 24;
114 dev->mode_config.prefer_shadow = 1;
115
116 dev->mode_config.funcs = (void *)&hibmc_mode_funcs;
117
118 ret = hibmc_de_init(priv);
119 if (ret) {
120 drm_err(dev, "failed to init de: %d\n", ret);
121 return ret;
122 }
123
124 /* if DP existed, init DP */
125 if ((readl(priv->mmio + HIBMC_DP_HOST_SERDES_CTRL) &
126 HIBMC_DP_HOST_SERDES_CTRL_MASK) == HIBMC_DP_HOST_SERDES_CTRL_VAL) {
127 ret = hibmc_dp_init(priv);
128 if (ret)
129 drm_err(dev, "failed to init dp: %d\n", ret);
130 }
131
132 ret = hibmc_vdac_init(priv);
133 if (ret) {
134 drm_err(dev, "failed to init vdac: %d\n", ret);
135 return ret;
136 }
137
138 return 0;
139 }
140
141 /*
142 * It can operate in one of three modes: 0, 1 or Sleep.
143 */
hibmc_set_power_mode(struct hibmc_drm_private * priv,u32 power_mode)144 void hibmc_set_power_mode(struct hibmc_drm_private *priv, u32 power_mode)
145 {
146 u32 control_value = 0;
147 void __iomem *mmio = priv->mmio;
148 u32 input = 1;
149
150 if (power_mode > HIBMC_PW_MODE_CTL_MODE_SLEEP)
151 return;
152
153 if (power_mode == HIBMC_PW_MODE_CTL_MODE_SLEEP)
154 input = 0;
155
156 control_value = readl(mmio + HIBMC_POWER_MODE_CTRL);
157 control_value &= ~(HIBMC_PW_MODE_CTL_MODE_MASK |
158 HIBMC_PW_MODE_CTL_OSC_INPUT_MASK);
159 control_value |= HIBMC_FIELD(HIBMC_PW_MODE_CTL_MODE, power_mode);
160 control_value |= HIBMC_FIELD(HIBMC_PW_MODE_CTL_OSC_INPUT, input);
161 writel(control_value, mmio + HIBMC_POWER_MODE_CTRL);
162 }
163
hibmc_set_current_gate(struct hibmc_drm_private * priv,unsigned int gate)164 void hibmc_set_current_gate(struct hibmc_drm_private *priv, unsigned int gate)
165 {
166 u32 gate_reg;
167 u32 mode;
168 void __iomem *mmio = priv->mmio;
169
170 /* Get current power mode. */
171 mode = (readl(mmio + HIBMC_POWER_MODE_CTRL) &
172 HIBMC_PW_MODE_CTL_MODE_MASK) >> HIBMC_PW_MODE_CTL_MODE_SHIFT;
173
174 switch (mode) {
175 case HIBMC_PW_MODE_CTL_MODE_MODE0:
176 gate_reg = HIBMC_MODE0_GATE;
177 break;
178
179 case HIBMC_PW_MODE_CTL_MODE_MODE1:
180 gate_reg = HIBMC_MODE1_GATE;
181 break;
182
183 default:
184 gate_reg = HIBMC_MODE0_GATE;
185 break;
186 }
187 writel(gate, mmio + gate_reg);
188 }
189
hibmc_hw_config(struct hibmc_drm_private * priv)190 static void hibmc_hw_config(struct hibmc_drm_private *priv)
191 {
192 u32 reg;
193
194 /* On hardware reset, power mode 0 is default. */
195 hibmc_set_power_mode(priv, HIBMC_PW_MODE_CTL_MODE_MODE0);
196
197 /* Enable display power gate & LOCALMEM power gate*/
198 reg = readl(priv->mmio + HIBMC_CURRENT_GATE);
199 reg &= ~HIBMC_CURR_GATE_DISPLAY_MASK;
200 reg &= ~HIBMC_CURR_GATE_LOCALMEM_MASK;
201 reg |= HIBMC_CURR_GATE_DISPLAY(1);
202 reg |= HIBMC_CURR_GATE_LOCALMEM(1);
203
204 hibmc_set_current_gate(priv, reg);
205
206 /*
207 * Reset the memory controller. If the memory controller
208 * is not reset in chip,the system might hang when sw accesses
209 * the memory.The memory should be resetted after
210 * changing the MXCLK.
211 */
212 reg = readl(priv->mmio + HIBMC_MISC_CTRL);
213 reg &= ~HIBMC_MSCCTL_LOCALMEM_RESET_MASK;
214 reg |= HIBMC_MSCCTL_LOCALMEM_RESET(0);
215 writel(reg, priv->mmio + HIBMC_MISC_CTRL);
216
217 reg &= ~HIBMC_MSCCTL_LOCALMEM_RESET_MASK;
218 reg |= HIBMC_MSCCTL_LOCALMEM_RESET(1);
219
220 writel(reg, priv->mmio + HIBMC_MISC_CTRL);
221 }
222
hibmc_hw_map(struct hibmc_drm_private * priv)223 static int hibmc_hw_map(struct hibmc_drm_private *priv)
224 {
225 struct drm_device *dev = &priv->dev;
226 struct pci_dev *pdev = to_pci_dev(dev->dev);
227 resource_size_t ioaddr, iosize;
228
229 ioaddr = pci_resource_start(pdev, 1);
230 iosize = pci_resource_len(pdev, 1);
231 priv->mmio = devm_ioremap(dev->dev, ioaddr, iosize);
232 if (!priv->mmio) {
233 drm_err(dev, "Cannot map mmio region\n");
234 return -ENOMEM;
235 }
236
237 return 0;
238 }
239
hibmc_hw_init(struct hibmc_drm_private * priv)240 static int hibmc_hw_init(struct hibmc_drm_private *priv)
241 {
242 int ret;
243
244 ret = hibmc_hw_map(priv);
245 if (ret)
246 return ret;
247
248 hibmc_hw_config(priv);
249
250 return 0;
251 }
252
hibmc_unload(struct drm_device * dev)253 static int hibmc_unload(struct drm_device *dev)
254 {
255 struct pci_dev *pdev = to_pci_dev(dev->dev);
256
257 drm_atomic_helper_shutdown(dev);
258
259 free_irq(pdev->irq, dev);
260
261 pci_disable_msi(to_pci_dev(dev->dev));
262
263 return 0;
264 }
265
hibmc_load(struct drm_device * dev)266 static int hibmc_load(struct drm_device *dev)
267 {
268 struct pci_dev *pdev = to_pci_dev(dev->dev);
269 struct hibmc_drm_private *priv = to_hibmc_drm_private(dev);
270 int ret;
271
272 ret = hibmc_hw_init(priv);
273 if (ret)
274 goto err;
275
276 ret = drmm_vram_helper_init(dev, pci_resource_start(pdev, 0),
277 pci_resource_len(pdev, 0));
278 if (ret) {
279 drm_err(dev, "Error initializing VRAM MM; %d\n", ret);
280 goto err;
281 }
282
283 ret = hibmc_kms_init(priv);
284 if (ret)
285 goto err;
286
287 ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
288 if (ret) {
289 drm_err(dev, "failed to initialize vblank: %d\n", ret);
290 goto err;
291 }
292
293 ret = pci_enable_msi(pdev);
294 if (ret) {
295 drm_warn(dev, "enabling MSI failed: %d\n", ret);
296 } else {
297 /* PCI devices require shared interrupts. */
298 ret = request_irq(pdev->irq, hibmc_interrupt, IRQF_SHARED,
299 dev->driver->name, dev);
300 if (ret)
301 drm_warn(dev, "install irq failed: %d\n", ret);
302 }
303
304 /* reset all the states of crtc/plane/encoder/connector */
305 drm_mode_config_reset(dev);
306
307 return 0;
308
309 err:
310 hibmc_unload(dev);
311 drm_err(dev, "failed to initialize drm driver: %d\n", ret);
312 return ret;
313 }
314
hibmc_pci_probe(struct pci_dev * pdev,const struct pci_device_id * ent)315 static int hibmc_pci_probe(struct pci_dev *pdev,
316 const struct pci_device_id *ent)
317 {
318 struct hibmc_drm_private *priv;
319 struct drm_device *dev;
320 int ret;
321
322 ret = aperture_remove_conflicting_pci_devices(pdev, hibmc_driver.name);
323 if (ret)
324 return ret;
325
326 priv = devm_drm_dev_alloc(&pdev->dev, &hibmc_driver,
327 struct hibmc_drm_private, dev);
328 if (IS_ERR(priv)) {
329 DRM_ERROR("failed to allocate drm_device\n");
330 return PTR_ERR(priv);
331 }
332
333 dev = &priv->dev;
334 pci_set_drvdata(pdev, dev);
335
336 ret = pcim_enable_device(pdev);
337 if (ret) {
338 drm_err(dev, "failed to enable pci device: %d\n", ret);
339 goto err_return;
340 }
341
342 pci_set_master(pdev);
343
344 ret = hibmc_load(dev);
345 if (ret) {
346 drm_err(dev, "failed to load hibmc: %d\n", ret);
347 goto err_return;
348 }
349
350 ret = drm_dev_register(dev, 0);
351 if (ret) {
352 drm_err(dev, "failed to register drv for userspace access: %d\n",
353 ret);
354 goto err_unload;
355 }
356
357 drm_client_setup(dev, NULL);
358
359 return 0;
360
361 err_unload:
362 hibmc_unload(dev);
363 err_return:
364 return ret;
365 }
366
hibmc_pci_remove(struct pci_dev * pdev)367 static void hibmc_pci_remove(struct pci_dev *pdev)
368 {
369 struct drm_device *dev = pci_get_drvdata(pdev);
370
371 drm_dev_unregister(dev);
372 hibmc_unload(dev);
373 }
374
hibmc_pci_shutdown(struct pci_dev * pdev)375 static void hibmc_pci_shutdown(struct pci_dev *pdev)
376 {
377 drm_atomic_helper_shutdown(pci_get_drvdata(pdev));
378 }
379
380 static const struct pci_device_id hibmc_pci_table[] = {
381 { PCI_VDEVICE(HUAWEI, 0x1711) },
382 {0,}
383 };
384
385 static struct pci_driver hibmc_pci_driver = {
386 .name = "hibmc-drm",
387 .id_table = hibmc_pci_table,
388 .probe = hibmc_pci_probe,
389 .remove = hibmc_pci_remove,
390 .shutdown = hibmc_pci_shutdown,
391 .driver.pm = &hibmc_pm_ops,
392 };
393
394 drm_module_pci_driver(hibmc_pci_driver);
395
396 MODULE_DEVICE_TABLE(pci, hibmc_pci_table);
397 MODULE_AUTHOR("RongrongZou <zourongrong@huawei.com>");
398 MODULE_DESCRIPTION("DRM Driver for Hisilicon Hibmc");
399 MODULE_LICENSE("GPL v2");
400