1 /*
2  * Copyright (C) 2012 Russell King
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  */
8 #include <linux/clk.h>
9 #include <linux/module.h>
10 #include <drm/drmP.h>
11 #include <drm/drm_crtc_helper.h>
12 #include "armada_crtc.h"
13 #include "armada_drm.h"
14 #include "armada_gem.h"
15 #include "armada_hw.h"
16 #include <drm/armada_drm.h>
17 #include "armada_ioctlP.h"
18 
19 #ifdef CONFIG_DRM_ARMADA_TDA1998X
20 #include <drm/i2c/tda998x.h>
21 #include "armada_slave.h"
22 
23 static struct tda998x_encoder_params params = {
24 	/* With 0x24, there is no translation between vp_out and int_vp
25 	FB	LCD out	Pins	VIP	Int Vp
26 	R:23:16	R:7:0	VPC7:0	7:0	7:0[R]
27 	G:15:8	G:15:8	VPB7:0	23:16	23:16[G]
28 	B:7:0	B:23:16	VPA7:0	15:8	15:8[B]
29 	*/
30 	.swap_a = 2,
31 	.swap_b = 3,
32 	.swap_c = 4,
33 	.swap_d = 5,
34 	.swap_e = 0,
35 	.swap_f = 1,
36 	.audio_cfg = BIT(2),
37 	.audio_frame[1] = 1,
38 	.audio_format = AFMT_SPDIF,
39 	.audio_sample_rate = 44100,
40 };
41 
42 static const struct armada_drm_slave_config tda19988_config = {
43 	.i2c_adapter_id = 0,
44 	.crtcs = 1 << 0, /* Only LCD0 at the moment */
45 	.polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT,
46 	.interlace_allowed = true,
47 	.info = {
48 		.type = "tda998x",
49 		.addr = 0x70,
50 		.platform_data = &params,
51 	},
52 };
53 #endif
54 
55 static void armada_drm_unref_work(struct work_struct *work)
56 {
57 	struct armada_private *priv =
58 		container_of(work, struct armada_private, fb_unref_work);
59 	struct drm_framebuffer *fb;
60 
61 	while (kfifo_get(&priv->fb_unref, &fb))
62 		drm_framebuffer_unreference(fb);
63 }
64 
65 /* Must be called with dev->event_lock held */
66 void __armada_drm_queue_unref_work(struct drm_device *dev,
67 	struct drm_framebuffer *fb)
68 {
69 	struct armada_private *priv = dev->dev_private;
70 
71 	/*
72 	 * Yes, we really must jump through these hoops just to store a
73 	 * _pointer_ to something into the kfifo.  This is utterly insane
74 	 * and idiotic, because it kfifo requires the _data_ pointed to by
75 	 * the pointer const, not the pointer itself.  Not only that, but
76 	 * you have to pass a pointer _to_ the pointer you want stored.
77 	 */
78 	const struct drm_framebuffer *silly_api_alert = fb;
79 	WARN_ON(!kfifo_put(&priv->fb_unref, &silly_api_alert));
80 	schedule_work(&priv->fb_unref_work);
81 }
82 
83 void armada_drm_queue_unref_work(struct drm_device *dev,
84 	struct drm_framebuffer *fb)
85 {
86 	unsigned long flags;
87 
88 	spin_lock_irqsave(&dev->event_lock, flags);
89 	__armada_drm_queue_unref_work(dev, fb);
90 	spin_unlock_irqrestore(&dev->event_lock, flags);
91 }
92 
93 static int armada_drm_load(struct drm_device *dev, unsigned long flags)
94 {
95 	const struct platform_device_id *id;
96 	struct armada_private *priv;
97 	struct resource *res[ARRAY_SIZE(priv->dcrtc)];
98 	struct resource *mem = NULL;
99 	int ret, n, i;
100 
101 	memset(res, 0, sizeof(res));
102 
103 	for (n = i = 0; ; n++) {
104 		struct resource *r = platform_get_resource(dev->platformdev,
105 							   IORESOURCE_MEM, n);
106 		if (!r)
107 			break;
108 
109 		/* Resources above 64K are graphics memory */
110 		if (resource_size(r) > SZ_64K)
111 			mem = r;
112 		else if (i < ARRAY_SIZE(priv->dcrtc))
113 			res[i++] = r;
114 		else
115 			return -EINVAL;
116 	}
117 
118 	if (!res[0] || !mem)
119 		return -ENXIO;
120 
121 	if (!devm_request_mem_region(dev->dev, mem->start,
122 			resource_size(mem), "armada-drm"))
123 		return -EBUSY;
124 
125 	priv = devm_kzalloc(dev->dev, sizeof(*priv), GFP_KERNEL);
126 	if (!priv) {
127 		DRM_ERROR("failed to allocate private\n");
128 		return -ENOMEM;
129 	}
130 
131 	platform_set_drvdata(dev->platformdev, dev);
132 	dev->dev_private = priv;
133 
134 	/* Get the implementation specific driver data. */
135 	id = platform_get_device_id(dev->platformdev);
136 	if (!id)
137 		return -ENXIO;
138 
139 	priv->variant = (struct armada_variant *)id->driver_data;
140 
141 	ret = priv->variant->init(priv, dev->dev);
142 	if (ret)
143 		return ret;
144 
145 	INIT_WORK(&priv->fb_unref_work, armada_drm_unref_work);
146 	INIT_KFIFO(priv->fb_unref);
147 
148 	/* Mode setting support */
149 	drm_mode_config_init(dev);
150 	dev->mode_config.min_width = 320;
151 	dev->mode_config.min_height = 200;
152 
153 	/*
154 	 * With vscale enabled, the maximum width is 1920 due to the
155 	 * 1920 by 3 lines RAM
156 	 */
157 	dev->mode_config.max_width = 1920;
158 	dev->mode_config.max_height = 2048;
159 
160 	dev->mode_config.preferred_depth = 24;
161 	dev->mode_config.funcs = &armada_drm_mode_config_funcs;
162 	drm_mm_init(&priv->linear, mem->start, resource_size(mem));
163 
164 	/* Create all LCD controllers */
165 	for (n = 0; n < ARRAY_SIZE(priv->dcrtc); n++) {
166 		if (!res[n])
167 			break;
168 
169 		ret = armada_drm_crtc_create(dev, n, res[n]);
170 		if (ret)
171 			goto err_kms;
172 	}
173 
174 #ifdef CONFIG_DRM_ARMADA_TDA1998X
175 	ret = armada_drm_connector_slave_create(dev, &tda19988_config);
176 	if (ret)
177 		goto err_kms;
178 #endif
179 
180 	ret = drm_vblank_init(dev, n);
181 	if (ret)
182 		goto err_kms;
183 
184 	ret = drm_irq_install(dev);
185 	if (ret)
186 		goto err_kms;
187 
188 	dev->vblank_disable_allowed = 1;
189 
190 	ret = armada_fbdev_init(dev);
191 	if (ret)
192 		goto err_irq;
193 
194 	drm_kms_helper_poll_init(dev);
195 
196 	return 0;
197 
198  err_irq:
199 	drm_irq_uninstall(dev);
200  err_kms:
201 	drm_mode_config_cleanup(dev);
202 	drm_mm_takedown(&priv->linear);
203 	flush_work(&priv->fb_unref_work);
204 
205 	return ret;
206 }
207 
208 static int armada_drm_unload(struct drm_device *dev)
209 {
210 	struct armada_private *priv = dev->dev_private;
211 
212 	drm_kms_helper_poll_fini(dev);
213 	armada_fbdev_fini(dev);
214 	drm_irq_uninstall(dev);
215 	drm_mode_config_cleanup(dev);
216 	drm_mm_takedown(&priv->linear);
217 	flush_work(&priv->fb_unref_work);
218 	dev->dev_private = NULL;
219 
220 	return 0;
221 }
222 
223 void armada_drm_vbl_event_add(struct armada_crtc *dcrtc,
224 	struct armada_vbl_event *evt)
225 {
226 	unsigned long flags;
227 
228 	spin_lock_irqsave(&dcrtc->irq_lock, flags);
229 	if (list_empty(&evt->node)) {
230 		list_add_tail(&evt->node, &dcrtc->vbl_list);
231 
232 		drm_vblank_get(dcrtc->crtc.dev, dcrtc->num);
233 	}
234 	spin_unlock_irqrestore(&dcrtc->irq_lock, flags);
235 }
236 
237 void armada_drm_vbl_event_remove(struct armada_crtc *dcrtc,
238 	struct armada_vbl_event *evt)
239 {
240 	if (!list_empty(&evt->node)) {
241 		list_del_init(&evt->node);
242 		drm_vblank_put(dcrtc->crtc.dev, dcrtc->num);
243 	}
244 }
245 
246 void armada_drm_vbl_event_remove_unlocked(struct armada_crtc *dcrtc,
247 	struct armada_vbl_event *evt)
248 {
249 	unsigned long flags;
250 
251 	spin_lock_irqsave(&dcrtc->irq_lock, flags);
252 	armada_drm_vbl_event_remove(dcrtc, evt);
253 	spin_unlock_irqrestore(&dcrtc->irq_lock, flags);
254 }
255 
256 /* These are called under the vbl_lock. */
257 static int armada_drm_enable_vblank(struct drm_device *dev, int crtc)
258 {
259 	struct armada_private *priv = dev->dev_private;
260 	armada_drm_crtc_enable_irq(priv->dcrtc[crtc], VSYNC_IRQ_ENA);
261 	return 0;
262 }
263 
264 static void armada_drm_disable_vblank(struct drm_device *dev, int crtc)
265 {
266 	struct armada_private *priv = dev->dev_private;
267 	armada_drm_crtc_disable_irq(priv->dcrtc[crtc], VSYNC_IRQ_ENA);
268 }
269 
270 static irqreturn_t armada_drm_irq_handler(int irq, void *arg)
271 {
272 	struct drm_device *dev = arg;
273 	struct armada_private *priv = dev->dev_private;
274 	struct armada_crtc *dcrtc = priv->dcrtc[0];
275 	uint32_t v, stat = readl_relaxed(dcrtc->base + LCD_SPU_IRQ_ISR);
276 	irqreturn_t handled = IRQ_NONE;
277 
278 	/*
279 	 * This is rediculous - rather than writing bits to clear, we
280 	 * have to set the actual status register value.  This is racy.
281 	 */
282 	writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ISR);
283 
284 	/* Mask out those interrupts we haven't enabled */
285 	v = stat & dcrtc->irq_ena;
286 
287 	if (v & (VSYNC_IRQ|GRA_FRAME_IRQ|DUMB_FRAMEDONE)) {
288 		armada_drm_crtc_irq(dcrtc, stat);
289 		handled = IRQ_HANDLED;
290 	}
291 
292 	return handled;
293 }
294 
295 static int armada_drm_irq_postinstall(struct drm_device *dev)
296 {
297 	struct armada_private *priv = dev->dev_private;
298 	struct armada_crtc *dcrtc = priv->dcrtc[0];
299 
300 	spin_lock_irq(&dev->vbl_lock);
301 	writel_relaxed(dcrtc->irq_ena, dcrtc->base + LCD_SPU_IRQ_ENA);
302 	writel(0, dcrtc->base + LCD_SPU_IRQ_ISR);
303 	spin_unlock_irq(&dev->vbl_lock);
304 
305 	return 0;
306 }
307 
308 static void armada_drm_irq_uninstall(struct drm_device *dev)
309 {
310 	struct armada_private *priv = dev->dev_private;
311 	struct armada_crtc *dcrtc = priv->dcrtc[0];
312 
313 	writel(0, dcrtc->base + LCD_SPU_IRQ_ENA);
314 }
315 
316 static struct drm_ioctl_desc armada_ioctls[] = {
317 	DRM_IOCTL_DEF_DRV(ARMADA_GEM_CREATE, armada_gem_create_ioctl,
318 		DRM_UNLOCKED),
319 	DRM_IOCTL_DEF_DRV(ARMADA_GEM_MMAP, armada_gem_mmap_ioctl,
320 		DRM_UNLOCKED),
321 	DRM_IOCTL_DEF_DRV(ARMADA_GEM_PWRITE, armada_gem_pwrite_ioctl,
322 		DRM_UNLOCKED),
323 };
324 
325 static void armada_drm_lastclose(struct drm_device *dev)
326 {
327 	armada_fbdev_lastclose(dev);
328 }
329 
330 static const struct file_operations armada_drm_fops = {
331 	.owner			= THIS_MODULE,
332 	.llseek			= no_llseek,
333 	.read			= drm_read,
334 	.poll			= drm_poll,
335 	.unlocked_ioctl		= drm_ioctl,
336 	.mmap			= drm_gem_mmap,
337 	.open			= drm_open,
338 	.release		= drm_release,
339 };
340 
341 static struct drm_driver armada_drm_driver = {
342 	.load			= armada_drm_load,
343 	.open			= NULL,
344 	.preclose		= NULL,
345 	.postclose		= NULL,
346 	.lastclose		= armada_drm_lastclose,
347 	.unload			= armada_drm_unload,
348 	.get_vblank_counter	= drm_vblank_count,
349 	.enable_vblank		= armada_drm_enable_vblank,
350 	.disable_vblank		= armada_drm_disable_vblank,
351 	.irq_handler		= armada_drm_irq_handler,
352 	.irq_postinstall	= armada_drm_irq_postinstall,
353 	.irq_uninstall		= armada_drm_irq_uninstall,
354 #ifdef CONFIG_DEBUG_FS
355 	.debugfs_init		= armada_drm_debugfs_init,
356 	.debugfs_cleanup	= armada_drm_debugfs_cleanup,
357 #endif
358 	.gem_free_object	= armada_gem_free_object,
359 	.prime_handle_to_fd	= drm_gem_prime_handle_to_fd,
360 	.prime_fd_to_handle	= drm_gem_prime_fd_to_handle,
361 	.gem_prime_export	= armada_gem_prime_export,
362 	.gem_prime_import	= armada_gem_prime_import,
363 	.dumb_create		= armada_gem_dumb_create,
364 	.dumb_map_offset	= armada_gem_dumb_map_offset,
365 	.dumb_destroy		= armada_gem_dumb_destroy,
366 	.gem_vm_ops		= &armada_gem_vm_ops,
367 	.major			= 1,
368 	.minor			= 0,
369 	.name			= "armada-drm",
370 	.desc			= "Armada SoC DRM",
371 	.date			= "20120730",
372 	.driver_features	= DRIVER_GEM | DRIVER_MODESET |
373 				  DRIVER_HAVE_IRQ | DRIVER_PRIME,
374 	.ioctls			= armada_ioctls,
375 	.fops			= &armada_drm_fops,
376 };
377 
378 static int armada_drm_probe(struct platform_device *pdev)
379 {
380 	return drm_platform_init(&armada_drm_driver, pdev);
381 }
382 
383 static int armada_drm_remove(struct platform_device *pdev)
384 {
385 	drm_put_dev(platform_get_drvdata(pdev));
386 	return 0;
387 }
388 
389 static const struct platform_device_id armada_drm_platform_ids[] = {
390 	{
391 		.name		= "armada-drm",
392 		.driver_data	= (unsigned long)&armada510_ops,
393 	}, {
394 		.name		= "armada-510-drm",
395 		.driver_data	= (unsigned long)&armada510_ops,
396 	},
397 	{ },
398 };
399 MODULE_DEVICE_TABLE(platform, armada_drm_platform_ids);
400 
401 static struct platform_driver armada_drm_platform_driver = {
402 	.probe	= armada_drm_probe,
403 	.remove	= armada_drm_remove,
404 	.driver	= {
405 		.name	= "armada-drm",
406 		.owner	= THIS_MODULE,
407 	},
408 	.id_table = armada_drm_platform_ids,
409 };
410 
411 static int __init armada_drm_init(void)
412 {
413 	armada_drm_driver.num_ioctls = DRM_ARRAY_SIZE(armada_ioctls);
414 	return platform_driver_register(&armada_drm_platform_driver);
415 }
416 module_init(armada_drm_init);
417 
418 static void __exit armada_drm_exit(void)
419 {
420 	platform_driver_unregister(&armada_drm_platform_driver);
421 }
422 module_exit(armada_drm_exit);
423 
424 MODULE_AUTHOR("Russell King <rmk+kernel@arm.linux.org.uk>");
425 MODULE_DESCRIPTION("Armada DRM Driver");
426 MODULE_LICENSE("GPL");
427 MODULE_ALIAS("platform:armada-drm");
428